-
Notifications
You must be signed in to change notification settings - Fork 3
Initor
The Initor
module is responsible for setting up the kernel environment before the main kernel's HostEntry
entry point is called. It uses the multiboot information table passed by the (unknown multiboot-compliant) bootloader, to locate the module files, and then calculate how much memory the kernel requires to start up. Based on that information, it finds a suitable continuous chunk of physical memory, solely for other kernel module segments, symbol tables, strings, and hash-tables. In that chunk, the module segments are loaded, they are relocated to the appropriate KERNEL_OFFSET
(virtual-address).
The Initor module calculates how much memory the kernel environment will require based on the following information:
-
It will add up the total memory image size of all kernel modules - based on the farthest address used in the kernel module to hold text or data. Each module is given 4-KB spacing to protect against any minor errors.
-
During init-time, the Initor module holds a global symbol table, which centrally holds all symbolic definitions, of all modules. This also prevents duplicate symbols from being linked separately (in C++ two weak symbols may be present in different modules, but the linker should choose only one).
-
A array of
KernelSymbol*
buckets is kept, to make a hash-table. This is not generally used by other kernel-modules after init-time, because of theModuleLoader
subsystem in theKernelHost
, which then stores the symbol tables on its own later. -
For the symbol tables, all string tables are copied into the kernel environment chunk. An array of
char*
pointers is kept at the beginning, to hold pointers to string tables of the modules by theirorderIndex
. So, the Initor module accesses symbol names in this part of the environment memory. -
A array of
struct KernelModule
objects is kept holding information about each kernel-module including the physical-base address, virtual-base address, symbol table, string table, etc. -
The KernelHost (or main) module requires space for page-tables and a stack - so a AUTO_DAT memory buffer is also provided at the end - of size 32-KB which can be changed.
Although, the kernel-environment, as described above has enough information to easily load and relocate the kernel modules, the KernelHost requires support from the Initor module - to get a table of page-frame entries located at a 2-MB aligned address. So, at the closest 2-MB aligned address of the kernel-environment, the Initor module also allocates a MM_FRAME array - whose size is equal to the number of page-frames in physical memory.
Although the Initor module could know that HostEntry
is the entry of the KernelHost, it rather uses the ELF file of the first module to get the entry point of the kernel. As the KernelHost is listed as the first module in the grub.cfg
configuration file - the entry point of the KernelHost is called.
The Initor module passes arguments to the entry point of the main-module. It must be capable of using those arguments, to locate data structure, especially the AUTO_DAT buffer provided for allocating a new stack, and then copying those argument into the new stack.
unsigned (*callMain)(unsigned long multibootTable, unsigned long kernelBase, unsigned long kernelSize, struct KernelSymbol *globalSymbolTable, unsigned long globalSymbolCount, char **physStrtabByIndex, struct KernelSymbol **symbolBuckets, struct KernelModule *modInfoObjs);
Parameters:
-
unsigned long multibootTable
- The physical address of the multiboot information table passed by the bootloader. This is usually unmodified. -
unsigned long kernelBase
- The physical address where the kernel environment has been loaded. The preferred address on the iA-PC architecture is the 16-MB mark above DMA memory. It can be anywhere - but is 99% 2-MB aligned (unless on low-memory devices where 2-MB aligning is impossible). -
unsigned long kernelSize
- The size of the kernel environment. This doesn't include the page-frame entries at the next 2-MB aligned address after the end of the kernel-environment (which iskernelBase + kernelSize
). Their address can be calculated easily - and their size is equal to the no. of page-frames in physical memory into the size of each page-frame entry - (seesizeof_mmframe
in the page-frame allocator's header file). -
struct KernelSymbol *globalSymbolTable
- The physical address where theInitor
module kept theKernelSymbol
objects holding values and pointers to the symbol names (in physical memory). -
unsigned long globalSymbolCount
- The total no. of entries present in the symbol table passed as argument 4. -
char **physStrtabByIndex
- TheInitor
module copies the string tables after this array. This array (having as many entries as the number of kernel-modules loaded by the bootloader) holds the pointers to the string tables (in physical memory) of each kernel-module. -
struct KernelSymbol **symbolBuckets
- The KernelHost doesn't use this - but still, it holds any array ofKernelSymbol *
pointers as buckets of an hash-table. Note that the no. of buckets is equal to the global symbol count. -
struct KernelModule *modInfoObjs
- An array ofstruct KernelModule
object holding information about each module. The count of modules is available in the multiboot-information table.
The booting process of the Silcos kernel is quite generic - you'll have to name your "main" module (the one which will get control first) the "KernelHost" (or modify the code in the Initor) in the grub.cfg
file. The multiboot information table will hold a entry for this module, whose first 10 letters should be "KernelHost" which identifies it as the "main" module.
The Initor
module uses a few headers like <Multiboot2.h>
, and some in Utils
. Import these in your kernel, so that the Initor can use them.
**Big fat note on C & C++ inter-usage in code: ** The Silcos Initor uses the _CBUILD
macro before including headers to inform you that it is a C file. If your kernel is built in C, either remove the C++ parts of the headers, or simply add a #define _CBUILD
at the first of all your C files.