More PMode Help
Posted: Thu Apr 22, 2004 11:00 pm
I'm playing around with a bootloader that enables the A20 line and then launches into PM (and eventually will load a 2nd stage loader that will handle loading the kernel from a filesystem).
I can't seem to get the [computer] (using Bochs as an emulator) to go into Pmode, as soon as I set the PE bit the emulator resets. I'm guessing I have something setup wrong in my GDT or how I reference it, but I can't find it. Any help would be greatly appreciated. You'll have to pardon the AT&T syntax, I use gas to assemble:
.code16
.set SEL_DATA, 0x8
.set SEL_LINEAR, 0x10
.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 # Initialize GDTR
movl %cr0, %eax
orb $0x1, %al
movl %eax, %cr0
ljmp $SEL_DATA, $pmode
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 .
movw $pmodemsg, %si
call putstr
# 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
# |________________________________________|________________________________|
gdt_ptr: .word (gdt_end-gdt-1)
.word (gdt+0x7C00)
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 0x0 # [Off. 4] Base Address (23:16)
.byte 0x8E # [Off. 5] Flags
.byte 0xA7 # [Off. 6] Seg Limit & Flags
.byte 0x0 # [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 0x86 # [Off. 5] Flags
.byte 0xA7 # [Off. 6] Seg Limit & Flags
.byte 0x0 # [Off. 7] Base Address (31:24)
gdt_end:
.org 510
.word 0xaa55
-------------
Everything works fine as long as I don't go into protected mode, so I'm building and loading the binary file fine.
I can't seem to get the [computer] (using Bochs as an emulator) to go into Pmode, as soon as I set the PE bit the emulator resets. I'm guessing I have something setup wrong in my GDT or how I reference it, but I can't find it. Any help would be greatly appreciated. You'll have to pardon the AT&T syntax, I use gas to assemble:
.code16
.set SEL_DATA, 0x8
.set SEL_LINEAR, 0x10
.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 # Initialize GDTR
movl %cr0, %eax
orb $0x1, %al
movl %eax, %cr0
ljmp $SEL_DATA, $pmode
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 .
movw $pmodemsg, %si
call putstr
# 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
# |________________________________________|________________________________|
gdt_ptr: .word (gdt_end-gdt-1)
.word (gdt+0x7C00)
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 0x0 # [Off. 4] Base Address (23:16)
.byte 0x8E # [Off. 5] Flags
.byte 0xA7 # [Off. 6] Seg Limit & Flags
.byte 0x0 # [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 0x86 # [Off. 5] Flags
.byte 0xA7 # [Off. 6] Seg Limit & Flags
.byte 0x0 # [Off. 7] Base Address (31:24)
gdt_end:
.org 510
.word 0xaa55
-------------
Everything works fine as long as I don't go into protected mode, so I'm building and loading the binary file fine.