Author Topic: Writing a BIOS: Setup code in Nasm  (Read 20342 times)

nobody

  • Guest
Writing a BIOS: Setup code in Nasm
« on: December 01, 2008, 12:57:11 PM »
I am looking for code which switches from real to protected mode as part of a BIOS initialisation routine.  I've found code to do this in redboot, Coreboot (LinuxBIOS), and several other places, but they are all using the GNU assembler, and they all hand-craft the jump instructions.

The Nasm documentation seems to suggest it's possible to mix 16 and 32-bit instructions, and this should allow me to write this code without 'tricks', however my code always triple-faults when performing the jmp just after setting up GDT and enabling pmode.

Is this possible?

Many thanks,
Simon.

nobody

  • Guest
Re: Writing a BIOS: Setup code in Nasm
« Reply #1 on: December 01, 2008, 01:52:06 PM »
Perhaps I should make it a bit clearer what I'm doing.  I've written the following code
and run it in qemu on Linux.

I know that this will never work on a real machine - it's just a learning exercise for myself.  If I don't choose the correct value to load into the data selectors I get a triple fault, however I don't understand where this number comes from.

Can anyone explain how this works?

thanks.

<----cut here ----->|<----cut here ----->|<----cut here ----->|<----cut here ----->
; Compile with:
; nasm -o bios.bin bios.S
; Run Qemu with:
; qemu -cpu 486 -L ./ -hda /dev/zero -serial stdio -m 16 -nographic
;

ORG 0xffff0000    ; 64k BIOS
   BITS 16
rom_start:

cli
   lgdt   [gdtDesc]
   mov   eax,cr0         ; protected mode
   or   ax,1
   mov   cr0,eax
   jmp   word pm_start

pm_start:
   ; Signal we are in PM via COM1, output a byte on serial port.
   mov   dx, 0x3f8
   mov   al, 'P'
   out   dx, al

; Load data selectors
   mov   eax, 0x2
   mov   ds, eax
   mov   es, eax
   mov   fs, eax
   mov   gs, eax

; Signal we are done via COM1
   mov   dx, 0x3f8
   mov   al, 'F'
   out   dx, al
   jmp   $

ALIGN   4
gdtDesc:
   dw   (gdtEnd - gdt)
   dw   gdt

ALIGN   4
gdt:
   dd   0,0                                 ; null.
   dw   0xffff, 0x0000
   db   0x00, 10011010b, 11001111b, 0x00    ; code
   dw   0xffff, 0x0000
   db   0x00, 10010010b, 11001111b, 0x00    ; data
gdtEnd:
   TIMES   0xfff0-($-$$) DB 0xff
reset_entry:               ; power on
   jmp rom_start
   TIMES   0x10000-($-$$) DB 0xff
<----cut here ----->|<----cut here ----->|<----cut here ----->|<----cut here ----->

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Writing a BIOS: Setup code in Nasm
« Reply #2 on: December 01, 2008, 08:00:19 PM »
I'm over my head here - no experience with bios code (and I'll have to review the unit on "decrypting descriptors")...

But I think you'll want a far jump after the "mov cr0, eax"...

jmp 8:pm_start

(8 would be the offset of your code descriptor) If the descriptor says 32-bit code, you'll want a "bits 32" directive in there too. Then, 16 (0x10) would be the correct value to load into the segment registers (cs is loaded by the far jump) - it's a byte offset into the descriptor table, not a "descriptor number"...

That should help, but may not be enough to do it. If you've got some "working" Gas code, we can probably help you "translate" that. Good luck!

Best,
Frank

nobody

  • Guest
Re: Writing a BIOS: Setup code in Nasm
« Reply #3 on: December 01, 2008, 09:14:14 PM »
Thanks Frank.

The working Gas code is here:
http://cvs.cens.ucla.edu/viewcvs/viewcvs.cgi/stargate/ecos/packages/hal/i386/pc/current/src/romboot.S?rev=HEAD&content-type=text/vnd.viewcvs-markup

I don't understand why that code copies the descriptor to DRAM.  Surely it should be possible to make this work directly from flash memory at 0xffff0000?  Or is there some fundamental limit on the gdt registers that means their descriptors have to be in the lowest 1MB?

I tried your suggestions but they don't work. The JMP you suggested doesn't seem to work - triple fault on the jmp instruction.  I tried various combinations of BITS32 before and after the jump, but not joy.

I am a total Nasm beginner, I'm afraid, and this is probably not the best project to start with, but if I could get the Gas code converted that would be something!

regards,
Simon.