Hello, Users!
Currently I am writing my own bootloader. And I was thinking what is the best way to pass through information from the bootloader to the kernel. I have a multiple stage bootloader the first stage searches the second stage by a fat12 specification and the second stage sets everything up and then it loads the kernel also by a fat12 specification. However I would like to pass on some information from my bootloader to my kernel? What would be the best way to do this? I thought maybe reserve a memory address and store the information there so that the kernel can also access it and read it out. Or is it somehow possible to pass a parameter to the kernel like grub does?
-Tera4D
Passing settings
Re: Passing settings
Hi,
There are a few ways to do this - here are my thoughts on each. I don't know what language you have used for your kernel, but I'll assume C/C++ because that's what I'm familiar with.
1. Fixed address (e.g. 0x1000) - simple to implement but makes the assumption that memory at 0x1000 (or whatever) is free, when you should be allocating dynamically from the BIOS System Memory Map.
2. Pass by register (a la GRUB) - if in long mode, do this in RDI and your compiler (which follows the System V ABI) will just pick up the value as the first function parameter without troubling the stack. In 32 bit mode, you will need a specialist assembly stub to set up a stack and store / pass the function for your C code.
3. Pass by stack or your compiler's usual calling convention (my preferred option). My second stage loader for CBoot always set up a stack for the kernel and passed the usual argc / argv combination. This meant that the kernel's main function looked just like an application's main function - but the whole thing needed a bit more setting up. One of the nice, clean things about this is that you do not need a statically linked assembly stub.
Whatever you do, use a magic number and / or checksum so that the kernel can verify it has been booted by your loader.
Cheers,
Adam
There are a few ways to do this - here are my thoughts on each. I don't know what language you have used for your kernel, but I'll assume C/C++ because that's what I'm familiar with.
1. Fixed address (e.g. 0x1000) - simple to implement but makes the assumption that memory at 0x1000 (or whatever) is free, when you should be allocating dynamically from the BIOS System Memory Map.
2. Pass by register (a la GRUB) - if in long mode, do this in RDI and your compiler (which follows the System V ABI) will just pick up the value as the first function parameter without troubling the stack. In 32 bit mode, you will need a specialist assembly stub to set up a stack and store / pass the function for your C code.
3. Pass by stack or your compiler's usual calling convention (my preferred option). My second stage loader for CBoot always set up a stack for the kernel and passed the usual argc / argv combination. This meant that the kernel's main function looked just like an application's main function - but the whole thing needed a bit more setting up. One of the nice, clean things about this is that you do not need a statically linked assembly stub.
Whatever you do, use a magic number and / or checksum so that the kernel can verify it has been booted by your loader.
Cheers,
Adam
Re: Passing settings
Thank you for your fast response Adam.
You are right my kernel is going to be written in C (I actually have not started a kernel yet)
I made some simple kernels which only display a message for testing.
But with a magic number you mean first I write a number (0xAFFAAFFA for example) to the adress space (0x1000 for example) and then in my kernel ill verify that it actually is 0xAFFAAFFA and then read on?
But if doing this wouldnt it be better like lets say. Create a configure program which loads this and then jumps to the kernel?
-Tera4D
You are right my kernel is going to be written in C (I actually have not started a kernel yet)
I made some simple kernels which only display a message for testing.
But with a magic number you mean first I write a number (0xAFFAAFFA for example) to the adress space (0x1000 for example) and then in my kernel ill verify that it actually is 0xAFFAAFFA and then read on?
But if doing this wouldnt it be better like lets say. Create a configure program which loads this and then jumps to the kernel?
-Tera4D
Re: Passing settings
That's it. You should do this whichever method you use to pass settings.tera4d wrote:But with a magic number you mean first I write a number (0xAFFAAFFA for example) to the adress space (0x1000 for example) and then in my kernel ill verify that it actually is 0xAFFAAFFA and then read on?
Not too sure what you mean here, but let me outline a fairly dynamic system as outlined in point 3 above:But if doing this wouldnt it be better like lets say. Create a configure program which loads this and then jumps to the kernel?
- Stage 1 loader, a boot sector which loads stage 1.5 from the FAT12 disk, passes (in ax, for example) the address of its "readFile" function and then jumps to your second stage.
- Stage 2 loader, a combination of 16 and 32 bit code, written in assembly. This creates a system memory map and then loads the kernel using stage 1's readFile function. The kernel can be loaded above 1 MiB if you keep switching between RMode and PMode. The Stage 2 loader could even contain an ELF relocator if your kernel is in ELF format.
- Stage 2 now sets up paging and an initial stack. It also sets up your information table, with the magic number, address of the memory map and whatever else you like. Because Stage 2 has access to the system memory map, it can do all this in memory which you *know* to be free.
- Push argc (1) and argv (the address of stage 2's information table) and call the kernel entry point.
- The kernel checks that argc == 1 and that *argv == MAGIC_NUMBER. If so, it continues as normal.
Cheers,
Adam
Re: Passing settings
Thank you very much!
You stated it clearly enough for me to understand hahha ^^
You stated it clearly enough for me to understand hahha ^^
Re: Passing settings
Doing it via command line has the additional benefit that users could employ a different bootloader (e.g. GRUB or LILO) with minimum adaption work.
Every good solution is obvious once you've found it.
Re: Passing settings
Thats true, However I dont think that I can pull that off haha.
I'd better stick with something easy as I am not very expirienced with both asm and osdevelopment.
Altough I am learning on the go
I'd better stick with something easy as I am not very expirienced with both asm and osdevelopment.
Altough I am learning on the go
- Love4Boobies
- Member
- Posts: 2111
- Joined: Fri Mar 07, 2008 5:36 pm
- Location: Bucharest, Romania
Re: Passing settings
I see all the usual ways already mentioned. I'll provide links to the Multiboot specifications in case anyone cares:
- Multiboot 1 - using a register to pass the address to a structure
- Multiboot 2 (WIP!) - using a tag-based approach
"Computers in the future may weigh no more than 1.5 tons.", Popular Mechanics (1949)
[ Project UDI ]
[ Project UDI ]