Home arrow Forums
OSDEV Forums  


<< Start < Previous 1 2 3 4 5 Next > End >>
wojtekw86
User

Junior Osdever
Posts: 24
graphgraph
Karma: 0  
My C kernel does not load - 2006/07/04 07:17 Ok, 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 ax07c0h     mov ssax     mov esp03ffh     inicjacja trybu wideo 80x25 (tekstowego)     xor ahah     mov al3     int 10h     ladowanie jadra pod adres 1000h:0000h     xor ahah     int 10h   mov ah2   mov al10   mov ch0   mov cl2   mov dh0   mov bx1000h   mov esbx   xor bxbx   int 13h     mov ax,0xb800     mov gs,ax     mov word [gs:0],0x641     lgdt [gdtr]          mov eaxcr0     or eax1     mov cr0eax     jmp codesel:pmode [BITS 32] pmode:     mov axdatasel     mov ssax     mov dsax     mov esax     mov fsax     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 - ($ - startdb 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



KERNEL (in C)
Code:

 void k_main() {     unsigned char *vga = (unsigned char *)0xb8000;     unsigned char *str "W";         *vga = *str;         *(vga 1) = 3; }



linker
Code:

 OUTPUT_FORMAT("binary") ENTRY(c_jajo) SECTIONS { .text 0x00010000 : { code = .; _code = .; __code = .; *(.text) . = ALIGN(4096); } .data : { data = .; _data = .; __data = .; *(.data) . = ALIGN(4096); } .bss : { bss = .; _bss = .; __bss = .; *(.bss) . = ALIGN(4096); } end = .; _end = .; __end = .; }



building script
Code:

 echo "==========> Doing p -> p.bin" nasm -f bin p -o p.bin echo "==========> Doing entry -> entry.o" nasm -f elf entry.asm -o entry.o echo "==========> Doing kernel.c -> kernel.o" gcc -c kernel.-O2 -o kernel.o echo "==========> Doing kernel.map + entry.o + kernel.o -> kernel.bin" ld -Map kernel.map entry.o kernel.-T link.ld -o kernel.bin echo "==========> Doing p.bin + kerlen.bin -> obraz.img" ./merge p.bin kernel.bin obraz.img echo "==========> Done!"



"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
graph
Karma: 10  
Re:My C kernel does not load - 2006/07/04 11:19 Hello 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
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/04 13:21 gaf 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
graph
Karma: 10  
Re:My C kernel does not load - 2006/07/04 15:09 I 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).

Code:

 rmodephysical address segment*16 offset pmodephysical address descriptor_base offset


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:

Code:

 gs.base 0xB8000 (line 81) offset  0xB8000 physical gs.base offset != 0xB8000


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 ?

Code:

 int main() {     charvideo-memory reinterpret_cast<char*>(0xB8000);     video-memory[0] = 'Z';     video-memory[1] =  4; }


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
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/04 15:24 gaf 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
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/04 15:28 The 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
graph
Karma: 10  
Re:My C kernel does not load - 2006/07/05 06:08 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...

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 axdatasel     mov ssax     mov dsax     mov esax     mov fsax     mov gsax     mov esp0x8000     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 - ($ - startdb 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
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/05 06:33 Ok... 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
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/05 07:34 1) I know now...
2) I think I understand...
  | | The administrator has disabled public write access.
wojtekw86
User

Junior Osdever
Posts: 24
graphgraph
Karma: 0  
Re:My C kernel does not load - 2006/07/05 09:27 6) 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?

#define KERNEL_GDT 0x2000

typedef struct {
unsigned short limit;
unsigned short base_0_15;
unsigned char base_16_23;
unsigned char dpl_type;
unsigned char gav_lim;
unsigned char base_24_31;
} sys_desc;

void setup_gdt(int i, unsigned long base, unsigned long limit, char type)
{
sys_desc *desc = (sys_desc*)KERNEL_GDT;
desc[i].limit = limit & 0xFFFF;
desc[i].base_0_15 = base << 16;
desc[i].base_16_23 = (base & 0xFF0000) >> 16;
desc[i].dpl_type = 0x90 | type;
desc[i].gav_lim = ((limit & 0xF0000) >> 16) | 0xC0;
desc[i].base_24_31 = 0;
}


Post edited by: wojtekw86, at: 2006/07/05 10:28
  | | The administrator has disabled public write access.
<< Start < Previous 1 2 3 4 5 Next > End >>

A WebArticles site. Sponsored by Evoleto. Motorola V525 / Business Directory / Delaware Incorporation / Home Made Bazaar