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