Call Simple C Kernel

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
dromenox
Posts: 5
Joined: Fri Oct 24, 2014 8:31 am

Call Simple C Kernel

Post by dromenox »

I'll start developing my first operating system and wanted to do the kernel in C because it is much easier than Assembly. I know that the bootloader has to be done in assembly but that's not the problem. The problem is that I'm not getting the bootloader to call the program in C. I know I'll have to create the libraries but for now just want to test it. I found some tutorials that used Grub to call the C but I want to build my own bootloader.

I want the kernel to run in 32-bit protected mode, but still did not understand how to do this.

I did this misery code but do not know what the right way to compile and link.

Code: Select all

[BITS 16]
[ORG 0x7C00]

extern kmain

call kmain

TIMES 510 - ($ - $$) db 0
DW 0xAA55

Code: Select all

void kmain(void)
{
	
}


If someone can give me the base I'll be able to start developing the functions like print and read the keyboard.

Thank you and sorry for these basic questions.
User avatar
iansjack
Member
Member
Posts: 4707
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Call Simple C Kernel

Post by iansjack »

The Wiki outlines what you need to do. http://wiki.osdev.org/Rolling_Your_Own_Bootloader

Whilst some will argue that there are good reasons to write your own bootloader, you are making life difficult for yourself when you are clearly just starting out. I'd strongly advise you to use Grub until you have learnt a whole lot more.
Cjreek
Member
Member
Posts: 70
Joined: Thu May 28, 2009 2:41 pm
Location: Germany

Re: Call Simple C Kernel

Post by Cjreek »

You have to enter protected mode before calling your kernel because your kernel is 32 bit code.
also you won't get far except your kernel fits into the first 512-2 Bytes of a floppy Disk. (Which is also very unlikely).

You probably should read some tutorials in the wiki on Bootloaders and how to start with your OS.
dromenox
Posts: 5
Joined: Fri Oct 24, 2014 8:31 am

Re: Call Simple C Kernel

Post by dromenox »

iansjack wrote:The Wiki outlines what you need to do. http://wiki.osdev.org/Rolling_Your_Own_Bootloader

Whilst some will argue that there are good reasons to write your own bootloader, you are making life difficult for yourself when you are clearly just starting out. I'd strongly advise you to use Grub until you have learnt a whole lot more.
I understood the code of the bootloader line by line. What I dont know how to do is enter protected mode and call the kernel in C.
User avatar
Combuster
Member
Member
Posts: 9301
Joined: Wed Oct 18, 2006 3:45 am
Libera.chat IRC: [com]buster
Location: On the balcony, where I can actually keep 1½m distance
Contact:

Re: Call Simple C Kernel

Post by Combuster »

dromenox wrote:I understood the code of the bootloader line by line. What I dont know how to do is enter protected mode and call the kernel in C.
Did you realize you're contradicting yourself?
"Certainly avoid yourself. He is a newbie and might not realize it. You'll hate his code deeply a few years down the road." - Sortie
[ My OS ] [ VDisk/SFS ]
User avatar
iansjack
Member
Member
Posts: 4707
Joined: Sat Mar 31, 2012 3:07 am
Location: Chichester, UK

Re: Call Simple C Kernel

Post by iansjack »

dromenox wrote:I understood the code of the bootloader line by line. What I dont know how to do is enter protected mode and call the kernel in C.
Well, if you managed to write a bootloader all by yourself then you should have no problem understanding the rest. It's all clearly detailed in the Intel Programmer's Manuals - reading these is a prerequisite for OS development on x86 processors. On the other hand, if you have just cut-and-pasted a bootloader from somewhere that probably doesn't mean you have the requisite knowledge to do the rest.

In either case, you need no further help from us. I have already pointed you to the appropriate page in the Wiki.

(I still think you should choose the easy route and use Grub to start with.)
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Call Simple C Kernel

Post by b.zaar »

dromenox wrote:
iansjack wrote:The Wiki outlines what you need to do. http://wiki.osdev.org/Rolling_Your_Own_Bootloader

