Skip to content

Commit 7651ddd

Browse files
committed
WIP
1 parent 5d24f5d commit 7651ddd

File tree

17 files changed

+178
-204
lines changed

17 files changed

+178
-204
lines changed

integration-test/bins/Cargo.lock

Lines changed: 20 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

integration-test/bins/multiboot2_chainloader/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ log = { version = "0.4.17", default-features = false }
1616
good_memory_allocator = "0.1.7"
1717
multiboot = "0.8.0"
1818
util = { path = "../util" }
19+
multiboot2 = { path = "../../../multiboot2" }
20+
multiboot2-header = { path = "../../../multiboot2-header" }
Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,58 @@
1+
use core::any::Any;
2+
use elf_rs::{ElfFile, ProgramHeaderEntry, ProgramType};
3+
14
/// Loads the first module into memory. Assumes that the module is a ELF file.
25
/// The handoff is performed according to the Multiboot2 spec.
3-
pub fn load_module(modules: multiboot::information::ModuleIter) -> ! {
4-
loop {}
6+
pub fn load_module(mut modules: multiboot::information::ModuleIter) -> ! {
7+
let elf_mod = modules.next().expect("Should have payload");
8+
let elf_bytes = unsafe {
9+
core::slice::from_raw_parts(
10+
elf_mod.start as *const u64 as *const u8,
11+
(elf_mod.end - elf_mod.start) as usize,
12+
)
13+
};
14+
log::info!("Bootstrapping ELF: {}", elf_mod.string.unwrap_or("<unknown>"));
15+
let elf = elf_rs::Elf32::from_bytes(elf_bytes).expect("Should be valid ELF");
16+
elf.program_header_iter()
17+
.filter(|ph| ph.ph_type() == ProgramType::LOAD)
18+
.for_each(|ph| {
19+
map_memory(ph);
20+
});
21+
22+
// TODO check if ELF has multiboot2 header tag
23+
24+
// TODO build MBI
25+
26+
27+
// TODO
28+
let mbi = 0;
29+
// handoff
30+
unsafe {
31+
core::arch::asm!(
32+
"jmp *%ecx",
33+
in("eax") multiboot2::MULTIBOOT2_BOOTLOADER_MAGIC,
34+
in("ebx") mbi,
35+
in("ecx") elf.entry_point() as u32,
36+
options(noreturn, att_syntax));
37+
}
38+
}
39+
40+
/// Blindly copies the LOAD segment content at its desired address in physical
41+
/// address space. The loader assumes that the addresses to not clash with the
42+
/// loader (or anything else).
43+
fn map_memory(ph: ProgramHeaderEntry) {
44+
log::debug!("Mapping LOAD segment {ph:#?}");
45+
let dest_ptr = ph.vaddr() as *mut u8;
46+
let content = ph.content().expect("Should have content");
47+
unsafe {
48+
core::ptr::copy(content.as_ptr(), dest_ptr, content.len())
49+
};
50+
let mut dest_ptr = unsafe { dest_ptr.add(ph.filesz() as usize) };
51+
52+
// Zero .bss memory
53+
for _ in 0..(ph.memsz() - ph.filesz()) {
54+
unsafe {
55+
core::ptr::write(dest_ptr, 0);
56+
}
57+
}
558
}

integration-test/bins/multiboot2_chainloader/src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,3 @@ fn rust_entry(multiboot_magic: u32, multiboot_hdr: *const u32) -> ! {
2424
let module_iter = mbi.modules().expect("Should provide modules");
2525
loader::load_module(module_iter);
2626
}
27-
28-

integration-test/bins/multiboot2_chainloader/src/multiboot.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,22 @@
11
//! Parsing the Multiboot information. Glue code for the [`multiboot`] code.
22
3-
use core::{mem, slice};
4-
use core::str::Utf8Error;
53
use anyhow::anyhow;
6-
use multiboot::information::{MemoryManagement, Multiboot, PAddr, SIGNATURE_EAX};
4+
use core::slice;
75
pub use multiboot::information::ModuleIter;
86
pub use multiboot::information::Multiboot as Mbi;
7+
use multiboot::information::{MemoryManagement, Multiboot, PAddr, SIGNATURE_EAX};
98

109
static mut MEMORY_MANAGEMENT: Mem = Mem;
1110

1211
/// Returns an object to access the fields of the Multiboot information
1312
/// structure.
14-
pub fn get_mbi<'a>(magic: u32, ptr: u32) -> anyhow::Result<Multiboot<'a, 'static>>
15-
{
13+
pub fn get_mbi<'a>(magic: u32, ptr: u32) -> anyhow::Result<Multiboot<'a, 'static>> {
1614
if magic != SIGNATURE_EAX {
1715
return Err(anyhow!("Unknown Multiboot signature {magic:x}"));
1816
}
19-
unsafe {
20-
Multiboot::from_ptr(ptr as u64, &mut MEMORY_MANAGEMENT)
21-
}.ok_or(anyhow!("Can't read Multiboot boot information from pointer"))
17+
unsafe { Multiboot::from_ptr(ptr as u64, &mut MEMORY_MANAGEMENT) }.ok_or(anyhow!(
18+
"Can't read Multiboot boot information from pointer"
19+
))
2220
}
2321

2422
/// Glue object between the global allocator and the multiboot crate.

integration-test/bins/multiboot2_chainloader/src/start.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ start:
4949
push %ebp
5050
mov %esp, %ebp
5151
# x86 SystemV calling convention: Push arguments in reverse order to stack
52-
push %edi
5352
push %esi
53+
push %edi
5454
call rust_entry
5555
ud2
5656

integration-test/bins/multiboot2_payload/Cargo.toml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,5 @@ anyhow = { version = "1.0.69", default-features = false }
1414
good_memory_allocator = "0.1.7"
1515
log = { version = "0.4.17", default-features = false }
1616
multiboot2 = { path = "../../../multiboot2", features = ["unstable"] }
17-
# Wait for release > 3.0.1
18-
qemu-exit = { git = "https://github.com/rust-embedded/qemu-exit.git", rev = "3cee0efb5c1842b5261850c57b3b4d608542ff03" }
1917
util = { path = "../util" }
2018
x86 = "0.52.0"

integration-test/bins/multiboot2_payload/src/integrationtest.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,8 @@ fn print_module_info(mbi: &BootInformation) -> anyhow::Result<()> {
9898
);
9999
println!(" grub cfg passed as boot module:");
100100
let grup_cfg_ptr = module.start_address() as *const u32 as *const u8;
101-
let grub_cfg = unsafe {
102-
core::slice::from_raw_parts(
103-
grup_cfg_ptr,
104-
module.module_size() as usize,
105-
)
106-
};
101+
let grub_cfg =
102+
unsafe { core::slice::from_raw_parts(grup_cfg_ptr, module.module_size() as usize) };
107103
let grub_cfg = core::str::from_utf8(grub_cfg).map_err(anyhow::Error::msg)?;
108104
println!("=== file begin ===");
109105
for line in grub_cfg.lines() {

integration-test/bins/multiboot2_payload/src/main.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,16 @@ extern crate util;
1010
core::arch::global_asm!(include_str!("start.S"), options(att_syntax));
1111
core::arch::global_asm!(include_str!("multiboot2_header.S"));
1212

13-
use alloc::vec;
14-
use core::panic::PanicInfo;
15-
use log::{debug, error, info};
16-
use qemu_exit::QEMUExit;
17-
use util::init_environment;
13+
use util::{init_environment, qemu_exit_success};
1814

1915
mod integrationtest;
2016

21-
const QEMU_EXIT_PORT: u16 = 0xf4;
22-
/// Custom error code to report success.
23-
const QEMU_EXIT_SUCCESS: u32 = 73;
24-
2517
/// Entry into the Rust code from assembly.
2618
#[no_mangle]
2719
fn rust_entry(multiboot2_magic: u32, multiboot2_hdr: *const u32) -> ! {
2820
main(multiboot2_magic, multiboot2_hdr).expect("Should run multiboot2 integration test");
29-
info!("Integration test finished successfully");
30-
qemu_exit::x86::X86::new(QEMU_EXIT_PORT, QEMU_EXIT_SUCCESS).exit_success()
21+
log::info!("Integration test finished successfully");
22+
qemu_exit_success()
3123
}
3224

3325
/// Executes the main logic.
@@ -36,7 +28,7 @@ fn main(multiboot2_magic: u32, multiboot2_hdr: *const u32) -> anyhow::Result<()>
3628
if multiboot2_magic != multiboot2::MULTIBOOT2_BOOTLOADER_MAGIC {
3729
Err(anyhow::Error::msg("Invalid bootloader magic"))?
3830
}
39-
debug!("multiboot2_hdr={multiboot2_hdr:x?}, multiboot2_magic=0x{multiboot2_magic:x?}");
31+
log::debug!("multiboot2_hdr={multiboot2_hdr:x?}, multiboot2_magic=0x{multiboot2_magic:x?}");
4032

4133
let mbi = unsafe { multiboot2::load(multiboot2_hdr as _) }.map_err(anyhow::Error::msg)?;
4234

integration-test/bins/util/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@ publish = false
88
[dependencies]
99
good_memory_allocator = "0.1.7"
1010
log = { version = "0.4.17", default-features = false }
11+
# Wait for release > 3.0.1
12+
qemu-exit = { git = "https://github.com/rust-embedded/qemu-exit.git", rev = "3cee0efb5c1842b5261850c57b3b4d608542ff03" }

integration-test/bins/util/src/lib.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,19 @@ extern crate alloc;
55

66
use core::panic::PanicInfo;
77
use log::error;
8+
use qemu_exit::QEMUExit;
9+
10+
static QEMU_EXIT: qemu_exit::X86 = qemu_exit::X86::new(QEMU_EXIT_PORT, QEMU_EXIT_SUCCESS);
811

912
#[macro_use]
1013
pub mod macros;
1114
pub mod allocator;
1215
pub mod debugcon;
1316

17+
const QEMU_EXIT_PORT: u16 = 0xf4;
18+
/// Custom error code to report success.
19+
const QEMU_EXIT_SUCCESS: u32 = 73;
20+
1421
/// Initializes the environment.
1522
pub fn init_environment() {
1623
debugcon::DebugconLogger::init();
@@ -22,5 +29,14 @@ pub fn init_environment() {
2229
#[panic_handler]
2330
fn panic_handler(info: &PanicInfo) -> ! {
2431
error!("PANIC! {}", info);
25-
loop {}
32+
qemu_exit_failure()
33+
}
34+
35+
36+
pub fn qemu_exit_success() -> ! {
37+
QEMU_EXIT.exit_success()
38+
}
39+
40+
pub fn qemu_exit_failure() -> ! {
41+
QEMU_EXIT.exit_failure()
2642
}

0 commit comments

Comments
 (0)