Need help with C bootloader

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.
Post Reply
ByteBit
Posts: 6
Joined: Mon Jun 16, 2014 2:40 pm

Need help with C bootloader

Post by ByteBit »

The last 3 days I searched the web for articles about writing a bootloader in C, because it was getting boring to write code in
Assembly.
All I came up so far was this (http://dc0d32.blogspot.in/2010/06/real- ... iting.html).
I tried the first example but I couldn't get it working correctly.

Code: Select all

__asm__(".code16gcc\n");
__asm__ ("jmpl  $0, $main\n");
 
#define __NOINLINE  __attribute__((noinline))
#define __REGPARM   __attribute__ ((regparm(3)))
#define __NORETURN  __attribute__((noreturn))

void    __NOINLINE __REGPARM print(const char   *s){
        while(*s){
                __asm__ __volatile__ ("int  $0x10" : : "a"(0x0E00 | *s), "b"(7));
                s++;
        }
}
 
void __NORETURN main(){
    print("woo hoo!\r\n:)");
    while(1);
}
First error occours at

Code: Select all

__asm__ ("jmpl  $0, $main\n");
//Error: bootloader.o:bootloader.c:(.text+0x2): undefined reference to 'main'
while using the linker.

I was able to fix that by changing "main" to "_main" cause I read somewhere that in the process of building function's names get prefixed
with a "_" (Is that right?). After this everything ran without any troubles, but if I run it in Virtual Box nothing is displayed on screen.
Also of couse I searched the first on the internet and added a return call to it, but that didn't solve the problem either.

Btw: I use DJGPP on Windows XP x86 for compiling my code
User avatar
sortie
Member
Member
Posts: 931
Joined: Wed Mar 21, 2012 3:01 pm
Libera.chat IRC: sortie

Re: Need help with C bootloader

Post by sortie »

Your endeavour here seems fairly crazy and pointless to me. The whole point of a bootloader is getting C code running. It doesn't take that much assembly code to load a kernel, switch to 32-bit mode and jump to the kernel. Besides, if you are interesting in C you shouldn't be writing a bootloader but use an existing bootloader such as GRUB. There's not that much interesting going on in bootloaders besides dealing with how modern hardware is compatible with designs made by idiots and working around hardware bugs. Though, using an existing bootloader like GRUB may not be practical for you since you use obsolete tools (DJGPP) on an obsolete operating system (Windows XP). I get the feeling that what you are building is a fragile hack and that making it work reliably is more work than just writing a bootloader carefully in assembly. Mind that some bootloaders like GRUB internally use C code, they do this by compiling it as a small 32-bit operating system that is loaded into memory and the core bootloader switches to 32-bit mode to execute it. When the 32-bit C bootloader wants to do BIOS calls it swiches back to 16-bit mode. This is do-able in a bootloader as it hasn't taken over the hardware fully yet, but it's a very poor design for a real operating system as it should personally control the firmware instead of battling with the firmware for control over it.

C symbols are prefixed with a single underscores on some obsolete Unix platforms using a.out as the executable format and usually as well on Windows. Modern Unix operating systems follow the System V ABI and don't have a leading underscore as there is no need for it.
User avatar
neon
Member
Member
Posts: 1567
Joined: Sun Feb 18, 2007 7:28 pm
Contact:

Re: Need help with C bootloader

Post by neon »

Hello,

I never understood what the difficulty of writing boot programs in C is. It really is not hard and not much different then any other operating system service. There is a common error made however; the boot record is not a boot loader. The boot record should be written in assembly however through some hacks it can be written with some ancient compilers that support 16 bit binary output.

The boot loader itself can be written in C with ease. You have a few options here depending on firmware and design,

1. With EFI Firmware, you can boot directly into a C boot loader and skip the boot record and real mode stages altogether. This is by far the simplest method; the OSDev Wiki has a good article on EFI.

2. With BIOS Firmware, you have a few options. You just need an assembly language stub to set up the C environment and jump to the actual C boot loader. You need to decide on design structure here; the C boot loader portion must be able to call the BIOS services directly and be able to fall back to real mode as needed in order to chain load other boot records. For example, if the C boot loader runs in 32 bit protected mode, you must support either v8086 mode or dropping down to real mode to call the BIOS [this is the method I use.] If the C boot loader is compiled as 16 bit real mode code instead, you can call it directly [not recommended though due to real mode limitations.]

Build a single boot image containing both your assembly stub program and the C boot loader and have the boot record load and execute the boot image. The stub program must set up the environment and copy over the C boot loader part of the boot image to where it should be ran in memory and calls its entry point. This method can be extended in multiple loading stages to support boot images of any size.

There are many different ways and possible designs you can come up with, but it really is not that hard. I can provide more information on my specific design if interested, but I encourage you to look farther into the requirements and try to find one that works best for your design goals and needs. I also encourage looking into other C boot loaders that are open source to get some more insight - but take note that there is no best design; it is whatever that is best for your needs and most compatible with your build environment.

Finally, I highly advise knowing how to use your tools correctly. If you ever come across a compiler or linker error that you cannot resolve, you are not yet ready for this task. Sorry, but its just how it is; those are basic errors.
The whole point of a bootloader is getting C code running
No. The point of a boot loader is, as its name implies, getting an operating system loaded properly into memory and transferring control. C boot loaders provide all the benefits of high level languages over assembly language : through good design one can achieve firmware independence and hardware independence and extensability; they can effectively be their own little operating system themselves. Many boot loaders also act as boot managers to allow chain loading other boot applications or operating systems.
OS Development Series | Wiki | os | ncc
char c[2]={"\x90\xC3"};int main(){void(*f)()=(void(__cdecl*)(void))(void*)&c;f();}
ByteBit
Posts: 6
Joined: Mon Jun 16, 2014 2:40 pm

Re: Need help with C bootloader

Post by ByteBit »

Ok. Today I gave VectorLinux a try and build the code it on that system. Everything worked well :D
It just seems to be a mistake of the compiler. Thanks for your help.

@sortie: The system with WinXp on it is my secoundary system. Normally I use my Win7 pc.
Post Reply