mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
commit to journal of bad ideas issue #243: a misguided attempt at a PDDB API.
This commit is contained in:
parent
21e320a905
commit
46f1f60cda
6 changed files with 206 additions and 80 deletions
|
|
@ -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<PddbDict>;
|
||||
// creates a dictionary only if it does not already exist
|
||||
pub fn create(dict_name: &str) -> Option<PddbDict>;
|
||||
|
||||
// returns a key only if it exists
|
||||
pub fn get(&mut self, key_name: &str, key_changed_cb: CB) -> Result<PddbKey>;
|
||||
// updates an existing key's value. mainly used by write().
|
||||
pub fn update(&mut self, key: PddbKey) -> Result<Option<PddbKey>>;
|
||||
// creates a key or overwrites it
|
||||
pub fn insert(&mut self, key: PddbKey) -> Option<PddbKey>; // 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<CB>
|
||||
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<usize>;
|
||||
// writes will call update() on the dictionary
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize>;
|
||||
// provided for compatibility with Rust API
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
|
||||
}
|
||||
|
||||
pub struct PddbBasis {
|
||||
|
||||
}
|
||||
2
services/pddb/src/frontend.rs
Normal file
2
services/pddb/src/frontend.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod pddbkey;
|
||||
pub use pddbkey::*;
|
||||
44
services/pddb/src/frontend/pddbkey.rs
Normal file
44
services/pddb/src/frontend/pddbkey.rs
Normal file
|
|
@ -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<dyn FnMut() + 'a>,
|
||||
// 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<usize> { Ok(0) }
|
||||
// writes will call update() on the dictionary
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize> { Ok(0) }
|
||||
// provided for compatibility with Rust API
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<u64> { Ok(0) }
|
||||
*/
|
||||
}
|
||||
|
|
@ -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<Self, xous::Error> {
|
||||
pub fn new(xns: &xous_names::XousNames) -> core::result::Result<Self, xous::Error> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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<PddbKey<'a>, &'a [u8]>,
|
||||
callback: Box<dyn FnMut() + 'a>,
|
||||
}
|
||||
impl<'a> PddbDict<'a> {
|
||||
// opens a dictionary only if it exists
|
||||
pub fn open(dict_name: &str) -> Option<PddbDict> { None }
|
||||
// creates a dictionary only if it does not already exist
|
||||
pub fn create(dict_name: &str) -> Option<PddbDict> { None }
|
||||
|
||||
// returns a key only if it exists
|
||||
pub fn get(&mut self, key_name: &str, key_changed_cb: impl FnMut() + 'a) -> Result<Option<PddbKey>> {
|
||||
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<Option<PddbKey>> { Ok(None) }
|
||||
// creates a key or overwrites it
|
||||
pub fn insert(&mut self, key: PddbKey) -> Option<PddbKey> { 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) {}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -113,6 +113,15 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||
"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<dyn std::error::Error>> {
|
|||
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`
|
||||
"
|
||||
|
|
|
|||
Loading…
Reference in a new issue