mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-07-14 06:24:14 +00:00
rz shell command
This change adds an "rz" command to the shell that calls a function rz(). It switches the IO from the shell to a ZMODEM receiver that produces a Rust upload object that collects the uploaded bytes and computes a CRC32 checksum on the fly. In a later change, we will retain the most recent payload in a shell-owned object until it is consumed by an "install" command. Limitations: * Sender hangup will cause the receiver to block forever and the prompt not to come back, since kata-uart-client does reads that block forever. * Logging must be set to a level higher than debug or messages from the zmodem crate itself corrupt the transfer. * The sender must rate limit to ~150 bytes/sec to avoid running too far ahead of the Renode UART, which drops bytes when the RX FIFO is full. * Uploading too big a payload will cause a kata_panic! unless the heap size is increased in kata-debug-console/src/run.rs Demo: KATA> loglevel error ERROR KATA> rz **B0100000023be50 [Ctrl-C] $ sz -O ~/random < /tmp/term | pv -L 150 > /tmp/term Sending: random Bytes Sent: 15360/ 16384 BPS:26805 ETA 00:00 150 B 0:00:01 [ 146 B/s] [ <=> Bytes Sent: 16384 BPS:144 ] Transfer complete 16.6KiB 0:01:53 [ 149 B/s] [ <=> ] $ stty sane -echo -icanon; socat - /tmp/term 2> /dev/null; stty sane; size: 16384, crc32: 991b1d60 KATA> [Ctrl-C] $ crc32 ~/random 991b1d60 Change-Id: I53252b821a829a667a23a9fd072f71c6955fdc1a GitOrigin-RevId: c818a35f186dcd8c083891bfaa84ad0a9f9fef7d
This commit is contained in:
parent
929966d376
commit
7363bd638c
@ -5,7 +5,9 @@ authors = ["Matt Harvey <mattharvey@google.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
crc = { version = "1.4.0", default_features = false }
|
||||
cstr_core = "0.2"
|
||||
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
|
||||
kata-io = { path = "../kata-io" }
|
||||
kata-line-reader = { path = "../kata-line-reader" }
|
||||
kata-proc-common = { path = "../../ProcessManager/kata-proc-common" }
|
||||
@ -13,3 +15,4 @@ kata-security-interface = { path = "../../SecurityCoordinator/kata-security-inte
|
||||
kata-storage-interface = { path = "../../StorageManager/kata-storage-interface" }
|
||||
log = "0.4"
|
||||
postcard = { version = "0.7", features = ["alloc"], default-features = false }
|
||||
zmodem = { path = "../zmodem" }
|
||||
|
@ -6,6 +6,7 @@ use alloc::vec::Vec;
|
||||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
use cstr_core::CString;
|
||||
use hex;
|
||||
use postcard;
|
||||
|
||||
use kata_io as io;
|
||||
@ -15,10 +16,13 @@ use kata_storage_interface::kata_storage_delete;
|
||||
use kata_storage_interface::kata_storage_read;
|
||||
use kata_storage_interface::kata_storage_write;
|
||||
|
||||
mod rz;
|
||||
|
||||
/// Error type indicating why a command line is not runnable.
|
||||
enum CommandError {
|
||||
UnknownCommand,
|
||||
BadArgs,
|
||||
IO,
|
||||
Formatter(fmt::Error),
|
||||
}
|
||||
|
||||
@ -27,6 +31,7 @@ impl fmt::Display for CommandError {
|
||||
match self {
|
||||
CommandError::UnknownCommand => write!(f, "unknown command"),
|
||||
CommandError::BadArgs => write!(f, "invalid arguments"),
|
||||
CommandError::IO => write!(f, "input / output error"),
|
||||
CommandError::Formatter(e) => write!(f, "{}", e),
|
||||
}
|
||||
}
|
||||
@ -50,6 +55,12 @@ impl From<fmt::Error> for CommandError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Error> for CommandError {
|
||||
fn from(_err: io::Error) -> CommandError {
|
||||
CommandError::IO
|
||||
}
|
||||
}
|
||||
|
||||
/// Read-eval-print loop for the DebugConsole command line interface.
|
||||
pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
||||
let mut line_reader = LineReader::new();
|
||||
@ -57,7 +68,7 @@ pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
||||
const PROMPT: &str = "KATA> ";
|
||||
let _ = output.write_str(PROMPT);
|
||||
match line_reader.read_line(output, input) {
|
||||
Ok(cmdline) => dispatch_command(cmdline, output),
|
||||
Ok(cmdline) => dispatch_command(cmdline, input, output),
|
||||
Err(e) => {
|
||||
let _ = writeln!(output, "\n{}", e);
|
||||
}
|
||||
@ -69,7 +80,7 @@ pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
||||
///
|
||||
/// The line is split on whitespace. The first token is the command; the
|
||||
/// remaining tokens are the arguments.
|
||||
fn dispatch_command(cmdline: &str, output: &mut dyn io::Write) {
|
||||
fn dispatch_command(cmdline: &str, input: &mut dyn io::Read, output: &mut dyn io::Write) {
|
||||
let mut args = cmdline.split_ascii_whitespace();
|
||||
match args.nth(0) {
|
||||
Some(command) => {
|
||||
@ -88,6 +99,7 @@ fn dispatch_command(cmdline: &str, output: &mut dyn io::Write) {
|
||||
"kvwrite" => kvwrite_command(&mut args, output),
|
||||
"install" => install_command(&mut args, output),
|
||||
"loglevel" => loglevel_command(&mut args, output),
|
||||
"rz" => rz_command(input, output),
|
||||
"ps" => ps_command(),
|
||||
"scecho" => scecho_command(cmdline, output),
|
||||
"start" => start_command(&mut args, output),
|
||||
@ -155,7 +167,7 @@ fn scecho_command(cmdline: &str, output: &mut dyn io::Write) -> Result<(), Comma
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Set/display the max log level for the DebugConsole.
|
||||
/// Implements a command to configure the max log level for the DebugConsole.
|
||||
fn loglevel_command(
|
||||
args: &mut dyn Iterator<Item = &str>,
|
||||
output: &mut dyn io::Write,
|
||||
@ -175,6 +187,21 @@ fn loglevel_command(
|
||||
Ok(writeln!(output, "{}", log::max_level())?)
|
||||
}
|
||||
|
||||
/// Implements a command to receive a blob using ZMODEM.
|
||||
fn rz_command(
|
||||
input: &mut dyn io::Read,
|
||||
mut output: &mut dyn io::Write,
|
||||
) -> Result<(), CommandError> {
|
||||
let upload = rz::rz(input, &mut output)?;
|
||||
writeln!(
|
||||
output,
|
||||
"size: {}, crc32: {}",
|
||||
upload.contents().len(),
|
||||
hex::encode(upload.crc32().to_be_bytes())
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Implements a "ps" command that dumps seL4 scheduler state to the console.
|
||||
fn ps_command() -> Result<(), CommandError> {
|
||||
extern "C" {
|
||||
|
50
apps/system/components/DebugConsole/kata-shell/src/rz.rs
Normal file
50
apps/system/components/DebugConsole/kata-shell/src/rz.rs
Normal file
@ -0,0 +1,50 @@
|
||||
/// Wrapper types for fully-buffered ZMODEM receives.
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crc::crc32;
|
||||
use crc::Hasher32;
|
||||
|
||||
use zmodem;
|
||||
|
||||
use kata_io as io;
|
||||
|
||||
pub struct Upload {
|
||||
digest: crc32::Digest,
|
||||
contents: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Upload {
|
||||
pub fn new() -> Upload {
|
||||
Upload {
|
||||
digest: crc32::Digest::new(crc32::IEEE),
|
||||
contents: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn crc32(&self) -> u32 {
|
||||
self.digest.sum32()
|
||||
}
|
||||
|
||||
pub fn contents(&self) -> &[u8] {
|
||||
self.contents.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Upload {
|
||||
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.digest.write(buf);
|
||||
self.contents.extend_from_slice(buf);
|
||||
Ok(buf.len())
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Receives using ZMODEM and wraps the result as an Upload.
|
||||
pub fn rz<R: io::Read, W: io::Write>(r: R, w: W) -> Result<Upload, io::Error> {
|
||||
let mut upload = Upload::new();
|
||||
zmodem::recv::recv(r, w, &mut upload)?;
|
||||
Ok(upload)
|
||||
}
|
Loading…
Reference in New Issue
Block a user