SeaBIOS modifies its internal e820 structure, but does not propagate these changes back to coreboot tables. This resulted in multiple errors in MemTest86 when run on 2 GB platforms, probably because of some memory-mapped devices.
This patch copies back modified e820 tables before booting an OS or a payload.
Change-Id: I16a3f059695717daedb1e997ce4e62018c7e02b3 Signed-off-by: Krystian Hebel krystian.hebel@3mdeb.com --- src/e820map.c | 2 ++ src/e820map.h | 2 ++ src/fw/coreboot.c | 50 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/src/e820map.c b/src/e820map.c index 39445cf6399d..2d2de6094b14 100644 --- a/src/e820map.c +++ b/src/e820map.c @@ -148,5 +148,7 @@ e820_remove(u64 start, u64 size) void e820_prepboot(void) { + // Synchronize memory maps. + coreboot_update_memtable(); dump_map(); } diff --git a/src/e820map.h b/src/e820map.h index de8b523003c5..78bf1ce76572 100644 --- a/src/e820map.h +++ b/src/e820map.h @@ -23,4 +23,6 @@ void e820_prepboot(void); extern struct e820entry e820_list[]; extern int e820_count;
+extern void coreboot_update_memtable(void); + #endif // e820map.h diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c index 7c0954b5398c..aa07baad3a7f 100644 --- a/src/fw/coreboot.c +++ b/src/fw/coreboot.c @@ -189,10 +189,6 @@ coreboot_preinit(void) e820_add(m->start, m->size, type); }
- // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this - // confuses grub. So, override it. - e820_add(0, 16*1024, E820_RAM); - struct cb_cbmem_ref *cbref = find_cb_subtable(cbh, CB_TAG_CBMEM_CONSOLE); if (cbref) { cbcon = (void*)(u32)cbref->cbmem_addr; @@ -567,3 +563,49 @@ cbfs_payload_setup(void) boot_add_cbfs(cfile->fhdr, desc, bootprio_find_named_rom(filename, 0)); } } + +// Mirror changes done on e820 to coreboot tables. +void +coreboot_update_memtable(void) +{ + if (!CONFIG_COREBOOT) + return; + + // Find coreboot table. + struct cb_header *cbh = find_cb_table(); + if (!cbh) { + dprintf(1, "Unable to find coreboot table!\n"); + return; + } + char *end = (char *)cbh + sizeof(*cbh) + cbh->table_bytes; + dprintf(3, "Now attempting to find coreboot memory map\n"); + struct cb_memory *dst = find_cb_subtable(cbh, CB_TAG_MEMORY); + if (!dst) { + dprintf(1, "Unable to find coreboot memory table!\n"); + return; + } + + // Remove old memory table, overwriting it with following subtables + // and append an updated memory table to the end. + u32 old_size = dst->size; + char *src = (char *)dst + old_size; + memcpy(dst, src, (end - src)); + dst = (struct cb_memory *)(end - old_size); + u32 new_size = e820_count * sizeof(struct e820entry); + dst->tag = CB_TAG_MEMORY; + // Tables are binary compatible, except that CB_MEM_TABLE became + // E820_RESERVED. + memcpy((char*)dst + sizeof(struct cb_memory), e820_list, new_size); + new_size += sizeof(struct cb_memory); + dst->size = new_size; + + // Update header fields (size and checksum). + cbh->table_bytes += new_size - old_size; + cbh->table_checksum = ipchksum((char*)cbh + sizeof(*cbh), cbh->table_bytes); + cbh->header_checksum = 0; + cbh->header_checksum = ipchksum((char*)cbh, sizeof(*cbh)); + + // Ughh - coreboot likes to set a map at 0x0000-0x1000, but this + // confuses grub. So, override it in e820 only. + e820_add(0, 16*1024, E820_RAM); +}