My C kernel does not load - 2006/07/04 07:17Ok, so... - bootloader works fine (alone) - everything is compiling smooth - im doing everything under linux (nasm + gcc + bochs)
but when I try to load kernel using my bootloader I get a message: ">>PANIC<< prefetch: getHostMemAddr vetoed direct read, pAddr=0x000a0000" in bochs every single time... ...
I was searching thru the internet and tried many solutions but none does not work....
some code:
Bootloader
Code:
org 7C00h
[BITS 16]
start:
; ustawienie stosu dla rybu rzeczywistego (przestrzen pamieci 07c0h:0200h - 07c0h:03ffh)
mov ax, 07c0h
mov ss, ax
mov esp, 03ffh
; inicjacja trybu wideo 80x25 (tekstowego)
xor ah, ah
mov al, 3
int 10h
; ladowanie jadra pod adres 1000h:0000h
xor ah, ah
int 10h
mov ah, 2
mov al, 10
mov ch, 0
mov cl, 2
mov dh, 0
mov bx, 1000h
mov es, bx
xor bx, bx
int 13h
mov ax,0xb800
mov gs,ax
mov word [gs:0],0x641
lgdt [gdtr]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp codesel:pmode
[BITS 32]
pmode:
mov ax, datasel
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov ax,videosel
mov gs,ax
mov word [gs:0],0x741 ; Display white A in protected mode
jmp codesel:0x10000
[BITS 16]
gdtr:
dw gdt_end - gdt - 1
dd gdt
gdt:
nullsel equ $-gdt
gdt0:
; NULL Descriptor
dd 0
dd 0
codesel equ $-gdt
code_gdt:
dw 0x0FFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
datasel equ $-gdt
data_gdt:
dw 0x0FFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
videosel equ $-gdt
dw 3999 ; Limit 80*25*2-1
dw 0x8000 ; Base 0xb8000
db 0x0b
db 0x92
db 0x00
db 0x00
gdt_end:
times 510 - ($ - start) db 0
db 55h
db 0AAh
entry - program connecting asm bootloader with c kernel
Code:
[BITS 32]
GLOBAL c_jajo
c_jajo:
[EXTERN k_main]
call k_main
hlt
"merge" is a program written by me which is making one file from 2,3....x files... (it works fine for sure)
I am newbie in OS programming althought I have been learning assembler couple years ago and I am (even) good in C/C++ (studying it on university and other languages (like PHP, Java...) and "computer" things...). Sorry for my bad english (I have not been using "it" long time ).
| | The administrator has disabled public write access.
OSDEV Community
Advertisement
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re:My C kernel does not load - 2006/07/04 11:19Hello wojtekw, although I had a quite thorough look at your code I couldn't find any real mistake. Either I'm just blind, or it's one of the more subtile bugs..
Here's a list of what I did notice:
line 6: It should actually be 0x400 and not 0x3ff as the stack-pointer is not a limit
line 14: Setting the video-mode once is more than enough. Actually you don't have to set it at all as 80*25 is the default resolution
line 42: While you reload the stack-selector, the stack-pointer doesn't get updated - it's still 0x400. As the segment-base was changed to zero, the stack is now created somewhere in the lower-memory area
GCC probably assumes that gs is loaded with a flat selector (base: 0, limit: 0xFFFFF)
Your linker-script doesn't include *(.rodata), which is however needed to store the string. You should add it to the bss section
As I already said I frankly doubt that any of the above mentioned points causes the crash. Maybe you could try to isolate the problem a little more:
- Is the pmode A displayed if you hang the kernel after printing it ? - Can you push a value while running in pmode ? - Does the kernel also crash if the C code just returns without printing anything ?
regards, gaf
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/04 13:21gaf wrote:
line 6: It should actually be 0x400 and not 0x3ff as the stack-pointer is not a limit RE: changed
line 14: Setting the video-mode once is more than enough. Actually you don't have to set it at all as 80*25 is the default resolution RE: does not matter -> wanted to clear the screen .
line 42: While you reload the stack-selector, the stack-pointer doesn't get updated - it's still 0x400. As the segment-base was changed to zero, the stack is now created somewhere in the lower-memory area RE: do not understand what is the stack-selector & stack-pointer? I know I should know that (I do not understand clearly some parts of code) but I thought that if I will force it to work I will be changing something and learning in this way .
GCC probably assumes that gs is loaded with a flat selector (base: 0, limit: 0xFFFFF) RE: Hmmm... whats the point?
Your linker-script doesn't include *(.rodata), which is however needed to store the string. You should add it to the bss section RE: Included... Question.. is ALIGN(4096) in my case is good?
(...)
Maybe you could try to isolate the problem a little more: (...) - Does the kernel also crash if the C code just returns without printing anything ? RE: NO... 8|... It works fine... I know that the ERRoR means that I am reading from the memory location that I havent to... (or not? I read that in internet)...
Thx for answer by the way... ... I am new here... are there on this portal any good articles about OS programming?
PS. I am using bochs. I made a configuration file, but I must load it any time I want to run bochs? What should I do to force bochs to load it itself? Thx in advance...
Post edited by: wojtekw86, at: 2006/07/04 14:26
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re:My C kernel does not load - 2006/07/04 15:09I do not understand what is the stack-selector & stack-pointer? But you do know how a stack works in general ? Otherwise you should really have a look at the concept (wikipedia).
At start-up your computer is in real-mode, and the very first thing the boot-loader does is to enable the stack: line 5 of the code sets the stack-segment (ss) to 0x7c0, and line 6 initializes the stack-pointer (esp) with 0x400. The physical address of the stack is thus 0x7c0*16 + 0x400 = 0x7c00 + 400 = 0x8000.
Once protected mode is enabled, addresses get calculated using the second equation. As all of your gdt descriptors (with the exception of gs) have a base-address of zero, the stack's address would now be: 0x00000000 + 0x400 = 0x400
As you can see the stack's address has changed during the switch. This only doesn't cause any problems with your current code as the real-mode portion doesn't even use the stack. If it did make use of it, all pushed data would get lost, which would eventually lead to a crash.
To fix the issue, all you have to do is to add a "mov esp, 0x8000" in line 48. Thatway the physical address of the stack is the same in pmode as in real-mode.
GCC probably assumes that gs is loaded with a flat selector (base: 0, limit: 0xFFFFF)
RE: Hmmm... whats the point? It's for instance possible that gcc produces the following code to print the W in your C kernel:
mov byte [gs:0xB8000], 'W'
Again the actual address is calculated by the 2nd equation I gave above. As the base-address of gs is however not zero as gcc would expect, the result is wrong:
I would thus recommend that you remove line 48 from your code to avoid problems with the C compiler.
Is ALIGN(4096) in my case is good? It's not necessary to align the sections, but it also shouldn't cause you any trouble. The only case where I could imagine an ALIGN(4096) to be useful is when paging is use, where it might increase performance a little bit. In your case it just increases the size of the executable by some 12 kilobytes .
Does the kernel also crash if the C code just returns without printing anything ?
RE: NO... 8|... It works fine... Does this code work ?
The whole thing still sounds like a problem with rodata to me. Maybe adding another asterix already fixes the issue: *(.rodata*)..
If you're still having problem, the output of "objdump -x kernel.o > output.txt" might be useful to find out what exactly goes wrong.
I know that the error means that I am reading from the memory location that I havent to
Basically yes.. Address 0xA0000 is used for VGA memory. There's thus not really any point in reading from that area, which is why bochs throws an error.
You however should be carefull as bochs often tends to produce quite obscure error messages: I for instance don't see anything in your code that could cause a read from video-memory. Most likely it is just the final result of something completly different going wrong much earlier..
Are there on this portal any good articles about OS programming? You mean apart from the articles section ?
Another very good resource for all kinds of tutorial is bonafide, which also features a couple of beginner tutorials like Bran's Kernel Development. I myself learned most of the low-level basics from Chris Giese's protected-mode tutorials, that cover the booting process from power-on till protected-mode.
Apart from that there are two wikis dedicated to operating-system development: mega-tokyo and osdev.org. The latter has however just opened and thus doesn't yet include much information.
I am using bochs. I made a configuration file, but I must load it any time I want to run bochs? What should I do to force bochs to load it itself? On Windows the simplest solution whould be to copy the file in the same directory as bochs.exe - on Linux the file should be stored in the user's home directory. Bochs will then automatically find the configure script..
regards,
gaf
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/04 15:24gaf wrote: ... To fix the issue, all you have to do is to add a "mov esp, 0x8000" in line 48. Thatway the physical address of the stack is the same in pmode as in real-mode.
(...) // Than you are saying...
I would thus recommend that you remove line 48 from your code to avoid problems with the C compiler.
So I should not touch line 48 at all? Is it fine? If you could, please past me this fragments of code as it should look...
Thx... I will tryout those changes...
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/04 15:28The whole thing still sounds like a problem with rodata to me. Maybe adding another asterix already fixes the issue: *(.rodata*)..
IT WORKS !!! Yuuupiii!!!
But I still want your reply on my earlier post... -> want to know everything..
| | The administrator has disabled public write access.
gaf
User Platinum Osdever
Posts: 153
Karma: 10
Re:My C kernel does not load - 2006/07/05 06:08So I should not touch line 48 at all? Is it fine? If you could, please past me this fragments of code as it should look...
I was refering to the unedited loader code in both cases: The idea is to first remove the old line ("mov ax, videosel") and then insert the new code ("mov esp, 0x8000"). I admit that it was a bit misleading..
Code:
org 7C00h
(snip)
[BITS 32]
pmode:
mov ax, datasel
mov ss, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov esp, 0x8000
mov [0xB8000], 0x741 ; Display white A in protected mode
jmp codesel:0x10000
[BITS 16]
gdtr:
dw gdt_end - gdt - 1
dd gdt
gdt:
nullsel equ $-gdt
gdt0:
; NULL Descriptor
dd 0
dd 0
codesel equ $-gdt
code_gdt:
dw 0x0FFFF
dw 0
db 0
db 10011010b
db 11001111b
db 0
datasel equ $-gdt
data_gdt:
dw 0x0FFFF
dw 0
db 0
db 10010010b
db 11001111b
db 0
gdt_end:
times 510 - ($ - start) db 0
db 55h
db 0AAh
regards,
gaf
Post edited by: gaf, at: 2006/07/05 07:10
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/05 06:33Ok... thx. Now... I wanted to know such things...
1) Is GDT some sort of map of memory where I decide where to place VGA Soundcard and other sections, or not? If yes then cool... I just want to know what is it in global meaning... 2) I should set GDT before entering PMODE or I can do it after...? If yes do I must define it before and after or can only after? B'cause I wanted to write this part of code in C... Where should that part of code be placed (where is the best place for it?) 3) I read some stuff now and I do not understand one thing... There is stated that "lets say GDT will be under address 0x2000 and IDT under 0x2500 ... and then ... this will give us 2KiB for each of it"... 2KiB? "500" in Hex is 2KiB? How to count it? It is a little bit weird for me... could you explain? 4) What is happening when I am reloading GDT - setting up in diffrent place and reloading? Whats going with old GDT? And does Kernel should have separate GDT for itself and other GDT for other things? 5) How do I know how many memory do I have... how many and how big GDT's and IDT's can I make?
Thx 4 your help again...
Post edited by: wojtekw86, at: 2006/07/05 08:10
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/05 07:341) I know now... 2) I think I understand...
| | The administrator has disabled public write access.
wojtekw86
User Junior Osdever
Posts: 24
Karma: 0
Re:My C kernel does not load - 2006/07/05 09:276) I tried to understand... read many articles about GDT and so on, but do not understand why in this code is "int i"? Why do we need to set i while we have base and limit of each part GDT?