Hello -

First time poster, so take it easy on me :)

This is a great project -- I was able to get a kvm+coreboot+SeaBIOS
environment going pretty easily.  I started with the master branch of
coreboot and went from there.

I am having a problem trying to load a Linux kernel+initramfs cbfs
payload from SeaBIOS.  I can successfully boot the same
kernel+initramfs straight from coreboot (without SeaBIOS) as a
payload.

I started this topic on the SeaBIOS list -- there's a lot of good
background in the replies there:

  http://www.seabios.org/pipermail/seabios/2014-August/008215.html

I now think my problem lies in the cbfstool and the Linux trampoline.

Summarizing the analysis from those posts: the Linux trampoline code
does not set up the segment descriptors for __BOOT_CS and __BOOT_DS as
described in the Linux kernel documentation:

  ... a GDT must be loaded with the descriptors for selectors
  __BOOT_CS(0x10) and __BOOT_DS(0x18); both descriptors must be 4G
  flat segment; __BOOT_CS must have execute/read permission, and
  __BOOT_DS must have read/write permission;

Now in the working coreboot case it turns out the segment descriptors
at selectors 0x10 and 0x18, setup in the coreboot ramstage, match what
the Linux kernel expects (see coreboot/src/arch/x86/lib/c_start.S).

In the non-working SeaBIOS case the segment descriptors are configured
differently and the cbfs Linux payload does not work.

If the cbfs Linux payload is to be used in multiple environments
should the trampoline take care of descriptors that Linux requires?

Attached is a patch to util/cbfstool/linux_trampoline.c that does just
that.  Basically I borrowed the descriptor configs from
coreboot/src/arch/x86/lib/c_start.S for selectors 0x10 and 0x18.

Apologies for my poor x86 assembly coding -- first time.

Cheers,
Curt
diff --git a/util/cbfstool/linux_trampoline.c b/util/cbfstool/linux_trampoline.c
index 368d63a..3ac8913 100644
--- a/util/cbfstool/linux_trampoline.c
+++ b/util/cbfstool/linux_trampoline.c
@@ -54,88 +54,101 @@ jne .headerSearch
 cmp %ecx, %ebx // reached the end == not found anything?
 je 2f // give up
 
 // we assume the checksum is okay, no test
 mov 4(%ecx), %ebx
 add %ecx, %ebx // ebx = cb_header + header_bytes
 mov 20(%ecx), %ecx // ecx = table_entries
 
 .tableScan:
 cmp $CB_TAG_FORWARD, (%ebx)
 jne .testMemory
 
 /* forward tag: assume 32bit pointer */
 mov 8(%ebx), %ecx
 jmp .headerSearch
 
 .testMemory:
 cmp $CB_TAG_MEMORY, (%ebx)
 jne .testFramebuffer
 
 /* memory tag: copy e820 map and entry count. also determine alt_mem_k */
 mov 4(%ebx), %eax
 sub $8, %eax
 shr $2, %eax /* eax = number of dwords of e820 data */
 cmp $(32 * 5), %eax /* linux wants at most 32 entries of 5 dwords */
 jng 1f
 mov $(32 * 5), %eax /* only copy 32 entries */
 1:
 mov %eax, %esi
 mov $5, %edi
 div %edi
 mov %eax, (LINUX_PARAM_LOC + E820_NR_OFFSET)
 mov %esi, %eax
 xchg %eax, %ecx
 lea 8(%ebx), %esi /* e820 data source */
 mov $(LINUX_PARAM_LOC + E820_OFFSET), %edi
 rep movsl
 xchg %eax, %ecx
 jmp .endScan
 
 .testFramebuffer:
 cmp $CB_TAG_FRAMEBUFFER, (%ebx)
 jne .endScan
 /* TODO: handle framebuffer tag */
 
 .endScan:
 add 4(%ebx), %ebx
 dec %ecx
 jnz .tableScan
 
