//! Fixed two-page seal model. The page-table adapter is specified separately. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Error { Access, Invalid, Stale, Busy } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Permission { Unmapped, ReadOnly, ReadWrite } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Grant { generation: u32, holder: P } impl Grant

{ pub const fn forge(generation: u32, holder: P) -> Self { Self { generation, holder } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Snapshot { pub frames: [u64; 2], pub contents: [u8; 2], pub recipient: Option

, pub acquired: bool, pub owner_maps: [Permission; 2], pub recipient_maps: [Permission; 2], pub sealed: bool, pub revision: u32, } pub struct SealedPages { owner: P, generation: u32, state: Snapshot

, } impl SealedPages

{ pub fn new(owner: P, frames: [u64; 2]) -> Result { if frames[0] == 0 || frames[1] == 0 || frames[0] == frames[1] { return Err(Error::Invalid); } Ok(Self { owner, generation: 1, state: Snapshot { frames, contents: [0; 2], recipient: None, acquired: false, owner_maps: [Permission::Unmapped; 2], recipient_maps: [Permission::Unmapped; 2], sealed: false, revision: 0, }}) } pub fn snapshot(&self) -> Snapshot

{ self.state } pub fn grant(&mut self, caller: P, recipient: P) -> Result, Error> { if caller != self.owner { return Err(Error::Access); } if recipient == self.owner { return Err(Error::Invalid); } if self.state.recipient.is_some() { return Err(Error::Busy); } self.state.recipient = Some(recipient); self.state.revision += 1; Ok(Grant { generation: self.generation, holder: recipient }) } pub fn acquire(&mut self, caller: P, grant: Grant

) -> Result<(), Error> { if grant.generation != self.generation { return Err(Error::Stale); } if grant.holder != caller || self.state.recipient != Some(caller) { return Err(Error::Access); } self.state.acquired = true; self.state.revision += 1; Ok(()) } pub fn map(&mut self, caller: P, page: usize, writable: bool) -> Result<(u64, Permission), Error> { let frame = *self.state.frames.get(page).ok_or(Error::Invalid)?; if caller != self.owner && !(self.state.recipient == Some(caller) && self.state.acquired) { return Err(Error::Access); } if self.state.sealed && writable { return Err(Error::Access); } let permission = if writable { Permission::ReadWrite } else { Permission::ReadOnly }; let slots = if caller == self.owner { &mut self.state.owner_maps } else { &mut self.state.recipient_maps }; if slots[page] != Permission::Unmapped { return Err(Error::Busy); } slots[page] = permission; self.state.revision += 1; Ok((frame, permission)) } pub fn unmap(&mut self, caller: P, page: usize) -> Result<(), Error> { if page >= 2 { return Err(Error::Invalid); } let slots = if caller == self.owner { &mut self.state.owner_maps } else if self.state.recipient == Some(caller) && self.state.acquired { &mut self.state.recipient_maps } else { return Err(Error::Access); }; if slots[page] == Permission::Unmapped { return Err(Error::Invalid); } slots[page] = Permission::Unmapped; self.state.revision += 1; Ok(()) } pub fn write(&mut self, caller: P, page: usize, byte: u8) -> Result<(), Error> { if page >= 2 { return Err(Error::Invalid); } let map = if caller == self.owner { &self.state.owner_maps } else if self.state.recipient == Some(caller) && self.state.acquired { &self.state.recipient_maps } else { return Err(Error::Access); }; if map[page] != Permission::ReadWrite || self.state.sealed { return Err(Error::Access); } self.state.contents[page] = byte; self.state.revision += 1; Ok(()) } pub fn read(&self, caller: P, page: usize) -> Result { if page >= 2 { return Err(Error::Invalid); } let map = if caller == self.owner { &self.state.owner_maps } else if self.state.recipient == Some(caller) && self.state.acquired { &self.state.recipient_maps } else { return Err(Error::Access); }; if map[page] == Permission::Unmapped { return Err(Error::Access); } Ok(self.state.contents[page]) } pub fn seal(&mut self, caller: P) -> Result<(), Error> { if caller != self.owner { return Err(Error::Access); } if self.state.sealed { return Err(Error::Busy); } for permission in self.state.owner_maps.iter_mut() .chain(self.state.recipient_maps.iter_mut()) { if *permission == Permission::ReadWrite { *permission = Permission::ReadOnly; } } self.state.sealed = true; self.state.revision += 1; Ok(()) } }