[SeaBIOS] Problems with Linux payload

Curt Brune curt at cumulusnetworks.com
Wed Aug 27 23:17:55 CEST 2014


Hello Kevin -

On Mon Aug 18 14:56, Kevin O'Connor wrote:
> Unfortunately, I don't see anything in the log that looks suspicious.
> Since you are using qemu/kvm, you could try attaching a debugger (if
> you are familiar with gdb).
> 
> There's documentation online and in the SeaBIOS' README file.  In a
> nutshell, run qemu with "-s -S" and then run "gdb" in another terminal
> and send it "target remote localhost:1234" along with something like
> "br *0x40000" to set a break point at the start of the payload.
> 
> Another option would be to try with a known working payload and verify
> if you can get SeaBIOS to launch it.

Thanks for your time and suggestions.

As a control I tried using the libpayload example
(http://www.coreboot.org/Libpayload) as a SeaBIOS payload and that
worked fine.  So SeaBIOS seems fine.

I went down the gdb route and found some interesting results, but
still not sure what is wrong.  It has been educational :)

Using gdb I worked my way through coreboot and SeaBIOS loading and
into cbfs_run_payload().  cbfs_run_payload() loads the payload OK and
jumps to the trampoline @ 0x40000 fine.  The trampoline does various
things and eventually jumps to the kernel code @ 0x1000000.  In gdb
this looks like:

   => 0x1000000:   cld    
      0x1000001:   test   BYTE PTR [esi+0x211],0x40
      0x1000008:   jne    0x1000016
      0x100000a:   cli    
      0x100000b:   mov    eax,0x18
      0x1000010:   mov    ds,eax
      0x1000012:   mov    es,eax
      0x1000014:   mov    ss,eax           <--- CPU resets executing this
      0x1000016:   lea    esp,[esi+0x1e8]
      0x100001c:   call   0x1000021

The source code for this location comes from the kernel file
linux/arch/x86/boot/compressed/head_64.S

I found executing the "mov ss,eax" instruction @ 0x1000014 would cause
the virtual machine to reboot.  I presume some kind of stack/memory
exception happened and the exception handler resets the CPU.

Just before executing that instruction the CPU registers look like
this (from the qemu monitor):

  (qemu) info registers
  EAX=00000018 EBX=1ffd6610 ECX=00000000 EDX=00000000
  ESI=00090000 EDI=00090334 EBP=00040070 ESP=00006fa4
  EIP=01000014 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
  ES =0018 000f0000 0000ffff 00009b00 DPL=0 CS16 [-RA]
  CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
  SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  DS =0018 000f0000 0000ffff 00009b00 DPL=0 CS16 [-RA]
  FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
  TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
  GDT=     000f4b78 00000037
  IDT=     000f4bb6 00000000
  CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
  DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
  DR6=00000000ffff0ff0 DR7=0000000000000400
  EFER=0000000000000000
  FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80

So setting SS from 0x10 to 0x18 caused the exception.  Of note the DS
and ES registers were set from 0x10 to 0x18 without any problem.

Now armed with qemu/gdb knowledge I went through my working case,
where my kernel is loaded directly by coreboot.  SeaBIOS is not used
in this case.  My kernel boots fine in this case.

Just before executing the troublesome instruction @ 0x1000014 the CPU
registers look like this (from the qemu monitor) in the working case:

  (qemu) info registers
  EAX=00000018 EBX=1ffd6610 ECX=00000000 EDX=00000000
  ESI=00090000 EDI=00090334 EBP=00127ff0 ESP=1ffd0f88
  EIP=01000014 EFL=00000046 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
  ES =0018 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  CS =0010 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
  SS =0018 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  DS =0018 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  FS =0018 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  GS =0018 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
  LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
  TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
  GDT=     1ffec000 00000047
  IDT=     001218c4 0000009f
  CR0=60000011 CR2=00000000 CR3=00000000 CR4=00000000
  DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
  DR6=00000000ffff0ff0 DR7=0000000000000400
  EFER=0000000000000000
  FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80

Here the interesting thing is that DS, ES and SS *already* contained
0x18.  In the SeaBIOS case those registers contained 0x10 before the
Linux kernel set them up.

That's all I got.  Any clues?

Cheers,
Curt



More information about the SeaBIOS mailing list