Skip to content

Commit d93209b

Browse files
authored
feat(prototyper): allocate the patched fdt on the heap. (rustsbi#155)
* feat(prototyper): allocate the patched fdt on the heap. Signed-off-by: jackfiled <[email protected]> * fix(prototyper): add more comments for the buffer leaking operation and fix typo. Signed-off-by: jackfiled <[email protected]> * feat(prototyper): extend the heap size to 1M. Signed-off-by: jackfiled <[email protected]> * feat(prototyper): update serde-device-tree version. Signed-off-by: jackfiled <[email protected]> --------- Signed-off-by: jackfiled <[email protected]>
2 parents 5f42737 + d30ed90 commit d93209b

File tree

5 files changed

+45
-20
lines changed

5 files changed

+45
-20
lines changed

prototyper/prototyper/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sbi-spec = { version = "0.0.8", features = [
2424
serde = { version = "1.0.202", default-features = false, features = ["derive"] }
2525
aclint = { git = "https://github.com/rustsbi/aclint", rev = "b2136a66" }
2626
fast-trap = { git = "https://github.com/rustsbi/fast-trap", rev = "8d855afa", features = ["riscv-m"] }
27-
serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", rev = "805718b", default-features = false, features = ["ser"] }
27+
serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", rev = "f051687", default-features = false, features = ["ser"] }
2828
uart_xilinx = { git = "https://github.com/duskmoon314/uart-rs/", rev = "12be9142" }
2929
xuantie-riscv = { git = "https://github.com/rustsbi/xuantie", rev = "7a521c04" }
3030
bouffalo-hal = { git = "https://github.com/rustsbi/bouffalo-hal", rev = "968b949", features = [

prototyper/prototyper/build.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ SECTIONS {
8080
8181
.text : ALIGN(0x1000) {
8282
*(.fdt)
83-
*(.patched_fdt)
8483
}
8584
. = ALIGN(4);
8685
sbi_end = .;

prototyper/prototyper/config/default.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
num_hart_max = 8
22
stack_size_per_hart = 16384 # 16 * 1024
3-
heap_size = 32768 # 32 * 1024
3+
heap_size = 1048576 # 1024 * 1024
44
page_size = 4096
55
log_level = "INFO"
66
jump_address = 0x80200000

prototyper/prototyper/src/firmware/mod.rs

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ cfg_if::cfg_if! {
1111
}
1212
}
1313

14-
use alloc::format;
14+
use alloc::{format, vec};
1515
#[allow(unused)]
1616
use core::arch::{asm, naked_asm};
1717
use core::ops::Range;
@@ -38,9 +38,6 @@ pub struct BootHart {
3838
pub extern "C" fn raw_fdt() {
3939
naked_asm!(concat!(".incbin \"", env!("PROTOTYPER_FDT_PATH"), "\""),)
4040
}
41-
const DEVICE_TREE_BUFFER_LENGTH: usize = 0x10000;
42-
#[unsafe(link_section = ".patched_fdt")]
43-
static mut DEVICE_TREE_BUFFER: [u8; DEVICE_TREE_BUFFER_LENGTH] = [0u8; DEVICE_TREE_BUFFER_LENGTH];
4441

4542
#[inline]
4643
#[cfg(feature = "fdt")]
@@ -71,16 +68,12 @@ pub fn get_boot_hart(opaque: usize, nonstandard_a2: usize) -> BootHart {
7168
pub fn patch_device_tree(device_tree_ptr: usize) -> usize {
7269
use serde_device_tree::buildin::Node;
7370
use serde_device_tree::ser::serializer::ValueType;
74-
use serde_device_tree::*;
71+
use serde_device_tree::{Dtb, DtbPtr};
7572
let Ok(ptr) = DtbPtr::from_raw(device_tree_ptr as *mut _) else {
7673
panic!("Can not parse device tree!");
7774
};
78-
let origin_size = ptr.align();
75+
let original_length = ptr.align();
7976
let dtb = Dtb::from(ptr);
80-
// TODO: use probe length instead of a magic const number.
81-
if origin_size + 2048 > DEVICE_TREE_BUFFER_LENGTH {
82-
panic!("dtb file is too big!");
83-
}
8477

8578
// Update const
8679
unsafe {
@@ -91,7 +84,7 @@ pub fn patch_device_tree(device_tree_ptr: usize) -> usize {
9184
let sbi_end = unsafe { SBI_END_ADDRESS };
9285

9386
let dtb = dtb.share();
94-
let root: serde_device_tree::buildin::Node =
87+
let root: Node =
9588
serde_device_tree::from_raw_mut(&dtb).unwrap_or_else(fail::device_tree_deserialize_root);
9689
let tree: Node = root.deserialize();
9790

@@ -129,17 +122,38 @@ pub fn patch_device_tree(device_tree_ptr: usize) -> usize {
129122
let patch2 =
130123
serde_device_tree::ser::patch::Patch::new(&path_name, &new_base_2 as _, ValueType::Node);
131124
let raw_list = [patch1, patch2];
132-
// Only patch `reserved-memory` when it not exists.
125+
// Only add `reserved-memory` section when it not exists.
133126
let list = if tree.find("/reserved-memory").is_some() {
134127
&raw_list[1..]
135128
} else {
136129
&raw_list[..]
137130
};
138131

139-
unsafe {
140-
serde_device_tree::ser::to_dtb(&tree, &list, &mut DEVICE_TREE_BUFFER).unwrap();
141-
DEVICE_TREE_BUFFER.as_ptr() as _
142-
}
132+
// Firstly, allocate a temporary buffer to store the fdt and get the real total size of the patched fdt.
133+
// TODO: The serde_device_tree can provide a function to calculate the accuracy size of patched fdt.
134+
debug!(
135+
"Allocate temporary DTB buffer with length 0x{:x}.",
136+
original_length + 2048
137+
);
138+
let mut temporary_buffer = vec![0u8; original_length + 2048];
139+
serde_device_tree::ser::to_dtb(&tree, &list, &mut temporary_buffer).unwrap();
140+
let Ok(patched_dtb_ptr) = DtbPtr::from_raw(temporary_buffer.as_mut_ptr()) else {
141+
panic!("Failed to parse the patched dtb.")
142+
};
143+
let patched_length = patched_dtb_ptr.align();
144+
145+
// Secondly, allocate the exactly buffer to store the fdt.
146+
let mut patched_dtb_buffer = vec![0u8; patched_length];
147+
serde_device_tree::ser::to_dtb(&tree, &list, &mut patched_dtb_buffer).unwrap();
148+
// Intentionally leak the buffer so that the patched DTB remains valid for the lifetime of the firmware.
149+
// This is required because the returned pointer is used elsewhere and must not be deallocated.
150+
let patched_dtb = patched_dtb_buffer.leak();
151+
info!(
152+
"The patched dtb is located at 0x{:x} with length 0x{:x}.",
153+
patched_dtb.as_ptr() as usize,
154+
patched_length
155+
);
156+
patched_dtb.as_ptr() as usize
143157
}
144158

145159
static mut SBI_START_ADDRESS: usize = 0;

prototyper/prototyper/src/sbi/heap.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use buddy_system_allocator::LockedHeap;
44
#[unsafe(link_section = ".bss.heap")]
55
static mut HEAP: [u8; HEAP_SIZE] = [0; HEAP_SIZE];
66

7+
const BUDDY_MAX_ORDER: usize = 20;
78
#[global_allocator]
8-
static HEAP_ALLOCATOR: LockedHeap<15> = LockedHeap::<15>::empty();
9+
static HEAP_ALLOCATOR: LockedHeap<BUDDY_MAX_ORDER> = LockedHeap::<BUDDY_MAX_ORDER>::empty();
910

1011
pub fn sbi_heap_init() {
1112
unsafe {
@@ -17,5 +18,16 @@ pub fn sbi_heap_init() {
1718

1819
#[alloc_error_handler]
1920
pub fn handle_alloc_error(layout: core::alloc::Layout) -> ! {
21+
error!("Heap stats:");
22+
{
23+
let heap = HEAP_ALLOCATOR.lock();
24+
error!("\tTotal size: {}", heap.stats_total_bytes());
25+
error!("\tRequested size: {}", heap.stats_alloc_user());
26+
error!("\tAllocated size: {}", heap.stats_alloc_actual());
27+
error!(
28+
"Currently the heap only support allocate buffer with max length {} bytes.",
29+
1 << (BUDDY_MAX_ORDER - 1)
30+
);
31+
}
2032
panic!("Heap allocation error, layout = {:?}", layout);
2133
}

0 commit comments

Comments
 (0)