Skip to content

Commit bc96b2e

Browse files
committed
ser: add patch bootargs for dtb from config.toml
- Add set and get bootargs functions for the dtb that already loaded into psram with serde-device-tree crate. - Adjust firmware and dtb loading order for patching dtb. - Test on m1s dock board, which works well. Refs: rustsbi/serde-device-tree#13 Signed-off-by: DongQing <[email protected]>
1 parent 04c2fcc commit bc96b2e

File tree

6 files changed

+141
-49
lines changed

6 files changed

+141
-49
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ riscv = "0.12.1"
2222
embedded-sdmmc = "0.8.1"
2323
picotoml = { git = "https://github.com/rustsbi/poplar", branch = "refactor/riscv", default-features = false }
2424
serde = { version = "1.0", default-features = false, features = ["derive"] }
25+
serde-device-tree = { git = "https://github.com/rustsbi/serde-device-tree", default-features = false, features = ["ser"]}
2526

2627
[[bin]]
2728
name = "bouffaloader"

src/error.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/// Errors that can occur during the loading process.
1+
/// Errors that can occur during the loading process and device tree parsing.
22
#[derive(Debug)]
33
pub enum Error<BE>
44
where
@@ -8,6 +8,10 @@ where
88
BlockDevice(embedded_sdmmc::Error<BE>),
99
/// The file length is too long.
1010
FileLength(u32),
11+
/// The file is not a valid DTB.
12+
InvalidDTB,
13+
/// The device tree magic number is invalid.
14+
InvalideMagic(u32),
1115
}
1216

1317
impl<BE> From<embedded_sdmmc::Error<BE>> for Error<BE>

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
mod config;
44
pub mod error;
55
pub mod sdcard;
6+
pub mod ser;
67
pub mod utils;
78

89
pub use error::Error;

