[SeaBIOS] [PATCH] coreboot: update memory table before handling execution to payload/system

Krystian Hebel krystian.hebel at 3mdeb.com
Mon Nov 5 13:27:10 CET 2018


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 at 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);
+}
-- 
2.17.1




More information about the SeaBIOS mailing list