mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
[boot] Don't double-load read-only program data
The bootloader's load_program was reproducing all loadable program header sections into new pages. Now only do that for sections containing BSS sections (eg, where file size and mem size do not match).
This commit is contained in:
@@ -57,36 +57,24 @@ load_program(
|
|||||||
buffer data)
|
buffer data)
|
||||||
{
|
{
|
||||||
status_line status(L"Loading program:", name);
|
status_line status(L"Loading program:", name);
|
||||||
|
|
||||||
const elf::header *header = reinterpret_cast<const elf::header*>(data.pointer);
|
const elf::header *header = reinterpret_cast<const elf::header*>(data.pointer);
|
||||||
|
uintptr_t program_base = reinterpret_cast<uintptr_t>(data.pointer);
|
||||||
|
|
||||||
if (data.count < sizeof(elf::header) || !is_elfheader_valid(header))
|
if (data.count < sizeof(elf::header) || !is_elfheader_valid(header))
|
||||||
error::raise(uefi::status::load_error, L"ELF file not valid");
|
error::raise(uefi::status::load_error, L"ELF file not valid");
|
||||||
|
|
||||||
size_t num_sections = 0;
|
size_t num_sections = 0;
|
||||||
uintptr_t prog_base = uintptr_t(-1);
|
|
||||||
uintptr_t prog_end = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < header->ph_num; ++i) {
|
for (int i = 0; i < header->ph_num; ++i) {
|
||||||
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
|
ptrdiff_t offset = header->ph_offset + i * header->ph_entsize;
|
||||||
const elf::program_header *pheader =
|
const elf::program_header *pheader =
|
||||||
offset_ptr<elf::program_header>(data.pointer, offset);
|
offset_ptr<elf::program_header>(data.pointer, offset);
|
||||||
|
|
||||||
if (pheader->type != elf::PT_LOAD)
|
if (pheader->type == elf::PT_LOAD)
|
||||||
continue;
|
++num_sections;
|
||||||
|
|
||||||
++num_sections;
|
|
||||||
uintptr_t end = pheader->vaddr + pheader->mem_size;
|
|
||||||
if (pheader->vaddr < prog_base) prog_base = pheader->vaddr;
|
|
||||||
if (end > prog_end) prog_end = end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init::program_section *sections = new init::program_section [num_sections];
|
init::program_section *sections = new init::program_section [num_sections];
|
||||||
program.sections = { .pointer = sections, .count = num_sections };
|
|
||||||
|
|
||||||
size_t total_size = prog_end - prog_base;
|
|
||||||
size_t num_pages = memory::bytes_to_pages(total_size);
|
|
||||||
void *pages = g_alloc.allocate_pages(num_pages, alloc_type::program, true);
|
|
||||||
program.phys_base = reinterpret_cast<uintptr_t>(pages);
|
|
||||||
|
|
||||||
size_t next_section = 0;
|
size_t next_section = 0;
|
||||||
for (int i = 0; i < header->ph_num; ++i) {
|
for (int i = 0; i < header->ph_num; ++i) {
|
||||||
@@ -97,18 +85,26 @@ load_program(
|
|||||||
if (pheader->type != elf::PT_LOAD)
|
if (pheader->type != elf::PT_LOAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
init::program_section §ion = program.sections[next_section++];
|
init::program_section §ion = sections[next_section++];
|
||||||
|
|
||||||
void *src_start = offset_ptr<void>(data.pointer, pheader->offset);
|
size_t page_count = memory::bytes_to_pages(pheader->mem_size);
|
||||||
void *dest_start = offset_ptr<void>(pages, pheader->vaddr - prog_base);
|
|
||||||
|
if (pheader->mem_size > pheader->file_size) {
|
||||||
|
void *pages = g_alloc.allocate_pages(page_count, alloc_type::program, true);
|
||||||
|
void *source = offset_ptr<void>(data.pointer, pheader->offset);
|
||||||
|
g_alloc.copy(pages, source, pheader->file_size);
|
||||||
|
section.phys_addr = reinterpret_cast<uintptr_t>(pages);
|
||||||
|
} else {
|
||||||
|
section.phys_addr = program_base + pheader->offset;
|
||||||
|
}
|
||||||
|
|
||||||
g_alloc.copy(dest_start, src_start, pheader->file_size);
|
|
||||||
section.phys_addr = reinterpret_cast<uintptr_t>(dest_start);
|
|
||||||
section.virt_addr = pheader->vaddr;
|
section.virt_addr = pheader->vaddr;
|
||||||
section.size = pheader->mem_size;
|
section.size = pheader->mem_size;
|
||||||
section.type = static_cast<init::section_flags>(pheader->flags);
|
section.type = static_cast<init::section_flags>(pheader->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
program.sections = { .pointer = sections, .count = num_sections };
|
||||||
|
program.phys_base = program_base;
|
||||||
program.entrypoint = header->entrypoint;
|
program.entrypoint = header->entrypoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,6 +128,12 @@ verify_kernel_header(init::program &program)
|
|||||||
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
console::print(L" Loaded kernel vserion: %d.%d.%d %x\r\n",
|
||||||
header->version_major, header->version_minor, header->version_patch,
|
header->version_major, header->version_minor, header->version_patch,
|
||||||
header->version_gitsha);
|
header->version_gitsha);
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (auto §ion : program.sections)
|
||||||
|
console::print(L" Section: p:0x%lx v:0x%lx fs:0x%x ms:0x%x\r\n",
|
||||||
|
section.phys_addr, section.virt_addr, section.file_size, section.mem_size);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace loader
|
} // namespace loader
|
||||||
|
|||||||
@@ -256,17 +256,14 @@ map_section(
|
|||||||
{
|
{
|
||||||
using kernel::init::section_flags;
|
using kernel::init::section_flags;
|
||||||
|
|
||||||
size_t pages = memory::bytes_to_pages(section.size);
|
|
||||||
|
|
||||||
map_pages(
|
map_pages(
|
||||||
args,
|
args,
|
||||||
section.phys_addr,
|
section.phys_addr,
|
||||||
section.virt_addr,
|
section.virt_addr,
|
||||||
pages,
|
memory::bytes_to_pages(section.size),
|
||||||
has_flag(section.type, section_flags::write),
|
has_flag(section.type, section_flags::write),
|
||||||
has_flag(section.type, section_flags::execute));
|
has_flag(section.type, section_flags::execute));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} // namespace paging
|
} // namespace paging
|
||||||
} // namespace boot
|
} // namespace boot
|
||||||
|
|||||||
@@ -184,7 +184,6 @@ log_mtrrs()
|
|||||||
process *
|
process *
|
||||||
load_simple_process(init::program &program)
|
load_simple_process(init::program &program)
|
||||||
{
|
{
|
||||||
|
|
||||||
process *p = new process;
|
process *p = new process;
|
||||||
vm_space &space = p->space();
|
vm_space &space = p->space();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user