Skip to content

Commit 40a8e1f

Browse files
committed
feat: 优化 UbootShell 命令执行逻辑,添加重试机制并改进命令响应处理
1 parent d8941b0 commit 40a8e1f

File tree

2 files changed

+88
-38
lines changed

2 files changed

+88
-38
lines changed

ostool/src/run/uboot.rs

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,10 @@ impl Runner {
321321
self.ctx.shell_run_cmd(&cmd)?;
322322
}
323323

324+
let mut net_ok = false;
325+
324326
let mut uboot = handle.join().unwrap()?;
327+
uboot.set_env("autoload", "yes")?;
325328

326329
if let Some(ref ip) = ip_string
327330
&& let Ok(output) = uboot.cmd("net list")
@@ -334,13 +337,8 @@ impl Runner {
334337

335338
info!("Board network ok");
336339

337-
if let Some(ref board_ip) = self.config.net.as_ref().unwrap().board_ip {
338-
uboot.set_env("ipaddr", board_ip)?;
339-
} else {
340-
uboot.cmd("dhcp")?;
341-
}
342-
343340
uboot.set_env("serverip", ip.clone())?;
341+
net_ok = true;
344342
}
345343

346344
let mut fdt_load_addr = None;
@@ -354,30 +352,34 @@ impl Runner {
354352
ramfs_load_addr = Some(addr as u64);
355353
}
356354

