mirror of
https://github.com/AmbiML/sparrow-kata-full.git
synced 2025-07-15 06:51:49 +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"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
crc = { version = "1.4.0", default_features = false }
|
||||||
cstr_core = "0.2"
|
cstr_core = "0.2"
|
||||||
|
hex = { version = "0.4.3", default-features = false, features = ["alloc"] }
|
||||||
kata-io = { path = "../kata-io" }
|
kata-io = { path = "../kata-io" }
|
||||||
kata-line-reader = { path = "../kata-line-reader" }
|
kata-line-reader = { path = "../kata-line-reader" }
|
||||||
kata-proc-common = { path = "../../ProcessManager/kata-proc-common" }
|
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" }
|
kata-storage-interface = { path = "../../StorageManager/kata-storage-interface" }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
postcard = { version = "0.7", features = ["alloc"], default-features = false }
|
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;
|
||||||
use core::fmt::Write;
|
use core::fmt::Write;
|
||||||
use cstr_core::CString;
|
use cstr_core::CString;
|
||||||
|
use hex;
|
||||||
use postcard;
|
use postcard;
|
||||||
|
|
||||||
use kata_io as io;
|
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_read;
|
||||||
use kata_storage_interface::kata_storage_write;
|
use kata_storage_interface::kata_storage_write;
|
||||||
|
|
||||||
|
mod rz;
|
||||||
|
|
||||||
/// Error type indicating why a command line is not runnable.
|
/// Error type indicating why a command line is not runnable.
|
||||||
enum CommandError {
|
enum CommandError {
|
||||||
UnknownCommand,
|
UnknownCommand,
|
||||||
BadArgs,
|
BadArgs,
|
||||||
|
IO,
|
||||||
Formatter(fmt::Error),
|
Formatter(fmt::Error),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +31,7 @@ impl fmt::Display for CommandError {
|
|||||||
match self {
|
match self {
|
||||||
CommandError::UnknownCommand => write!(f, "unknown command"),
|
CommandError::UnknownCommand => write!(f, "unknown command"),
|
||||||
CommandError::BadArgs => write!(f, "invalid arguments"),
|
CommandError::BadArgs => write!(f, "invalid arguments"),
|
||||||
|
CommandError::IO => write!(f, "input / output error"),
|
||||||
CommandError::Formatter(e) => write!(f, "{}", e),
|
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.
|
/// Read-eval-print loop for the DebugConsole command line interface.
|
||||||
pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
pub fn repl(output: &mut dyn io::Write, input: &mut dyn io::Read) -> ! {
|
||||||
let mut line_reader = LineReader::new();
|
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> ";
|
const PROMPT: &str = "KATA> ";
|
||||||
let _ = output.write_str(PROMPT);
|
let _ = output.write_str(PROMPT);
|
||||||
match line_reader.read_line(output, input) {
|
match line_reader.read_line(output, input) {
|
||||||
Ok(cmdline) => dispatch_command(cmdline, output),
|
Ok(cmdline) => dispatch_command(cmdline, input, output),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let _ = writeln!(output, "\n{}", 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
|
/// The line is split on whitespace. The first token is the command; the
|
||||||
/// remaining tokens are the arguments.
|
/// 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();
|
let mut args = cmdline.split_ascii_whitespace();
|
||||||
match args.nth(0) {
|
match args.nth(0) {
|
||||||
Some(command) => {
|
Some(command) => {
|
||||||
@ -88,6 +99,7 @@ fn dispatch_command(cmdline: &str, output: &mut dyn io::Write) {
|
|||||||
"kvwrite" => kvwrite_command(&mut args, output),
|
"kvwrite" => kvwrite_command(&mut args, output),
|
||||||
"install" => install_command(&mut args, output),
|
"install" => install_command(&mut args, output),
|
||||||
"loglevel" => loglevel_command(&mut args, output),
|
"loglevel" => loglevel_command(&mut args, output),
|
||||||
|
"rz" => rz_command(input, output),
|
||||||
"ps" => ps_command(),
|
"ps" => ps_command(),
|
||||||
"scecho" => scecho_command(cmdline, output),
|
"scecho" => scecho_command(cmdline, output),
|
||||||
"start" => start_command(&mut args, output),
|
"start" => start_command(&mut args, output),
|
||||||
@ -155,7 +167,7 @@ fn scecho_command(cmdline: &str, output: &mut dyn io::Write) -> Result<(), Comma
|
|||||||
Ok(())
|
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(
|
fn loglevel_command(
|
||||||
args: &mut dyn Iterator<Item = &str>,
|
args: &mut dyn Iterator<Item = &str>,
|
||||||
output: &mut dyn io::Write,
|
output: &mut dyn io::Write,
|
||||||
@ -175,6 +187,21 @@ fn loglevel_command(
|
|||||||
Ok(writeln!(output, "{}", log::max_level())?)
|
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.
|
/// Implements a "ps" command that dumps seL4 scheduler state to the console.
|
||||||
fn ps_command() -> Result<(), CommandError> {
|
fn ps_command() -> Result<(), CommandError> {
|
||||||
extern "C" {
|
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