This patch adds "high coreboot table support" to coreboot version 2.
authorStefan Reinauer <stepan@coresystems.de>
Tue, 17 Mar 2009 14:38:48 +0000 (14:38 +0000)
committerStefan Reinauer <stepan@openbios.org>
Tue, 17 Mar 2009 14:38:48 +0000 (14:38 +0000)
Some bootloaders seem to overwrite memory starting at 0x600, thus destroying
the coreboot table integrity, rendering the table useless.

By moving the table to the high tables area (if it's activated), this problem
is fixed.

In order to move the table, a 40 bytes mini coreboot table with a single sub
table is placed at 0x500/0x530 that points to the real coreboot table. This is
comparable to the ACPI RSDT or the MP floating table.

This patch also adds "table forward" support to flashrom and nvramtool.

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>
Acked-by: Peter Stuge <peter@stuge.se>
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@4011 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

src/arch/i386/boot/coreboot_table.c
src/arch/i386/boot/coreboot_table.h
src/arch/i386/boot/tables.c
src/include/boot/coreboot_tables.h

index 55a1697a598d901c6bb1c93290c91c7c6187bb87..032a0f3264c1aa1b816da0518e353118254c0430 100644 (file)
@@ -196,6 +196,18 @@ void lb_strings(struct lb_header *header)
 
 }
 
+struct lb_forward *lb_forward(struct lb_header *header, struct lb_header *next_header)
+{
+       struct lb_record *rec;
+       struct lb_forward *forward;
+       rec = lb_new_record(header);
+       forward = (struct lb_forward *)rec;
+       forward->tag = LB_TAG_FORWARD;
+       forward->size = sizeof(*forward);
+       forward->forward = (uint64_t) next_header;
+       return forward;
+}
+
 void lb_memory_range(struct lb_memory *mem,
        uint32_t type, uint64_t start, uint64_t size)
 {
@@ -239,14 +251,17 @@ static void lb_reserve_table_memory(struct lb_header *head)
        }
 }
 
-unsigned long lb_table_fini(struct lb_header *head)
+static unsigned long lb_table_fini(struct lb_header *head, int fixup)
 {
        struct lb_record *rec, *first_rec;
        rec = lb_last_record(head);
        if (head->table_entries) {
                head->table_bytes += rec->size;
        }
-       lb_reserve_table_memory(head);
+
+       if (fixup)
+               lb_reserve_table_memory(head);
+
        first_rec = lb_first_record(head);
        head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes);
        head->header_checksum = 0;
@@ -406,6 +421,22 @@ unsigned long write_coreboot_table(
        struct lb_header *head;
        struct lb_memory *mem;
 
+#if HAVE_HIGH_TABLES == 1
+       printk_debug("Writing high table forward entry at 0x%08lx\n",
+                       low_table_end);
+       head = lb_table_init(low_table_end);
+       lb_forward(head, rom_table_end);
+       lb_table_fini(head, 0);
+
+       low_table_end = (unsigned long)head;
+       printk_debug("New low_table_end: 0x%08lx\n", low_table_end);
+       printk_debug("Now going to write high coreboot table at 0x%08lx\n",
+                       rom_table_end);
+       
+       head = lb_table_init(rom_table_end);
+       rom_table_end = (unsigned long)head;
+       printk_debug("rom_table_end = 0x%08lx\n", rom_table_end);
+#else
        if(low_table_end > (0x1000 - sizeof(struct lb_header))) { /* after 4K */
                /* We need to put lbtable on  to [0xf0000,0x100000) */
                head = lb_table_init(rom_table_end);
@@ -414,6 +445,7 @@ unsigned long write_coreboot_table(
                head = lb_table_init(low_table_end);
                low_table_end = (unsigned long)head;
        }
+#endif
  
        printk_debug("Adjust low_table_end from 0x%08lx to ", low_table_end);
        low_table_end += 0xfff; // 4K aligned
@@ -469,6 +501,6 @@ unsigned long write_coreboot_table(
        lb_strings(head);
 
        /* Remember where my valid memory ranges are */
-       return lb_table_fini(head);
+       return lb_table_fini(head, 1);
        
 }
index 4c8c44a18cdbd0b33741f7d74faa3f69ea672ea6..9a9be84d43009eebf63b520b271825648ffbd511 100644 (file)
@@ -17,7 +17,6 @@ struct lb_memory *lb_memory(struct lb_header *header);
 void lb_memory_range(struct lb_memory *mem, 
        uint32_t type, uint64_t start, uint64_t size);
 struct lb_mainboard *lb_mainboard(struct lb_header *header);
-unsigned long lb_table_fini(struct lb_header *header);
 
 /* Routines to extract part so the coreboot table or information
  * from the coreboot table.
index 58c5ce896a8c389316c86238252fe4e5e543f8de..72f23449114d3a0e179a00d7f7d8544743de0d73 100644 (file)
@@ -75,7 +75,7 @@ struct lb_memory *write_tables(void)
        unsigned long high_table_start, high_table_end=0;
 
        if (high_tables_base) {
-               printk_debug("High Tables Base is %lx.\n", high_tables_base);
+               printk_debug("High Tables Base is %llx.\n", high_tables_base);
                high_table_start = high_tables_base;
                high_table_end = high_tables_base;
        } else {
@@ -189,26 +189,19 @@ struct lb_memory *write_tables(void)
                                rom_table_start, rom_table_end);
 #endif
 
+#if HAVE_HIGH_TABLES == 1
+       if (high_tables_base) {
+               write_coreboot_table(low_table_start, low_table_end,
+                               high_table_start, high_table_end);
+       } else {
+               printk_err("ERROR: No high_tables_base.\n");
+               write_coreboot_table(low_table_start, low_table_end,
+                             rom_table_start, rom_table_end);
+       }
+#else
        /* The coreboot table must be in 0-4K or 960K-1M */
        write_coreboot_table(low_table_start, low_table_end,
                              rom_table_start, rom_table_end);
-
-#if 0 && HAVE_HIGH_TABLES == 1
-       /* This is currently broken and should be severely refactored. Ideally
-        * we only have a pointer to the coreboot table in the low memory, so
-        * anyone can find the real position.
-        * write_coreboot_table does a lot more than just writing the coreboot
-        * table. It magically decides where the table should go, and therefore
-        * it consumes two base addresses. If we call write_coreboot_table like
-        * below, we get weird effects.
-        */
-       /* And we want another copy in high area because the low area might be
-        * corrupted
-        */
-       if (high_tables_base) {
-               write_coreboot_table(high_table_start, high_table_end,
-                                     high_table_start, high_table_end);
-       }
 #endif
  
        return get_lb_mem();
index 3f8e60698e16088c2184dc23ac10bdb065070ee8..f0ab7af7cbc7d2d0d462fbf6d7e521ce9d7e0ad3 100644 (file)
@@ -155,6 +155,13 @@ struct lb_console {
        uint16_t type;
 };
 
+#define LB_TAG_FORWARD         0x0011
+struct lb_forward {
+       uint32_t tag;
+       uint32_t size;
+       uint64_t forward;
+};
+
 #define LB_TAG_CONSOLE_SERIAL8250      0
 #define LB_TAG_CONSOLE_VGA             1
 #define LB_TAG_CONSOLE_BTEXT           2