feat(modules): now it loads segments with correct rights, not RWX everywhere

This commit is contained in:
karina
2026-05-03 18:30:49 +04:00
parent bedb03fc37
commit fb55cb1b9a
6 changed files with 97 additions and 55 deletions
+48 -44
View File
@@ -183,49 +183,10 @@ static efi_status_t load_modules(efi_file_handle_t* root, Bootinfo* boot_info) {
Elf64_Ehdr* mod_elf = (Elf64_Ehdr*)module_addr;
Elf64_Phdr* phdrs = (Elf64_Phdr*)(module_addr + mod_elf->e_phoff);
uint64_t min_vaddr = (uint64_t)-1;
uint64_t max_vaddr = 0;
for (int i = 0; i < mod_elf->e_phnum; i++) {
if (phdrs[i].p_type == PT_LOAD) {
if (phdrs[i].p_vaddr < min_vaddr) min_vaddr = phdrs[i].p_vaddr;
uint64_t end = phdrs[i].p_vaddr + phdrs[i].p_memsz;
if (end > max_vaddr) max_vaddr = end;
}
}
min_vaddr &= ~0xFFFULL;
max_vaddr = (max_vaddr + 0xFFFULL) & ~0xFFFULL;
uint64_t total_vsize = max_vaddr - min_vaddr;
uintn_t final_pages = total_vsize / PAGE_SIZE;
efi_physical_address_t final_phys = 0;
status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, final_pages, &final_phys);
if (EFI_ERROR(status)) {
gBS->FreePages(module_addr, pages);
continue;
}
memset((void*)final_phys, 0, total_vsize);
for (int i = 0; i < mod_elf->e_phnum; i++) {
if (phdrs[i].p_type == PT_LOAD && phdrs[i].p_filesz > 0) {
void* dest = (void*)(final_phys + (phdrs[i].p_vaddr - min_vaddr));
void* src = (void*)(module_addr + phdrs[i].p_offset);
uint8_t* d = dest;
uint8_t* s = src;
for (uintn_t j = 0; j < phdrs[i].p_filesz; j++) d[j] = s[j];
}
}
BootModule* mod = &boot_info->modules[boot_info->moduleCount];
mod->physicalBase = final_phys;
mod->virtualBase = min_vaddr;
mod->size = total_vsize;
mod->entry = (void*)mod_elf->e_entry;
mod->capabilities = 0;
mod->segmentCount = 0;
for (int i = 0; i < 31; i++) {
wchar_t wc = entry->FileName[i];
@@ -234,11 +195,54 @@ static efi_status_t load_modules(efi_file_handle_t* root, Bootinfo* boot_info) {
}
mod->name[31] = '\0';
print(WSTR(" [MODULE] "));
print(entry->FileName);
print(WSTR("\r\n"));
int alloc_failed = 0;
boot_info->moduleCount++;
for (int i = 0; i < mod_elf->e_phnum && mod->segmentCount < BOOT_MODULE_MAX_SEGMENTS; i++) {
if (phdrs[i].p_type != PT_LOAD) continue;
uint64_t vaddr_page = phdrs[i].p_vaddr & ~0xFFFULL;
uint64_t offset_in_page = phdrs[i].p_vaddr & 0xFFFULL;
uint64_t total_size = offset_in_page + phdrs[i].p_memsz;
uint64_t aligned_size = (total_size + 0xFFFULL) & ~0xFFFULL;
uintn_t seg_pages = aligned_size / PAGE_SIZE;
efi_physical_address_t seg_phys = 0;
status = gBS->AllocatePages(AllocateAnyPages, EfiLoaderData, seg_pages, &seg_phys);
if (EFI_ERROR(status)) {
alloc_failed = 1;
break;
}
memset((void*)seg_phys, 0, aligned_size);
if (phdrs[i].p_filesz > 0) {
uint8_t* dest = (uint8_t*)(seg_phys + offset_in_page);
uint8_t* src = (uint8_t*)(module_addr + phdrs[i].p_offset);
for (uintn_t j = 0; j < phdrs[i].p_filesz; j++) dest[j] = src[j];
}
BootModuleSegment* seg = &mod->segments[mod->segmentCount];
seg->physicalBase = seg_phys;
seg->virtualBase = vaddr_page;
seg->size = aligned_size;
seg->flags = phdrs[i].p_flags;
mod->segmentCount++;
}
if (alloc_failed) {
for (int i = 0; i < (int)mod->segmentCount; i++) {
uint64_t sz = mod->segments[i].size;
uintn_t pg = sz / PAGE_SIZE;
gBS->FreePages(mod->segments[i].physicalBase, pg);
}
} else {
print(WSTR(" [MODULE] "));
print(entry->FileName);
print(WSTR("\r\n"));
boot_info->moduleCount++;
}
}
gBS->FreePages(module_addr, pages);