jmping to kernel...
jmping to kernel...
Im a bit confused, once my bootloader has activated A20, read my kernel and past into 32-bit mode, what are the steps I have to take to pass control to my kernel?
(also I load my kernel at 0x7e00 I was wondering if this was a good idea or not?)
Thanks in advance,
Jules
(also I load my kernel at 0x7e00 I was wondering if this was a good idea or not?)
Thanks in advance,
Jules
-
- Member
- Posts: 223
- Joined: Thu Jul 05, 2007 8:58 am
assuming your kernel is in the memory as executable code (so properly linked and relocated (if aplicable)) and you know the adres of the entry point the only thing you have to do is jump straight in it. You could however use your bootloader to gain system information from the bios, but that is an action to do before going into pmode.
Loading at 0x7e00 gives some problems as that if you're bootloader doesn't relocate itself to a safe location, it will be overwritten in the proces, which can cause nasty results
Loading at 0x7e00 gives some problems as that if you're bootloader doesn't relocate itself to a safe location, it will be overwritten in the proces, which can cause nasty results
0x7e00 is exactly 512 bytes after 0x7c00, so i don't think anything should be overwritten.
I do a jump:
0x7e00:0x0000
But vmware says that there was a stack error in kernel mode.
don't know how to fix this.
Any ideas?
Thanks in advance,
Jules
P.S. yes i have loaded it, but isn't there something you have to do to set up a segment?
I do a jump:
0x7e00:0x0000
But vmware says that there was a stack error in kernel mode.
don't know how to fix this.
Any ideas?
Thanks in advance,
Jules
P.S. yes i have loaded it, but isn't there something you have to do to set up a segment?
try this:
Make sure that your code segment is the 2nd GDT entry (hence 0x08).
Code: Select all
jmp 0x08:0x7e00
Hi,
If your boot loader is only 512 bytes (less the BPB and/or partition table) then you're doing something wrong, like only loading one sector of the kernel (when you know the kernel will grow to more than that) and not having decent error handling (for e.g. I'm currently using about 270 bytes for ASCIIZ strings for BIOS error messages alone).
For protected mode, the value you load into CS (using the "jmp far") is an entry in the GDT. For example, "jmp 0x7E00:0x0000" would jump to the code segment described by GDT entry number 0xFC0 (at offset 0x7E00 in the GDT).
Cheers,
Brendan
Where's your stack (and ".bss" section)?suthers wrote:0x7e00 is exactly 512 bytes after 0x7c00, so i don't think anything should be overwritten.
If your boot loader is only 512 bytes (less the BPB and/or partition table) then you're doing something wrong, like only loading one sector of the kernel (when you know the kernel will grow to more than that) and not having decent error handling (for e.g. I'm currently using about 270 bytes for ASCIIZ strings for BIOS error messages alone).
I thought you were in 32-bit protected mode (doing "0x7e00:0x0000" looks like something you'd do if you were in real mode).suthers wrote:I do a jump:
0x7e00:0x0000
For protected mode, the value you load into CS (using the "jmp far") is an entry in the GDT. For example, "jmp 0x7E00:0x0000" would jump to the code segment described by GDT entry number 0xFC0 (at offset 0x7E00 in the GDT).
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
only problem with loading at 0x7E00 is that if your kernel gets large enough you might overwrite video memory and when you write to video memory you will overwrite some of your kernel, when you execute the code that should be there you will have problems.
Working On:Bootloader, RWFS Image Program
Leviathan: http://leviathanv.googlecode.com
Kernel:Working on Design Doc
Leviathan: http://leviathanv.googlecode.com
Kernel:Working on Design Doc
I have changed my jmp to:
But I still get a "stack fault in kernel mode".
I made sure that the code GDT is the second GDT so that 0x08 points to the right GDT.
Any ideas what im doing wrong?
Thanks in advance,
Jules
Code: Select all
jmp 0x08:0x7e00
I made sure that the code GDT is the second GDT so that 0x08 points to the right GDT.
Any ideas what im doing wrong?
Thanks in advance,
Jules
Ok, here is my code:
Any ideas what's wrong with it?
And yes I have set up a stack...
Thanks in advance,
Jules
P.S. Please don't yell at me for any stupid mistakes i've made...
Code: Select all
[BITS 16]
[ORG 0x7C00]
start:
mov [drive_id], dl
mov ax, cs
mov ds, ax
mov es, ax
mov fs, ax
mov ax, 0x1D0
mov ss, ax
mov sp, 0x200
sti
mov si, init_message
call PutStr
call enable_A20
call read
cli
lgdt [gdt_desc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:.32_bit
[BITS 32]
.32_bit
mov eax, 10h
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
mov dl, 0x04
mov ecx, 0B81E0h
mov esi, enabled_32
call PutStr_32
jmp 0x08:0x7e00
.hang
jmp .hang
PutStr_32:
.next_char
lodsb
or al,al
jz .end
mov byte [ds:ecx], al
inc ecx
mov byte [ds:ecx], dl
inc ecx
jmp .next_char
.end
ret
[BITS 16]
enable_A20:
cli
call waitkeyclear
mov al, 0xd1
out 0x64, al
call waitkeyclear
mov al, 0xdf
out 0x60, al
call waitkeyclear
mov cx, 0x10
.waisttime
nop
nop
xor ax, ax
loop .waisttime
mov al, 0xd0
out 0x64, al
call waitkeyfull
in al, 0x60
test al, 2
jnz .A20_on
mov al, 'A'
call halt
.A20_on
sti
mov si, A20_success
call PutStr
sti
ret
waitkeyclear:
xor al, al
in al, 0x64
test al, 2
jnz waitkeyclear
ret
waitkeyfull:
xor cx, cx
in al, 0x64
test al, 1
jz waitkeyfull
ret
halt:
sti
mov si, A20_fail
call PutStr
hlt
PutStr:
mov ah,0x0E
mov bh,0x00
mov bl,0x07
.nextchar
lodsb
or al,al
jz .return
int 0x10
jmp .nextchar
.return
ret
read:
sti
xor ax, ax
mov di, 5
.track1
mov al, 1
mov dh, 0
mov dl, [drive_id]
mov ch, 0
mov cl, 2
mov bx, 0x7e00
mov es, bx
mov bx, 0x0000
int 0x13
dec di
jz .err
jc .track1
jmp .success
.err
mov si, Read_fail
call PutStr
jmp .end
.success
mov si, Read_success
call PutStr
.end
mov dx,0x3F2
mov al,0x0C
out dx,al
ret
gdt:
gdt_null:
dd 0
dd 0
gdt_code:
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
enabled_32 db '32bit mode enabled', 0
drive_id dw ''
A20_success db 'A20 Enabled', 13, 10, 0
A20_fail db 'A20 Enabling failed', 13, 10, 0
Read_success db 'Floppy read successfully', 13, 10, 0
Read_fail db 'Floppy read failure', 13, 10, 0
init_message db 'Welcome to SOS V 0.0.1', 13, 10, 0
times 510-($-$$) db 0
dw 0AA55h
And yes I have set up a stack...
Thanks in advance,
Jules
P.S. Please don't yell at me for any stupid mistakes i've made...
Hi,
To be more honest, IIRC the error messages in VMware are fairly crappy, so "stack fault in kernel mode" could mean anything (not even sure if it's general protection fault or not, or which instruction caused the problem). Try running this through Bochs to get real debugging information so you can find out what's wrong!
Cheers,
Brendan
suthers wrote:Ok, here is my code:
Code: Select all
[BITS 16]
[ORG 0x7C00]
jmp start ;Some Compaq machines won't boot if first instruction isn't a JMP
;Should put a dummy BPB (BIOS Paramater Block) here so that DOS/Windows can format the disk
;later (DOS/Windows tends to wet it's pants otherwise)
start:
; mov [drive_id], dl ** DS not set yet, so this could write anywhere **
mov ax, cs
mov ds, ax
mov [drive_id], dl ;** Shifted from above **
mov es, ax
; mov fs, ax ;Segment register unused so no need to initialize
mov ax, 0x1D0
cli ;Possibly unnecessary, but a good habit (in case IRQ occurs after SS set but before SP set)
mov ss, ax
mov sp, 0x200 ;ss:sp = 0x01D0:0x0200 = 0x00002000
sti
mov si, init_message
call PutStr
call enable_A20
call read
cli
lgdt [gdt_desc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:.32_bit
[BITS 32]
.32_bit
mov eax, 10h
mov ds, eax
mov es, eax
mov fs, eax
mov gs, eax
mov ss, eax
;OK, at this point, what does "SS:ESP" contain? The highest 16-bits of ESP
;aren't set to anything and could contain trash. SS_base = 0x00000000 so if
;ESP isn't trash it'd point to 0x00000000+0x00000200 or 0x00000200 (but
;SS:ESP could point to 0x12340200 for all you know).
mov dl, 0x04
; mov ecx, 0B81E0h Assemblers are good - try:
mov ecx,0B8000 + 6 * (40 * 2) ;So you can figure out where the magic number came from later
mov esi, enabled_32
call PutStr_32
jmp 0x08:0x7e00
.hang
jmp .hang
PutStr_32:
cld ;Should set direction *somewhere* before using string instructions
.next_char
lodsb
or al,al
jz .end
mov byte [ds:ecx], al ;Try using "lodsb" with "stosw" (with ah = attribute)
inc ecx
mov byte [ds:ecx], dl
inc ecx
jmp .next_char
.end
ret
[BITS 16]
enable_A20:
;Unfortunately, different motherboards use different methods to enable the
;A20 gate. Try BIOS function first ("mov ax,0x2401; int 0x15"). Also, consider
;testing if A20 actually is enabled correctly instead of assuming it is, by
;testing if the value at 0x0000:0x0000 (or 0x00000000) remains the same as the
;value at 0xFFFF:0x0010 (or 0x00100000).
cli
call waitkeyclear
mov al, 0xd1
out 0x64, al
call waitkeyclear
mov al, 0xdf
out 0x60, al
call waitkeyclear
mov cx, 0x10
.waisttime ;Hehe, you mean "waste" not "waist"
nop
nop
xor ax, ax
loop .waisttime
mov al, 0xd0
out 0x64, al
call waitkeyfull
in al, 0x60
test al, 2
jnz .A20_on ;Why not do a "jz halt" instead?
; mov al, 'A' ** unused **
call halt ;WTF - see comments below
.A20_on
sti
mov si, A20_success
call PutStr
sti
ret
waitkeyclear:
xor al, al
in al, 0x64
test al, 2
jnz waitkeyclear
ret
waitkeyfull:
xor cx, cx
in al, 0x64
test al, 1
jz waitkeyfull
ret
;OK, what is this "halt" code meant to do? It looks like it prints a string, then
;waits until an IRQ occurs (could be anywhere from 0 ms to 55 ms), then falls through
;to the "PutStr" routine which prints the string again (starting from the byte after
;the first string's terminator.
halt:
sti
mov si, A20_fail
call PutStr
.die:
hlt
jmp .die ;I'm guessing you missed this!
PutStr:
cld ;Should set direction *somewhere* before using string instructions
mov ah,0x0E
mov bh,0x00
mov bl,0x07
.nextchar
lodsb
or al,al
jz .return
int 0x10
jmp .nextchar
.return
ret
read:
sti
xor ax, ax
mov di, 5
.track1
mov al, 1
mov dh, 0
mov dl, [drive_id]
mov ch, 0
mov cl, 2
mov bx, 0x7e00
mov es, bx
mov bx, 0x0000
int 0x13
dec di
; jz .err Should see if it worked before deciding it didn't
; jc .track1
; jmp .success
jnc .success
dec di
jnz .track1
;WTF? If it didn't load correctly you display a different string and then
;continue as if it has loaded correctly???
.err
mov si, Read_fail
call PutStr
jmp .end ;Should probably lock up here instead (note: with interrupt enabled the BIOS will turn floppy motor off).
.success
mov si, Read_success
call PutStr
.end
mov dx,0x3F2
mov al,0x0C
out dx,al
ret
align 4 ;Align your GDT!
gdt:
gdt_null:
; dd 0 ;These values are unused by the CPU, so let's use them!
; dd 0
dw 0 ;First 2 bytes of (unused) NULL descriptor
gdt_desc: ;From below
dw gdt_end - gdt - 1 ;GDT limit (also part of NULL descriptor)
dd gdt ;GDT base address (also part of NULL descriptor)
;I should charge you $20 for adding the comments below... ;-)
gdt_code:
dw 0FFFFh ;Limit (low word) = 0xFFFF
dw 0 ;Base (low word) = 0x0000
db 0 ;Base (middle byte) = 0x00
db 10011010b ;Present, DPL=0, non-system, type = "code execute/read"
db 11001111b ;4KB limit granularity, 32-bit default size, limit high nibble = 0xF
db 0 ;Base (high byte) = 0x00
gdt_data:
dw 0FFFFh ;Limit (low word) = 0xFFFF
dw 0 ;Base (low word) = 0x0000
db 0 ;Base (middle byte) = 0x00
db 10010010b ;Present, DPL=0, non-system, type = "data read/write"
db 11001111b ;4KB limit granularity, 32-bit default size, limit high nibble = 0xF
db 0 ;Base (high byte) = 0x00
gdt_end:
;gdt_desc: ;Shifted above
; dw gdt_end - gdt - 1
; dd gdt
enabled_32 db '32bit mode enabled', 0
drive_id dw ''
A20_success db 'A20 Enabled', 13, 10, 0
A20_fail db 'A20 Enabling failed', 13, 10, 0
Read_success db 'Floppy read successfully', 13, 10, 0
Read_fail db 'Floppy read failure', 13, 10, 0
init_message db 'Welcome to SOS V 0.0.1', 13, 10, 0
times 510-($-$$) db 0
dw 0AA55h
Honestly, no - I can't be sure that any of the problems I noticed would have caused a "stack fault in kernel mode".suthers wrote:Any ideas what's wrong with it?
To be more honest, IIRC the error messages in VMware are fairly crappy, so "stack fault in kernel mode" could mean anything (not even sure if it's general protection fault or not, or which instruction caused the problem). Try running this through Bochs to get real debugging information so you can find out what's wrong!
I'll try not to mention any of the design flaws (like what's going to happen when the boot code becomes larger than 512 bytes, or the kernel becomes larger than about 600 KB), or the severe lack of comments...suthers wrote:P.S. Please don't yell at me for any stupid mistakes i've made...
Cheers,
Brendan
For all things; perfection is, and will always remain, impossible to achieve in practice. However; by striving for perfection we create things that are as perfect as practically possible. Let the pursuit of perfection be our guide.
I tried your code on Boch's but I never got a stack fault in kernel mode,
it just prints the welcome message and then reboots,so I made a few changes,and it's working now,so here you are...
Pleasse note I never tested it on real pc just with Boch's.
it just prints the welcome message and then reboots,so I made a few changes,and it's working now,so here you are...
Code: Select all
[BITS 16]
[ORG 0x7C00]
jmp start
bpbOEM db "My OS "
bpbBytesPerSector: DW 512
bpbSectorsPerCluster: DB 1
bpbReservedSectors: DW 1
bpbNumberOfFATs: DB 2
bpbRootEntries: DW 224
bpbTotalSectors: DW 2880
bpbMedia: DB 0xf0 ;; 0xF1
bpbSectorsPerFAT: DW 9
bpbSectorsPerTrack: DW 18
bpbHeadsPerCylinder: DW 2
bpbHiddenSectors: DD 0
bpbTotalSectorsBig: DD 0
bsDriveNumber: DB 0
bsUnused: DB 0
bsExtBootSignature: DB 0x29
bsSerialNumber: DD 0xa0a1a2a3
bsVolumeLabel: DB "MOS FLOPPY "
bsFileSystem: DB "FAT12 "
start:
mov [drive_id], dl
mov ax, cs
mov ds, ax
mov es, ax
mov fs, ax
mov ax, 0x1D0
mov ss, ax
mov sp, 0x200
sti
mov si, init_message
call PutStr
call enable_A20
call read
cli
lgdt [gdt_desc]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp 0x08:.32_bit
[BITS 32]
.32_bit
sti
mov ax, 0x10 ; set data segments to data selector (0x10)
mov ds, ax
mov ss, ax
mov es, ax
mov esp, 90000h ; stack begins from 90000h
mov dl, 0x04
mov ecx, 0B81E0h
mov esi, enabled_32
call PutStr_32
; jmp 0x08:0x7e00
cli
hlt
PutStr_32:
.next_char
lodsb
or al,al
jz .end
mov byte [ds:ecx], al
inc ecx
mov byte [ds:ecx], dl
inc ecx
jmp .next_char
.end
ret
[BITS 16]
enable_A20:
cli
call waitkeyclear
mov al, 0xd1
out 0x64, al
call waitkeyclear
mov al, 0xdf
out 0x60, al
call waitkeyclear
mov cx, 0x10
.waisttime
nop
nop
xor ax, ax
loop .waisttime
mov al, 0xd0
out 0x64, al
call waitkeyfull
in al, 0x60
test al, 2
jnz .A20_on
mov al, 'A'
call halt
.A20_on
sti
mov si, A20_success
call PutStr
sti
ret
waitkeyclear:
xor al, al
in al, 0x64
test al, 2
jnz waitkeyclear
ret
waitkeyfull:
xor cx, cx
in al, 0x64
test al, 1
jz waitkeyfull
ret
halt:
sti
mov si, A20_fail
call PutStr
hlt
PutStr:
mov ah,0x0E
mov bh,0x00
mov bl,0x07
.nextchar
lodsb
or al,al
jz .return
int 0x10
jmp .nextchar
.return
ret
read:
sti
xor ax, ax
mov di, 5
.track1
mov al, 1
mov dh, 0
mov dl, [drive_id]
mov ch, 0
mov cl, 2
mov bx, 0x7e00
mov es, bx
mov bx, 0x0000
int 0x13
dec di
jz .err
jc .track1
jmp .success
.err
mov si, Read_fail
call PutStr
jmp .end
.success
mov si, Read_success
call PutStr
.end
mov dx,0x3F2
mov al,0x0C
out dx,al
ret
gdt:
gdt_null:
dd 0
dd 0
gdt_code:
dw 0FFFFh
dw 0
db 0
db 10011010b
db 11001111b
db 0
gdt_data:
dw 0FFFFh
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
gdt_desc:
dw gdt_end - gdt - 1
dd gdt
enabled_32 db '32bit mode enabled', 0
drive_id dw ''
A20_success db 'A20 Enabled', 13, 10, 0
A20_fail db 'A20 Enabling failed', 13, 10, 0
Read_success db 'Floppy read successfully', 13, 10, 0
Read_fail db 'Floppy read failure', 13, 10, 0
init_message db 'Welcome to SOS V 0.0.1', 13, 10, 0
times 510-($-$$) db 0
dw 0xAA55
The man who follows the crowd will usually get no further than the crowd.
The man who walks alone is likely to find himself in places
no one has ever been before.
The man who walks alone is likely to find himself in places
no one has ever been before.
Thanks for checking my code.
Still getting the error though, probably has something to do with how i'm linking it or how the kernel is written...
My kernel:
My kernel starter:
My linker script:
Anything wrong with any of these?
Thanks in advance,
Jules
Still getting the error though, probably has something to do with how i'm linking it or how the kernel is written...
My kernel:
Code: Select all
char *video_address = (char*)0xB8320;
char attributes = 0x04;
void print(char *text);
void sys_hlt();
void kernel_main()
{
print("Kernel started");
sys_hlt();
while(1){ asm volatile ("nop"); }//just incase the hlt doesn't work (happens occasionally don't know why)
return;
}
void print(char *text)
{
while(*text !=0)
{
*video_address = *text;
*video_address++;
*video_address = attributes;
*video_address++;
*text++;
}
return;
}
void sys_hlt()
{
asm volatile ("cli");
asm volatile ("hlt");
return;
}
Code: Select all
[BITS 32]
[global main]
[extern _kernel_main]
main:
mov dl, 0x04
mov ecx, 0B8280h
mov esi, kernel_starter_active
call PutStr_32
call _kernel_main
hlt
PutStr_32:
.next_char
lodsb
or al,al
jz .end
mov byte [ds:ecx], al
inc ecx
mov byte [ds:ecx], dl
inc ecx
jmp .next_char
.end
ret
kernel_starter_active db 'kernel starter active', 0
Code: Select all
OUTPUT_FORMAT("binary")
ENTRY(main)
Thanks in advance,
Jules