x86: Add a new API for e820

The existing mechanism is pretty painful as it requires manual
calculations for anything but a trivial setup.

Add a new API for adding e820 entries.

Signed-off-by: Simon Glass <sjg@chromium.org>
diff --git a/arch/x86/lib/e820.c b/arch/x86/lib/e820.c
index 00ca947..bcc5f6f 100644
--- a/arch/x86/lib/e820.c
+++ b/arch/x86/lib/e820.c
@@ -3,8 +3,11 @@
  * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
  */
 
+#define LOG_CATEGORY	LOGC_ARCH
+
 #include <efi_loader.h>
 #include <lmb.h>
+#include <log.h>
 #include <asm/e820.h>
 #include <asm/global_data.h>
 
@@ -60,6 +63,50 @@
 	return 4;
 }
 
+void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
+	       int max_entries)
+{
+	memset(ctx, '\0', sizeof(*ctx));
+	ctx->entries = entries;
+	ctx->max_entries = max_entries;
+}
+
+void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size)
+{
+	struct e820_entry *entry = &ctx->entries[ctx->count++];
+
+	if (ctx->count <= ctx->max_entries) {
+		entry->addr = addr;
+		entry->size = size;
+		entry->type = type;
+	}
+	ctx->addr = addr + size;
+}
+
+void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size)
+{
+	e820_add(ctx, type, ctx->addr, size);
+}
+
+void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 addr)
+{
+	e820_next(ctx, type, addr - ctx->addr);
+}
+
+int e820_finish(struct e820_ctx *ctx)
+{
+	if (ctx->count > ctx->max_entries) {
+		printf("e820 has %d entries but room for only %d\n", ctx->count,
+		       ctx->max_entries);
+		panic("e820 table too large");
+	}
+	log_debug("e820 map installed, n=%d\n", ctx->count);
+	if (_DEBUG)
+		e820_dump(ctx->entries, ctx->count);
+
+	return ctx->count;
+}
+
 #if CONFIG_IS_ENABLED(EFI_LOADER)
 void efi_add_known_memory(void)
 {