357-
let loadaddr = if let Ok(addr) = uboot.env_int("loadaddr") {
358-
info!("Found $loadaddr: {addr:#x}");
355+
let kernel_entry = if let Some(entry) = self.config.kernel_load_addr_int() {
356+
info!("Using configured kernel load address: {entry:#x}");
357+
entry
358+
} else if let Ok(entry) = uboot.env_int("kernel_addr_r") {
359+
info!("Using $kernel_addr_r as kernel entry: {entry:#x}");
360+
entry as u64
361+
} else if let Ok(entry) = uboot.env_int("loadaddr") {
362+
info!("Using $loadaddr as kernel entry: {entry:#x}");
363+
entry as u64
364+
} else {
365+
return Err(anyhow!("Cannot determine kernel entry address"));
366+
};
367+
368+
let fit_loadaddr = if let Ok(addr) = uboot.env_int("kernel_comp_addr_r") {
369+
info!("image load to kernel_comp_addr_r: {addr:#x}");
359370
addr as u64
360-
} else if let Ok(addr) = uboot.env_int("kernel_comp_addr_r") {
361-
uboot.set_env("loadaddr", format!("{addr:#x}"))?;
362-
info!("Set $loadaddr to kernel_comp_addr_r: {addr:#x}");
371+
} else if let Ok(addr) = uboot.env_int("kernel_addr_c") {
372+
info!("image load to kernel_addr_c: {addr:#x}");
363373
addr as u64
364374
} else {
365-
let addr = uboot.env_int("kernel_addr_c")? as u64;
366-
uboot.set_env("loadaddr", format!("{addr:#x}"))?;
367-
info!("Set $loadaddr to kernel_addr_c: {addr:#x}");
375+
let addr = (kernel_entry + 0x02000000) & 0xffff_ffff_ff00_0000;
376+
info!("No kernel_comp_addr_r or kernel_addr_c, use calculated address: {addr:#x}");
368377
addr
369378
};
370379

371-
let kernel_entry = if let Some(entry) = self.config.kernel_load_addr_int() {
372-
info!("Using configured kernel load address: {entry:#x}");
373-
entry
374-
} else {
375-
uboot
376-
.env_int("kernel_addr_r")
377-
.expect("kernel_addr_r not found") as u64
378-
};
380+
uboot.set_env("loadaddr", format!("{:#x}", fit_loadaddr))?;
379381

380-
info!("fitimage loadaddr: {loadaddr:#x}");
382+
info!("fitimage loadaddr: {fit_loadaddr:#x}");
381383
info!("kernel entry: {kernel_entry:#x}");
382384
let dtb = self.config.dtb_file.clone();
383385
if let Some(ref dtb_file) = dtb {
@@ -396,18 +398,34 @@ impl Runner {
396398
)
397399
.await?;
398400

399-
if self.config.net.is_some() {
400-
info!("TFTP upload FIT image to board...");
401-
let filename = fitimage.file_name().unwrap().to_str().unwrap();
401+
let fitname = fitimage.file_name().unwrap().to_str().unwrap();
402402

403-
let tftp_cmd = format!("tftp {filename}");
404-
uboot.cmd(&tftp_cmd)?;
405-
uboot.cmd_without_reply("bootm")?;
406-
} else {
407-
info!("No TFTP config, using loady to upload FIT image...");
408-
Self::uboot_loady(&mut uboot, loadaddr as usize, fitimage);
409-
uboot.cmd_without_reply("bootm")?;
410-
}
403+
let bootcmd =
404+
if let Some(ref board_ip) = self.config.net.as_ref().and_then(|e| e.board_ip.clone()) {
405+
uboot.set_env("ipaddr", board_ip)?;
406+
format!("tftp {fitname} && bootm",)
407+
} else if net_ok {
408+
format!("dhcp {fitname} && bootm",)
409+
} else {
410+
info!("No TFTP config, using loady to upload FIT image...");
411+
Self::uboot_loady(&mut uboot, fit_loadaddr as usize, fitimage);
412+
"bootm".to_string()
413+
};
414+
415+
info!("Booting kernel with command: {}", bootcmd);
416+
uboot.cmd_without_reply(&bootcmd)?;
417+
// if self.config.net.is_some() {
418+
// info!("TFTP upload FIT image to board...");
419+
// let filename = fitimage.file_name().unwrap().to_str().unwrap();
420+
421+
// let tftp_cmd = format!("tftp {filename}");
422+
// uboot.cmd(&tftp_cmd)?;
423+
// uboot.cmd_without_reply("bootm")?;
424+
// } else {
425+
// info!("No TFTP config, using loady to upload FIT image...");
426+
// Self::uboot_loady(&mut uboot, fit_loadaddr as usize, fitimage);
427+
// uboot.cmd_without_reply("bootm")?;
428+
// }
411429

412430
let tx = uboot.tx.take().unwrap();
413431
let rx = uboot.rx.take().unwrap();

uboot-shell/src/lib.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,17 +176,49 @@ impl UbootShell {
176176
Ok(())
177177
}
178178

179-
pub fn cmd(&mut self, cmd: &str) -> Result<String> {
180-
info!("cmd: {cmd}");
181-
self.cmd_without_reply(cmd)?;
179+
fn _cmd(&mut self, cmd: &str) -> Result<String> {
180+
let ok_str = "cmd-ok";
181+
let cmd_with_id = format!("{cmd}&& echo {ok_str}");
182+
self.cmd_without_reply(&cmd_with_id)?;
182183
let perfix = self.perfix.clone();
183184
let res = self
184185
.wait_for_reply(&perfix)?
185186
.trim_end()
186187
.trim_end_matches(self.perfix.as_str().trim())
187188
.trim_end()
188189
.to_string();
189-
Ok(res)
190+
if res.ends_with(ok_str) {
191+
let res = res
192+
.trim()
193+
.trim_end_matches(ok_str)
194+
.trim_end()
195+
.trim_start_matches(&cmd_with_id)
196+
.trim()
197+
.to_string();
198+
Ok(res)
199+
} else {
200+
Err(Error::other(format!(
201+
"command `{cmd}` failed, response: {res}",
202+
)))
203+
}
204+
}
205+
206+
pub fn cmd(&mut self, cmd: &str) -> Result<String> {
207+
info!("cmd: {cmd}");
208+
let mut retry = 3;
209+
while retry > 0 {
210+
match self._cmd(cmd) {
211+
Ok(res) => return Ok(res),
212+
Err(e) => {
213+
warn!("cmd `{}` failed: {}, retrying...", cmd, e);
214+
retry -= 1;
215+
thread::sleep(Duration::from_millis(100));
216+
}
217+
}
218+
}
219+
Err(Error::other(format!(
220+
"command `{cmd}` failed after retries",
221+
)))
190222
}
191223

192224
pub fn set_env(&mut self, name: impl Into<String>, value: impl Into<String>) -> Result<()> {

0 commit comments

Comments
 (0)