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 <s...@chromium.org>
---

Changes in v3:
- Add new patch with an API for e820

 arch/x86/include/asm/e820.h | 87 ++++++++++++++++++++++++++++++++++++-
 arch/x86/lib/e820.c         | 47 ++++++++++++++++++++
 2 files changed, 133 insertions(+), 1 deletion(-)

diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
index cc3758b59fd..a535818b2d5 100644
--- a/arch/x86/include/asm/e820.h
+++ b/arch/x86/include/asm/e820.h
@@ -3,6 +3,8 @@
 
 #define E820MAX                128     /* number of entries in E820MAP */
 
+#ifdef __ASSEMBLY__
+
 #define E820_RAM       1
 #define E820_RESERVED  2
 #define E820_ACPI      3
@@ -10,9 +12,21 @@
 #define E820_UNUSABLE  5
 #define E820_COUNT     6       /* Number of types */
 
-#ifndef __ASSEMBLY__
+#else
+
 #include <linux/types.h>
 
+/* Available e820 memory-region types */
+enum e820_type {
+       E820_RAM        = 1,
+       E820_RESERVED,
+       E820_ACPI,
+       E820_NVS,
+       E820_UNUSABLE,
+
+       E820_COUNT,
+};
+
 struct e820_entry {
        __u64 addr;     /* start of memory segment */
        __u64 size;     /* size of memory segment */
@@ -22,10 +36,81 @@ struct e820_entry {
 #define ISA_START_ADDRESS      0xa0000
 #define ISA_END_ADDRESS                0x100000
 
+/**
+ * Context to use for e820_add()
+ *
+ * @entries: Table being filled in
+ * @addr: Current address we are up to
+ * @count: Number of entries added to @entries so far
+ * @max_entries: Maximum number of entries allowed
+ */
+struct e820_ctx {
+       struct e820_entry *entries;
+       u64 addr;
+       int count;
+       int max_entries;
+};
+
+/**
+ * e820_init() - Start setting up an e820 table
+ *
+ * @ctx: Context to set up
+ * @entries: Place to put entries
+ * @max_entries: Maximum size of @entries
+ */
+void e820_init(struct e820_ctx *ctx, struct e820_entry *entries,
+              int max_entries);
+
+/**
+ * e820_add() - Add an entry to the table
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @addr: Start address of entry
+ * @size Size of entry
+ */
+void e820_add(struct e820_ctx *ctx, enum e820_type type, u64 addr, u64 size);
+
+/**
+ * e820_to_addr() - Add an entry that covers the space up to a given address
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @end_addr: Address where the entry should finish
+ */
+void e820_to_addr(struct e820_ctx *ctx, enum e820_type type, u64 end_addr);
+
+/**
+ * e820_next() - Add an entry that carries on from the last one
+ *
+ * @ctx: Context
+ * @type: Type of entry
+ * @size Size of entry
+ */
+void e820_next(struct e820_ctx *ctx, enum e820_type type, u64 size);
+
+/**
+ * e820_finish() - Finish the table
+ *
+ * Checks the table is not too large, panics if so
+ *
+ * @ctx: Context
+ * Returns: Number of entries
+ */
+int e820_finish(struct e820_ctx *ctx);
+
 /* Implementation-defined function to install an e820 map */
 unsigned int install_e820_map(unsigned int max_entries,
                              struct e820_entry *);
 
+/**
+ * e820_dump() - Dump the e820 table
+ *
+ * @entries: Pointer to start of table
+ * @count: Number of entries in the table
+ */
+void e820_dump(struct e820_entry *entries, uint count);
+
 /**
  * cb_install_e820_map() - Install e820 map provided by coreboot sysinfo
  *
diff --git a/arch/x86/lib/e820.c b/arch/x86/lib/e820.c
index 00ca94776d2..bcc5f6f3044 100644
--- a/arch/x86/lib/e820.c
+++ b/arch/x86/lib/e820.c
@@ -3,8 +3,11 @@
  * Copyright (C) 2015, Bin Meng <bmeng...@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 @@ __weak unsigned int install_e820_map(unsigned int 
max_entries,
        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)
 {
-- 
2.43.0

Reply via email to