[SeaBIOS] [PATCH] fw/coreboot.c: Use coreboot table to find cbfs

Arthur Heymans posted 1 patch 1 week, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/seabios tags/patchew/20210430082826.394372-1-arthur@aheymans.xyz

[SeaBIOS] [PATCH] fw/coreboot.c: Use coreboot table to find cbfs

Posted by Arthur Heymans 1 week, 1 day ago
The "cbfs master header" cbfs file is considered a legacy feature in
coreboot and is planned for removal in the master branch. Since 2015
the coreboot tables have exported info about the active cbfs.

This change uses the cbfs information in the coreboot tables instead
of following the cbfs master header pointer in the bootblock to find
cbfs. This change makes it possible to access CBFS fmap regions that
don't feature a "cbfs master header", which is the case with Googles
VBOOT solution.

This breaks compatibility with very old coreboot build (build before
fb5d5b16 "2015-07-14, cbtable: describe boot media"). Keeping
backward compatibility with the "cbfs master header" would complicate
the code.

Signed-off-by: Arthur Heymans <arthur@aheymans.xyz>

diff --git a/src/Kconfig b/src/Kconfig
index 3a8ffa1..51ba827 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -93,15 +93,6 @@ endchoice
         help
             Support CBFS files compressed using the lzma decompression
             algorithm.
-    config CBFS_LOCATION
-        depends on COREBOOT_FLASH
-        hex "CBFS memory end location"
-        default 0
-        help
-            Memory address of where the CBFS data ends.  This should
-            be zero for normal builds.  It may be a non-zero value if
-            the CBFS filesystem is at a non-standard location (eg,
-            0xffe00000 if CBFS ends 2Meg below the end of flash).
 
     config MULTIBOOT
         depends on COREBOOT
diff --git a/src/fw/coreboot.c b/src/fw/coreboot.c
index 7c0954b..8a35c1d 100644
--- a/src/fw/coreboot.c
+++ b/src/fw/coreboot.c
@@ -88,6 +88,18 @@ struct cbmem_console {
 #define CBMC_OVERFLOW (1 << 31)
 static struct cbmem_console *cbcon = NULL;
 
+#define CB_TAG_BOOT_MEDIA_PARAMS 0x30
+
+struct cb_boot_media_params {
+  u32 tag;
+  u32 size;
+  /* offsets are relative to start of boot media */
+  u64 fmap_offset;
+  u64 cbfs_offset;
+  u64 cbfs_size;
+  u64 boot_media_size;
+};
+
 static u16
 ipchksum(char *buf, int count)
 {
@@ -146,7 +158,12 @@ find_cb_subtable(struct cb_header *cbh, u32 tag)
 struct cb_header *
 find_cb_table(void)
 {
-    struct cb_header *cbh = find_cb_header(0, 0x1000);
+    static struct cb_header *cbh;
+
+    if (cbh)
+        return cbh;
+
+    cbh= find_cb_header(0, 0x1000);
     if (!cbh)
         return NULL;
     struct cb_forward *cbf = find_cb_subtable(cbh, CB_TAG_FORWARD);
@@ -317,20 +334,8 @@ ulzma(u8 *dst, u32 maxlen, const u8 *src, u32 srclen)
  * Coreboot flash format
  ****************************************************************/
 
-#define CBFS_HEADER_MAGIC 0x4F524243
-#define CBFS_VERSION1 0x31313131
-
-struct cbfs_header {
-    u32 magic;
-    u32 version;
-    u32 romsize;
-    u32 bootblocksize;
-    u32 align;
-    u32 offset;
-    u32 pad[2];
-} PACKED;
-
 #define CBFS_FILE_MAGIC 0x455649484352414cLL // LARCHIVE
+#define CBFS_ALIGNMENT 64
 
 struct cbfs_file {
     u64 magic;
@@ -429,30 +434,50 @@ coreboot_cbfs_init(void)
     if (!CONFIG_COREBOOT_FLASH)
         return;
 
-    struct cbfs_header *hdr = *(void **)(CONFIG_CBFS_LOCATION - 4);
-    if ((u32)hdr & 0x03) {
-        dprintf(1, "Invalid CBFS pointer %p\n", hdr);
+    dprintf(3, "Attempting to initialize coreboot cbfs\n");
+
+    struct cb_header *cbh = find_cb_table();
+    if (!cbh) {
+        dprintf(1, "cbfs_init: unable to find cb table\n");
         return;
     }
-    if (CONFIG_CBFS_LOCATION && (u32)hdr > CONFIG_CBFS_LOCATION)
-        // Looks like the pointer is relative to CONFIG_CBFS_LOCATION
-        hdr = (void*)hdr + CONFIG_CBFS_LOCATION;
-    if (hdr->magic != cpu_to_be32(CBFS_HEADER_MAGIC)) {
-        dprintf(1, "Unable to find CBFS (ptr=%p; got %x not %x)\n"
-                , hdr, hdr->magic, cpu_to_be32(CBFS_HEADER_MAGIC));
+
+    struct cb_boot_media_params *cbbmp =
+        find_cb_subtable(cbh, CB_TAG_BOOT_MEDIA_PARAMS);
+
+    if (!cbbmp) {
+        dprintf(1, "cbfs_init: unable to find boot media params\n");
         return;
     }
-    dprintf(1, "Found CBFS header at %p\n", hdr);
 
-    u32 romsize = be32_to_cpu(hdr->romsize);
-    u32 romstart = CONFIG_CBFS_LOCATION - romsize;
-    struct cbfs_file *fhdr = (void*)romstart + be32_to_cpu(hdr->offset);
+    const u32 romsize = cbbmp->boot_media_size;
+    const u32 cbfs_start = cbbmp->cbfs_offset - romsize;
+    const u32 cbfs_end = cbfs_start + cbbmp->cbfs_size - 1;
+
+    dprintf(3, "cbfs_init: cbfs_start=0x%08x, cbfs_end=0x%08x\n", cbfs_start,
+            cbfs_end);
+
+    u32 offset = cbfs_start;
+
     for (;;) {
-        if ((u32)fhdr - romstart > romsize)
-            break;
-        u64 magic = fhdr->magic;
-        if (magic != CBFS_FILE_MAGIC)
+        if (offset > cbfs_end || offset < cbfs_start)
             break;
+
+        struct cbfs_file *fhdr = (void*)offset;
+
+        if (fhdr->magic != CBFS_FILE_MAGIC) {
+            offset++;
+            offset = ALIGN(offset, CBFS_ALIGNMENT);
+            continue;
+        }
+
+        /* Skip empty space */
+        if (strcmp(fhdr->filename, "") == 0) {
+            offset += ALIGN(be32_to_cpu(fhdr->offset) + be32_to_cpu(fhdr->len)
+                           , CBFS_ALIGNMENT);
+            continue;
+        }
+
         struct cbfs_romfile_s *cfile = malloc_tmp(sizeof(*cfile));
         if (!cfile) {
             warn_noalloc();
@@ -473,8 +498,8 @@ coreboot_cbfs_init(void)
         }
         romfile_add(&cfile->file);
 
-        fhdr = (void*)ALIGN((u32)cfile->data + cfile->rawsize
-                            , be32_to_cpu(hdr->align));
+        offset = ALIGN((u32)cfile->data + cfile->rawsize
+                       , CBFS_ALIGNMENT);
     }
 
     process_links_file();
-- 
2.30.2

_______________________________________________
SeaBIOS mailing list -- seabios@seabios.org
To unsubscribe send an email to seabios-leave@seabios.org