diff --git a/nel_os_bootloader/src/main.rs b/nel_os_bootloader/src/main.rs index 6ad5a23..5a93fb4 100644 --- a/nel_os_bootloader/src/main.rs +++ b/nel_os_bootloader/src/main.rs @@ -4,11 +4,11 @@ extern crate alloc; use alloc::{boxed::Box, vec}; -use core::arch::asm; -use goblin::elf; +use core::{arch::asm, slice}; +use goblin::elf::{self, Elf}; use uefi::{ allocator::Allocator, - boot::{MemoryType, ScopedProtocol}, + boot::{AllocateType, MemoryType, ScopedProtocol}, mem::memory_map::MemoryMap, prelude::*, println, @@ -56,6 +56,48 @@ fn read_kernel(name: &CStr16) -> Box<[u8]> { buf.into_boxed_slice() } +fn load_elf(bin: Box<[u8]>) -> u64 { + let elf = elf::Elf::parse(&bin).expect("Failed to parse elf"); + let mut dest_start = u64::MAX; + let mut dest_end = 0u64; + + elf.program_headers + .iter() + .filter(|header| header.p_type == elf::program_header::PT_LOAD) + .for_each(|header| { + dest_start = dest_start.min(header.p_vaddr); + dest_end = dest_end.max(header.p_vaddr + header.p_memsz); + }); + + uefi::boot::allocate_pages( + AllocateType::Address(dest_start), + MemoryType::LOADER_DATA, + dest_end + .checked_sub(dest_start) + .and_then(|size| size.checked_add(4095)) + .map(|size| size / 4096) + .unwrap_or(0) as usize, + ) + .expect("Failed to allocate pages"); + + elf.program_headers + .iter() + .filter(|header| header.p_type == elf::program_header::PT_LOAD) + .for_each(|header| { + let dest = unsafe { + slice::from_raw_parts_mut(header.p_vaddr as *mut u8, header.p_memsz as usize) + }; + + let file_size = header.p_filesz as usize; + let offset = header.p_offset as usize; + + dest[..file_size].copy_from_slice(&bin[offset..offset + file_size]); + dest[file_size..].fill(0); + }); + + elf.entry +} + #[entry] fn main() -> Status { uefi::helpers::init().unwrap(); @@ -78,13 +120,17 @@ fn main() -> Status { let kernel = read_kernel(cstr16!("nel_os_kernel.elf")); - let elf = elf::Elf::parse(&kernel).expect("Failed to parse kernel"); + let entry_point = load_elf(kernel); - println!("Entry point: {}", elf.entry); + println!("Entry point: {:#x}", entry_point); + + let entry: extern "sysv64" fn() = unsafe { core::mem::transmute(entry_point) }; unsafe { let _ = uefi::boot::exit_boot_services(Some(MemoryType::LOADER_DATA)); } + entry(); + hlt_loop(); } diff --git a/nel_os_kernel/x86_64-nel_os.json b/nel_os_kernel/x86_64-nel_os.json index 4879c24..1261f66 100644 --- a/nel_os_kernel/x86_64-nel_os.json +++ b/nel_os_kernel/x86_64-nel_os.json @@ -15,5 +15,13 @@ "features": "-mmx,-sse,+soft-float", "rustc-abi": "x86-softfloat", "code-model": "kernel", - "max-atomic-width": 64 + "max-atomic-width": 64, + "position-independent-executables": false, + "post-link-args": { + "ld.lld": [ + "--entry=asm_main", + "--image-base=0x100000", + "--static" + ] + } }