Whilst some will argue that there are good reasons to write your own bootloader, you are making life difficult for yourself when you are clearly just starting out. I'd strongly advise you to use Grub until you have learnt a whole lot more.
I understood the code of the bootloader line by line. What I dont know how to do is enter protected mode and call the kernel in C.
The boot loader doesn't directly call the C kernel, that's the job of an asm stub that you will need with your kernel when using your own boot loader or Grub. Your own boot loader should load the kernel and maybe a ramdisk then set up the system with a very basic protected mode environment by setting the GDT, A20 line and disabling interrupts. From the boot loader you jump to the start adress in the kernel which should point to your asm stub that then saves any information like the multiboot parameters and calls your C kernel.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
remy
Posts: 23
Joined: Thu Nov 20, 2014 4:06 pm

Re: Call Simple C Kernel

Post by remy »

Here is what I successed to do but with a kernel written in asm :

boot.asm :

Code: Select all

[org 0x7c00]

KERNEL_OFFSET equ 0x1000

call load_kernel

;Switch PM
cli
lgdt [gdt_descriptor] 

mov eax, cr0 
or eax, 0x1 
mov cr0, eax 

jmp 0x8:init_pm 

[bits 32]
init_pm :
	mov ax, 0x10
	mov ds, ax
	mov ss, ax
	mov es, ax
	mov fs, ax
	mov gs, ax
	
	mov ebp, 0x90000
	mov esp, ebp
	
	call KERNEL_OFFSET
	jmp $

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[bits 16]

load_kernel:
	mov bx, KERNEL_OFFSET
	mov dh, 15
	mov dl, 0
	
	mov ah, 0x02
	mov al, dh
	mov ch, 0x00
	mov dh, 0x00
	mov cl, 0x02
	int 0x13
	ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[bits 16]

GDT:
;null : 
	dd 0x0 
	dd 0x0

;code : 
	dw 0xffff		;Limit
	dw 0x0			;Base
	db 0x0			;Base
	db 10011010b 	;1st flag, Type flag
	db 11001111b 	;2nd flag, Limit
	db 0x0			;Base

;data : 
	dw 0xffff		
	dw 0x0			
	db 0x0
	db 10010010b 
	db 11001111b 
	db 0x0

gdt_descriptor :
	dw $ - GDT - 1 		;16-bit size
	dd GDT				;32-bit start address

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
times 510 -($-$$) db 0
dw 0xaa55
kernel.asm:

Code: Select all

[bits 32]

mov al, 'K'
mov ah, 3 ; cyan
mov edx, 0xb8000
mov [edx], ax
jmp $
I build the floppy image so that:

Code: Select all

nasm boot.asm -o boot.bin
dd if=/dev/zero of=image.bin bs=512 count=2880
dd if=boot.bin of=image.bin conv=notrunc

nasm kernel.asm -o kernel.bin
dd if=kernel.bin of=image.bin conv=notrunc bs=512 seek=1

qemu -fda image.bin -boot a
This way it works ! that's almost that...
But now, I replace kernel.asm by this kernel.c

kernel.c

Code: Select all

void main () {
	char * vga = (char *) 0xb8000 ;
	*vga = "X";
}
And the following script:

Code: Select all

nasm boot.asm -o boot.bin
dd if=/dev/zero of=image.bin bs=512 count=2880
dd if=boot.bin of=image.bin conv=notrunc

gcc -ffreestanding -m32 -c kernel32.c -o kernel.bin
dd if=kernel.bin of=image.bin conv=notrunc bs=512 seek=1

qemu -fda image.bin -boot a
Note that I'm running a 64bit Linux distro, so I use the '-m32' gcc option to compile to 32bits
But it doesn't work...... please help !
seuti
Member
Member
Posts: 74
Joined: Tue Aug 19, 2014 1:20 pm

Re: Call Simple C Kernel

Post by seuti »

remy wrote:-snip-
What about it doesn't work? Do you get an error?

