Skip to content

Commit e5187de

Browse files
committed
Read and cache required ELF info at the start
1 parent 306ec4a commit e5187de

File tree

3 files changed

+45
-20
lines changed

3 files changed

+45
-20
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ description = "An experimental pure-Rust x86 bootloader."
77

88
[dependencies]
99
rlibc = "1"
10-
xmas-elf = "0.6.0"
10+
xmas-elf = { git = "https://github.com/phil-opp/xmas-elf.git" }
1111
x86_64 = "0.2.0-alpha-001"
1212
usize_conversions = "0.2.0"
1313
os_bootinfo = "0.2.0-alpha"
1414
spin = "0.4.6"
15+
fixedvec = "0.2.3"
1516

1617
[profile.dev]
1718
panic = "abort"

src/main.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ extern crate x86_64;
1717
extern crate usize_conversions;
1818
extern crate os_bootinfo;
1919
extern crate spin;
20+
#[macro_use]
21+
extern crate fixedvec;
2022

2123
pub use x86_64::PhysAddr;
2224
use x86_64::VirtAddr;
@@ -44,10 +46,32 @@ mod printer;
4446
pub extern "C" fn load_elf(kernel_start: PhysAddr, kernel_size: u64,
4547
memory_map_addr: VirtAddr, memory_map_entry_count: u64) -> !
4648
{
47-
let kernel_start_ptr = usize_from(kernel_start.as_u64()) as *const u8;
48-
let kernel = unsafe { slice::from_raw_parts(kernel_start_ptr, usize_from(kernel_size)) };
49-
let elf_file = xmas_elf::ElfFile::new(kernel).unwrap();
50-
xmas_elf::header::sanity_check(&elf_file).unwrap();
49+
use fixedvec::FixedVec;
50+
use xmas_elf::program::{ProgramHeader, ProgramHeader64};
51+
52+
let mut preallocated_space = alloc_stack!([ProgramHeader64; 32]);
53+
let mut segments = FixedVec::new(&mut preallocated_space);
54+
let entry_point;
55+
56+
{
57+
let kernel_start_ptr = usize_from(kernel_start.as_u64()) as *const u8;
58+
let kernel = unsafe { slice::from_raw_parts(kernel_start_ptr, usize_from(kernel_size)) };
59+
let elf_file = xmas_elf::ElfFile::new(kernel).unwrap();
60+
xmas_elf::header::sanity_check(&elf_file).unwrap();
61+
62+
entry_point = elf_file.header.pt2.entry_point();
63+
64+
for program_header in elf_file.program_iter() {
65+
match program_header {
66+
ProgramHeader::Ph64(header) => {
67+
segments.push(*header).expect("does not support more than 32 program segments")
68+
},
69+
ProgramHeader::Ph32(_) => panic!("does not support 32 bit elf files"),
70+
}
71+
}
72+
}
73+
74+
5175

5276
// idea: embed memory map in frame allocator and mark allocated frames as used
5377
let mut memory_map = boot_info::create_from(memory_map_addr, memory_map_entry_count);
@@ -61,7 +85,7 @@ pub extern "C" fn load_elf(kernel_start: PhysAddr, kernel_size: u64,
6185
let p4 = unsafe { &mut *(usize_from(p4_addr.as_u64()) as *const PageTable as *mut PageTable) };
6286
p4.zero();
6387

64-
let stack_end = page_table::map_kernel(kernel_start, &elf_file, p4, &mut frame_allocator);
88+
let stack_end = page_table::map_kernel(kernel_start, &segments, p4, &mut frame_allocator);
6589

6690
let boot_info_page = Page::containing_address(VirtAddr::new(0x1000));
6791
let boot_info_frame = frame_allocator.allocate_frame();
@@ -96,7 +120,7 @@ pub extern "C" fn load_elf(kernel_start: PhysAddr, kernel_size: u64,
96120
enable_nxe_bit();
97121
enable_write_protect_bit();
98122

99-
let entry_point = VirtAddr::new(elf_file.header.pt2.entry_point());
123+
let entry_point = VirtAddr::new(entry_point);
100124
printer::PRINTER.lock().clear_screen();
101125
unsafe { context_switch(p4_addr, entry_point, stack_end, boot_info_addr) };
102126
}

src/page_table.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ use frame_allocator::FrameAllocator;
22
use x86_64::{PhysAddr, VirtAddr, align_up};
33
use x86_64::structures::paging::{PAGE_SIZE, PageTable, PageTableFlags, PageTableEntry, Page, PhysFrame};
44
use usize_conversions::usize_from;
5-
use xmas_elf;
6-
use xmas_elf::program::{self, ProgramHeader};
5+
use xmas_elf::program::{self, ProgramHeader64};
6+
use fixedvec::FixedVec;
77

8-
pub(crate) fn map_kernel(kernel_start: PhysAddr, elf_file: &xmas_elf::ElfFile, p4: &mut PageTable,
9-
frame_allocator: &mut FrameAllocator) -> VirtAddr
8+
pub(crate) fn map_kernel(kernel_start: PhysAddr, segments: &FixedVec<ProgramHeader64>,
9+
p4: &mut PageTable, frame_allocator: &mut FrameAllocator) -> VirtAddr
1010
{
11-
for program_header in elf_file.program_iter() {
12-
map_segment(kernel_start, program_header, p4, frame_allocator);
11+
for segment in segments {
12+
map_segment(segment, kernel_start, p4, frame_allocator);
1313
}
1414

1515
// create a stack
@@ -35,24 +35,24 @@ pub(crate) fn identity_map(frame: PhysFrame, flags: PageTableFlags, p4: &mut Pag
3535
map_page(page, frame, flags, p4, frame_allocator);
3636
}
3737

38-
pub(crate) fn map_segment(kernel_start: PhysAddr, program_header: ProgramHeader, p4: &mut PageTable,
38+
pub(crate) fn map_segment(segment: &ProgramHeader64, kernel_start: PhysAddr, p4: &mut PageTable,
3939
frame_allocator: &mut FrameAllocator)
4040
{
4141
unsafe fn zero_frame(frame: &PhysFrame) {
4242
let frame_ptr = frame.start_address().as_u64() as *mut [u8; PAGE_SIZE as usize];
4343
*frame_ptr = [0; PAGE_SIZE as usize];
4444
}
4545

46-
let typ = program_header.get_type().unwrap();
46+
let typ = segment.get_type().unwrap();
4747
match typ {
4848
program::Type::Load => {
49-
let mem_size = program_header.mem_size();
50-
let file_size = program_header.file_size();
51-
let file_offset = program_header.offset();
49+
let mem_size = segment.mem_size();
50+
let file_size = segment.file_size();
51+
let file_offset = segment.offset();
5252
let phys_start_addr = kernel_start + file_offset;
53-
let virt_start_addr = VirtAddr::new(program_header.virtual_addr());
53+
let virt_start_addr = VirtAddr::new(segment.virtual_addr());
5454

55-
let flags = program_header.flags();
55+
let flags = segment.flags();
5656
let mut page_table_flags = PageTableFlags::PRESENT;
5757
if !flags.is_execute() { page_table_flags |= PageTableFlags::NO_EXECUTE };
5858
if flags.is_write() { page_table_flags |= PageTableFlags::WRITABLE };

0 commit comments

Comments
 (0)