Skip to content

Commit

Permalink
Stage64: Allocate region for kernel based on exe's len
Browse files Browse the repository at this point in the history
  • Loading branch information
corigan01 committed Jan 5, 2025
1 parent 9017c0f commit 2cf2b2d
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 29 deletions.
83 changes: 56 additions & 27 deletions bootloader/stage-64bit/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
\___\_\_,_/\_,_/_//_/\__/\_,_/_/_/_/ /____/\___/\_,_/\_,_/\__/_/
Part of the Quantum OS Project
Copyright 2024 Gavin Kellam
Copyright 2025 Gavin Kellam
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
Expand Down Expand Up @@ -34,9 +34,15 @@ use elf::{
tables::{ArchKind, SegmentKind},
};
use lldebug::{debug_ready, logln, make_debug};
use mem::phys::{PhysMemoryEntry, PhysMemoryMap};
use mem::phys::{PhysMemoryEntry, PhysMemoryKind, PhysMemoryMap};
use serial::{Serial, baud::SerialBaud};
use util::{
align_to,
bytes::HumanBytes,
consts::{MIB, PAGE_4K},
};

mod paging;
mod panic;

make_debug! {
Expand All @@ -57,57 +63,80 @@ fn main(stage_to_stage: &Stage32toStage64) {
logln!("Stage64!");
let (kernel_elf_ptr, kernel_elf_size) = stage_to_stage.kernel_ptr;

let elf = Elf::new(unsafe {
core::slice::from_raw_parts(kernel_elf_ptr as *const u8, kernel_elf_size as usize)
});

let kernel_exe_len = elf
.exe_size()
.expect("Unable to determine the size of the Kernel's exe!");

logln!("Kernel Size: {}", HumanBytes::from(kernel_exe_len));
build_memory_map(stage_to_stage, kernel_exe_len);

let elf_header = match elf.header() {

Check warning on line 77 in bootloader/stage-64bit/src/main.rs

View workflow job for this annotation

GitHub Actions / Build OS

unused variable: `elf_header`
Ok(elf::tables::ElfHeader::Header64(h)) if h.arch() == ArchKind::X64 && h.is_le() => h,
_ => panic!("Kernel's elf is not valid!"),
};

elf.load_into(|h| {
if h.segment_kind() != SegmentKind::Load {
return None;
}

None
})
.unwrap();
}

fn build_memory_map(s2s: &Stage32toStage64, kernel_exe_len: usize) {
unsafe {
let mm = &mut *MEMORY_MAP.get();

for memory_region in stage_to_stage.memory_map.iter() {
for memory_region in s2s.memory_map.iter() {
mm.add_region(memory_region)
.expect("Unable to build kernel's memory map!");
}

logln!(
"Free Memory : {} Mib",
mm.bytes_of(mem::phys::PhysMemoryKind::Free) / util::consts::MIB
mm.bytes_of(PhysMemoryKind::Free) / MIB
);
logln!(
"Reserved Memory : {} Mib",
mm.bytes_of(mem::phys::PhysMemoryKind::Reserved) / util::consts::MIB
mm.bytes_of(PhysMemoryKind::Reserved) / MIB
);

let (s32_start, s32_len) = stage_to_stage.stage32_ptr;
let (s32_start, s32_len) = s2s.stage32_ptr;
mm.add_region(PhysMemoryEntry {
kind: mem::phys::PhysMemoryKind::Bootloader,
kind: PhysMemoryKind::Bootloader,
start: s32_start,
end: s32_start + s32_len,
})
.expect("Unable to add stage32 to memory map");

let (s64_start, s64_len) = stage_to_stage.stage64_ptr;
let (s64_start, s64_len) = s2s.stage64_ptr;
mm.add_region(PhysMemoryEntry {
kind: mem::phys::PhysMemoryKind::Bootloader,
kind: PhysMemoryKind::Bootloader,
start: s64_start,
end: s64_start + s64_len,
})
.expect("Unable to add stage64 to memory map");

let kernels_pages = mm
.find_continuous_of(
PhysMemoryKind::Free,
align_to(kernel_exe_len as u64, PAGE_4K) as usize,
PAGE_4K,
1 * MIB as u64,
)
.map(|p| PhysMemoryEntry {
kind: PhysMemoryKind::Kernel,
..p
})
.expect("Unable to find region for kernel pages");
mm.add_region(kernels_pages).unwrap();

logln!("{}", mm);
}

let elf = Elf::new(unsafe {
core::slice::from_raw_parts(kernel_elf_ptr as *const u8, kernel_elf_size as usize)
});

let elf_header = match elf.header() {
Ok(elf::tables::ElfHeader::Header64(h)) if h.arch() == ArchKind::X64 && h.is_le() => h,
_ => panic!("Kernel's elf is not valid!"),
};

elf.load_into(|h| {
if h.segment_kind() != SegmentKind::Load {
return None;
}

None
})
.unwrap();
}
24 changes: 24 additions & 0 deletions bootloader/stage-64bit/src/paging.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
____ __ __ __
/ __ \__ _____ ____ / /___ ____ _ / / ___ ___ ____/ /__ ____
/ /_/ / // / _ `/ _ \/ __/ // / ' \ / /__/ _ \/ _ `/ _ / -_) __/
\___\_\_,_/\_,_/_//_/\__/\_,_/_/_/_/ /____/\___/\_,_/\_,_/\__/_/
Part of the Quantum OS Project

Copyright 2025 Gavin Kellam

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial
portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
30 changes: 30 additions & 0 deletions crates/elf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,36 @@ impl<'a> Elf<'a> {
self.entry_point()
}

pub fn exe_size(&self) -> Result<usize> {
let mut lowest_addr = u64::MAX;
let mut highest_addr = 0;

match self.program_headers()? {
tables::ElfProgramHeaders::ProgHeader64(header) => header
.iter()
.map(|h| tables::ElfGenProgramHeader::from(h))
.filter(|h| h.segment_kind() == tables::SegmentKind::Load)
.for_each(|h| {
lowest_addr = lowest_addr.min(h.expected_vaddr());
highest_addr = highest_addr.max(h.expected_vaddr() + h.in_mem_size() as u64);
}),
tables::ElfProgramHeaders::ProgHeader32(header) => header
.iter()
.map(|h| tables::ElfGenProgramHeader::from(h))
.filter(|h| h.segment_kind() == tables::SegmentKind::Load)
.for_each(|h| {
lowest_addr = lowest_addr.min(h.expected_vaddr());
highest_addr = highest_addr.max(h.expected_vaddr() + h.in_mem_size() as u64);
}),
}

if lowest_addr >= highest_addr {
Ok(0)
} else {
Ok((highest_addr - lowest_addr) as usize)
}
}

pub fn entry_point(&self) -> Result<*const u8> {
Ok(match self.header()? {
tables::ElfHeader::Header64(h) => h.entry_point() as *const u8,
Expand Down
2 changes: 0 additions & 2 deletions crates/util/src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA

use core::fmt::{Alignment, Display, Formatter};

use crate::align_to;

/// A type that represents a size in bytes, and can convert it to a human-readable string.
///
/// # Example
Expand Down
4 changes: 4 additions & 0 deletions crates/util/src/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWA
pub const KIB: usize = 1024;
pub const MIB: usize = 1024 * KIB;
pub const GIB: usize = 1024 * MIB;

pub const PAGE_4K: usize = 4 * KIB;
pub const PAGE_2M: usize = 2 * MIB;
pub const PAGE_1G: usize = 1 * GIB;

0 comments on commit 2cf2b2d

Please sign in to comment.