1- use fdt_parser:: { Fdt , FdtHeader } ;
1+ //! DTB (Device Tree Blob) related functionality.
2+ use core:: ptr:: NonNull ;
23
3- use core :: fmt :: Write ;
4+ use fdt_parser :: Fdt ;
45use lazyinit:: LazyInit ;
56
6- static BOOTARGS_STR : LazyInit < heapless :: String < 256 > > = LazyInit :: new ( ) ;
7+ static BOOTARG : LazyInit < usize > = LazyInit :: new ( ) ;
78
8- pub fn bootargs_message ( ) -> Option < & ' static str > {
9- let fdt_addr = crate :: get_bootarg ( ) ;
9+ /// Initializes the boot argument.
10+ pub fn init ( arg : usize ) {
11+ BOOTARG . init_once ( arg) ;
12+ }
13+
14+ /// Returns the boot argument.
15+ /// This is typically the device tree blob address passed from the bootloader.
16+ pub fn get_bootarg ( ) -> usize {
17+ * BOOTARG
18+ }
1019
11- if fdt_addr == 0 {
12- return None ;
20+ /// Get the cached FDT or initialize it if not already done.
21+ pub fn get_fdt ( ) -> Option < & ' static Fdt < ' static > > {
22+ static CACHED_FDT : LazyInit < Option < Fdt < ' static > > > = LazyInit :: new ( ) ;
23+
24+ // Return cached FDT if available
25+ if let Some ( fdt) = CACHED_FDT . get ( ) {
26+ return fdt. as_ref ( ) ;
1327 }
1428
15- let virt_addr = crate :: mem:: phys_to_virt ( crate :: mem:: PhysAddr :: from ( fdt_addr) ) . as_usize ( ) ;
16-
17- let fdt_header = unsafe {
18- let header_size = core:: mem:: size_of :: < FdtHeader > ( ) ;
19- let ptr = virt_addr as * const u8 ;
20- core:: slice:: from_raw_parts ( ptr, header_size)
21- } ;
22-
23- let fdt_header = match FdtHeader :: from_bytes ( fdt_header) {
24- Ok ( header) => header,
25- Err ( _) => return None ,
26- } ;
27-
28- let fdt_bytes = unsafe {
29- let ptr = virt_addr as * const u8 ;
30- let size = fdt_header. total_size ( ) as usize ;
31- core:: slice:: from_raw_parts ( ptr, size)
32- } ;
33-
34- let fdt = match Fdt :: from_bytes ( fdt_bytes) {
35- Ok ( fdt) => fdt,
36- Err ( _) => return None ,
37- } ;
38-
39- if let Some ( chosen) = fdt. chosen ( ) {
40- if let Some ( bootargs) = chosen. bootargs ( ) {
41- // Store bootargs in static variable
42- let mut bootargs_str = heapless:: String :: < 256 > :: new ( ) ;
43- if write ! ( bootargs_str, "{}" , bootargs) . is_ok ( ) {
44- BOOTARGS_STR . init_once ( bootargs_str) ;
45- return Some ( BOOTARGS_STR . as_str ( ) ) ;
46- }
47- }
29+ fn init_fdt ( ) -> Option < Fdt < ' static > > {
30+ let fdt_paddr = get_bootarg ( ) ;
31+ let fdt_ptr = NonNull :: new ( crate :: mem:: phys_to_virt ( fdt_paddr. into ( ) ) . as_mut_ptr ( ) ) ?;
32+ Fdt :: from_ptr ( fdt_ptr) . ok ( )
4833 }
49- None
34+
35+ CACHED_FDT . init_once ( init_fdt ( ) ) . as_ref ( )
5036}
37+
38+ /// Get the bootargs chosen from the device tree.
39+ pub fn get_chosen_bootargs ( ) -> Option < & ' static str > {
40+ static CACHED_BOOTARGS : LazyInit < Option < & ' static str > > = LazyInit :: new ( ) ;
41+
42+ // If bootargs are already cached, return them
43+ if let Some ( bootargs) = CACHED_BOOTARGS . get ( ) {
44+ return * bootargs;
45+ }
46+
47+ fn init_bootargs ( ) -> Option < & ' static str > {
48+ let fdt = get_fdt ( ) ?;
49+ fdt. chosen ( ) ?. bootargs ( )
50+ }
51+
52+ * CACHED_BOOTARGS . init_once ( init_bootargs ( ) )
53+ }
0 commit comments