Protected Mode Troubles

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Ryan S.

Protected Mode Troubles

Post by Ryan S. »

I'm attempting to write a bootsector that will enable the A20 line and then throw protected mode up. It's been a few days now and I still cannot find what error is causing my pmode enabling section to fail. I'm using Bochs on FreeBSD for testing. It appears anytime I try to enable the PE flags in cr0 the machine resets. I'm assuming it's some problem with my GDTR or GDT but I cannot find the error. Here is the assembly code I'm working off:

   .set SEL_CODE,      0x8   
   .set SEL_LINEAR,   0x10
.org 0x000
.code16
   ljmp $0x7C0, $start      # far jump to load the CS with known value
               # some BIOS' start at 07c0:0000 and others
               # at 0000:7c00
   .globl   start
start:
   movw $0x7C0, %ax      # load known address
   movw %ax, %ds         # into the segment
   movw %ax, %es         # registers.
   movw %ax, %fs
   movw %ax, %gs

   xorw %ax, %ax         # setup
   movw %ax, %ss         # ... the
   movw $0xffff, %sp      # ... stack

   movw $bootmessage, %si      # put something
   call putstr         # on the screen
   call gateA20         # enable the A20 line

   pushw $0x2
   popf
   lgdt (gdt_ptr+0x7C00)      # Initialize GDTR, need a linear address
               # not a segmented one.
   movl %cr0, %eax
   orb $0x1, %al
   movl %eax, %cr0
   ljmp $SEL_CODE, $pmode      # long jump to reload %cs


gateA20:
   push %si
   push %ax
   movw $A20Message, %si
   call putstr
   inb $0x92, %al
   orb $0x02, %al
   outb %al, $0x92
   pop %ax
   pop %si
   ret

putstr:
   push %ax
   push %bx
   movb $0x0e, %ah
   movw $0x0007, %bx
putstr.0:
   lodsb
   testb %al, %al
   jz putstr.1
   int $0x10
   jmp putstr.0
putstr.1:
   pop %bx
   pop %ax
   ret

.code32
pmode:
   jmp   .

   
# Enter protected mode
   
bootmessage:   .asciz "SOS Bootloader (v.01)\n"
A20Message:   .asciz "Enabling A20 line...\n"
pmodemsg:   .asciz "Jumping to PMode...\n"


# GDT
# Segment Descriptor Layout:
#
# 31 24 23 22 21 20 19 16 15 14 13 12 11 8 7 0 Byte
# _________________________________________________________________________
# | | |D | |A | Seg | | D | | | |
# | Base 31:24 |G |/ |O |V | Limit |P | P |S | Type | Base 23:16| 4
# | | |B | |L | 19:16 | | L | | | |
# |___________________|__|__|__|__|________|__|_____|__|________|___________|
#
# 31 16 15 0
# _________________________________________________________________________
# | | |
# | Base Address 15:00 | Segment Limit 15:00 | 0
# |________________________________________|________________________________|

.org 0x0120
gdt_ptr:   .word gdt_end-gdt-1
      .word (gdt+0x7C00)
      .byte 0x0
gdt:
gdt.0:      # Null selector
   .word 0         # [Off. 0] Segment Limit (15:00)
   .word 0         # [Off. 2] Base Address (15:00)
   .byte 0         # [Off. 4] Base Address (23:16)
   .byte 0         # [Off. 5] Flags
   .byte 0         # [Off. 6] Seg Limit & Flags
   .byte 0         # [Off. 7] Base Address (31:24)
   
gdt.1:      # Code (0x7C00 base)
   .word 0xFFFF      # [Off. 0] Segment Limit (15:00)
   .word 0x7C00      # [Off. 2] Base Address (15:00)
   .byte 0x00      # [Off. 4] Base Address (23:16)
   .byte 0x9A      # [Off. 5] Flags
   .byte 0xCF      # [Off. 6] Seg Limit & Flags
   .byte 0x00      # [Off. 7] Base Address (31:24)
   
