|
-
Aug 20th, 2002, 02:18 PM
#1
Thread Starter
Lively Member
Protected Mode
Hey Guys
I have been writing my own boot loader and have followed loads of examples and have got together one that pretty much does what i want except when i switch to protected mode it crashes and reboots the machine here is the code.
Code:
; ------------------------------------------------------------------------
; Phoenix OS boot loader (c)2002 Peter Liddle
; ------------------------------------------------------------------------
; This code is the boot loader for the Phoenix OS
; ------------------------------------------------------------------------
[BITS 16] ;Set code generation to 16 bit mode
[ORG 0x0000] ;Tell compiler this si offset 0, it isn;t but will be after jump
jmp BOOT
; -------------------------------------
; Data section
; ------------------------------------------------------------------------
DATA:
BootDrv db 0x80
BootMsg db 'Booting Phoenix OS', 0x0D, 0x0A, 0
PModeMsg db 'Jumping to Protected Mode', 0x0D, 0x0A, 0
PModeEnabledMsg db 'Where in Protected Mode at Last', 0x0D, 0x0A, 0
EnablA20Msg db 'Enabling A20 Line', 0x0D, 0x0A, 0
A20EnabledMsg db 'A20 Line is Now Turned On', 0x0D, 0x0A, 0
IDTptr DW 7FFh ;LIMIT 256 IDT Slots
DD 0000h ;BASE (Linear)
GDTptr DW 17FFh ;LIMIT 768 slots
DD 0800h ;BASE (Linear)
; ------------------------------------------
; Functions section
; ------------------------------------------------------------------------
.386
RESETDISK: ; Reset drive
mov ax, 0 ;
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Actually Reset
jc RESETDISK ; ERROR => reset again
ret
READ:
mov ax, 0x1000 ; ES:BX = 0x1000:0000
mov es, ax ;
mov bx, 0 ;
call RESETDISK ; First Reset Disk
mov ah, 0x2 ; Load disk data to ES:BX
mov al, 0x1 ; Load 1 sectors
mov ch, 0x0 ; Track=1
mov cl, 0x2 ; Sector=2
mov dh, 0x00 ; Head=0
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Read!
jc READ ; ERROR => Try again
ret
PRINTMSG: ; Dump ds:si to screen.
lodsb ; load byte at ds:si into al
or al,al ; test if character is 0 (end)
jz done
mov ah,0eh ; put character
mov bx,0007 ; attribute
int 0x10 ; call BIOS
jmp PRINTMSG
done:
ret
CLEARBUF:
XOR CX,CX
in al, 64h ; get input from keyboard status port
test al, 02h ; test the buffer full flag
loopnz CLEARBUF ; loop until buffer is empty
ret
; ------------------------------------------------------------------------
; ------------------------------------------
; Boot Code
; ------------------------------------------------------------------------
BOOT:
;mov [BootDrv],dl ; Save Boot Drive
;Set up Location of Data Segment
mov ax,0x7C0
mov ds,ax
cli ; Turn Off interrupts while we setup a stack and A20 and Get to P-Mode
;Set Up Stack
mov ax,0x9000 ; this seems to be the typical place for a stack
mov ss,ax
mov sp,0xFFFF ; let's use the whole segment. Why not? We can :)
mov si,BootMsg ; display our startup message
call PRINTMSG
;call READ ; Load in a sector
;Enable A20 Address Line
mov si,EnablA20Msg ; display our startup message
call PRINTMSG
;Turn on A20 Line
call CLEARBUF ; Wait till keyboard Buffer is empty
mov al, 0D1h ; keyboard: write to output port
out 64h, al ; output command to keyboard
call CLEARBUF ; Wait till keyboard Buffer is empty again
mov al, 0x0DF ; keyboard: set A20
out 0x60, al ; send it to the keyboard controller
mov cx, 0x14
call CLEARBUF ; Wait 25 sec for A20 to be enabled
nop
nop
mov si,A20EnabledMsg ; display our startup message
call PRINTMSG
;Lets Get Into P-Mode
mov si, PModeMsg
call PRINTMSG
; Set Global Descriptor Table here, this must be done PRIOR to Prot Mode
LIDT [IDTptr]
LGDT [GDTptr]
mov eax, CR0 ; load the control register in
or eax, 1 ; set bit 1: pmode bit
mov CR0, EAX ; copy it back to the control register
jmp $+2 ; and clear the prefetch queue
nop
nop
db 066h, 0EAh
dw prot, 06h
dw 08h
[BITS 32]
prot:
; Set up segments
mov ebx, 10h
mov ds, bx
mov es, bx
mov fs, bx
mov gs, bx
mov si, PModeEnabledMsg
call PRINTMSG
MOV BX, 10h
MOV DS,BX
MOV ES,BX
MOV FS,BX
MOV GS,BX
MOV SS,BX
;jmp 0x1000:0000
times 510-($-$$) db 0
dw 0xAA55
"Let's all join forces, rule with an iron hand...and prove to all the world, metal rules the land..."
-- Judas Priest
My email is [email protected]
-
Aug 28th, 2002, 09:27 AM
#2
I don't really know, but the actions you take at the moment of switching to p would probably be the error. I guess you have a good reason for the db and dw lines there.
Another possibility is a segmentation fault when you try to print the success message. This seems very likely to me on second reflection.
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 7th, 2002, 12:24 PM
#3
Thread Starter
Lively Member
I managed to fix the problem in the end and for teh benefit of everyone here is my working bootloader.
Code:
; ------------------------------------------------------------------------
; Phoenix OS boot loader (c)2002 Peter Liddle
; ------------------------------------------------------------------------
; This code is the boot loader for the Phoenix OS
; ------------------------------------------------------------------------
[BITS 16] ;Set code generation to 16 bit mode
[ORG 0x0000] ;Tell compiler this its at offset 0x000, it isn;t but will be after jump
jmp 0x07C0:BOOT
; -------------------------------------
; Data section
; ------------------------------------------------------------------------
DATA:
BootDrv db 0x80
BootMsg db 'Booting Phoenix OS', 0x0D, 0x0A, 0
PModeMsg db 'Jumping to Protected Mode', 0x0D, 0x0A, 0
PModeEnabledMsg db 'Where in Protected Mode at Last', 0x0D, 0x0A, 0
EnablA20Msg db 'Enabling A20 Line', 0x0D, 0x0A, 0
A20EnabMsg db 'A20 Line is Now Turned On', 0x0D, 0x0A, 0
TestMsg db 'Blah Blah Blah', 0x0D, 0x0A, 0
GDT: ; our descriptors
; NULL descriptor
dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; unused descriptor
dw 0
dw 0
db 0
db 0
db 0
db 0
; data segment descriptor
LINEAR_DATA_SEL EQU $-GDT
dw 0FFFFh ; limit 0xFFFF (1 meg, 4 gig)
dw 0 ; base for this line is always 0
db 0
db 92h ; present, ring 0, data, expand-up, writable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
; code segment descriptor
LINEAR_CODE_SEL EQU $-GDT
dw 0FFFFh ; limit 0xFFFF (1 meg, 4 gig)
dw 0 ; base for this line is always 0
db 0
db 9Ah ; present, ring 0, code, non-conforming, readable
db 0CFh ; page-granular (4 gig limit), 32-bit
db 0
GDT_END:
GDTptr:
dw GDT_END - GDT - 1 ; GDT limit
dd 0x07C00 + GDT ; linear, physical address of GDT
; ------------------------------------------
; Functions section
; ------------------------------------------------------------------------
.386
RESETDISK: ; Reset drive
mov ax, 0 ;
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Actually Reset
jc RESETDISK ; ERROR => reset again
ret
READ:
mov ax, 0x1000 ; ES:BX = 0x1000:0000
mov es, ax ;
mov bx, 0 ;
call RESETDISK ; First Reset Disk
mov ah, 0x2 ; Load disk data to ES:BX
mov al, 0x2 ; Load 1 sectors
mov ch, 0x0 ; Track=1
mov cl, 0x8 ; Sector=2
mov dh, 0x00 ; Head=0
mov dl, [BootDrv] ; Drive=BootDrv
int 13h ; Read!
jc READ ; ERROR => Try again
ret
PRINTMSG: ; Dump ds:si to screen.
lodsb ; load byte at ds:si into al
or al,al ; test if character is 0 (end)
jz done
mov ah,0eh ; put character
mov bx,0007 ; attribute
int 0x10 ; call BIOS
jmp PRINTMSG
done:
ret
CLEARBUF:
XOR CX,CX
in al, 64h ; get input from keyboard status port
test al, 02h ; test the buffer full flag
loopnz CLEARBUF ; loop until buffer is empty
ret
; ------------------------------------------------------------------------
; ------------------------------------------
; Boot Code
; ------------------------------------------------------------------------
BOOT:
mov ax,0x7C0 ; Set The data Segment to right address
mov ds,ax
mov eax,0x0000 ; Zero all other irrelevant segments
mov ES,ax
mov FS,ax
mov GS,ax
cli ; Turn Off interrupts while we setup a stack and A20 and Get to P-Mode
;Set Up Stack
mov ax,0x9000 ; this seems to be the typical place for a stack
mov ss,ax
mov sp,0xFFFF ; let's use the whole segment. Why not? We can :)
sti ; Turn interupts back on
mov si,BootMsg ; display our startup message
call PRINTMSG
;Enable A20 Address Line
mov si,EnablA20Msg ; display our startup message
call PRINTMSG
;Read in Next Bit for Loading
call READ ; Load in a sector
cli ; Turn interupts off again
;Turn on A20 Line
call CLEARBUF ; Wait till keyboard Buffer is empty
mov al, 0D1h ; keyboard: write to output port
out 64h, al ; output command to keyboard
call CLEARBUF ; Wait till keyboard Buffer is empty again
mov al, 0x0DF ; keyboard: set A20
out 0x60, al ; send it to the keyboard controller
mov cx, 0x14
call CLEARBUF ; Wait 25 sec for A20 to be enabled
nop
nop
sti ; Turn interupts back on
mov si,A20EnabMsg ; display our startup message
call PRINTMSG
cli ; Turn interupts off again
;Lets Get Into P-Mode
mov si, PModeMsg
call PRINTMSG
; Set Global Descriptor Table here, this must be done PRIOR to Protected Mode
LGDT [GDTptr]
;Lets Get Into P-Mod
mov EAX, CR0 ; load the control register in
or EAX, 0x1 ; set bit 1: pmode bit
mov CR0, EAX ; copy it back to the control register
;jmp $+2
;nop
;nop
;mov EAX,GDTptr
jmp LINEAR_CODE_SEL:PMODECODE + 0x7c00
[BITS 32]
PMODECODE:
mov EAX, LINEAR_DATA_SEL
mov ds,EAX
mov es,EAX
mov fs,EAX
mov gs,EAX
here:
jmp 0x1000:0000
jmp here
times 510-($-$$) db 0
dw 0xAA55
"Let's all join forces, rule with an iron hand...and prove to all the world, metal rules the land..."
-- Judas Priest
My email is [email protected]
-
Sep 9th, 2002, 02:56 AM
#4
Thanks, that's cool. Mind if I use it as a model for my tries?
Is this a bootstrap or must it be loaded? Cuz it seems a little bit large for a bootstrap...
All the buzzt
 CornedBee
