Skip to content

Commit 5d24f5d

Browse files
committed
wip
1 parent e213464 commit 5d24f5d

File tree

21 files changed

+316
-29
lines changed

21 files changed

+316
-29
lines changed

integration-test/bins/multiboot2_payload/.cargo/config.toml renamed to integration-test/bins/.cargo/config.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@ build-std-features = ["compiler-builtins-mem"]
66
target = "x86-unknown-none.json"
77
rustflags = [
88
"-C", "code-model=kernel",
9-
"-C", "link-arg=-Tlink.ld",
9+
# "-C", "link-arg=-Tlink.ld",
1010
"-C", "relocation-model=static",
1111
]

integration-test/bins/multiboot2_payload/Cargo.lock renamed to integration-test/bins/Cargo.lock

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

integration-test/bins/Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[workspace]
2+
members = [
3+
"multiboot2_chainloader",
4+
"multiboot2_payload",
5+
"util"
6+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "multiboot2_chainloader"
3+
description = "Multiboot chainloader that loads a Multiboot2 payload"
4+
version = "0.1.0"
5+
edition = "2021"
6+
publish = false
7+
8+
[profile.release]
9+
codegen-units = 1
10+
lto = true
11+
12+
[dependencies]
13+
anyhow = { version = "1.0.69", default-features = false }
14+
elf_rs = "0.3.0"
15+
log = { version = "0.4.17", default-features = false }
16+
good_memory_allocator = "0.1.7"
17+
multiboot = "0.8.0"
18+
util = { path = "../util" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
let linker_script = "multiboot2_chainloader/link.ld";
3+
println!("cargo:rerun-if-changed={linker_script}");
4+
println!("cargo:rustc-link-arg=-T{linker_script}");
5+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
ENTRY(start)
2+
3+
PHDRS
4+
{
5+
/* PT_LOAD FLAGS (page table permissions) not necessary, as we perform
6+
legacy boot. Linker probably sets sensible defaults anyway. */
7+
kernel_rx PT_LOAD;
8+
kernel_rw PT_LOAD;
9+
kernel_ro PT_LOAD;
10+
}
11+
12+
SECTIONS {
13+
/* Chainloader linked at 8M, payload at 16M */
14+
.text 8M : AT(8M) ALIGN(4K)
15+
{
16+
KEEP(*(.multiboot_header));
17+
*(.text .text.*)
18+
} : kernel_rx
19+
20+
.rodata :
21+
{
22+
*(.rodata .rodata.*)
23+
} : kernel_ro
24+
25+
.data :
26+
{
27+
*(.data .data.*)
28+
} : kernel_rw
29+
30+
.bss :
31+
{
32+
*(COMMON)
33+
*(.bss .bss.*)
34+
} : kernel_rw
35+
36+
/DISCARD/ :
37+
{
38+
*(.eh_frame .eh_frame*)
39+
}
40+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/// Loads the first module into memory. Assumes that the module is a ELF file.
2+
/// The handoff is performed according to the Multiboot2 spec.
3+
pub fn load_module(modules: multiboot::information::ModuleIter) -> ! {
4+
loop {}
5+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#![no_main]
2+
#![no_std]
3+
#![feature(error_in_core)]
4+
5+
mod loader;
6+
mod multiboot;
7+
8+
extern crate alloc;
9+
10+
#[macro_use]
11+
extern crate util;
12+
13+
use util::init_environment;
14+
15+
core::arch::global_asm!(include_str!("start.S"), options(att_syntax));
16+
17+
/// Entry into the Rust code from assembly using the x86 SystemV calling
18+
/// convention.
19+
#[no_mangle]
20+
fn rust_entry(multiboot_magic: u32, multiboot_hdr: *const u32) -> ! {
21+
init_environment();
22+
log::debug!("multiboot_hdr={multiboot_hdr:x?}, multiboot_magic=0x{multiboot_magic:x?}");
23+
let mbi = multiboot::get_mbi(multiboot_magic, multiboot_hdr as u32).unwrap();
24+
let module_iter = mbi.modules().expect("Should provide modules");
25+
loader::load_module(module_iter);
26+
}
27+
28+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Parsing the Multiboot information. Glue code for the [`multiboot`] code.
2+
3+
use core::{mem, slice};
4+
use core::str::Utf8Error;
5+
use anyhow::anyhow;
6+
use multiboot::information::{MemoryManagement, Multiboot, PAddr, SIGNATURE_EAX};
7+
pub use multiboot::information::ModuleIter;
8+
pub use multiboot::information::Multiboot as Mbi;
9+
10+
static mut MEMORY_MANAGEMENT: Mem = Mem;
11+
12+
/// Returns an object to access the fields of the Multiboot information
13+
/// structure.
14+
pub fn get_mbi<'a>(magic: u32, ptr: u32) -> anyhow::Result<Multiboot<'a, 'static>>
15+
{
16+
if magic != SIGNATURE_EAX {
17+
return Err(anyhow!("Unknown Multiboot signature {magic:x}"));
18+
}
19+
unsafe {
20+
Multiboot::from_ptr(ptr as u64, &mut MEMORY_MANAGEMENT)
21+
}.ok_or(anyhow!("Can't read Multiboot boot information from pointer"))
22+
}
23+
24+
/// Glue object between the global allocator and the multiboot crate.
25+
struct Mem;
26+
27+
impl MemoryManagement for Mem {
28+
unsafe fn paddr_to_slice(&self, addr: PAddr, size: usize) -> Option<&'static [u8]> {
29+
let ptr = addr as *const u64 as *const u8;
30+
Some(slice::from_raw_parts(ptr, size))
31+
}
32+
33+
// If you only want to read fields, you can simply return `None`.
34+
unsafe fn allocate(&mut self, _length: usize) -> Option<(PAddr, &mut [u8])> {
35+
None
36+
}
37+
38+
unsafe fn deallocate(&mut self, addr: PAddr) {
39+
if addr != 0 {
40+
unimplemented!()
41+
}
42+
}
43+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Symbol from main.rs
2+
.extern rust_entry
3+
4+
.code32
5+
6+
.section .multiboot_header, "a", @progbits
7+
8+
/*
9+
* Multiboot v1 Header.
10+
* Required so that we can be booted by QEMU via the "-kernel" parameter.
11+
*/
12+
.align 8
13+
.global multiboot_header
14+
multiboot_header:
15+
.long 0x1badb002
16+
.long 0x0
17+
.long -0x1badb002
18+
19+
.section .text
20+
21+
.global start
22+
start:
23+
# Prepare Multiboot2-handoff parameters for Rust
24+
mov %eax, %edi
25+
mov %ebx, %esi
26+
27+
# Prepare stack + align it to 16 byte (for SSE registers)
28+
mov $stack_end, %eax
29+
sub $16, %eax
30+
# x86 quirk: stack is n-aligned at address x when %esp+$8 is n-aligned
31+
add $8, %eax
32+
33+
# Set stack
34+
mov %eax, %esp
35+
mov %eax, %ebp
36+
37+
# Enable SSE.
38+
# Strictly speaking, this is not necessary, but I activated SSE in the
39+
# compiler spec json file. Rustc/LLVM produces SSE coe for example from the
40+
# core::fmt code.
41+
mov %cr0, %eax
42+
and $0xFFFB, %ax # clear coprocessor emulation CR0.EM
43+
or $0x2, %ax # set coprocessor monitoring CR0.MP
44+
mov %eax, %cr0
45+
mov %cr4, %eax
46+
or $(3 << 9), %ax # set CR4.OSFXSR and CR4.OSXMMEXCPT
47+
mov %eax, %cr4
48+
49+
push %ebp
50+
mov %esp, %ebp
51+
# x86 SystemV calling convention: Push arguments in reverse order to stack
52+
push %edi
53+
push %esi
54+
call rust_entry
55+
ud2
56+
57+
.section .data
58+
59+
# 16K natural-aligned stack.
60+
.align 16384
61+
stack_begin:
62+
.zero 16384
63+
stack_end:

integration-test/bins/multiboot2_payload/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,5 @@ log = { version = "0.4.17", default-features = false }
1616
multiboot2 = { path = "../../../multiboot2", features = ["unstable"] }
1717
# Wait for release > 3.0.1
1818
qemu-exit = { git = "https://github.com/rust-embedded/qemu-exit.git", rev = "3cee0efb5c1842b5261850c57b3b4d608542ff03" }
19+
util = { path = "../util" }
1920
x86 = "0.52.0"
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
fn main() {
2-
println!("cargo:rerun-if-changed=link.ld");
2+
let linker_script = "multiboot2_payload/link.ld";
3+
println!("cargo:rerun-if-changed={linker_script}");
4+
println!("cargo:rustc-link-arg=-T{linker_script}");
35
}

integration-test/bins/multiboot2_payload/link.ld

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ PHDRS
1010
}
1111

1212
SECTIONS {
13+
/* Chainloader linked at 8M, payload at 16M */
1314
.text 16M : AT(16M) ALIGN(4K)
1415
{
1516
*(.multiboot2_header)
@@ -34,6 +35,6 @@ SECTIONS {
3435

3536
/DISCARD/ :
3637
{
37-
*(.eh_frame .eh_frame.*)
38+
*(.eh_frame .eh_frame*)
3839
}
3940
}

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use crate::println;
21
use alloc::format;
32
use alloc::vec::Vec;
43
use multiboot2::BootInformation;

0 commit comments

Comments
 (0)