I'm adding a Geos platform driver that needs to be able to confirm that it's running on the correct hardware, and it does this by locating the Coreboot tables and parsing them for the vendor/part fields.
Unfortunately, it's not working entirely.
I borrowed code from flashrom's cbtable.c and tweaked it:
...
#define BYTES_TO_MAP (1024*1024)
struct lb_record *coreboot_init(void)
{
uint8_t *table_area;
unsigned long addr, start;
struct lb_header *lb_table;
struct lb_record *rec, *last;
start = 0x0;
table_area = phys_to_virt(start);
printk(KERN_INFO "trying %#x (%#x)\n", start, table_area);
lb_table = find_lb_table(table_area, 0x00000, 0x1000);
printk(KERN_INFO "find_lb_table returns %#x\n", lb_table);
if (!lb_table) {
printk(KERN_INFO "2nd try %#x (%#x)\n", start, table_area);
lb_table = find_lb_table(table_area, 0xf0000 - start, BYTES_TO_MAP - start);
printk(KERN_INFO "find_lb_table returns %#x\n", lb_table);
}
if (lb_table) {
struct lb_forward *forward = (struct lb_forward *)
(((char *)lb_table) + lb_table->header_bytes);
printk(KERN_INFO "forward=%#x\n", forward);
if (forward->tag == LB_TAG_FORWARD) {
start = forward->forward;
start &= ~(PAGE_SIZE - 1);
table_area = phys_to_virt(start);
printk(KERN_INFO "3rd try %#x (%#x)\n", start, table_area);
lb_table = find_lb_table(table_area, 0x00000, 0x1000);
printk(KERN_INFO "find_lb_table returns %#x\n", lb_table);
}
}
if (!lb_table) {
msg_pinfo("No coreboot table found.\n");
return NULL;
}
addr = ((char *)lb_table) - ((char *)table_area) + start;
msg_pinfo("coreboot table found at 0x%lx.\n",
(unsigned long)lb_table - (unsigned long)table_area + start);
rec = (struct lb_record *)(((char *)lb_table) + lb_table->header_bytes);
last = (struct lb_record *)(((char *)rec) + lb_table->table_bytes);
msg_pdbg("coreboot header(%d) checksum: %04x table(%d) checksum: %04x entries: %d\n",
lb_table->header_bytes, lb_table->header_checksum,
lb_table->table_bytes, lb_table->table_checksum,
lb_table->table_entries);
search_lb_records(rec, last, addr + lb_table->header_bytes);
return rec;
}
EXPORT_SYMBOL(coreboot_init);
const char *coreboot_vendor(void)
{
return lb_vendor;
}
EXPORT_SYMBOL(coreboot_vendor);
const char *coreboot_part(void)
{
return lb_part;
}
EXPORT_SYMBOL(coreboot_part);
And obviously threw in some debugging.
Here's what I get when I run it:
rying 0x0 (0xc0000000)
find_lb_table returns 0xc0000500
forward=0xc0000518
3rd try 0x1f7d1000 (0xdf7d1000)
BUG: unable to handle kernel paging request at df7d1000
IP: [<c10fe1fe>] find_lb_table+0x26/0x11b
*pde = 017fb067 *pte = 00000000
Oops: 0000 [#1]
last sysfs file:
Modules linked in:
Pid: 1, comm: swapper Not tainted 2.6.39.3 #1 Bochs Bochs
EIP: 0060:[<c10fe1fe>] EFLAGS: 00010287 CPU: 0
EIP is at find_lb_table+0x26/0x11b
EAX: df7d1000 EBX: df7d1000 ECX: 00000004 EDX: 00000000
ESI: df7d1000 EDI: c122ea56 EBP: 00001000 ESP: dec3bf8c
DS: 007b ES: 007b FS: 0000 GS: 0000 SS: 0068
Process swapper (pid: 1, ti=dec3a000 task=dec38000 task.ti=dec3a000)
Stack:
df7d1000 00000000 1f7d1000 c0000500 df7d1000 00000000 c10fe45b c122eb05
1f7d1000 df7d1000 00000000 c1286631 00000000 c1291dab 00000000 c10010fa
c1291d8d c12b554c c1286631 00000000 00000000 c12866af 00000000 c11cb796
Call Trace:
[<c10fe45b>] ? coreboot_init+0xb2/0x13a
[<c1286631>] ? start_kernel+0x269/0x269
[<c1291dab>] ? geos_init+0x1e/0x50
[<c10010fa>] ? do_one_initcall+0x6f/0x10d
[<c1291d8d>] ? sysenter_setup+0x2c4/0x2c4
[<c1286631>] ? start_kernel+0x269/0x269
[<c12866af>] ? kernel_init+0x7e/0xf7
[<c11cb796>] ? kernel_thread_helper+0x6/0xd
Code: 0f b7 c0 5f c3 55 57 56 53 83 ec 08 01 d0 89 cd 89 04 24 89 54 24 04 e9 ee
00 00 00 8b 1c 24 bf 56 ea 22 c1 89 de b9 04 00 00 00 <f3> a6 0f 85 ce 00 00 00
8b 44 24 04 03 43 0c 50 ff 74 24 08 68
EIP: [<c10fe1fe>] find_lb_table+0x26/0x11b SS:ESP 0068:dec3bf8c
CR2: 00000000df7d1000
---[ end trace 93d72a36b9146f22 ]---
Kernel panic - not syncing: Attempted to kill init!
Pid: 1, comm: swapper Tainted: G D 2.6.39.3 #1
Call Trace:
[<c11c981e>] ? panic+0x4d/0x12a
[<c101f1e7>] ? do_exit+0x226/0x57d
[<c1004200>] ? oops_end+0x82/0x86
[<c101565a>] ? no_context+0x10c/0x116
[<c1015940>] ? vmalloc_sync_all+0xa9/0xa9
[<c101576b>] ? bad_area_nosemaphore+0xa/0xc
[<c1015a9d>] ? do_page_fault+0x15d/0x350
[<c111a255>] ? check_modem_status+0x184/0x184
[<c101cf09>] ? __call_console_drivers+0x41/0x4d
[<c1015940>] ? vmalloc_sync_all+0xa9/0xa9
[<c11cb01c>] ? error_code+0x58/0x60
[<c11c0000>] ? br_multicast_add_group+0x480/0x495
[<c1015940>] ? vmalloc_sync_all+0xa9/0xa9
[<c10fe1fe>] ? find_lb_table+0x26/0x11b
[<c10fe45b>] ? coreboot_init+0xb2/0x13a
[<c1286631>] ? start_kernel+0x269/0x269
[<c1291dab>] ? geos_init+0x1e/0x50
[<c10010fa>] ? do_one_initcall+0x6f/0x10d
[<c1291d8d>] ? sysenter_setup+0x2c4/0x2c4
[<c1286631>] ? start_kernel+0x269/0x269
[<c12866af>] ? kernel_init+0x7e/0xf7
[<c11cb796>] ? kernel_thread_helper+0x6/0xd
What am I missing? What's wrong with the forward pointer?
Thanks,
-Philip