feat(settings): settings app: apps list + per-capability allow/revoke, about (who/role), sign out; system-only caps permissions/session (install refused); pm MANAGE_BADGE copy (list/apps/allow/revoke only), APPS op; init WHO + session pass-on; factory decisions seeded for new system apps; k-ui list_item/toggle, screens/back/scroll
This commit is contained in:
@@ -24,6 +24,15 @@ pub const LIST: usize = 5;
|
||||
/// owner takes it away (a running app that had it is stopped) or gives it.
|
||||
pub const REVOKE: usize = 6;
|
||||
pub const ALLOW: usize = 7;
|
||||
/// Writes one line per installed app into the page, for a program to read:
|
||||
/// id, name, then the required, optional and granted capabilities' bits
|
||||
/// (decimal), tab separated. Reply `OK` with the text's length in word 1.
|
||||
pub const APPS: usize = 8;
|
||||
|
||||
/// On the badge of the copy of its endpoint the permission manager gives
|
||||
/// an app granted `permissions`: through it only `LIST`, `APPS`, `REVOKE`
|
||||
/// and `ALLOW` work, never installing or launching.
|
||||
pub const MANAGE_BADGE: usize = 1 << 61;
|
||||
|
||||
/// The request page's size.
|
||||
pub const PAGE_SIZE: usize = 4096;
|
||||
@@ -46,4 +55,6 @@ pub mod reply {
|
||||
pub const FAILED: usize = 9;
|
||||
/// The offered folder has no `manifest.toml`.
|
||||
pub const NO_MANIFEST: usize = 10;
|
||||
/// Word 1: the capabilities it asks for that only system apps may have.
|
||||
pub const SYSTEM_ONLY: usize = 11;
|
||||
}
|
||||
|
||||
@@ -104,27 +104,9 @@ pub mod window {
|
||||
pub const OK: usize = 0;
|
||||
pub const PIXEL_BYTES: usize = 4;
|
||||
/// Longest name the OS bar shows.
|
||||
pub const NAME_BYTES: usize = 24;
|
||||
pub use crate::name::BYTES as NAME_BYTES;
|
||||
|
||||
/// A name in three words, NUL padded, cut at `NAME_BYTES`.
|
||||
pub fn pack_name(name: &[u8]) -> [usize; 3] {
|
||||
let mut bytes = [0u8; NAME_BYTES];
|
||||
let n = name.len().min(NAME_BYTES);
|
||||
bytes[..n].copy_from_slice(&name[..n]);
|
||||
core::array::from_fn(|i| {
|
||||
u64::from_le_bytes(bytes[i * 8..i * 8 + 8].try_into().unwrap_or([0; 8])) as usize
|
||||
})
|
||||
}
|
||||
|
||||
/// The name in `words`, and how long it is.
|
||||
pub fn unpack_name(words: [usize; 3]) -> ([u8; NAME_BYTES], usize) {
|
||||
let mut bytes = [0u8; NAME_BYTES];
|
||||
for (chunk, w) in bytes.chunks_mut(8).zip(words) {
|
||||
chunk.copy_from_slice(&(w as u64).to_le_bytes());
|
||||
}
|
||||
let len = bytes.iter().position(|b| *b == 0).unwrap_or(NAME_BYTES);
|
||||
(bytes, len)
|
||||
}
|
||||
pub use crate::name::{pack as pack_name, unpack as unpack_name};
|
||||
|
||||
/// A rectangle in two words: `x | y << 16` and `w | h << 16`.
|
||||
pub fn pack_rect(x: ScreenCoord, y: ScreenCoord, w: Dimension, h: Dimension) -> [usize; 2] {
|
||||
|
||||
@@ -15,6 +15,7 @@ pub mod input;
|
||||
pub mod log;
|
||||
pub mod macros;
|
||||
pub mod mapping;
|
||||
pub mod name;
|
||||
pub mod permission;
|
||||
#[cfg(kani)]
|
||||
pub mod proofs;
|
||||
|
||||
23
crates/types/src/name.rs
Normal file
23
crates/types/src/name.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
//! A short name (a user's, an app's) in three message words, NUL padded.
|
||||
|
||||
pub const BYTES: usize = 24;
|
||||
|
||||
/// `name`, cut at `BYTES`.
|
||||
pub fn pack(name: &[u8]) -> [usize; 3] {
|
||||
let mut bytes = [0u8; BYTES];
|
||||
let n = name.len().min(BYTES);
|
||||
bytes[..n].copy_from_slice(&name[..n]);
|
||||
core::array::from_fn(|i| {
|
||||
u64::from_le_bytes(bytes[i * 8..i * 8 + 8].try_into().unwrap_or([0; 8])) as usize
|
||||
})
|
||||
}
|
||||
|
||||
/// The name in `words`, and how long it is.
|
||||
pub fn unpack(words: [usize; 3]) -> ([u8; BYTES], usize) {
|
||||
let mut bytes = [0u8; BYTES];
|
||||
for (chunk, w) in bytes.chunks_mut(8).zip(words) {
|
||||
chunk.copy_from_slice(&(w as u64).to_le_bytes());
|
||||
}
|
||||
let len = bytes.iter().position(|b| *b == 0).unwrap_or(BYTES);
|
||||
(bytes, len)
|
||||
}
|
||||
@@ -20,6 +20,15 @@ pub const NONE: usize = usize::MAX;
|
||||
/// Sent one way (no reply: the sender is about to be stopped) through the
|
||||
/// endpoint copy init gives a session's shell: the user signs out.
|
||||
pub const SIGN_OUT: usize = 1;
|
||||
/// Through the same copy: who is signed in. Reply `[role, name...]`, the
|
||||
/// name in three words (`types::name`); role as in `role`.
|
||||
pub const WHO: usize = 2;
|
||||
|
||||
pub mod role {
|
||||
pub const OWNER: usize = 1;
|
||||
pub const STANDARD: usize = 2;
|
||||
pub const GUEST: usize = 3;
|
||||
}
|
||||
/// The badge on that copy; spawn clients' badges are small indices.
|
||||
pub const SESSION_BADGE: usize = 0x5E55;
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ const STORAGE_SHIFT: u32 = 16;
|
||||
const ARGS_BIT: usize = 1 << 24;
|
||||
const DISPLAY_SHIFT: u32 = 32;
|
||||
const DATA_SHIFT: u32 = 40;
|
||||
const PERMISSIONS_SHIFT: u32 = 48;
|
||||
const SESSION_SHIFT: u32 = 56;
|
||||
|
||||
/// Where the arguments page sits: the program's arguments, NUL separated,
|
||||
/// the first its name. Below the stack, which ends at the image.
|
||||
@@ -27,6 +29,10 @@ pub struct StartArg {
|
||||
pub display: Option<CapSlot>,
|
||||
/// The app's own data folder, read-write (its `storage` capability).
|
||||
pub data: Option<CapSlot>,
|
||||
/// Managing other apps' permissions (the `permissions` capability).
|
||||
pub permissions: Option<CapSlot>,
|
||||
/// Who is signed in, and signing out (the `session` capability).
|
||||
pub session: Option<CapSlot>,
|
||||
}
|
||||
|
||||
fn field(arg: usize, shift: u32) -> Option<CapSlot> {
|
||||
@@ -46,6 +52,8 @@ impl StartArg {
|
||||
| if self.args { ARGS_BIT } else { 0 }
|
||||
| put(self.display, DISPLAY_SHIFT)
|
||||
| put(self.data, DATA_SHIFT)
|
||||
| put(self.permissions, PERMISSIONS_SHIFT)
|
||||
| put(self.session, SESSION_SHIFT)
|
||||
}
|
||||
|
||||
pub fn decode(arg: usize) -> Self {
|
||||
@@ -56,6 +64,8 @@ impl StartArg {
|
||||
args: arg & ARGS_BIT != 0,
|
||||
display: field(arg, DISPLAY_SHIFT),
|
||||
data: field(arg, DATA_SHIFT),
|
||||
permissions: field(arg, PERMISSIONS_SHIFT),
|
||||
session: field(arg, SESSION_SHIFT),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -73,6 +83,8 @@ mod tests {
|
||||
args: true,
|
||||
display: CapSlot::new(7),
|
||||
data: CapSlot::new(62),
|
||||
permissions: CapSlot::new(9),
|
||||
session: CapSlot::new(63),
|
||||
};
|
||||
assert_eq!(StartArg::decode(a.encode()), a);
|
||||
assert_eq!(StartArg::decode(0), StartArg::default());
|
||||
|
||||
Reference in New Issue
Block a user