Files
k-os/crates/init/src/manifest.rs

188 lines
7.0 KiB
Rust

//! What init starts, in order: the system's boot policy, as data.
use types::budget::Limits;
/// Whether a program holds the session: who is signed in, signing out.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Session {
No,
/// For itself only (the shell).
Own,
/// To pass on to apps granted `session` (the permission manager).
PassOn,
}
/// 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. With `user`, the path is inside the signed-in user's folder.
#[derive(Clone, Copy)]
pub struct Scope {
pub path: &'static [u8],
pub write: bool,
pub user: bool,
}
const fn disk(path: &'static [u8], write: bool) -> Scope {
Scope { path, write, user: false }
}
const fn users(path: &'static [u8], write: bool) -> Scope {
Scope { path, write, user: true }
}
pub struct Program {
pub name: &'static str,
pub file: &'static [u8],
pub limits: Limits,
/// Its stack, in pages.
pub stack_pages: usize,
/// Serves an endpoint, which it finds in slot 0.
pub serves: bool,
/// Handed over in this order, after it starts.
pub devices: &'static [Device],
/// 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 slots after `uses`.
pub storage: &'static [Scope],
/// 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<Limits>,
/// May halt the machine.
pub system_control: bool,
/// The session (`types::spawn::SIGN_OUT`, `WHO`), in the next slot.
pub session: Session,
/// Takes Ctrl+C: a terminal copy with `types::terminal::CONTROL`, last.
pub takes_ctrl_c: bool,
/// Started again if it dies (see init's supervise.rs).
pub restart: bool,
/// Its clients keep state in it (a subscription, focus, a handle), so
/// they are restarted after it is.
pub restarts_clients: bool,
/// Pinged by the watchdog (see init's watchdog.rs): not if a handler of
/// its waits for the user, which a ping cannot tell from a hang.
pub pinged: 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,
stack_pages: crate::load::STACK_PAGES,
serves: true,
devices: &[],
uses: &[],
storage: &[],
console: false,
spawns: None,
system_control: false,
session: Session::No,
takes_ctrl_c: false,
restart: true,
restarts_clients: false,
pinged: true,
}
}
/// 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) },
// The display subscribes to it.
Program { devices: &[Device::Input], restarts_clients: true, ..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 themes, read once at start.
storage: &[disk(b"themes", false)],
// Its clients subscribe and take focus.
restarts_clients: true,
// Its windows' state (input queues among it) is ~10 KiB, and the
// server is built on the stack.
stack_pages: 14,
// The framebuffer is ~1000 pages at 1280x800, and so is each of
// the (at most 8) windows' pixel buffers, which it owns.
..server("display", b"bin/display", Limits { pages: 9300, regions: 13, ..SMALL })
},
// Text on the display, lines from the keyboard (it takes input focus).
// Its clients wait on lines and Ctrl+C. It draws its own text now,
// beside a screenful of grid.
Program { uses: &["display"], restarts_clients: true, stack_pages: 8, ..server("terminal", b"bin/terminal", SMALL) },
server("session", b"bin/session", SMALL),
];
/// Started for each sign-in, before anything that touches a user's files.
/// It holds the screen (through the terminal), its keystore and randomness,
/// and exits once it has handed over who is in and their key.
pub const GATEKEEPER: Program = Program {
uses: &["terminal"],
devices: &[Device::Keystore, Device::Random],
// A user's record is KiBs, and it handles a few at once.
stack_pages: 12,
// It exits once it has handed over; a new one runs at each sign-in.
restart: false,
// argon2's 16 MiB, its image and a little more.
..server("gatekeeper", b"bin/gatekeeper", Limits { pages: 4096 + 160, regions: 6, ..SMALL })
};
/// Started for each signed-in user, and stopped when they sign out. The
/// permission manager is the only one that equips apps (docs/apps.md): it
/// reaches the user's apps, their data and decisions, and the system's apps
/// (read-only), and runs apps through init.
pub const SESSION: &[Program] = &[Program {
uses: &["terminal", "display"],
storage: &[users(b"", true), disk(b"apps", false)],
// Room for several apps at a time (24 MiB between them).
spawns: Some(Limits { pages: 6144, endpoints: 12, notifications: 12, regions: 12 }),
// The shell holds handles to the apps it ran, which die with it.
restarts_clients: true,
session: Session::PassOn,
// Installing waits for the user's consent.
pinged: false,
..server("permission", b"bin/permission", Limits { pages: 96, ..SMALL })
}];
/// Run on the test image after the SMP self-test, instead of the desktop:
/// spawns through init, then reports and halts. `flaky` dies when asked,
/// for spawntest to see it restarted.
pub const TESTS: &[Program] = &[server("flaky", b"bin/flaky", SMALL), Program {
serves: false,
// The permission manager, to run an app the way the shell does.
uses: &["permission", "flaky"],
storage: &[disk(b"", true), users(b"home", true)],
spawns: Some(Limits { pages: 128, endpoints: 2, notifications: 2, regions: 2 }),
system_control: true,
restart: false,
..server("spawntest", b"bin/spawntest", SMALL)
}];
/// The desktop; the test image runs the SMP self-test instead. The shell
/// holds the user's files and asks the permission manager to run apps;
/// it holds nothing to give them beyond that, and may sign the user out.
pub const DESKTOP: &[Program] = &[Program {
serves: false,
uses: &["terminal", "permission"],
storage: &[users(b"home", true)],
session: Session::Own,
takes_ctrl_c: true,
..server("shell", b"bin/shell", SMALL)
}];