#include "elf.h" extern void* memset(void* dest, int ch, uptr count); extern void* memcpy(void* dest, const void* src, uptr count); [[noreturn]] void ElfExecute(void* Binary, void* LoadAddr, struct boot_params* BootParams) { struct Elf64_Ehdr* ElfHeader = (struct Elf64_Ehdr*)Binary; // Here we would check if we have a valid elf binary // unfortunately, we would have no way to notify the // user, so we'll just pray it is // Hopefully we have progtam headers void* ProgramHeaders = Binary + ElfHeader->e_phoff; // Load everything into memory for (int i = 0; i < ElfHeader->e_phnum; i++) { struct Elf64_Phdr* ProgramHeader = (struct Elf64_Phdr*)ProgramHeaders; // Only load loadable segments if (ProgramHeader->p_type == PT_LOAD) { void* FileStart = Binary + ProgramHeader->p_offset; void* LoadStart = LoadAddr + ProgramHeader->p_vaddr; uptr LoadSize = ProgramHeader->p_memsz; if (LoadSize > ProgramHeader->p_filesz) LoadSize = ProgramHeader->p_filesz; memset(LoadStart, 0, ProgramHeader->p_memsz); memcpy(LoadStart, FileStart, LoadSize); } ProgramHeaders += ElfHeader->e_phentsize; } // Dynamically link ourself void* SectionHeaders = Binary + ElfHeader->e_shoff; for (int i = 0; i < ElfHeader->e_shnum; i++) { struct Elf64_Shdr* SectionHeader = (struct Elf64_Shdr*)SectionHeaders; // Find RELA segments if (SectionHeader->sh_type == SHT_RELA) { struct Elf64_Shdr* SymbolTable = (struct Elf64_Shdr*)(Binary + ElfHeader->e_shoff + ElfHeader->e_shentsize * SectionHeader->sh_link); void* RelocTab = Binary + SectionHeader->sh_offset; void* SymblTab = Binary + SymbolTable->sh_offset; for (int RelocOffset = 0; RelocOffset < SectionHeader->sh_size; RelocOffset += SectionHeader->sh_entsize) { struct Elf64_Rela* Reloc = RelocTab + RelocOffset; [[maybe_unused]] struct Elf64_Sym* Symbol = SymblTab + SymbolTable->sh_entsize * ELF64_R_SYM(Reloc->r_info); void* Target = LoadAddr + Reloc->r_offset; switch (ELF64_R_TYPE(Reloc->r_info)) { case ELF64_R_AMD64_RELATIVE: { *((u64*)Target) = (u64)(LoadAddr + Reloc->r_addend); break; } default: { while (1) {} } } } } SectionHeaders += ElfHeader->e_shentsize; } // Collect entry point [[noreturn]] void fake_dont_call(struct boot_params*); // stupid hack typeof(fake_dont_call)* KernelEntry = LoadAddr + ElfHeader->e_entry; // Set boot parameters struct setup_info* SetupInfo = (void*)BootParams + 0x1f1; SetupInfo->code32_start = (u64)LoadAddr; // Enter the kernel KernelEntry(BootParams); // we shouldnt ever end up here __builtin_unreachable(); }