I didn't understand what was going on in tables.c, and it seemed a
little fragile.
These three patches try to help that out. I would only recommend the
first two, but all three is closer to maintaining the functionality we
had.
When you're reviewing, it will be helpful to note that rom_tables_* ==
LOW_TABLES, high_tables_* == HIGH_TABLES, and low_tables==
coreboot-specific very low tables.
These patches are abuild tested and boot tested on Tyan s2892, qemu, and SimNOW.
tables.diff:
Add comments.
Remove ACPI-specific code.
Align low_table_end after gdt (so it matches high_table_end).
Correct "New low_table_end..." line in coreboot_table.c.
high_low.diff:
Factor out common code for writing tables.
both.diff:
If we need to have the tables written both times we can do something like this.
Signed-off-by: Myles Watson <[email protected]>
Thanks,
Myles
Index: cbv2/src/arch/i386/boot/tables.c
===================================================================
--- cbv2.orig/src/arch/i386/boot/tables.c 2009-05-13 15:30:26.000000000 -0600
+++ cbv2/src/arch/i386/boot/tables.c 2009-05-13 15:39:50.000000000 -0600
@@ -62,13 +62,12 @@
uint64_t high_tables_size;
#endif
+/* HIGH_TABLES means a table in very low memory + at the end of RAM. */
+/* LOW_TABLES means a table in very low memory + at 0xf0000 (rom_table_*). */
struct lb_memory *write_tables(void)
{
unsigned long low_table_start, low_table_end;
unsigned long rom_table_start, rom_table_end;
-#if HAVE_MP_TABLE == 1 && HAVE_LOW_TABLES == 1
- unsigned long new_low_table_end;
-#endif
#if HAVE_HIGH_TABLES == 1
/* Even if high tables are configured, all tables are copied both to the
@@ -114,18 +113,10 @@
*/
#if HAVE_ACPI_TABLES == 1
#if HAVE_HIGH_TABLES == 1
-#if HAVE_LOW_TABLES == 1
- unsigned long high_rsdp=ALIGN(high_table_end, 16);
-#endif
if (high_tables_base) {
high_table_end = write_acpi_tables(high_table_end);
high_table_end = (high_table_end+1023) & ~1023;
}
-#if HAVE_LOW_TABLES == 1
- unsigned long rsdt_location=(unsigned long*)(((acpi_rsdp_t*)high_rsdp)->rsdt_address);
- acpi_write_rsdp(rom_table_end, rsdt_location);
- rom_table_end = ALIGN(ALIGN(rom_table_end, 16) + sizeof(acpi_rsdp_t), 16);
-#endif
#else
#if HAVE_LOW_TABLES == 1
rom_table_end = write_acpi_tables(rom_table_end);
@@ -139,42 +130,27 @@
#if HAVE_MP_TABLE == 1
/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
+ /* Put it in the largest spot (960K-1M). */
#if HAVE_LOW_TABLES == 1
- new_low_table_end = write_smp_table(low_table_end); // low_table_end is 0x10 at this point
- /* Don't write anything in the traditional x86 BIOS data segment,
- * for example the linux kernel smp need to use 0x467 to pass reset vector
- * or use 0x40e/0x413 for EBDA finding...
- */
- if(new_low_table_end>0x400){
- unsigned mptable_size;
- unsigned mpc_start;
- low_table_end += SMP_FLOATING_TABLE_LEN; /* keep the mpf in 1k low, so kernel can find it */
- mptable_size = new_low_table_end - low_table_end;
- /* We can not put mptable low, we need to copy them to somewhere else*/
- if((rom_table_end+mptable_size)<0x100000) {
- /* We can copy mptable on rom_table */
- mpc_start = rom_table_end;
- rom_table_end += mptable_size;
- rom_table_end = (rom_table_end+1023) & ~1023;
- } else {
- /* We can need to put mptable before rom_table */
- mpc_start = rom_table_start - mptable_size;
- mpc_start &= ~1023;
- rom_table_start = mpc_start;
- }
- printk_debug("move mptable from 0x%0lx to 0x%0x, size 0x%0x\n", low_table_end, mpc_start, mptable_size);
- memcpy((unsigned char *)mpc_start, (unsigned char *)low_table_end, mptable_size);
- smp_write_floating_table_physaddr(low_table_end - SMP_FLOATING_TABLE_LEN, mpc_start);
- memset((unsigned char *)low_table_end, '\0', mptable_size);
- }
+ mpc_start = rom_table_end;
+ rom_table_end = write_smp_table(rom_table_end);
+ rom_table_end = (rom_table_end+1023) & ~1023;
+ if (mpc_start < 0x100000 && rom_table_end > 0x100000)
+ printk_err("MP table too big to fit below 1M %lx-%lx\n",
+ mpc_start, rom_table_end);
#endif /* HAVE_LOW_TABLES */
#if HAVE_HIGH_TABLES == 1
+#if HAVE_LOW_TABLES == 0
+ mpc_start = high_table_end;
+#endif
if (high_tables_base) {
high_table_end = write_smp_table(high_table_end);
high_table_end = (high_table_end+1023) & ~1023;
}
#endif
+ smp_write_floating_table_physaddr(low_table_end, mpc_start);
+ low_table_end += SMP_FLOATING_TABLE_LEN;
#endif /* HAVE_MP_TABLE */
if (low_table_end < 0x500) {
@@ -191,6 +167,7 @@
#endif
move_gdt(low_table_end);
low_table_end += &gdt_end - &gdt;
+ low_table_end = (low_table_end+1023) & ~1023;
#if HAVE_HIGH_TABLES == 1
}
#endif
@@ -206,17 +183,17 @@
#if HAVE_HIGH_TABLES == 1
if (high_tables_base) {
write_coreboot_table(low_table_start, low_table_end,
- high_table_start, high_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);
+ 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);
#endif
-
+
return get_lb_mem();
}
Index: cbv2/src/arch/i386/boot/coreboot_table.c
===================================================================
--- cbv2.orig/src/arch/i386/boot/coreboot_table.c 2009-05-13 15:30:26.000000000 -0600
+++ cbv2/src/arch/i386/boot/coreboot_table.c 2009-05-13 15:35:16.000000000 -0600
@@ -429,9 +429,8 @@
low_table_end);
head = lb_table_init(low_table_end);
lb_forward(head, (struct lb_header*)rom_table_end);
- lb_table_fini(head, 0);
- low_table_end = (unsigned long)head;
+ low_table_end = (unsigned long) lb_table_fini(head, 0);
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);
Index: cbv2/src/arch/i386/boot/tables.c
===================================================================
--- cbv2.orig/src/arch/i386/boot/tables.c 2009-05-13 15:35:16.000000000 -0600
+++ cbv2/src/arch/i386/boot/tables.c 2009-05-13 15:35:25.000000000 -0600
@@ -57,140 +57,105 @@
printk_debug("ok\n");
}
-#if HAVE_HIGH_TABLES == 1
-uint64_t high_tables_base = 0;
-uint64_t high_tables_size;
-#endif
-
-/* HIGH_TABLES means a table in very low memory + at the end of RAM. */
-/* LOW_TABLES means a table in very low memory + at 0xf0000 (rom_table_*). */
-struct lb_memory *write_tables(void)
+void write_table(unsigned long dir_start, unsigned long *dir_end,
+ unsigned long table_start, unsigned long *table_end)
{
- unsigned long low_table_start, low_table_end;
- unsigned long rom_table_start, rom_table_end;
-
-#if HAVE_HIGH_TABLES == 1
- /* Even if high tables are configured, all tables are copied both to the
- * low and the high area, so payloads and OSes don't need to know about
- * the high tables.
- */
- unsigned long high_table_start=0, high_table_end=0;
-
- if (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 {
- printk_debug("High Tables Base is not set.\n");
- }
-#endif
+ unsigned long dir_table_start = dir_start, dir_table_end = *dir_end;
+ unsigned long rom_table_start = table_start, rom_table_end = *table_end;
- rom_table_start = 0xf0000;
- rom_table_end = 0xf0000;
- /* Start low addr at 16 bytes instead of 0 because of a buglet
- * in the generic linux unzip code, as it tests for the a20 line.
- */
- low_table_start = 0;
- low_table_end = 16;
-
- post_code(0x9a);
-
-#if HAVE_LOW_TABLES == 1
/* This table must be betweeen 0xf0000 & 0x100000 */
rom_table_end = write_pirq_routing_table(rom_table_end);
rom_table_end = (rom_table_end + 1023) & ~1023;
-#endif
-#if HAVE_HIGH_TABLES == 1
- if (high_tables_base) {
- high_table_end = write_pirq_routing_table(high_table_end);
- high_table_end = (high_table_end + 1023) & ~1023;
- }
-#endif
/* Write ACPI tables */
/* write them in the rom area because DSDT can be large (8K on epia-m) which
* pushes coreboot table out of first 4K if set up in low table area
*/
#if HAVE_ACPI_TABLES == 1
-#if HAVE_HIGH_TABLES == 1
- if (high_tables_base) {
- high_table_end = write_acpi_tables(high_table_end);
- high_table_end = (high_table_end+1023) & ~1023;
- }
-#else
-#if HAVE_LOW_TABLES == 1
rom_table_end = write_acpi_tables(rom_table_end);
- rom_table_end = (rom_table_end+1023) & ~1023;
-#endif
-#endif
+ rom_table_end = (rom_table_end + 1023) & ~1023;
#endif
/* copy the smp block to address 0 */
post_code(0x96);
#if HAVE_MP_TABLE == 1
-
/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
/* Put it in the largest spot (960K-1M). */
-#if HAVE_LOW_TABLES == 1
- mpc_start = rom_table_end;
+ unsigned long mpc_start = rom_table_end;
rom_table_end = write_smp_table(rom_table_end);
- rom_table_end = (rom_table_end+1023) & ~1023;
+ rom_table_end = (rom_table_end + 1023) & ~1023;
if (mpc_start < 0x100000 && rom_table_end > 0x100000)
printk_err("MP table too big to fit below 1M %lx-%lx\n",
mpc_start, rom_table_end);
-#endif /* HAVE_LOW_TABLES */
+ smp_write_floating_table_physaddr(dir_table_end, mpc_start);
+ dir_table_end += SMP_FLOATING_TABLE_LEN;
+#endif /* HAVE_MP_TABLE */
-#if HAVE_HIGH_TABLES == 1
-#if HAVE_LOW_TABLES == 0
- mpc_start = high_table_end;
-#endif
- if (high_tables_base) {
- high_table_end = write_smp_table(high_table_end);
- high_table_end = (high_table_end+1023) & ~1023;
+ if (dir_table_end < 0x500) {
+ dir_table_end = 0x500;
}
-#endif
- smp_write_floating_table_physaddr(low_table_end, mpc_start);
- low_table_end += SMP_FLOATING_TABLE_LEN;
-#endif /* HAVE_MP_TABLE */
- if (low_table_end < 0x500) {
- low_table_end = 0x500;
- }
-
- // Relocate the GDT to reserved memory, so it won't get clobbered
-#if HAVE_HIGH_TABLES == 1
- if (high_tables_base) {
- move_gdt(high_table_end);
- high_table_end += &gdt_end - &gdt;
- high_table_end = (high_table_end+1023) & ~1023;
- } else {
-#endif
- move_gdt(low_table_end);
- low_table_end += &gdt_end - &gdt;
- low_table_end = (low_table_end+1023) & ~1023;
-#if HAVE_HIGH_TABLES == 1
- }
-#endif
+ /* Relocate the GDT to reserved memory, so it won't get clobbered. */
+ move_gdt(rom_table_end);
+ rom_table_end += &gdt_end - &gdt;
+ rom_table_end = (rom_table_end + 1023) & ~1023;
#if CONFIG_MULTIBOOT
/* The Multiboot information structure */
mbi = (struct multiboot_info *)rom_table_end;
- rom_table_end = write_multiboot_info(
- low_table_start, low_table_end,
- rom_table_start, rom_table_end);
+ rom_table_end = write_multiboot_info(dir_table_start, dir_table_end,
+ rom_table_start, rom_table_end);
#endif
+ *dir_end = dir_table_end;
+ *table_end = rom_table_end;
+}
+
#if HAVE_HIGH_TABLES == 1
+uint64_t high_tables_base = 0;
+uint64_t high_tables_size;
+#endif
+
+/* HIGH_TABLES means a table in very low memory + at the end of RAM. */
+/* LOW_TABLES means a table in very low memory + at 0xf0000 (rom_table_*). */
+struct lb_memory *write_tables(void)
+{
+ unsigned long low_table_start, low_table_end;
+ unsigned long rom_table_start, rom_table_end;
+
+ rom_table_start = 0xf0000;
+ rom_table_end = 0xf0000;
+
+ /* Start low addr at 16 bytes instead of 0 because of a buglet
+ * in the generic linux unzip code, as it tests for the a20 line.
+ */
+ low_table_start = 0;
+ low_table_end = 16;
+
+ post_code(0x9a);
+
+#if HAVE_HIGH_TABLES == 1
+ unsigned long high_table_start=0, high_table_end=0;
+
if (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;
+ write_table(low_table_start, &low_table_end,
+ high_table_start, &high_table_end);
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_table(low_table_start, &low_table_end,
+ rom_table_start, &rom_table_end);
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_table(low_table_start, &low_table_end,
+ rom_table_start, &rom_table_end);
write_coreboot_table(low_table_start, low_table_end,
rom_table_start, rom_table_end);
#endif
Index: cbv2/src/arch/i386/boot/tables.c
===================================================================
--- cbv2.orig/src/arch/i386/boot/tables.c 2009-05-13 15:21:31.000000000 -0600
+++ cbv2/src/arch/i386/boot/tables.c 2009-05-13 15:22:41.000000000 -0600
@@ -134,6 +134,9 @@
post_code(0x9a);
+ write_table(low_table_start, &low_table_end,
+ rom_table_start, &rom_table_end);
+
#if HAVE_HIGH_TABLES == 1
unsigned long high_table_start=0, high_table_end=0;
@@ -147,15 +150,11 @@
high_table_start, high_table_end);
} else {
printk_err("ERROR: No high_tables_base.\n");
- write_table(low_table_start, &low_table_end,
- rom_table_start, &rom_table_end);
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_table(low_table_start, &low_table_end,
- rom_table_start, &rom_table_end);
write_coreboot_table(low_table_start, low_table_end,
rom_table_start, rom_table_end);
#endif
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot