Skip to content

Commit bf40ce7

Browse files
committed
Reorganize dtb.rs
1 parent c45f795 commit bf40ce7

File tree

2 files changed

+54
-33
lines changed

2 files changed

+54
-33
lines changed

modules/axhal/src/dtb.rs

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,81 @@
11
//! DTB (Device Tree Blob) related functionality.
2-
use fdt_parser::{Fdt, FdtHeader};
3-
42
use core::fmt::Write;
3+
use fdt_parser::{Fdt, FdtHeader};
54
use lazyinit::LazyInit;
65

7-
static BOOTARGS_STR: LazyInit<heapless::String<256>> = LazyInit::new();
6+
/// Record address of the boot argument (DTB address).
7+
pub static BOOT_ARG: LazyInit<usize> = LazyInit::new();
8+
static CACHED_FDT: LazyInit<Fdt<'static>> = LazyInit::new();
9+
static BOOTARGS_STR: LazyInit<heapless::String<1024>> = LazyInit::new();
10+
11+
/// Returns the boot argument.
12+
/// This is typically the device tree blob address passed from the bootloader.
13+
pub fn get_bootarg() -> usize {
14+
*BOOT_ARG
15+
}
816

9-
/// Get the bootargs from the device tree.
10-
pub fn bootargs_message() -> Option<&'static str> {
11-
let fdt_addr = crate::get_bootarg();
17+
/// Get the cached FDT or initialize it if not already done.
18+
fn get_fdt() -> Option<&'static Fdt<'static>> {
19+
// Return cached FDT if available
20+
if let Some(fdt) = CACHED_FDT.get() {
21+
return Some(fdt);
22+
}
1223

24+
// Parse and cache the FDT
25+
let fdt_addr = get_bootarg();
1326
if fdt_addr == 0 {
1427
return None;
1528
}
1629

1730
let virt_addr = crate::mem::phys_to_virt(crate::mem::PhysAddr::from(fdt_addr)).as_usize();
1831

19-
let fdt_header = unsafe {
32+
let fdt = unsafe {
33+
// First read the header to get the size
2034
let header_size = core::mem::size_of::<FdtHeader>();
21-
let ptr = virt_addr as *const u8;
22-
core::slice::from_raw_parts(ptr, header_size)
23-
};
35+
let header_ptr = virt_addr as *const u8;
36+
let header_slice = core::slice::from_raw_parts(header_ptr, header_size);
2437

25-
let fdt_header = match FdtHeader::from_bytes(fdt_header) {
26-
Ok(header) => header,
27-
Err(_) => return None,
28-
};
38+
let fdt_header = match FdtHeader::from_bytes(header_slice) {
39+
Ok(header) => header,
40+
Err(_) => return None,
41+
};
2942

30-
let fdt_bytes = unsafe {
31-
let ptr = virt_addr as *const u8;
3243
let size = fdt_header.total_size() as usize;
33-
core::slice::from_raw_parts(ptr, size)
34-
};
44+
let fdt_ptr = virt_addr as *const u8;
45+
let fdt_slice = core::slice::from_raw_parts(fdt_ptr, size);
46+
47+
let fdt_slice_static = core::mem::transmute::<&[u8], &'static [u8]>(fdt_slice);
3548

36-
let fdt = match Fdt::from_bytes(fdt_bytes) {
37-
Ok(fdt) => fdt,
38-
Err(_) => return None,
49+
match Fdt::from_bytes(fdt_slice_static) {
50+
Ok(fdt) => fdt,
51+
Err(_) => return None,
52+
}
3953
};
4054

55+
// Store the FDT in the cache
56+
CACHED_FDT.init_once(fdt);
57+
CACHED_FDT.get()
58+
}
59+
60+
/// Get the bootargs chosen from the device tree.
61+
pub fn get_chosen() -> Option<&'static str> {
62+
// If bootargs are already cached, return them
63+
if let Some(bootargs) = BOOTARGS_STR.get() {
64+
return Some(bootargs.as_str());
65+
}
66+
67+
// Get or initialize the cached FDT
68+
let fdt = get_fdt()?;
69+
4170
if let Some(chosen) = fdt.chosen() {
4271
if let Some(bootargs) = chosen.bootargs() {
4372
// Store bootargs in static variable
44-
let mut bootargs_str = heapless::String::<256>::new();
73+
let mut bootargs_str = heapless::String::<1024>::new();
4574
if write!(bootargs_str, "{}", bootargs).is_ok() {
4675
BOOTARGS_STR.init_once(bootargs_str);
4776
return Some(BOOTARGS_STR.as_str());
77+
} else {
78+
warn!("Failed to write bootargs");
4879
}
4980
}
5081
}

modules/axhal/src/lib.rs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -109,19 +109,9 @@ pub use axplat::init::init_later;
109109
#[cfg(feature = "smp")]
110110
pub use axplat::init::{init_early_secondary, init_later_secondary};
111111

112-
use lazyinit::LazyInit;
113-
114-
static BOOT_ARG: LazyInit<usize> = LazyInit::new();
115-
116112
/// Initializes the platform and boot argument.
117113
/// This function should be called as early as possible.
118114
pub fn init_early(cpu_id: usize, arg: usize) {
119-
BOOT_ARG.init_once(arg);
115+
dtb::BOOT_ARG.init_once(arg);
120116
axplat::init::init_early(cpu_id, arg);
121117
}
122-
123-
/// Returns the boot argument.
124-
/// This is typically the device tree blob address passed from the bootloader.
125-
pub fn get_bootarg() -> usize {
126-
*BOOT_ARG
127-
}

0 commit comments

Comments
 (0)