"Writing specifications is like writing a novel. Writing code is like writing poetry."
- Anonymous, published by Raymond Chen
Don't PM me with your problems, I scan most of the forums daily. If you do PM me, I will not answer your question.
-
Sep 9th, 2002, 02:03 PM
#5
Thread Starter
Lively Member
Go Ahead i put it up there to help other people after the nightmare of a time i had it took my about 2 weeks to get this properly working.
Anyway it basically reads in data of the harddisk in sectors which you specify which sectors and amount in the read function. It then enables the A20 line and Switches into protected mode. Eventually i plan to have it then jump to my kernel but i got to sort my kernel first which i plan to write in c.
Anyway Best of Luck to all who are attempting a bootloader.
As to your question CornedBee on wether it is a bootstrap or needs to be loaded im guessing you mean does the whole thing fit in 1 sector and comprimes the whole bootloader and the answer is yes this is purely a boot loader compile and copy it to sec 1 of a disk and boot it.
Peter
"Let's all join forces, rule with an iron hand...and prove to all the world, metal rules the land..."
-- Judas Priest
My email is [email protected]
-
Sep 9th, 2002, 05:21 PM
#6
Frenzied Member
-
Sep 10th, 2002, 12:15 PM
#7
Thread Starter
Lively Member
Yeah i am a regular member at the MegaTokyo OS forum its brillant and it was with the help of the people on it i actually managed to get my bootloader working.
Peter
"Let's all join forces, rule with an iron hand...and prove to all the world, metal rules the land..."
-- Judas Priest
My email is [email protected]
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|