Please be more descriptive and follow the Posting Checklist (http://wiki.osdev.org/Posting_Checklist)
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Call Simple C Kernel

Post by neon »

The boot loader doesn't directly call the C kernel
That is not entirely correct. To see why, we must differentiate between a boot loader and boot manager. The boot loader portion is responsible for loading and setting the environment for use by a specific operating system. The boot manager is responsible for calling other boot loaders. Under these terms, the boot loader component of the software is already well aware of the requirements of the respective operating system and thus can call its entry point directly without concern. This is an important task as it allows boot loader configuration for setting kernel initialization command line flags.

The "assembly stub" that is being referred to here that is common in tutorials has nothing to do with calling the kernel program. The assembly stub exports the real entry point method in the same way that a C compiler would export _main. Thus from the perspective of the boot application, executing the entry point is the same regardless if an assembly stub is used.

With that said, nothing in this thread is about a boot loader but a boot record which is very different software and is what I think you were referring to. In other words, remy provided us a boot record not a boot loader which has very different requirements. And not even a valid boot record (many systems will not attempt to boot it.)

Given the space limitations of boot records, I suggest for remy to load a separate program and remain in real mode. This separate program is the boot loader, kernel, or executive (depending on your design goals and needs) that can include an assembly stub that switches to protected mode and goes into C.

In short, don't attempt protected mode in a boot record.
Last edited by neon on Fri Nov 21, 2014 5:46 pm, edited 4 times in total.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
remy
Posts: 23
Joined: Thu Nov 20, 2014 4:06 pm

Re: Call Simple C Kernel

Post by remy »

NB: sorry I actually switch to the wrong post, but it's okay for me, this is the same subject

While with the kernel.asm, I actually get something on the screen, there is nothing printed with the kernel.c (wich is actually black on black, but I should see it as it overrides the qemu splash screen)
I can't tell more because I have no idea why I can't jump to the C main...
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Call Simple C Kernel

Post by b.zaar »

neon wrote:The "assembly stub" that is being referred to here that is common in tutorials has nothing to do with calling the kernel program. The assembly stub exports the real entry point method in the same way that a C compiler would export _main. Thus from the perspective of the boot application, executing the entry point is the same regardless if an assembly stub is used.
The stub will create a stack and push the multiboot values on to the stack before the C kernel main is called, this step could be overlooked but it's much easily writing it in asm to create the final environment for the kernel.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Call Simple C Kernel

Post by b.zaar »

@remy the C kernel may be failing if the sections are not linked and then loaded in the order you're expecting. Generate a map file to look at the output.
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Call Simple C Kernel

Post by neon »

b.zaar wrote:
neon wrote:The "assembly stub" that is being referred to here that is common in tutorials has nothing to do with calling the kernel program. The assembly stub exports the real entry point method in the same way that a C compiler would export _main. Thus from the perspective of the boot application, executing the entry point is the same regardless if an assembly stub is used.
The stub will create a stack and push the multiboot values on to the stack before the C kernel main is called, this step could be overlooked but it's much easily writing it in asm to create the final environment for the kernel.
That is correct. However this is for the kernel whereas the original poster is transitioning from a boot record. He does not even have a boot loader - his boot record just loads a raw sector and calls the kernel directly skipping the boot loader stage completely. In other words, he still needs to scan the headers of the image to properly align the sections and call the entry point that was exported.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
User avatar
b.zaar
Member
Member
Posts: 294
Joined: Wed May 21, 2008 4:33 am
Location: Mars MTC +6:00
Contact:

Re: Call Simple C Kernel

Post by b.zaar »

neon wrote:
b.zaar wrote:
neon wrote:The "assembly stub" that is being referred to here that is common in tutorials has nothing to do with calling the kernel program. The assembly stub exports the real entry point method in the same way that a C compiler would export _main. Thus from the perspective of the boot application, executing the entry point is the same regardless if an assembly stub is used.
The stub will create a stack and push the multiboot values on to the stack before the C kernel main is called, this step could be overlooked but it's much easily writing it in asm to create the final environment for the kernel.
That is correct. However this is for the kernel whereas the original poster is transitioning from a boot record. He does not even have a boot loader - his boot record just loads a raw sector and calls the kernel directly skipping the boot loader stage completely. In other words, he still needs to scan the headers of the image to properly align the sections and call the entry point that was exported.
But the intention by both people was to call main, whether from a boot sector or a boot loader you rarely if ever call main directly. Even the multiboot specification includes an asm stub.

My advice was simply to create a stub that calls main and that is what you are saying "is not entirely correct."

I may be wrong but is there currently a kernel that links without some kind of asm stub?
"God! Not Unix" - Richard Stallman

Website: venom Dev
OS project: venom OS
Hexadecimal Editor: hexed
Post Reply