feat(init): add init crate with declarative boot manifest, boot sequence, supervisor and shutdown stubs
Also: make types from_raw/raw const fn, add create_process/kill/delegate/revoke to userspace syscall stubs.
This commit is contained in:
83
crates/init/src/boot.rs
Normal file
83
crates/init/src/boot.rs
Normal file
@@ -0,0 +1,83 @@
|
||||
use crate::manifest::{BootManifest, EndpointBinding, HardwareCap};
|
||||
use types::bounded::CapSlot;
|
||||
use userspace::syscall;
|
||||
|
||||
const MAX_ENDPOINTS: usize = 16;
|
||||
|
||||
struct EndpointEntry {
|
||||
name: &'static str,
|
||||
slot: CapSlot,
|
||||
}
|
||||
|
||||
struct EndpointRegistry {
|
||||
entries: [Option<EndpointEntry>; MAX_ENDPOINTS],
|
||||
count: usize,
|
||||
}
|
||||
|
||||
impl EndpointRegistry {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
entries: [const { None }; MAX_ENDPOINTS],
|
||||
count: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn register(&mut self, name: &'static str, slot: CapSlot) {
|
||||
if self.count < MAX_ENDPOINTS {
|
||||
self.entries[self.count] = Some(EndpointEntry { name, slot });
|
||||
self.count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn find(&self, name: &str) -> Option<CapSlot> {
|
||||
for entry in &self.entries {
|
||||
if let Some(e) = entry {
|
||||
if e.name == name {
|
||||
return Some(e.slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn boot(manifest: &BootManifest, create_cap: CapSlot) {
|
||||
let mut endpoints = EndpointRegistry::new();
|
||||
|
||||
for server in manifest.servers {
|
||||
let _pid = syscall::create_process(create_cap.value() as usize);
|
||||
|
||||
for binding in server.endpoints {
|
||||
if let EndpointBinding::Own { name } = binding {
|
||||
// TODO: create endpoint syscall, get CapSlot back
|
||||
// TODO: delegate endpoint cap to server process
|
||||
if let Some(slot) = CapSlot::new(0) {
|
||||
endpoints.register(name, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for hw_cap in server.hardware_caps {
|
||||
match hw_cap {
|
||||
HardwareCap::Framebuffer { base: _, pages: _ } => {
|
||||
// TODO: grant memory cap for framebuffer region
|
||||
}
|
||||
HardwareCap::Irq { irq: _ } => {
|
||||
// TODO: grant interrupt cap
|
||||
}
|
||||
HardwareCap::Memory { base: _, pages: _ } => {
|
||||
// TODO: grant memory cap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for app in manifest.apps {
|
||||
let _pid = syscall::create_process(create_cap.value() as usize);
|
||||
|
||||
for (_server_name, endpoint_name) in app.connects_to {
|
||||
let _ep = endpoints.find(endpoint_name);
|
||||
// TODO: delegate endpoint cap to app process
|
||||
}
|
||||
}
|
||||
}
|
||||
6
crates/init/src/lib.rs
Normal file
6
crates/init/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
#![no_std]
|
||||
|
||||
pub mod boot;
|
||||
pub mod manifest;
|
||||
pub mod shutdown;
|
||||
pub mod supervisor;
|
||||
92
crates/init/src/manifest.rs
Normal file
92
crates/init/src/manifest.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use types::address::PhysicalAddress;
|
||||
use types::bounded::{CapSlot, Priority};
|
||||
use types::id::IrqId;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum HardwareCap {
|
||||
Framebuffer { base: PhysicalAddress, pages: usize },
|
||||
Irq { irq: IrqId },
|
||||
Memory { base: PhysicalAddress, pages: usize },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum EndpointBinding {
|
||||
Own { name: &'static str },
|
||||
ConnectTo { server: &'static str, endpoint: &'static str },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ServerEntry {
|
||||
pub name: &'static str,
|
||||
pub priority: Priority,
|
||||
pub memory_pages: usize,
|
||||
pub hardware_caps: &'static [HardwareCap],
|
||||
pub endpoints: &'static [EndpointBinding],
|
||||
pub restartable: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AppEntry {
|
||||
pub name: &'static str,
|
||||
pub priority: Priority,
|
||||
pub memory_pages: usize,
|
||||
pub connects_to: &'static [(&'static str, &'static str)],
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct BootManifest {
|
||||
pub servers: &'static [ServerEntry],
|
||||
pub apps: &'static [AppEntry],
|
||||
}
|
||||
|
||||
pub static SNAKE_MANIFEST: BootManifest = BootManifest {
|
||||
servers: &[
|
||||
ServerEntry {
|
||||
name: "log",
|
||||
priority: Priority::DEFAULT,
|
||||
memory_pages: 64,
|
||||
hardware_caps: &[],
|
||||
endpoints: &[EndpointBinding::Own { name: "log" }],
|
||||
restartable: true,
|
||||
},
|
||||
ServerEntry {
|
||||
name: "permission",
|
||||
priority: Priority::DEFAULT,
|
||||
memory_pages: 32,
|
||||
hardware_caps: &[],
|
||||
endpoints: &[EndpointBinding::Own { name: "permission" }],
|
||||
restartable: true,
|
||||
},
|
||||
ServerEntry {
|
||||
name: "display",
|
||||
priority: Priority::DEFAULT,
|
||||
memory_pages: 256,
|
||||
hardware_caps: &[
|
||||
HardwareCap::Framebuffer {
|
||||
base: PhysicalAddress::from_raw(0x10008000),
|
||||
pages: 75,
|
||||
},
|
||||
],
|
||||
endpoints: &[EndpointBinding::Own { name: "display" }],
|
||||
restartable: true,
|
||||
},
|
||||
ServerEntry {
|
||||
name: "input",
|
||||
priority: Priority::DEFAULT,
|
||||
memory_pages: 32,
|
||||
hardware_caps: &[
|
||||
HardwareCap::Irq { irq: IrqId::from_raw(10) },
|
||||
],
|
||||
endpoints: &[EndpointBinding::Own { name: "input" }],
|
||||
restartable: true,
|
||||
},
|
||||
],
|
||||
apps: &[
|
||||
AppEntry {
|
||||
name: "snake",
|
||||
priority: Priority::DEFAULT,
|
||||
memory_pages: 64,
|
||||
connects_to: &[("display", "display"), ("input", "input")],
|
||||
},
|
||||
],
|
||||
};
|
||||
3
crates/init/src/shutdown.rs
Normal file
3
crates/init/src/shutdown.rs
Normal file
@@ -0,0 +1,3 @@
|
||||
pub fn shutdown() -> ! {
|
||||
userspace::syscall::exit();
|
||||
}
|
||||
7
crates/init/src/supervisor.rs
Normal file
7
crates/init/src/supervisor.rs
Normal file
@@ -0,0 +1,7 @@
|
||||
use crate::manifest::BootManifest;
|
||||
|
||||
pub fn supervise(_manifest: &BootManifest) -> ! {
|
||||
loop {
|
||||
userspace::syscall::yield_now();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user