Difference between revisions of "Kernel Loader"
(Add KInitialPageAllocator member funcs) |
|||
Line 57: | Line 57: | ||
<pre> | <pre> | ||
this->next_address = 0; | this->next_address = 0; | ||
+ | </pre> | ||
+ | |||
+ | == KInitialPageAllocator::Initialize == | ||
+ | This sets the allocator's next address (function inferred as it is (presumably) inlined and next_address is (presumably) private). | ||
+ | |||
+ | <pre> | ||
+ | this->next_address = address; | ||
+ | </pre> | ||
+ | |||
+ | == KInitialPageAllocator::Allocate == | ||
+ | This linearly allocates a page. | ||
+ | |||
+ | <pre> | ||
+ | virtual void *KInitialPageAllocator::Allocate() { | ||
+ | void *address = reinterpret_cast<void *>(this->next_address); | ||
+ | if (address == nullptr) { | ||
+ | // If called on uninitialized allocator, panic by infinite looping | ||
+ | while (true) {} | ||
+ | } | ||
+ | this->next_address += 0x1000; | ||
+ | memset(address, 0, 0x1000); | ||
+ | return address; | ||
+ | } | ||
+ | </pre> | ||
+ | |||
+ | == KInitialPageAllocator::Free == | ||
+ | This frees a page (implemented as noop in KernelLoader) | ||
+ | |||
+ | <pre> | ||
+ | virtual void KInitialPageAllocator::Free(void *address) { | ||
+ | // Does Nothing | ||
+ | } | ||
</pre> | </pre> | ||
Revision as of 04:18, 31 August 2019
The Kernel Loader ("KernelLdr"/"Kernelldr") was added in 8.0.0. It is responsible for applying relocations to the Kernel, and mapping the Kernel's .text/.rodata/.data/.bss at a random slide.
Kernel Loader
KernelLdr is called immediately by the Kernel's crt0 (after it deprivileges from EL2 to EL1, if required), with the following signature:
void KernelLoader_Main(uintptr_t kernel_base_address, KernelMap *kernel_map, uintptr_t ini1_base_address);
KernelLdr_Main
First, it clears BSS, and then sets SP = <BSS end>.
for (uint64_t *i = __bss_start; i != __bss_end; i++) { *i = 0; } SP = __bss_end;
Next, it applies relocations to itself and calls its init array.
KernelLdr_ApplyRelocations(&KernelLdr_Main, __dynamic_start); KernelLdr_libc_init_array();
Then, it calls the function which relocates the kernel, and jumps back to the kernel entrypoint.
// KernelLdr_LoadKernel returns (relocated_kernel_base - original_kernel_base). uintptr_t kernel_relocation_offset = KernelLdr_LoadKernel(kernel_base, kernel_map, ini_base); // dtor called for static page allocator. g_InitialPageAllocator.~KInitialPageAllocator(); // Jumps back to the kernel code that called KernelLdr_Main. ((void (*)(void))(kernel_relocation_offset + LR))();
KernelLdr_ApplyRelocations
TODO: Fill this out
KernelLdr_lib_init_array()
This is just standard libc init array code. .init_array is empty in all available binaries.
KernelLdr_LoadKernel
TODO: Fill this out
KInitialPageAllocator::KInitialPageAllocator
This sets the allocator's next address to 0 (guessed, since this is done statically in KernelLoader).
constexpr KInitialPageAllocator::KInitialPageAllocator : next_address(0) {}
KInitialPageAllocator::~KInitialPageAllocator
This just clears the allocator's next address.
this->next_address = 0;
KInitialPageAllocator::Initialize
This sets the allocator's next address (function inferred as it is (presumably) inlined and next_address is (presumably) private).
this->next_address = address;
KInitialPageAllocator::Allocate
This linearly allocates a page.
virtual void *KInitialPageAllocator::Allocate() { void *address = reinterpret_cast<void *>(this->next_address); if (address == nullptr) { // If called on uninitialized allocator, panic by infinite looping while (true) {} } this->next_address += 0x1000; memset(address, 0, 0x1000); return address; }
KInitialPageAllocator::Free
This frees a page (implemented as noop in KernelLoader)
virtual void KInitialPageAllocator::Free(void *address) { // Does Nothing }
Structures
KernelMap
Offset | Size | Description |
---|---|---|
0x0 | 4 | .text offset |
0x4 | 4 | .text end offset |
0x8 | 4 | .rodata end offset |
0xC | 4 | .rodata end offset |
0x10 | 4 | .rwdata offset |
0x14 | 4 | .rwdata end offset |
0x18 | 4 | .bss offset |
0x1C | 4 | .bss end offset |
0x20 | 4 | INI1 load offset |
0x24 | 4 | .dynamic end offset |
0x28 | 4 | .init_array end offset |
0x2C | 4 | .init_array end offset |
KInitialPageAllocator
KInitialPageAllocator is just a simple linear allocator.
Offset | Size | Description |
---|---|---|
0x0 | 8 | vtable; |
0x8 | 8 | Next Address; |
KInitialPageAllocator::vtable
Offset | Size | Description |
---|---|---|
0x0 | 8 | void *(*Allocate)(KInitialPageAllocator *this); |
0x8 | 8 | void (*Free)(KInitialPageAllocator *this, void *address); |