diff --git a/apps/system/components/DebugConsole/DebugConsole.camkes b/apps/system/components/DebugConsole/DebugConsole.camkes index 711eb0b..bea826c 100644 --- a/apps/system/components/DebugConsole/DebugConsole.camkes +++ b/apps/system/components/DebugConsole/DebugConsole.camkes @@ -10,6 +10,8 @@ import ; component DebugConsole { control; + dataport Buf(0x1000000) cpio_archive; + dataport Buf tx_dataport; uses rust_write_inf uart_write; diff --git a/apps/system/components/DebugConsole/kata-debug-console/src/run.rs b/apps/system/components/DebugConsole/kata-debug-console/src/run.rs index c4bddba..43cdd56 100644 --- a/apps/system/components/DebugConsole/kata-debug-console/src/run.rs +++ b/apps/system/components/DebugConsole/kata-debug-console/src/run.rs @@ -11,6 +11,7 @@ #![no_std] +use core::slice; use kata_io; use kata_os_common::allocator; use kata_os_common::logger::KataLogger; @@ -27,6 +28,8 @@ use slot_allocator::KATA_CSPACE_SLOTS; extern "C" { static SELF_CNODE_FIRST_SLOT: seL4_CPtr; static SELF_CNODE_LAST_SLOT: seL4_CPtr; + + static cpio_archive: *const u8; // CPIO archive of built-in files } #[no_mangle] @@ -62,8 +65,11 @@ pub extern "C" fn pre_init() { /// Entry point for DebugConsole. Runs the shell with UART IO. #[no_mangle] pub extern "C" fn run() -> ! { - trace!("run"); let mut tx = kata_uart_client::Tx::new(); let mut rx = kata_io::BufReader::new(kata_uart_client::Rx::new()); - kata_shell::repl(&mut tx, &mut rx); + let cpio_archive_ref = unsafe { + // XXX want begin-end or begin+size instead of a fixed-size block + slice::from_raw_parts(cpio_archive, 16777216) + }; + kata_shell::repl(&mut tx, &mut rx, cpio_archive_ref); } diff --git a/apps/system/components/DebugConsole/kata-shell/Cargo.toml b/apps/system/components/DebugConsole/kata-shell/Cargo.toml index c13e3a0..4c6c344 100644 --- a/apps/system/components/DebugConsole/kata-shell/Cargo.toml +++ b/apps/system/components/DebugConsole/kata-shell/Cargo.toml @@ -17,6 +17,7 @@ CONFIG_KERNEL_MCS = [] [dependencies] crc = { version = "1.4.0", default_features = false } +cpio = { git = "https://github.com/rcore-os/cpio" } hex = { version = "0.4.3", default-features = false, features = ["alloc"] } kata-io = { path = "../kata-io" } kata-line-reader = { path = "../kata-line-reader" } diff --git a/apps/system/components/DebugConsole/kata-shell/src/lib.rs b/apps/system/components/DebugConsole/kata-shell/src/lib.rs index 61c99c0..0acf35c 100644 --- a/apps/system/components/DebugConsole/kata-shell/src/lib.rs +++ b/apps/system/components/DebugConsole/kata-shell/src/lib.rs @@ -1,11 +1,11 @@ #![no_std] extern crate alloc; -use alloc::string::String; use alloc::vec; use alloc::vec::Vec; use core::fmt; use core::fmt::Write; +use cpio::CpioNewcReader; use hex; use log; @@ -24,8 +24,8 @@ use kata_security_interface::kata_security_echo; use kata_storage_interface::kata_storage_delete; use kata_storage_interface::kata_storage_read; use kata_storage_interface::kata_storage_write; -use kata_timer_interface::TimerServiceError; use kata_timer_interface::timer_service_completed_timers; +use kata_timer_interface::TimerServiceError; use kata_timer_interface::timer_service_oneshot; use kata_timer_interface::timer_service_wait; @@ -95,13 +95,17 @@ impl From for CommandError { } /// Read-eval-print loop for the DebugConsole command line interface. -pub fn repl(output: &mut dyn io::Write, input: &mut T) -> ! { +pub fn repl( + output: &mut dyn io::Write, + input: &mut T, + builtin_cpio: &[u8], +) -> ! { let mut line_reader = LineReader::new(); loop { const PROMPT: &str = "KATA> "; let _ = output.write_str(PROMPT); match line_reader.read_line(output, input) { - Ok(cmdline) => dispatch_command(cmdline, input, output), + Ok(cmdline) => dispatch_command(cmdline, input, output, builtin_cpio), Err(e) => { let _ = writeln!(output, "\n{}", e); } @@ -113,7 +117,12 @@ pub fn repl(output: &mut dyn io::Write, input: &mut T) -> ! { /// /// The line is split on whitespace. The first token is the command; the /// remaining tokens are the arguments. -fn dispatch_command(cmdline: &str, input: &mut dyn io::BufRead, output: &mut dyn io::Write) { +fn dispatch_command( + cmdline: &str, + input: &mut dyn io::BufRead, + output: &mut dyn io::Write, + builtin_cpio: &[u8], +) { let mut args = cmdline.split_ascii_whitespace(); match args.nth(0) { Some(command) => { @@ -124,13 +133,14 @@ fn dispatch_command(cmdline: &str, input: &mut dyn io::BufRead, output: &mut dyn // implementation to use its own preferred signature. let result = match command { "add" => add_command(&mut args, output), + "builtins" => builtins_command(&mut args, builtin_cpio, output), "echo" => echo_command(cmdline, output), "clear" => clear_command(output), "bundles" => bundles_command(output), "kvdelete" => kvdelete_command(&mut args, output), "kvread" => kvread_command(&mut args, output), "kvwrite" => kvwrite_command(&mut args, output), - "install" => install_command(&mut args, input, output), + "install" => install_command(&mut args, builtin_cpio, input, output), "loglevel" => loglevel_command(&mut args, output), "malloc" => malloc_command(&mut args, output), "mfree" => mfree_command(&mut args, output), @@ -165,6 +175,23 @@ fn dispatch_command(cmdline: &str, input: &mut dyn io::BufRead, output: &mut dyn }; } +/// Implements a "builtins" command that lists the contents of the built-in cpio archive. +fn builtins_command( + _args: &mut dyn Iterator, + builtin_cpio: &[u8], + output: &mut dyn io::Write, +) -> Result<(), CommandError> { + for e in CpioNewcReader::new(builtin_cpio) { + if e.is_err() { + writeln!(output, "{:?}", e.unwrap_err())?; + break; // NB: iterator does not terminate on error + } + let entry = e.unwrap(); + writeln!(output, "{} {}", entry.name, entry.data.len())?; + } + Ok(()) +} + /// Implements an "echo" command which writes its arguments to output. fn echo_command(cmdline: &str, output: &mut dyn io::Write) -> Result<(), CommandError> { const COMMAND_LENGTH: usize = 5; // "echo " @@ -273,6 +300,33 @@ fn bundles_command(output: &mut dyn io::Write) -> Result<(), CommandError> { Ok(()) } +fn collect_from_cpio( + filename: &str, + cpio: &[u8], + output: &mut dyn io::Write, +) -> Option { + for e in CpioNewcReader::new(cpio) { + if e.is_err() { + writeln!(output, "cpio error {:?}", e.unwrap_err()).ok()?; + // NB: iterator does not terminate on error but also won't advance + break; + } + let entry = e.unwrap(); + if entry.name == filename { + // Cheat, re-use zmodem data collector. + use kata_io::Write; + let mut upload = rz::Upload::new(); + let len = upload.write(entry.data).ok()?; + upload.finish(); + writeln!(output, "Collected {} bytes of data, crc32 {}", + len, hex::encode(upload.crc32().to_be_bytes())).ok()?; + return Some(upload.frames().clone()); + } + } + writeln!(output, "Built-in file \"{}\" not found", filename).ok()?; + None +} + fn collect_from_zmodem( input: &mut dyn io::BufRead, mut output: &mut dyn io::Write, @@ -288,6 +342,7 @@ fn collect_from_zmodem( fn install_command( args: &mut dyn Iterator, + builtin_cpio: &[u8], input: &mut dyn io::BufRead, mut output: &mut dyn io::Write, ) -> Result<(), CommandError> { @@ -305,7 +360,11 @@ fn install_command( Some("-z") => { collect_from_zmodem(input, &mut output).ok_or(CommandError::IO)? } - _ => { + Some(filename) => { + collect_from_cpio(filename, builtin_cpio, output) + .ok_or(CommandError::IO)? + } + None => { // TODO: pattern-fill pages kata_frame_alloc(8192).map_err(|_| CommandError::IO)? } diff --git a/apps/system/system.camkes b/apps/system/system.camkes index dfa16d8..52f8ccf 100644 --- a/apps/system/system.camkes +++ b/apps/system/system.camkes @@ -50,15 +50,15 @@ component VectorCoreHw { emits Interrupt data_fault; } -component VectorPayload { +component BuiltinCpioArchive { hardware; - dataport Buf(0x1000000) elf_file; + dataport Buf(0x1000000) cpio; } assembly { composition { component VectorCoreHw vctop; - component VectorPayload vc_payload; + component BuiltinCpioArchive cpio; component OpenTitanUART uart; component OpenTitanUARTDriver uart_driver; @@ -72,6 +72,10 @@ assembly { component StorageManager storage_manager; component TimerService timer_service; + // Built-in CPIO archive is visible only to DebugConsole. + connection seL4HardwareMMIO cpio_archive(from debug_console.cpio_archive, + to cpio.cpio); + // OpenTitanUARTDriver connection seL4HardwareMMIO uart_mem(from uart_driver.mmio_region, to uart.mmio_region); @@ -97,6 +101,7 @@ assembly { connection seL4HardwareMMIO vc_dtcm(from ml_coordinator.dtcm, to vctop.dtcm); + // TimerService connection seL4HardwareMMIO timer_csr(from timer_service.csr, to timer.csr); @@ -108,13 +113,17 @@ assembly { // Hookup ProcessManager to DebugConsole for shell commands. connection seL4RPCCall shell_process(from debug_console.proc_ctrl, to process_manager.proc_ctrl); - connection seL4RPCCall shell_package(from debug_console.pkg_mgmt, - to process_manager.pkg_mgmt); connection seL4RPCCall shell_ml(from debug_console.mlcoord, to ml_coordinator.mlcoord); connection seL4RPCCall shell_storage(from debug_console.storage, to storage_manager.storage); + // Note this allocates a 4KB shared memory region for pkg install + // to pass an ObjDescArray + connection seL4RPCOverMultiSharedData shell_package( + from debug_console.pkg_mgmt, + to process_manager.pkg_mgmt); + // Connect the MemoryInterface to each component that needs to allocate // global memory. Note this allocates a 4KB shared memory region to each // component and copies data between components. @@ -159,6 +168,9 @@ assembly { } configuration { + cpio.cpio_paddr = 0x46000000; + cpio.cpio_size = 0x1000000; + uart.mmio_region_paddr = 0x50000000; uart.mmio_region_size = 0x1000; uart.tx_watermark_irq_number = 1; @@ -176,9 +188,6 @@ assembly { vctop.instruction_fault_irq_number = 15; // kTopMatchaPlicIrqIdVcTopInstructionFault @ top_matcha.h vctop.data_fault_irq_number = 16; // kTopMatchaPlicIrqIdVcTopDataFault @ top_matcha.h - vc_payload.elf_file_paddr = 0x46000000; - vc_payload.elf_file_size = 0x1000000; - timer.csr_paddr = 0x50030000; timer.csr_size = 0x1000;