188 lines
7.0 KiB
Rust
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)
|
|
}];
|