diff --git a/Cargo.toml b/Cargo.toml index da4c61f..e4ce546 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ members = [ "crates/apps/snake", "crates/domain", "crates/elf", + "crates/init", "crates/kernel", "crates/platform", "crates/server-framework", diff --git a/crates/init/Cargo.toml b/crates/init/Cargo.toml new file mode 100644 index 0000000..e5af0a4 --- /dev/null +++ b/crates/init/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "init" +version = "0.1.0" +edition = "2024" + +[dependencies] +types = { workspace = true } +userspace = { workspace = true } diff --git a/crates/init/src/boot.rs b/crates/init/src/boot.rs new file mode 100644 index 0000000..420478b --- /dev/null +++ b/crates/init/src/boot.rs @@ -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; 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 { + 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 + } + } +} diff --git a/crates/init/src/lib.rs b/crates/init/src/lib.rs new file mode 100644 index 0000000..1eb71ed --- /dev/null +++ b/crates/init/src/lib.rs @@ -0,0 +1,6 @@ +#![no_std] + +pub mod boot; +pub mod manifest; +pub mod shutdown; +pub mod supervisor; diff --git a/crates/init/src/manifest.rs b/crates/init/src/manifest.rs new file mode 100644 index 0000000..dc93c96 --- /dev/null +++ b/crates/init/src/manifest.rs @@ -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")], + }, + ], +}; diff --git a/crates/init/src/shutdown.rs b/crates/init/src/shutdown.rs new file mode 100644 index 0000000..fb3aa46 --- /dev/null +++ b/crates/init/src/shutdown.rs @@ -0,0 +1,3 @@ +pub fn shutdown() -> ! { + userspace::syscall::exit(); +} diff --git a/crates/init/src/supervisor.rs b/crates/init/src/supervisor.rs new file mode 100644 index 0000000..081bad5 --- /dev/null +++ b/crates/init/src/supervisor.rs @@ -0,0 +1,7 @@ +use crate::manifest::BootManifest; + +pub fn supervise(_manifest: &BootManifest) -> ! { + loop { + userspace::syscall::yield_now(); + } +} diff --git a/crates/types/src/address.rs b/crates/types/src/address.rs index 28d3724..49a30df 100644 --- a/crates/types/src/address.rs +++ b/crates/types/src/address.rs @@ -2,11 +2,11 @@ pub struct EntryPoint(usize); impl EntryPoint { - pub fn from_raw(addr: usize) -> Self { + pub const fn from_raw(addr: usize) -> Self { Self(addr) } - pub fn raw(&self) -> usize { + pub const fn raw(&self) -> usize { self.0 } } @@ -15,11 +15,11 @@ impl EntryPoint { pub struct StackPointer(usize); impl StackPointer { - pub fn from_raw(addr: usize) -> Self { + pub const fn from_raw(addr: usize) -> Self { Self(addr) } - pub fn raw(&self) -> usize { + pub const fn raw(&self) -> usize { self.0 } } @@ -28,11 +28,11 @@ impl StackPointer { pub struct VirtualAddress(usize); impl VirtualAddress { - pub fn from_raw(addr: usize) -> Self { + pub const fn from_raw(addr: usize) -> Self { Self(addr) } - pub fn raw(&self) -> usize { + pub const fn raw(&self) -> usize { self.0 } } @@ -41,11 +41,11 @@ impl VirtualAddress { pub struct PhysicalAddress(usize); impl PhysicalAddress { - pub fn from_raw(addr: usize) -> Self { + pub const fn from_raw(addr: usize) -> Self { Self(addr) } - pub fn raw(&self) -> usize { + pub const fn raw(&self) -> usize { self.0 } diff --git a/crates/types/src/macros.rs b/crates/types/src/macros.rs index 86078fd..26603ef 100644 --- a/crates/types/src/macros.rs +++ b/crates/types/src/macros.rs @@ -4,11 +4,11 @@ macro_rules! kernel_id { pub struct $name($inner); impl $name { - pub fn from_raw(value: $inner) -> Self { + pub const fn from_raw(value: $inner) -> Self { Self(value) } - pub fn raw(&self) -> $inner { + pub const fn raw(&self) -> $inner { self.0 } } diff --git a/crates/userspace/src/syscall.rs b/crates/userspace/src/syscall.rs index 056f0ed..fcc6213 100644 --- a/crates/userspace/src/syscall.rs +++ b/crates/userspace/src/syscall.rs @@ -31,6 +31,22 @@ pub fn request_pages(count: usize) -> usize { arch::syscall1(SYS_REQUEST_PAGES, count) } +pub fn create_process(create_cap: usize) -> usize { + arch::syscall1(SYS_CREATE_PROCESS, create_cap) +} + +pub fn kill(process_cap: usize) -> usize { + arch::syscall1(SYS_KILL, process_cap) +} + +pub fn delegate(slot: usize, to: usize, permissions: usize) -> usize { + arch::syscall2(SYS_DELEGATE, slot, to) +} + +pub fn revoke(slot: usize) -> usize { + arch::syscall1(SYS_REVOKE, slot) +} + pub fn send(endpoint: usize, w0: usize, w1: usize, w2: usize, w3: usize) -> usize { arch::syscall5(SYS_SEND, endpoint, w0, w1, w2, w3) }