diff --git a/services/pddb/src/api.rs b/services/pddb/src/api.rs index 5a2f1d2dc..c98cb943b 100644 --- a/services/pddb/src/api.rs +++ b/services/pddb/src/api.rs @@ -7,72 +7,3 @@ pub(crate) enum Opcode { /// Suspend/resume callback SuspendResume, } - -// this is an intenal structure for managing the overall PDDB -pub(crate) struct PddbManager { - -} -impl PddbManager { - // return a list of open bases - fn list_basis(); -} - -// this is an internal struct for managing a basis -pub(crate) struct PddbBasis { - -} -impl PddbBasis { - // opening and closing basis will side-effect PddbDicts and PddbKeys - fn open(); // will result in a password box being triggered to open a basis - fn close(); -} - -// this structure can be shared on the user side? -pub struct PddbDict { - contents: Hashmap, -} -impl PddbDict { - // opens a dictionary only if it exists - pub fn open(dict_name: &str) -> Option; - // creates a dictionary only if it does not already exist - pub fn create(dict_name: &str) -> Option; - - // returns a key only if it exists - pub fn get(&mut self, key_name: &str, key_changed_cb: CB) -> Result; - // updates an existing key's value. mainly used by write(). - pub fn update(&mut self, key: PddbKey) -> Result>; - // creates a key or overwrites it - pub fn insert(&mut self, key: PddbKey) -> Option; // may return the displaced key - // deletes a key within the dictionary - pub fn remove(&mut self, key: PddbKey) -> Result<()>; - // deletes the entire dictionary - pub fn delete(&mut self); -} - -/// PddbKey is somewhat isomorphic to a File in Rust, in that it provides slices of [u8] that -/// can be `read()`, `write()` and `seek()`. -/// this is definitely a user-facing structure -pub struct PddbKey -where CB: FnMut(), { - // dictionary to search for the key within - dict: PddbDict, - // a copy of my name - name: String, - // called when the key changes (basis or is modified otherwise) - key_changed_cb: CB, - // mapped memory for the plaintext contexts, typically not all resident - mem: MemoryRange, -} - -impl PddbKey<'a, CB> { - // reads are transparent and "just happen" - pub fn read(&mut self, buf: &mut [u8]) -> Result; - // writes will call update() on the dictionary - pub fn write(&mut self, buf: &[u8]) -> Result; - // provided for compatibility with Rust API - pub fn seek(&mut self, pos: SeekFrom) -> Result; -} - -pub struct PddbBasis { - -} \ No newline at end of file diff --git a/services/pddb/src/frontend.rs b/services/pddb/src/frontend.rs new file mode 100644 index 000000000..3fc9d0382 --- /dev/null +++ b/services/pddb/src/frontend.rs @@ -0,0 +1,2 @@ +pub mod pddbkey; +pub use pddbkey::*; diff --git a/services/pddb/src/frontend/pddbkey.rs b/services/pddb/src/frontend/pddbkey.rs new file mode 100644 index 000000000..bd86b5efe --- /dev/null +++ b/services/pddb/src/frontend/pddbkey.rs @@ -0,0 +1,44 @@ +use std::io::{Error, ErrorKind, Result}; +use xous::MemoryRange; +use std::io::SeekFrom; + +use crate::PddbDict; + +/// PddbKey is somewhat isomorphic to a File in Rust, in that it provides slices of [u8] that +/// can be `read()`, `write()` and `seek()`. +/// this is definitely a user-facing structure +pub struct PddbKey<'a> { + // dictionary to search for the key within + dict: PddbDict<'a>, + // a copy of my name + name: String, + // called when the key changes (basis or is modified otherwise) + key_changed_cb: Box, + // mapped memory for the plaintext contexts, typically not all resident + mem: MemoryRange, +} + +impl<'a> PddbKey<'a> { + pub fn set_callback(&mut self, key_changed_cb: impl FnMut() + 'a) { + self.key_changed_cb = Box::new(key_changed_cb); + } + + pub fn new() { + let mem = xous::syscall::map_memory( + None, + None, + 4096, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ).expect("couldn't map initial memory page"); + + } + /* these get moved to traits */ + /* + // reads are transparent and "just happen" + pub fn read(&mut self, buf: &mut [u8]) -> Result { Ok(0) } + // writes will call update() on the dictionary + pub fn write(&mut self, buf: &[u8]) -> Result { Ok(0) } + // provided for compatibility with Rust API + pub fn seek(&mut self, pos: SeekFrom) -> Result { Ok(0) } + */ +} diff --git a/services/pddb/src/lib.rs b/services/pddb/src/lib.rs index befcdf6ff..f21690951 100644 --- a/services/pddb/src/lib.rs +++ b/services/pddb/src/lib.rs @@ -1,22 +1,99 @@ #![cfg_attr(target_os = "none", no_std)] pub mod api; +pub use api::*; +pub mod frontend; +pub use frontend::*; + use xous::{CID, send_message}; use num_traits::*; + +/// This constant maps onto a region that's "unused" by Xous, and claimable by user +/// processes. +const PDDB_BACKING_BASE: usize = 0x8000_0000; +/// This designates the largest contiguous extent that we could allocate for a file. +/// The backing isn't allocated -- it is merely reserved. Accesses to the backing trigger +/// page faults that are handled by the PDDB, and just the pages actively being dereferenced is +/// swapped into physical memory on demand. This does put a pretty hard upper limit on file sizes +/// on a 32-bit system, but PDDB is coded such that we could extend to a 64-bit system and +/// increase this limit my changing the constants here. +const PDDB_BACKING_SIZE: usize = 0x4000_0000; + +fn handle_exception(exception: xous::Exception) -> isize { + use xous::Exception::*; + match exception { + IllegalInstruction(epc, instruction) => { + println!( + "Caught illegal instruction {:08x} at {:08x}, just skipping it...", + epc, instruction + ); + 4 + } + InstructionAddressMisaligned(epc, addr) => { + println!( + "Misaligned instruction at {:08x} ({:08x}), trying to nudge forward a bit", + epc, addr + ); + 1 + } + InstructionAccessFault(epc, addr) + | LoadAccessFault(epc, addr) + | StoreAccessFault(epc, addr) => { + panic!( + "Access fault of some sort: ({:08x} {:08x}): {:?}", + epc, addr, epc + ); + } + LoadAddressMisaligned(epc, addr) | StoreAddressMisaligned(epc, addr) => { + println!( + "Load was misaligned ({:08x} @ {:08x}). Just skipping the instruction and hoping nobody notices.", epc, addr + ); + 4 + } + InstructionPageFault(epc, addr) | LoadPageFault(epc, addr) | StorePageFault(epc, addr) => { + println!("Memory access fault at address 0x{:08x} (pc is at 0x{:08x}), allocating a new page", addr, epc); + let base = addr & !4095; + let size = 4096; + xous::map_memory( + None, + xous::MemoryAddress::new(base), + size, + xous::MemoryFlags::R | xous::MemoryFlags::W, + ) + .expect("couldn't map memory"); + // Retry the instruction + 0 + } + Unknown(a1, a2, a3) => panic!("unknown exception: {:08x} {:08x} {:08x}", a1, a2, a3), + } +} + pub struct Pddb { conn: CID, + backing: MemoryRange, } impl Pddb { - pub fn new(xns: &xous_names::XousNames) -> Result { + pub fn new(xns: &xous_names::XousNames) -> core::result::Result { REFCOUNT.store(REFCOUNT.load(Ordering::Relaxed) + 1, Ordering::Relaxed); - let conn = xns.request_connection_blocking(api::SERVER_NAME_CODEC).expect("Can't connect to Pddb server"); + let conn = xns.request_connection_blocking(api::SERVER_NAME_PDDB).expect("Can't connect to Pddb server"); + + xous::syscall::set_exception_handler(handle_exception).unwrap(); + + let backing = unsafe {MemoryRange::new( + 0x8000_0000, + 0x1000_0000, + ).expect("couldn't reserve pages for file backing region") }; + Ok(Pddb { - conn + conn, + backing }) } - + pub(crate) fn conn(&self) -> CID { + self.conn + } } use core::sync::atomic::{AtomicU32, Ordering}; @@ -32,4 +109,59 @@ impl Drop for Pddb { // if there was object-specific state (such as a one-time use server for async callbacks, specific to the object instance), // de-allocate those items here. They don't need a reference count because they are object-specific } -} \ No newline at end of file +} + + + + + +use xous::MemoryRange; +use std::collections::HashMap; +use std::io::SeekFrom; +use std::io::{Error, ErrorKind, Result}; + +// this is an intenal structure for managing the overall PDDB +pub(crate) struct PddbManager { + +} +impl PddbManager { + // return a list of open bases + fn list_basis() {} +} + +// this is an internal struct for managing a basis +pub(crate) struct PddbBasis { + +} +impl PddbBasis { + // opening and closing basis will side-effect PddbDicts and PddbKeys + fn open() {} // will result in a password box being triggered to open a basis + fn close() {} +} + +// this structure can be shared on the user side? +pub struct PddbDict<'a> { + contents: HashMap, &'a [u8]>, + callback: Box, +} +impl<'a> PddbDict<'a> { + // opens a dictionary only if it exists + pub fn open(dict_name: &str) -> Option { None } + // creates a dictionary only if it does not already exist + pub fn create(dict_name: &str) -> Option { None } + + // returns a key only if it exists + pub fn get(&mut self, key_name: &str, key_changed_cb: impl FnMut() + 'a) -> Result> { + self.callback = Box::new(key_changed_cb); + Ok(None) + } + // updates an existing key's value. mainly used by write(). + pub fn update(&mut self, key: PddbKey) -> Result> { Ok(None) } + // creates a key or overwrites it + pub fn insert(&mut self, key: PddbKey) -> Option { None } // may return the displaced key + // deletes a key within the dictionary + pub fn remove(&mut self, key: PddbKey) -> Result<()> { Ok(()) } + // deletes the entire dictionary + pub fn delete(&mut self) {} +} + diff --git a/services/pddb/src/main.rs b/services/pddb/src/main.rs index 1c6ce4979..dcf1deb77 100644 --- a/services/pddb/src/main.rs +++ b/services/pddb/src/main.rs @@ -7,8 +7,6 @@ use num_traits::*; #[xous::xous_main] fn xmain() -> ! { - use crate::implementation::Pddb; - log_server::init_wait().unwrap(); log::set_max_level(log::LevelFilter::Info); log::info!("my PID is {}", xous::process::id()); @@ -17,8 +15,6 @@ fn xmain() -> ! { let pddb_sid = xns.register_name(api::SERVER_NAME_PDDB, None).expect("can't register server"); log::trace!("registered with NS -- {:?}", pddb_sid); - let mut pddb = Pddb::new(); - log::trace!("ready to accept requests"); // register a suspend/resume listener @@ -29,9 +25,9 @@ fn xmain() -> ! { let msg = xous::receive_message(pddb_sid).unwrap(); match FromPrimitive::from_usize(msg.body.id()) { Some(api::Opcode::SuspendResume) => xous::msg_scalar_unpack!(msg, token, _, _, _, { - pddb.suspend(); + /* pddb.suspend(); susres.suspend_until_resume(token).expect("couldn't execute suspend/resume"); - pddb.resume(); + pddb.resume(); */ }), None => { log::error!("couldn't convert opcode"); diff --git a/xtask/src/main.rs b/xtask/src/main.rs index f1c77b263..2094108b9 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -113,6 +113,15 @@ fn main() -> Result<(), Box> { "com", "susres", ]; + let pddb_dev_pkgs = [ + "ticktimer-server", + "log-server", + "susres", + "xous-names", + "trng", + "pddb", + ]; + let aestest_pkgs = ["ticktimer-server", "log-server", "aes-test"]; let mut args = env::args(); let task = args.nth(1); @@ -138,6 +147,16 @@ fn main() -> Result<(), Box> { Some("hw-image") => { build_hw_image(false, env::args().nth(2), &hw_pkgs, lkey, kkey, None, &[])? } + Some("pddb-dev") => build_hw_image( + false, + env::args().nth(2), + &pddb_dev_pkgs, + lkey, + kkey, + None, + &[], + )?, + Some("pddb-hosted") => run(false, &pddb_dev_pkgs)?, Some("benchmark") => build_hw_image( false, env::args().nth(2), @@ -231,6 +250,8 @@ burn-soc invoke the `usb_update.py` utility to stage the SoC gate nuke-soc 'Factory reset' - invoke the `usb_update.py` utility to burn the SoC gateware, erasing most secrets. For developers. generate-locales only generate the locales include for the language selected in xous-rs/src/locale.rs wycheproof-import generate binary test vectors for engine-25519 from whycheproof-import/x25519.json +pddb-dev PDDB testing only for live hardware +pddb-hosted PDDB testing in a hosted environment Please refer to tools/README_UPDATE.md for instructions on how to set up `usb_update.py` "