Skip to content

Commit 2237d2e

Browse files
committed
aarch64: pass bootinfo from bootloader to kernel
1 parent fa30f5f commit 2237d2e

File tree

14 files changed

+161
-144
lines changed

14 files changed

+161
-144
lines changed

bootloader/Cargo.lock

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

bootloader/Cargo.toml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@ edition = "2018"
77
[dependencies]
88
xmas-elf = "0.6.2"
99
fixedvec = "0.2.3"
10+
bootinfo = { path = "bootinfo" }
1011

1112
[target.'cfg(target_arch = "aarch64")'.dependencies]
1213
aarch64 = { git = "https://github.com/rcore-os/aarch64", version = "2.7.0" }
13-
bcm2837 = { git = "https://github.com/rcore-os/bcm2837", version = "2.0.0" }
14-
15-
[build-dependencies]
16-
cc = "1.0"
14+
bcm2837 = { git = "https://github.com/rcore-os/bcm2837", version = "2.1.0", features = ["bare_metal"] }

bootloader/bootinfo/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "bootinfo"
3+
version = "0.1.0"
4+
authors = ["equation314 <equation618@gmail.com>"]
5+
edition = "2018"
6+
7+
[dependencies]

bootloader/bootinfo/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//! Provides boot information to the kernel.
2+
#![no_std]
3+
4+
#[cfg(target_arch = "aarch64")]
5+
#[derive(Debug)]
6+
#[repr(C)]
7+
pub struct BootInfo {
8+
pub physical_memory_start: usize,
9+
pub physical_memory_end: usize,
10+
pub physical_memory_offset: usize,
11+
}
12+
13+
#[cfg(target_arch = "mips")]
14+
#[derive(Debug)]
15+
#[repr(C)]
16+
pub struct BootInfo {
17+
pub dtb: usize,
18+
}

bootloader/build.rs

