feat(modules): now it loads segments with correct rights, not RWX everywhere
This commit is contained in:
+48
-44
@@ -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);
|
||||
|
||||
@@ -32,4 +32,8 @@ typedef struct {
|
||||
uint64_t p_align;
|
||||
} Elf64_Phdr;
|
||||
|
||||
#define PT_LOAD 1
|
||||
#define PT_LOAD 1
|
||||
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
Reference in New Issue
Block a user