//! What init starts, in order: the system's boot policy, as data. use types::budget::Limits; /// A board device init hands to a program over its endpoint. #[derive(Clone, Copy, PartialEq, Eq)] pub enum Device { Gpu, Input, Keystore, Random, } /// A storage grant: a folder (or the whole disk, `b""`) and whether it may /// be changed. #[derive(Clone, Copy)] pub struct Scope { pub path: &'static [u8], pub write: bool, } pub struct Program { pub name: &'static str, pub file: &'static [u8], pub limits: Limits, /// Serves an endpoint, which it finds in slot 0. pub serves: bool, /// Handed over in this order, after it starts. pub devices: &'static [Device], /// Authenticates the owner: init waits for the master key before /// starting anything that touches user data. pub unlocks: bool, /// Earlier programs' endpoints it may call, in its next slots; each /// program's copy carries its own badge, so a server can tell them apart. pub uses: &'static [&'static str], /// Storage it may reach, in the slot after `uses`. pub storage: Option, /// Takes the console over from init; everyone else prints through it. pub console: bool, /// May have init spawn programs, whose limits together stay within this. pub spawns: Option, /// May halt the machine. pub system_control: bool, } /// Enough for a small program: its image, stack and a little heap. pub const SMALL: Limits = Limits { pages: 64, endpoints: 2, notifications: 2, regions: 2, }; const fn server(name: &'static str, file: &'static [u8], limits: Limits) -> Program { Program { name, file, limits, serves: true, devices: &[], unlocks: false, uses: &[], storage: None, console: false, spawns: None, system_control: false, } } /// Started on every boot. The log server comes first so the rest can print. pub const SERVERS: &[Program] = &[ Program { console: true, ..server("log", b"bin/log", SMALL) }, Program { devices: &[Device::Input], ..server("input", b"bin/input", Limits { regions: 4, ..SMALL }) }, // The input server's only client: it passes input on to the app in focus. Program { devices: &[Device::Gpu], uses: &["input"], // The framebuffer alone is ~1000 pages at 1280x800. ..server("display", b"bin/display", Limits { pages: 1280, regions: 4, ..SMALL }) }, // Text on the display, lines from the keyboard (it takes input focus). Program { uses: &["display"], ..server("terminal", b"bin/terminal", SMALL) }, // Nothing that touches user data starts before the owner is in. It // holds the screen (through the terminal), its keystore and randomness, // and exits once it has handed over the key. Program { uses: &["terminal"], devices: &[Device::Keystore, Device::Random], unlocks: true, // argon2's 16 MiB, its image and a little more. ..server("gatekeeper", b"bin/gatekeeper", Limits { pages: 4096 + 160, regions: 6, ..SMALL }) }, // The only one that equips apps (docs/apps.md): it reaches every app's // files and the owner's decisions, and runs apps through init. Program { uses: &["terminal", "display"], storage: Some(Scope { path: b"", write: true }), // Room for a few apps at a time. spawns: Some(Limits { pages: 512, endpoints: 8, notifications: 8, regions: 8 }), ..server("permission", b"bin/permission", Limits { pages: 96, ..SMALL }) }, server("session", b"bin/session", SMALL), ]; /// Run on the test image after the SMP self-test, instead of the desktop: /// spawns through init, then reports and halts. pub const TESTS: &[Program] = &[Program { serves: false, // The permission manager, to run an app the way the shell does. uses: &["permission"], storage: Some(Scope { path: b"", write: true }), spawns: Some(Limits { pages: 128, endpoints: 2, notifications: 2, regions: 2 }), system_control: true, ..server("spawntest", b"bin/spawntest", SMALL) }]; /// The desktop; the test image runs the SMP self-test instead. The shell /// holds the owner's files and asks the permission manager to run apps; /// it holds nothing to give them beyond that. pub const DESKTOP: &[Program] = &[Program { serves: false, uses: &["terminal", "permission"], storage: Some(Scope { path: b"home", write: true }), ..server("shell", b"bin/shell", SMALL) }];