#include #include #include "loader.h" #include "console.h" #include "elf.h" #include "error.h" #include "fs.h" #include "memory.h" #include "paging.h" #include "status.h" namespace args = kernel::args; namespace boot { namespace loader { buffer load_file( fs::file &disk, const wchar_t *name, const wchar_t *path, uefi::memory_type type) { status_line status(L"Loading file", name); fs::file file = disk.open(path); buffer b = file.load(type); console::print(L" Loaded at: 0x%lx, %d bytes\r\n", b.data, b.size); return b; } static bool is_elfheader_valid(const elf::header *header) { return header->magic[0] == 0x7f && header->magic[1] == 'E' && header->magic[2] == 'L' && header->magic[3] == 'F' && header->word_size == elf::word_size && header->endianness == elf::endianness && header->os_abi == elf::os_abi && header->machine == elf::machine && header->header_version == elf::version; } void load_program( args::program &program, const wchar_t *name, buffer data, uefi::boot_services *bs) { status_line status(L"Loading program:", name); const elf::header *header = reinterpret_cast(data.data); if (data.size < sizeof(elf::header) || !is_elfheader_valid(header)) error::raise(uefi::status::load_error, L"ELF file not valid"); uintptr_t prog_base = uintptr_t(-1); uintptr_t prog_end = 0; for (int i = 0; i < header->ph_num; ++i) { ptrdiff_t offset = header->ph_offset + i * header->ph_entsize; const elf::program_header *pheader = offset_ptr(data.data, offset); if (pheader->type != elf::PT_LOAD) continue; uintptr_t end = pheader->vaddr + pheader->mem_size; if (pheader->vaddr < prog_base) prog_base = pheader->vaddr; if (end > prog_end) prog_end = end; } size_t total_size = prog_end - prog_base; size_t num_pages = memory::bytes_to_pages(total_size); void *pages = nullptr; try_or_raise( bs->allocate_pages(uefi::allocate_type::any_pages, memory::program_type, num_pages, &pages), L"Failed allocating space for program"); bs->set_mem(pages, total_size, 0); for (int i = 0; i < header->ph_num; ++i) { ptrdiff_t offset = header->ph_offset + i * header->ph_entsize; const elf::program_header *pheader = offset_ptr(data.data, offset); if (pheader->type != elf::PT_LOAD) continue; void *src_start = offset_ptr(data.data, pheader->offset); void *dest_start = offset_ptr(pages, pheader->vaddr - prog_base); bs->copy_mem(dest_start, src_start, pheader->file_size); } program.phys_addr = reinterpret_cast(pages); program.size = total_size; program.virt_addr = prog_base; program.entrypoint = header->entrypoint; } } // namespace loader } // namespace boot