+/* Setup basic code and data segment selectors for Linux */
+/* Setup code segment descriptor, selector 0x10 - execute, read */
+mov  %esp, %eax
+sgdt (%eax)
+mov  2(%eax), %ebx
+movl  $0x0000ffff, 16(%ebx)
+movl  $0x00cf9b00, 20(%ebx)
+/* Setup data segment descriptor, selector 0x18 - data, read/write */
+movl  $0x0000ffff, 24(%ebx)
+movl  $0x00cf9300, 28(%ebx)
+
 /* finally: jump to kernel */
 mov $LINUX_PARAM_LOC, %esi
 jmp *(LINUX_PARAM_LOC + LINUX_ENTRY_OFFSET)
 
 
 2:
 hlt
 jmp 2b
 
 .trampoline_end:
 
 .global trampoline_start, trampoline_size
 trampoline_start:
 .long .trampoline_start
 trampoline_size:
 .long .trampoline_end - .trampoline_start
 #endif
 
 /* The code above is hand-crafted to fit various contraints.
  * To simplify porting, the below matches the above.
  * When changing any code in here, compile the above as a .S
  * file, objcopy it to binary and paste the result below (minus
  * the last 8 bytes which are trampoline_start and trampoline_size).
  */
 const unsigned char trampoline[] = {
 0xfc, 0x31, 0xd2, 0xb9, 0x00, 0x00, 0x00, 0x00, 0xbb, 0x00, 0x00, 0x01, 0x00, 0x01, 0xcb, 0x8b,
 0x01, 0x3d, 0x4c, 0x42, 0x49, 0x4f, 0x74, 0x07, 0x83, 0xc1, 0x10, 0x39, 0xcb, 0x75, 0xe9, 0x39,
-0xcb, 0x74, 0x60, 0x8b, 0x59, 0x04, 0x01, 0xcb, 0x8b, 0x49, 0x14, 0x83, 0x3b, 0x11, 0x75, 0x05,
-0x8b, 0x4b, 0x08, 0xeb, 0xd3, 0x83, 0x3b, 0x01, 0x75, 0x33, 0x8b, 0x43, 0x04, 0x83, 0xe8, 0x08,
-0xc1, 0xe8, 0x02, 0x3d, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0x05, 0xb8, 0xa0, 0x00, 0x00, 0x00, 0x89,
-0xc6, 0xbf, 0x05, 0x00, 0x00, 0x00, 0xf7, 0xf7, 0xa3, 0xe8, 0x01, 0x09, 0x00, 0x89, 0xf0, 0x91,
-0x8d, 0x73, 0x08, 0xbf, 0xd0, 0x02, 0x09, 0x00, 0xf3, 0xa5, 0x91, 0xeb, 0x05, 0x83, 0x3b, 0x12,
-0x75, 0x00, 0x03, 0x5b, 0x04, 0x49, 0x75, 0xb3, 0xbe, 0x00, 0x00, 0x09, 0x00, 0xff, 0x25, 0x14,
-0x02, 0x09, 0x00, 0xf4, 0xeb, 0xfd
+0xcb, 0x0f, 0x84, 0x85, 0x00, 0x00, 0x00, 0x8b, 0x59, 0x04, 0x01, 0xcb, 0x8b, 0x49, 0x14, 0x83,
+0x3b, 0x11, 0x75, 0x05, 0x8b, 0x4b, 0x08, 0xeb, 0xcf, 0x83, 0x3b, 0x01, 0x75, 0x33, 0x8b, 0x43,
+0x04, 0x83, 0xe8, 0x08, 0xc1, 0xe8, 0x02, 0x3d, 0xa0, 0x00, 0x00, 0x00, 0x7e, 0x05, 0xb8, 0xa0,
+0x00, 0x00, 0x00, 0x89, 0xc6, 0xbf, 0x05, 0x00, 0x00, 0x00, 0xf7, 0xf7, 0xa3, 0xe8, 0x01, 0x09,
+0x00, 0x89, 0xf0, 0x91, 0x8d, 0x73, 0x08, 0xbf, 0xd0, 0x02, 0x09, 0x00, 0xf3, 0xa5, 0x91, 0xeb,
+0x05, 0x83, 0x3b, 0x12, 0x75, 0x00, 0x03, 0x5b, 0x04, 0x49, 0x75, 0xb3, 0x89, 0xe0, 0x0f, 0x01,
+0x00, 0x8b, 0x58, 0x02, 0xc7, 0x43, 0x10, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43, 0x14, 0x00, 0x9b,
+0xcf, 0x00, 0xc7, 0x43, 0x18, 0xff, 0xff, 0x00, 0x00, 0xc7, 0x43, 0x1c, 0x00, 0x93, 0xcf, 0x00,
+0xbe, 0x00, 0x00, 0x09, 0x00, 0xff, 0x25, 0x14, 0x02, 0x09, 0x00, 0xf4, 0xeb, 0xfd
 };
 
 const void * const trampoline_start = &trampoline;
 const unsigned long trampoline_size = sizeof trampoline;
-- 
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to