src/main.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use bouffalo_rt::{Clocks, Peripherals, entry};
66
use bouffaloader::{Device, DynamicInfo};
77
use bouffaloader::{
88
sdcard,
9+
ser::{get_bootargs, set_bootargs},
910
utils::{format_hex, parse_hex, read_memory, write_memory},
1011
};
1112
use core::fmt::Write as _;
@@ -222,14 +223,18 @@ fn run_cli<
222223
},
223224
Base::Bootargs { command } => match command {
224225
Some(BootargsCommand::Get) => {
225-
writeln!(d.tx, "Bootargs: {:?}", b).ok();
226+
writeln!(d.tx, "Bootargs: {:?}", get_bootargs()).ok();
226227
}
227228
Some(BootargsCommand::Set { bootarg }) => match bootarg {
228229
Some(bootarg) => {
229230
b.clear();
230-
match b.push_str(bootarg) {
231+
let _ = b.push_str(bootarg);
232+
match set_bootargs(&b) {
231233
Ok(_) => writeln!(d.tx, "Bootargs set to: {:?}", b).ok(),
232-
Err(_) => writeln!(d.tx, "Cannot set bootargs for it's too long for current environment: {:?}", b).ok()
234+
Err(_) => {
235+
writeln!(d.tx, "Failed to set bootargs on value `{:?}`.", b)
236+
.ok()
237+
}
233238
};
234239
}
235240
None => {

src/sdcard.rs

Lines changed: 67 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use super::{Config, Device, Error, config::*};
1+
use super::{Config, Device, Error, config::*, ser::set_bootargs};
22
use embedded_hal::digital::OutputPin;
33
use embedded_io::{Read, Write};
44
use embedded_sdmmc::{
@@ -80,29 +80,26 @@ pub fn load_from_sdcard<
8080
return Err(());
8181
};
8282

83-
// Load firmware.
84-
let firmware_path = config.configs.firmware.as_ref().map(|s| s.as_str()).unwrap_or_else(|| {
85-
writeln!(d.tx, "warning: /config.toml: cannot find firmware path on key `configs.firmware`, using default configuration (/zImage).").ok();
86-
"ZIMAGE"
87-
});
88-
let (file_dir, file_name) = locate_file_by_path(&mut d.tx, "firmware", firmware_path);
89-
let Ok(firmware) = open_file_by_path(&mut volume_mgr, root_dir, file_dir, file_name) else {
83+
// Load device tree blob.
84+
let Some(opaque) = config.configs.opaque else {
85+
writeln!(d.tx, "warning: /config.toml: cannot find opaque file path on key `configs.opaque`, using default configuration (zeroing `a1` for non-existing opaque file).").ok();
86+
volume_mgr.close_dir(root_dir).unwrap();
87+
return Ok(0x0);
88+
};
89+
let dtb_path = opaque.as_str();
90+
let (file_dir, file_name) = locate_file_by_path(&mut d.tx, "dtb", dtb_path);
91+
let Ok(dtb) = open_file_by_path(&mut volume_mgr, root_dir, file_dir, file_name) else {
9092
writeln!(
9193
d.tx,
92-
"error: /config.toml: file not found for firmware path {}.",
93-
firmware_path
94+
"error: /config.toml: file not found for dtb path {}.",
95+
dtb_path
9496
)
9597
.ok();
9698
return Err(());
9799
};
98-
writeln!(
99-
d.tx,
100-
"info: /config.toml: firmware located on {}.",
101-
firmware_path
102-
)
103-
.ok();
104-
let result =
105-
load_file_into_memory(&mut volume_mgr, firmware, FIRMWARE_ADDRESS, FIRMWARE_LENGTH);
100+
writeln!(d.tx, "info: /config.toml: dtb located on {}.", dtb_path).ok();
101+
// Load `bl808.dtb`.
102+
let result = load_file_into_memory(&mut volume_mgr, dtb, OPAQUE_ADDRESS, OPAQUE_LENGTH);
106103
match result {
107104
Ok(bytes) => {
108105
writeln!(
@@ -113,7 +110,7 @@ pub fn load_from_sdcard<
113110
.ok();
114111
}
115112
Err(Error::FileLength(size)) => {
116-
writeln!(d.tx, "error: /config.toml: file size for firmware {} is {} bytes, but maximum supported firmware size on the current platform (BL808) is 32,704 KiB.", firmware_path, size).ok();
113+
writeln!(d.tx, "error: /config.toml: file size for dtb {} is {} bytes, but maximum supported dtb size on the current platform (BL808) is 64 KiB.", dtb_path, size).ok();
117114
return Err(());
118115
}
119116
Err(Error::BlockDevice(e)) => {
@@ -125,41 +122,64 @@ pub fn load_from_sdcard<
125122
.ok();
126123
return Err(());
127124
}
125+
Err(_) => {}
126+
}
127+
// Patch bootargs to dtb.
128+
if let Some(bootargs) = config.configs.bootargs {
129+
writeln!(d.tx, "debug: /config.toml: bootargs load start.").ok();
130+
let result = set_bootargs(&bootargs);
131+
writeln!(
132+
d.tx,
133+
"debug: /config.toml: bootargs `{}` load from dtb.",
134+
bootargs
135+
)
136+
.ok();
137+
match result {
138+
Ok(()) => {
139+
writeln!(d.tx, "info: /config.toml: bootargs set to `{}`.", bootargs).ok();
140+
}
141+
Err(Error::InvalideMagic(_magic)) => {
142+
writeln!(d.tx, "warning: /config.toml: bootargs is unused, as `config.opaque` does not include an opaque information file in DTB format.
143+
note: /config.toml: `config.bootargs` is set to `console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait quiet` in the configuration.").ok();
144+
}
145+
Err(_) => {
146+
writeln!(
147+
d.tx,
148+
"error: /config.toml: failed to set bootargs on value `{}`.",
149+
bootargs
150+
)
151+
.ok();
152+
}
153+
}
154+
} else {
155+
writeln!(d.tx, "warning: /config.toml: cannot find bootargs on key `configs.bootargs`, using default bootargs in DTB.").ok();
128156
}
129157

130158
let root_dir = volume_mgr.open_root_dir(volume0).map_err(|_| ())?;
131159

132-
// Load device tree blob.
133-
let Some(opaque) = config.configs.opaque else {
134-
writeln!(d.tx, "warning: /config.toml: cannot find opaque file path on key `configs.opaque`, using default configuration (zeroing `a1` for non-existing opaque file).").ok();
135-
volume_mgr.close_dir(root_dir).unwrap();
136-
return Ok(0x0);
137-
};
138-
let dtb_path = opaque.as_str();
139-
let (file_dir, file_name) = locate_file_by_path(&mut d.tx, "dtb", dtb_path);
140-
let Ok(dtb) = open_file_by_path(&mut volume_mgr, root_dir, file_dir, file_name) else {
160+
// Load firmware.
161+
let firmware_path = config.configs.firmware.as_ref().map(|s| s.as_str()).unwrap_or_else(|| {
162+
writeln!(d.tx, "warning: /config.toml: cannot find firmware path on key `configs.firmware`, using default configuration (/zImage).").ok();
163+
"ZIMAGE"
164+
});
165+
let (file_dir, file_name) = locate_file_by_path(&mut d.tx, "firmware", firmware_path);
166+
let Ok(firmware) = open_file_by_path(&mut volume_mgr, root_dir, file_dir, file_name) else {
141167
writeln!(
142168
d.tx,
143-
"error: /config.toml: file not found for dtb path {}.",
144-
dtb_path
169+
"error: /config.toml: file not found for firmware path {}.",
170+
firmware_path
145171
)
146172
.ok();
147173
return Err(());
148174
};
149-
writeln!(d.tx, "info: /config.toml: dtb located on {}.", dtb_path).ok();
150-
// TODO: apply bootargs to dtb.
151-
if is_dtb_format(&mut volume_mgr, dtb) {
152-
if let Some(bootargs) = config.configs.bootargs {
153-
writeln!(d.tx, "info: /config.toml: bootargs set to `{}`.", bootargs).ok();
154-
} else {
155-
writeln!(d.tx, "warning: /config.toml: cannot find bootargs on key `configs.bootargs`, using default bootargs in DTB.").ok();
156-
}
157-
} else {
158-
writeln!(d.tx, "warning: /config.toml: bootargs is unused, as `config.opaque` does not include an opaque information file in DTB format.
159-
note: /config.toml: `config.bootargs` is set to `console=ttyS0,115200n8 root=/dev/mmcblk0p2 rw rootwait quiet` in the configuration.").ok();
160-
}
161-
// Load `bl808.dtb`.
162-
let result = load_file_into_memory(&mut volume_mgr, dtb, OPAQUE_ADDRESS, OPAQUE_LENGTH);
175+
writeln!(
176+
d.tx,
177+
"info: /config.toml: firmware located on {}.",
178+
firmware_path
179+
)
180+
.ok();
181+
let result =
182+
load_file_into_memory(&mut volume_mgr, firmware, FIRMWARE_ADDRESS, FIRMWARE_LENGTH);
163183
match result {
164184
Ok(bytes) => {
165185
writeln!(
@@ -170,7 +190,7 @@ pub fn load_from_sdcard<
170190
.ok();
171191
}
172192
Err(Error::FileLength(size)) => {
173-
writeln!(d.tx, "error: /config.toml: file size for dtb {} is {} bytes, but maximum supported dtb size on the current platform (BL808) is 64 KiB.", dtb_path, size).ok();
193+
writeln!(d.tx, "error: /config.toml: file size for firmware {} is {} bytes, but maximum supported firmware size on the current platform (BL808) is 32,704 KiB.", firmware_path, size).ok();
174194
return Err(());
175195
}
176196
Err(Error::BlockDevice(e)) => {
@@ -182,7 +202,9 @@ pub fn load_from_sdcard<
182202
.ok();
183203
return Err(());
184204
}
205+
Err(_) => {}
185206
}
207+
186208
Ok(OPAQUE_ADDRESS)
187209
}
188210

src/ser.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use super::config::*;
2+
use super::error::Error;
3+
use heapless::String;
4+
use serde_device_tree::error::{Error as DtbError, ErrorType};
5+
use serde_device_tree::ser::patch::Patch;
6+
use serde_device_tree::ser::to_dtb;
7+
use serde_device_tree::{Dtb, DtbPtr, buildin::Node, buildin::StrSeq, from_raw_mut};
8+
9+
/// Set the bootargs of the dtb.
10+
pub fn set_bootargs(new_bootargs: &String<128>) -> Result<(), Error<()>> {
11+
match DtbPtr::from_raw(OPAQUE_ADDRESS as *mut u8) {
12+
Ok(ptr) => {
13+
// Get the aligned size of the dtb.
14+
let size = ptr.align();
15+
let dtb = Dtb::from(ptr).share();
16+
let root: Node = from_raw_mut(&dtb).map_err(|_| Error::InvalidDTB)?;
17+
let patch = Patch::new("/chosen/bootargs", new_bootargs);
18+
let patches = [patch];
19+
let mut temp_buffer =
20+
unsafe { core::slice::from_raw_parts_mut(FIRMWARE_ADDRESS as *mut u8, size * 2) };
21+
to_dtb(&root, &patches, &mut temp_buffer).map_err(|_| Error::InvalidDTB)?;
22+
let target =
23+
unsafe { core::slice::from_raw_parts_mut(OPAQUE_ADDRESS as *mut u8, size) };
24+
target.copy_from_slice(&temp_buffer[..size]);
25+
26+
Ok(())
27+
}
28+
Err(DtbError::Typed {
29+
error_type: ErrorType::InvalidMagic { wrong_magic },
30+
..
31+
}) => Err(Error::InvalideMagic(wrong_magic)),
32+
Err(_) => Err(Error::InvalidDTB),
33+
}
34+
}
35+
36+
/// Get the bootargs of the dtb.
37+
pub fn get_bootargs() -> Result<&'static str, ()> {
38+
match DtbPtr::from_raw(OPAQUE_ADDRESS as *mut u8) {
39+
Ok(ptr) => {
40+
let dtb = Dtb::from(ptr).share();
41+
let root: Node = from_raw_mut(&dtb).map_err(|_| ())?;
42+
let result = root
43+
.chosen()
44+
.ok_or(())?
45+
.get_prop("bootargs")
46+
.ok_or(())?
47+
.deserialize::<StrSeq>()
48+
.iter()
49+
.next()
50+
.ok_or(())?;
51+
if let Some(pos) = result.find(':') {
52+
return Ok(result.split_at(pos).0);
53+
} else {
54+
return Err(());
55+
}
56+
}
57+
Err(_) => Err(()),
58+
}
59+
}

0 commit comments

Comments
 (0)