feat(boot): gatekeeper gates boot (init→UI→gatekeeper→data); keystore disk + virtio-rng discovery; terminal READ_SECRET; storage SET_KEY; PageCount ≤8192, alloc cap gone; device window 0x01D0_0000; test-qemu types passcode over 2 boots

This commit is contained in:
2026-10-27 23:43:47 +01:00
parent b7ef67ffd8
commit 3b7d004285
36 changed files with 455 additions and 74 deletions

View File

@@ -110,8 +110,12 @@ impl<'a> Launcher<'a> {
if let Some(free) = self.served.iter_mut().find(|s| s.is_none()) {
*free = Some((p.name, ep));
}
if let Some(device) = p.device {
note = self.give(device, ep);
for device in p.devices {
note = self.give(*device, ep);
}
if p.unlocks {
unlock(ep)?;
note = ", the owner is in";
}
if console.is_some() {
hand_over_console(ep);
@@ -139,6 +143,8 @@ impl<'a> Launcher<'a> {
let (dev, given, none): (BoardDevice, _, _) = match device {
Device::Gpu => (self.devices.gpu, ", gpu handed over", ", no gpu"),
Device::Input => (self.devices.input, ", input device handed over", ", no input device"),
Device::Keystore => (self.devices.keystore, ", keystore handed over", ", no keystore"),
Device::Random => (self.devices.random, ", randomness handed over", ", no randomness"),
};
match libkos::device::give_device(ep, dev).is_ok() && dev.mmio.is_some() {
true => given,
@@ -147,6 +153,23 @@ impl<'a> Launcher<'a> {
}
}
/// Waits for the gatekeeper behind `ep` to authenticate the owner, then
/// passes the master key on to storage, which alone keeps it.
fn unlock(ep: CapSlot) -> Result<(), &'static str> {
use types::gatekeeper::{KEY, UNLOCK, reply};
match syscall::request(ep, [UNLOCK, 0, 0, 0]) {
Ok([reply::OK, ..]) => {}
_ => return Err("the gatekeeper could not unlock"),
}
let mut key = syscall::request(ep, [KEY, 0, 0, 0]).map_err(|_| "the gatekeeper gave no key")?;
let given = [0, 1].iter().all(|&half| {
let words = [types::storage::op::SET_KEY, half, key[half * 2], key[half * 2 + 1]];
syscall::request(crate::STORAGE_EP, words).is_ok_and(|r| r[0] == types::storage::reply::OK)
});
key.fill(0);
if given { Ok(()) } else { Err("storage would not take the key") }
}
/// From here on init prints through the log server, like everyone else,
/// and holds no console of its own.
fn hand_over_console(log: CapSlot) {