Lines changed: 5 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,11 @@
1-
extern crate cc;
2-
3-
use std::fs::File;
4-
use std::io::{Result, Write};
5-
use std::path::Path;
6-
71
fn main() {
8-
if let Ok(file_path) = gen_payload_asm() {
9-
cc::Build::new().file(&file_path).compile("payload");
10-
}
11-
}
12-
13-
/// include payload and dtb in sections of asm
14-
fn gen_payload_asm() -> Result<std::path::PathBuf> {
15-
let out_dir = std::env::var("OUT_DIR").unwrap();
16-
let payload = std::env::var("PAYLOAD").unwrap();
17-
let dtb = std::env::var("DTB").unwrap();
18-
19-
if !Path::new(&payload).is_file() {
20-
panic!("Kernel payload `{}` not found", payload)
21-
}
22-
23-
let mut has_dtb = true;
24-
25-
if !Path::new(&dtb).is_file() {
26-
has_dtb = false;
27-
}
28-
29-
let file_path = Path::new(&out_dir).join("payload.S");
30-
let mut f = File::create(&file_path).unwrap();
31-
32-
println!("{:x?} {:x?}", payload, file_path);
33-
34-
write!(f, "# generated by build.rs - do not edit")?;
35-
write!(f, r#"
36-
.section .payload,"a"
37-
.align 12
38-
.global _kernel_payload_start, _kernel_payload_end
39-
_kernel_payload_start:
40-
.incbin "{}"
41-
_kernel_payload_end:
42-
"#, payload)?;
43-
44-
println!("cargo:rerun-if-changed={}", payload);
452
println!("cargo:rerun-if-env-changed=PAYLOAD");
3+
println!("cargo:rerun-if-env-changed=DTB");
464

47-
if has_dtb {
48-
write!(f, r#"
49-
.section .dtb,"a"
50-
.align 12
51-
.global _dtb_start, _dtb_end
52-
_dtb_start:
53-
.incbin "{}"
54-
_dtb_end:
55-
"#, dtb)?;
56-
println!("{:x?} {:x?}", dtb, file_path);
5+
if let Ok(payload) = std::env::var("PAYLOAD") {
6+
println!("cargo:rerun-if-changed={}", payload);
7+
}
8+
if let Ok(dtb) = std::env::var("DTB") {
579
println!("cargo:rerun-if-changed={}", dtb);
58-
println!("cargo:rerun-if-env-changed=DTB");
5910
}
60-
61-
Ok(file_path)
6211
}

bootloader/src/arch/aarch64/mod.rs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use aarch64::addr::{PhysAddr, VirtAddr};
2-
use aarch64::paging::{memory_attribute::*, Page, PageTable, PageTableAttribute, PageTableFlags as EF, PhysFrame};
3-
use aarch64::paging::{Size1GiB, Size2MiB, Size4KiB};
2+
use aarch64::paging::{memory_attribute::*, PageTable, PageTableAttribute, PageTableFlags as EF};
3+
use aarch64::paging::{Page, PhysFrame, Size1GiB, Size2MiB, Size4KiB};
44
use aarch64::{asm::*, barrier, regs::*};
5-
use bcm2837::addr::{phys_to_virt, virt_to_phys, PHYSICAL_IO_BASE};
5+
use bcm2837::addr::{phys_to_virt, virt_to_phys};
6+
use bcm2837::addr::{PHYSICAL_IO_START, PHYSICAL_IO_END, PHYSICAL_MEMORY_OFFSET};
7+
use bcm2837::atags::Atags;
8+
use bootinfo::BootInfo;
69
use core::ptr;
710
use fixedvec::FixedVec;
811
use xmas_elf::program::{ProgramHeader64, Type};
@@ -39,15 +42,15 @@ fn create_page_table(start_paddr: usize, end_paddr: usize) {
3942
p2[page.p2_index()].set_block::<Size2MiB>(paddr, block_flags, MairNormal::attr_value());
4043
}
4144
// device memory
42-
for frame in PhysFrame::<Size2MiB>::range_of(PHYSICAL_IO_BASE as u64, 0x4000_0000) {
45+
for frame in PhysFrame::<Size2MiB>::range_of(PHYSICAL_IO_START as u64, PHYSICAL_IO_END as u64) {
4346
let paddr = frame.start_address();
4447
let vaddr = VirtAddr::new(phys_to_virt(paddr.as_u64() as usize) as u64);
4548
let page = Page::<Size2MiB>::containing_address(vaddr);
4649
p2[page.p2_index()].set_block::<Size2MiB>(paddr, block_flags | EF::PXN, MairDevice::attr_value());
4750
}
4851

4952
p3[0].set_frame(frame_lvl2, EF::default_table(), PageTableAttribute::new(0, 0, 0));
50-
p3[1].set_block::<Size1GiB>(PhysAddr::new(0x4000_0000), block_flags | EF::PXN, MairDevice::attr_value());
53+
p3[1].set_block::<Size1GiB>(PhysAddr::new(PHYSICAL_IO_END as u64), block_flags | EF::PXN, MairDevice::attr_value());
5154

5255
p4[0].set_frame(frame_lvl3, EF::default_table(), PageTableAttribute::new(0, 0, 0));
5356

@@ -101,7 +104,21 @@ fn enable_mmu() {
101104
unsafe { barrier::isb(barrier::SY) }
102105
}
103106

104-
pub fn map_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader64>) {
107+
/// Returns the (start address, end address) of the physical memory on this
108+
/// system if it can be determined. If it cannot, `None` is returned.
109+
///
110+
/// This function is expected to return `Some` under all normal cirumstances.
111+
fn probe_memory() -> Option<(usize, usize)> {
112+
let mut atags: Atags = Atags::get();
113+
while let Some(atag) = atags.next() {
114+
if let Some(mem) = atag.mem() {
115+
return Some((mem.start as usize, (mem.start + mem.size) as usize));
116+
}
117+
}
118+
None
119+
}
120+
121+
pub fn copy_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader64>) -> (BootInfo, usize) {
105122
// reverse program headers to avoid overlapping in memory copying
106123
let mut space = alloc_stack!([ProgramHeader64; 32]);
107124
let mut rev_segments = FixedVec::new(&mut space);
@@ -134,6 +151,16 @@ pub fn map_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader64>) {
134151
}
135152
}
136153

137-
create_page_table(0, PHYSICAL_IO_BASE);
154+
let (start, end) = probe_memory().expect("failed to find memory map");
155+
create_page_table(start, end);
138156
enable_mmu();
157+
158+
(
159+
BootInfo {
160+
physical_memory_start: start,
161+
physical_memory_end: end,
162+
physical_memory_offset: PHYSICAL_MEMORY_OFFSET,
163+
},
164+
end_vaddr.as_u64() as usize,
165+
)
139166
}

bootloader/src/arch/mipsel/mod.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use bootinfo::BootInfo;
12
use core::ptr;
23
use fixedvec::FixedVec;
34
use xmas_elf::program::{ProgramHeader32, Type};
@@ -6,14 +7,15 @@ const KERNEL_OFFSET: u32 = 0x80000000;
67

78
global_asm!(include_str!("boot.S"));
89

9-
pub fn copy_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader32>) {
10+
pub fn copy_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader32>) -> (BootInfo, usize) {
1011
// reverse program headers to avoid overlapping in memory copying
1112
let mut space = alloc_stack!([ProgramHeader32; 32]);
1213
let mut rev_segments = FixedVec::new(&mut space);
1314
for i in (0..segments.len()).rev() {
1415
rev_segments.push(segments[i]).unwrap();
1516
}
1617

18+
let mut end_vaddr = 0;
1719
for segment in &rev_segments {
1820
if segment.get_type() != Ok(Type::Load) {
1921
continue;
@@ -29,6 +31,15 @@ pub fn copy_kernel(kernel_start: usize, segments: &FixedVec<ProgramHeader32>) {
2931
ptr::copy(src, dst, file_size as usize);
3032
ptr::write_bytes(dst.offset(file_size as isize), 0, (mem_size - file_size) as usize);
3133
}
34+
if virt_addr + mem_size > end_vaddr {
35+
end_vaddr = virt_addr + mem_size;
36+
}
3237
}
3338

39+
(
40+
BootInfo {
41+
dtb: include_bytes!(concat!("../../../", env!("DTB"))).as_ptr() as usize,
42+
},
43+
end_vaddr as usize,
44+
)
3445
}

0 commit comments

Comments
 (0)