gdt.2:      # Linear (0x0 base)
   .word 0xFFFF      # [Off. 0] Segment Limit (15:00)
   .word 0x0      # [Off. 2] Base Address (15:00)
   .byte 0x0      # [Off. 4] Base Address (23:16)
   .byte 0x92      # [Off. 5] Flags
   .byte 0xCF      # [Off. 6] Seg Limit & Flags
   .byte 0x0      # [Off. 7] Base Address (31:24)
gdt_end:

.org 0x01fe
.word 0xaa55


Any help would be greatly appreciated.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Protected Mode Troubles

Post by Candy »

Ryan S. wrote: It's been a few days now and I still cannot find what error is causing my pmode enabling section to fail.
<snap>
gdt_ptr: .word gdt_end-gdt-1
.word (gdt+0x7C00)
.byte 0x0
gdt:
gdt.0: # Null selector
.word 0 # [Off. 0] Segment Limit (15:00)
.word 0 # [Off. 2] Base Address (15:00)
The structure for the lgdt loading structure is

Code: Select all

struct gdt_entry {
  uint16 length
  uint32 address
};
You provide it with a byte 0, while the computer interprets this as a dword (which is why I chose that non-arbitrary split in your code, it uses those two words too). The DWORD passed out is 0, so the computer in effect is taught your gdt is at 0x0, length of the gdt is correct.

You don't move the GDT to 0x0, so this is invalid.

Your computer attempts to interpret your IVT as a GDT, which obviously fails and the computer triples.
Ryan S.

Re:Protected Mode Troubles

Post by Ryan S. »

Hmm... I tried changing the byte to a word, so wouldn't that make the gdt_ptr a 48-bit value (0x0017 0x00007d2a).

I tried this and the simulator is still resetting.
User avatar
Candy
Member
Member
Posts: 3882
Joined: Tue Oct 17, 2006 11:33 pm
Location: Eindhoven

Re:Protected Mode Troubles

Post by Candy »

Ryan S. wrote: Hmm... I tried changing the byte to a word, so wouldn't that make the gdt_ptr a 48-bit value (0x0017 0x00007d2a).

I tried this and the simulator is still resetting.
hmz... *remembers something about alignment* what if you align the GDT to at least an 8-byte boundary? eg, you put it at 7d30 - 7d47 ?
Ryan S.

Re:Protected Mode Troubles

Post by Ryan S. »

No go... :-/

I tried puttiing it on a 8-byte and a 16-byte boundary. Any other ideas?
Slasher

Re:Protected Mode Troubles

Post by Slasher »

Hi, instead of using a far jump at the start, I'd use
Jmp start

use
Push cs
pop ax
mov ds,ax
mov es,ax
......
....
to set up the segment registers at the start of your code.
lgdt (gdt_ptr+0x7C00) # Initialize GDTR, need a linear address
# not a segmented one.
this is what is causing your problem. I'd suggest that you use
lgdt gdt_ptr
cause it will be access with DS:gdtr where you have already loaded DS with 0x7c0
Also disable interrupts until you have your idt installed

Hope this helps
Ryan S.

Re:Protected Mode Troubles

Post by Ryan S. »

Hmm. If lgdt uses the ds segment to load the data why does the Intel manual say that it expects a linear address? That was why I originally added the 0x7C00 value so it was a linear as opposed to a segmented address.
Ryan S.

Re:Protected Mode Troubles

Post by Ryan S. »

Well, that worked. It doesn't triple fault now when it goes into pmode anyway.

I think the Bochs BIOS starts execution at 0000:7C00 and when I link the binary file I had to change it to begin the text segment at 0x7C00 so the address being passed to lgtr is still the same as before when I was adding 7C00 onto it. I also changed the GDT entry to make the code segment descriptor base 0x0 instead of 0x7C00 so all the addresses would match up (I think that does it anyway).
Post Reply