1#![allow(clippy::if_same_then_else)]
7
8use alloc::{collections::BTreeMap, string::String, vec, vec::Vec};
9use core::sync::atomic::{AtomicBool, AtomicU32, Ordering};
10
11use spin::RwLock;
12
13use crate::{error::KernelError, process::ProcessId};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub enum ServiceState {
18 Stopped,
19 Starting,
20 Running,
21 Stopping,
22 Failed,
23 Restarting,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum RestartPolicy {
29 Never, OnFailure, Always, UnlessStopped, }
34
35#[derive(Debug, Clone, Copy, PartialEq, Eq)]
37pub enum DependencyType {
38 Requires, Wants, After, Before, }
43
44#[derive(Debug, Clone)]
46pub struct ServiceDefinition {
47 pub name: String,
48 pub description: String,
49 pub command: String,
50 pub arguments: Vec<String>,
51 pub environment: Vec<String>,
52 pub working_directory: String,
53 pub user: u32,
54 pub group: u32,
55 pub restart_policy: RestartPolicy,
56 pub restart_delay_ms: u32,
57 pub max_restarts: u32,
58 pub timeout_ms: u32,
59 pub dependencies: Vec<(String, DependencyType)>,
60 pub start_level: u32, pub stop_timeout: Option<u32>, }
63
64#[derive(Debug, Clone)]
66pub struct ServiceInfo {
67 pub definition: ServiceDefinition,
68 pub state: ServiceState,
69 pub pid: Option<ProcessId>,
70 pub start_time: u64,
71 pub restart_count: u32,
72 pub exit_code: Option<i32>,
73 pub last_error: Option<String>,
74}
75
76#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
78pub enum Runlevel {
79 Halt = 0, Single = 1, Multi = 2, Network = 3, Reserved = 4, Graphical = 5, Reboot = 6, }
87
88pub struct InitSystem {
90 services: RwLock<BTreeMap<String, ServiceInfo>>,
92
93 current_runlevel: AtomicU32,
95
96 target_runlevel: AtomicU32,
98
99 shutting_down: AtomicBool,
101
102 init_pid: AtomicU32,
104
105 start_order: RwLock<Vec<String>>,
107
108 monitoring_active: AtomicBool,
110}
111
112impl InitSystem {
113 pub fn new() -> Self {
115 Self {
116 services: RwLock::new(BTreeMap::new()),
117 current_runlevel: AtomicU32::new(Runlevel::Halt as u32),
118 target_runlevel: AtomicU32::new(Runlevel::Multi as u32),
119 shutting_down: AtomicBool::new(false),
120 init_pid: AtomicU32::new(1),
121 start_order: RwLock::new(Vec::new()),
122 monitoring_active: AtomicBool::new(false),
123 }
124 }
125}
126
127impl Default for InitSystem {
128 fn default() -> Self {
129 Self::new()
130 }
131}
132
133impl InitSystem {
134 pub fn initialize(&self) -> Result<(), KernelError> {
136 crate::println!("[INIT] Initializing init system...");
137
138 self.register_core_services()?;
140
141 self.compute_start_order()?;
143
144 self.monitoring_active.store(true, Ordering::SeqCst);
146
147 self.switch_runlevel(Runlevel::Single)?;
149
150 crate::println!("[INIT] Init system initialized");
151 Ok(())
152 }
153
154 pub fn register_service(&self, definition: ServiceDefinition) -> Result<(), KernelError> {
156 let name = definition.name.clone();
157
158 if self.services.read().contains_key(&name) {
159 return Err(KernelError::AlreadyExists {
160 resource: "service",
161 id: 0,
162 });
163 }
164
165 let info = ServiceInfo {
166 definition,
167 state: ServiceState::Stopped,
168 pid: None,
169 start_time: 0,
170 restart_count: 0,
171 exit_code: None,
172 last_error: None,
173 };
174
175 self.services.write().insert(name.clone(), info);
176 crate::println!("[INIT] Registered service: {}", name);
177
178 self.compute_start_order()?;
180
181 Ok(())
182 }
183
184 pub fn start_service(&self, name: &str) -> Result<(), KernelError> {
186 let mut services = self.services.write();
187
188 let service = services.get_mut(name).ok_or(KernelError::NotFound {
189 resource: "service",
190 id: 0,
191 })?;
192
193 if service.state == ServiceState::Running {
194 return Ok(()); }
196
197 crate::println!("[INIT] Starting service: {}", name);
198 service.state = ServiceState::Starting;
199
200 drop(services); self.check_dependencies(name)?;
203 let mut services = self.services.write();
204 let service = services
205 .get_mut(name)
206 .expect("service disappeared between dependency check and start");
207
208 let process_server = crate::services::process_server::get_process_server();
210
211 let pid = process_server.create_process(
212 ProcessId(self.init_pid.load(Ordering::SeqCst) as u64),
213 service.definition.command.clone(),
214 service.definition.user,
215 service.definition.group,
216 {
217 let mut args = vec![service.definition.command.clone()];
218 args.extend(service.definition.arguments.clone());
219 args
220 },
221 service.definition.environment.clone(),
222 )?;
223
224 service.pid = Some(pid);
225 service.state = ServiceState::Running;
226 service.start_time = self.get_system_time();
227 service.last_error = None;
228
229 crate::println!("[INIT] Service {} started with PID {}", name, pid.0);
230 Ok(())
231 }
232
233 pub fn stop_service(&self, name: &str) -> Result<(), KernelError> {
235 let mut services = self.services.write();
236
237 let service = services.get_mut(name).ok_or(KernelError::NotFound {
238 resource: "service",
239 id: 0,
240 })?;
241
242 if service.state != ServiceState::Running {
243 return Ok(()); }
245
246 crate::println!("[INIT] Stopping service: {}", name);
247 service.state = ServiceState::Stopping;
248
249 if let Some(pid) = service.pid {
250 let process_server = crate::services::process_server::get_process_server();
251
252 process_server.send_signal(pid, 15)?;
254
255 let timeout_secs = service.definition.stop_timeout.unwrap_or(10) as u64;
257 let start = crate::arch::timer::get_timestamp_secs();
258
259 loop {
260 if process_server.wait_for_child(pid, None).is_ok() {
262 break; }
264
265 let elapsed = crate::arch::timer::get_timestamp_secs().saturating_sub(start);
267 if elapsed >= timeout_secs {
268 crate::println!(
270 "[INIT] Service {} did not stop within {}s, sending SIGKILL",
271 name,
272 timeout_secs
273 );
274 if let Err(_e) = process_server.send_signal(pid, 9) {
275 crate::println!(
276 "[INIT] Warning: SIGKILL to PID {} failed: {:?}",
277 pid.0,
278 _e
279 );
280 }
281 break;
282 }
283
284 core::hint::spin_loop();
285 }
286
287 service.state = ServiceState::Stopped;
288 service.pid = None;
289
290 crate::println!("[INIT] Service {} stopped", name);
291 }
292
293 Ok(())
294 }
295
296 pub fn restart_service(&self, name: &str) -> Result<(), KernelError> {
298 self.stop_service(name)?;
299 self.start_service(name)?;
300 Ok(())
301 }
302
303 pub fn get_service_status(&self, name: &str) -> Option<ServiceInfo> {
305 self.services.read().get(name).cloned()
306 }
307
308 pub fn list_services(&self) -> Vec<ServiceInfo> {
310 self.services.read().values().cloned().collect()
311 }
312
313 pub fn switch_runlevel(&self, runlevel: Runlevel) -> Result<(), KernelError> {
315 let current = self.current_runlevel.load(Ordering::SeqCst);
316
317 if current == runlevel as u32 {
318 return Ok(()); }
320
321 crate::println!(
322 "[INIT] Switching from runlevel {} to {}",
323 current,
324 runlevel as u32
325 );
326 self.target_runlevel
327 .store(runlevel as u32, Ordering::SeqCst);
328
329 let services_to_stop =
331 self.get_services_for_runlevel_transition(current, runlevel as u32, false);
332
333 for service_name in services_to_stop {
334 self.stop_service(&service_name).ok();
335 }
336
337 let services_to_start =
339 self.get_services_for_runlevel_transition(current, runlevel as u32, true);
340
341 for service_name in services_to_start {
342 self.start_service(&service_name).ok();
343 }
344
345 self.current_runlevel
346 .store(runlevel as u32, Ordering::SeqCst);
347 crate::println!("[INIT] Switched to runlevel {}", runlevel as u32);
348
349 Ok(())
350 }
351
352 pub fn handle_service_exit(&self, pid: ProcessId, exit_code: i32) {
354 let mut services = self.services.write();
355
356 for service in services.values_mut() {
358 if service.pid == Some(pid) {
359 crate::println!(
360 "[INIT] Service {} exited with code {}",
361 service.definition.name,
362 exit_code
363 );
364
365 service.state = ServiceState::Stopped;
366 service.pid = None;
367 service.exit_code = Some(exit_code);
368
369 let should_restart = match service.definition.restart_policy {
371 RestartPolicy::Never => false,
372 RestartPolicy::OnFailure => exit_code != 0,
373 RestartPolicy::Always => !self.shutting_down.load(Ordering::SeqCst),
374 RestartPolicy::UnlessStopped => {
375 !self.shutting_down.load(Ordering::SeqCst)
376 && service.state != ServiceState::Stopped
377 }
378 };
379
380 if should_restart && service.restart_count < service.definition.max_restarts {
381 service.state = ServiceState::Restarting;
382 service.restart_count += 1;
383 let base_delay_ms = service.definition.restart_delay_ms as u64;
385 let exponent = core::cmp::min(service.restart_count, 5);
386 let delay_ms = base_delay_ms.saturating_mul(1u64 << exponent);
387 crate::println!(
388 "[INIT] Scheduling restart for service {} (attempt {}, delay {}ms)",
389 service.definition.name,
390 service.restart_count,
391 delay_ms
392 );
393 let target = crate::arch::timer::get_timestamp_ms().saturating_add(delay_ms);
395 let svc_name = service.definition.name.clone();
396 drop(services); while crate::arch::timer::get_timestamp_ms() < target {
399 core::hint::spin_loop();
400 }
401 if let Err(_e) = self.start_service(&svc_name) {
403 crate::println!(
404 "[INIT] Warning: failed to restart service {}: {:?}",
405 svc_name,
406 _e
407 );
408 }
409 return; } else if service.restart_count >= service.definition.max_restarts {
411 service.state = ServiceState::Failed;
412 service.last_error = Some(String::from("Max restart attempts exceeded"));
413 }
414
415 break;
416 }
417 }
418 }
419
420 pub fn shutdown(&self) -> Result<(), KernelError> {
422 crate::println!("[INIT] System shutdown initiated");
423 self.shutting_down.store(true, Ordering::SeqCst);
424
425 self.monitoring_active.store(false, Ordering::SeqCst);
427
428 self.switch_runlevel(Runlevel::Halt)?;
430
431 let services: Vec<String> = self.start_order.read().iter().rev().cloned().collect();
433 for service_name in services {
434 self.stop_service(&service_name).ok();
435 }
436
437 crate::println!("[INIT] System shutdown complete");
438 Ok(())
439 }
440
441 pub fn reboot(&self) -> Result<(), KernelError> {
443 crate::println!("[INIT] System reboot initiated");
444
445 self.shutdown()?;
447
448 self.switch_runlevel(Runlevel::Reboot)?;
450
451 crate::println!("[INIT] System rebooting...");
452
453 #[cfg(target_arch = "x86_64")]
455 {
456 unsafe {
460 use x86_64::instructions::port::Port;
461 let mut port: Port<u8> = Port::new(0x64);
462 port.write(0xFE);
463 }
464 }
465
466 #[cfg(target_arch = "aarch64")]
467 {
468 unsafe {
471 core::arch::asm!("ldr x0, =0x84000009", "hvc #0", options(nomem, nostack));
472 }
473 }
474
475 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
476 {
477 unsafe {
481 core::arch::asm!(
482 "li a7, 0x53525354", "li a6, 0", "li a0, 0", "li a1, 0", "ecall",
487 options(nomem, nostack)
488 );
489 }
490 }
491
492 Ok(())
493 }
494
495 fn register_core_services(&self) -> Result<(), KernelError> {
498 self.register_service(ServiceDefinition {
500 name: String::from("console"),
501 description: String::from("System Console"),
502 command: String::from("/sbin/getty"),
503 arguments: vec![String::from("tty0")],
504 environment: vec![],
505 working_directory: String::from("/"),
506 user: 0,
507 group: 0,
508 restart_policy: RestartPolicy::Always,
509 restart_delay_ms: 1000,
510 max_restarts: 5,
511 timeout_ms: 5000,
512 dependencies: vec![],
513 start_level: 10,
514 stop_timeout: None,
515 })?;
516
517 self.register_service(ServiceDefinition {
519 name: String::from("logger"),
520 description: String::from("System Logger"),
521 command: String::from("/sbin/syslogd"),
522 arguments: vec![],
523 environment: vec![],
524 working_directory: String::from("/"),
525 user: 0,
526 group: 0,
527 restart_policy: RestartPolicy::Always,
528 restart_delay_ms: 1000,
529 max_restarts: 5,
530 timeout_ms: 5000,
531 dependencies: vec![],
532 start_level: 5,
533 stop_timeout: None,
534 })?;
535
536 self.register_service(ServiceDefinition {
538 name: String::from("devmgr"),
539 description: String::from("Device Manager"),
540 command: String::from("/sbin/devmgr"),
541 arguments: vec![],
542 environment: vec![],
543 working_directory: String::from("/"),
544 user: 0,
545 group: 0,
546 restart_policy: RestartPolicy::OnFailure,
547 restart_delay_ms: 2000,
548 max_restarts: 3,
549 timeout_ms: 10000,
550 dependencies: vec![(String::from("logger"), DependencyType::After)],
551 start_level: 15,
552 stop_timeout: None,
553 })?;
554
555 self.register_service(ServiceDefinition {
557 name: String::from("network"),
558 description: String::from("Network Service"),
559 command: String::from("/sbin/netd"),
560 arguments: vec![],
561 environment: vec![],
562 working_directory: String::from("/"),
563 user: 0,
564 group: 0,
565 restart_policy: RestartPolicy::OnFailure,
566 restart_delay_ms: 3000,
567 max_restarts: 3,
568 timeout_ms: 30000,
569 dependencies: vec![
570 (String::from("devmgr"), DependencyType::Requires),
571 (String::from("logger"), DependencyType::After),
572 ],
573 start_level: 20,
574 stop_timeout: None,
575 })?;
576
577 self.register_service(ServiceDefinition {
579 name: String::from("firewall"),
580 description: String::from("Packet Filter Firewall"),
581 command: String::from("/sbin/fwd"),
582 arguments: vec![],
583 environment: vec![],
584 working_directory: String::from("/"),
585 user: 0,
586 group: 0,
587 restart_policy: RestartPolicy::OnFailure,
588 restart_delay_ms: 3000,
589 max_restarts: 3,
590 timeout_ms: 30000,
591 dependencies: vec![(String::from("network"), DependencyType::After)],
592 start_level: 18,
593 stop_timeout: None,
594 })?;
595
596 self.register_service(ServiceDefinition {
598 name: String::from("dns-resolver"),
599 description: String::from("DNS Resolver"),
600 command: String::from("/sbin/resolved"),
601 arguments: vec![],
602 environment: vec![],
603 working_directory: String::from("/"),
604 user: 0,
605 group: 0,
606 restart_policy: RestartPolicy::OnFailure,
607 restart_delay_ms: 3000,
608 max_restarts: 3,
609 timeout_ms: 30000,
610 dependencies: vec![(String::from("network"), DependencyType::Requires)],
611 start_level: 22,
612 stop_timeout: None,
613 })?;
614
615 self.register_service(ServiceDefinition {
617 name: String::from("ntp"),
618 description: String::from("NTP Time Sync"),
619 command: String::from("/sbin/ntpd"),
620 arguments: vec![],
621 environment: vec![],
622 working_directory: String::from("/"),
623 user: 0,
624 group: 0,
625 restart_policy: RestartPolicy::OnFailure,
626 restart_delay_ms: 3000,
627 max_restarts: 3,
628 timeout_ms: 30000,
629 dependencies: vec![(String::from("network"), DependencyType::After)],
630 start_level: 25,
631 stop_timeout: None,
632 })?;
633
634 self.register_service(ServiceDefinition {
636 name: String::from("ssh"),
637 description: String::from("SSH Server"),
638 command: String::from("/sbin/sshd"),
639 arguments: vec![],
640 environment: vec![],
641 working_directory: String::from("/"),
642 user: 0,
643 group: 0,
644 restart_policy: RestartPolicy::OnFailure,
645 restart_delay_ms: 3000,
646 max_restarts: 3,
647 timeout_ms: 30000,
648 dependencies: vec![(String::from("network"), DependencyType::After)],
649 start_level: 30,
650 stop_timeout: None,
651 })?;
652
653 Ok(())
654 }
655
656 fn compute_start_order(&self) -> Result<(), KernelError> {
657 let services = self.services.read();
658 let mut order = Vec::new();
659 let mut visited = BTreeMap::new();
660
661 let mut sorted_services: Vec<_> = services.keys().cloned().collect();
663 sorted_services.sort_by_key(|name| {
664 services
665 .get(name)
666 .map(|s| s.definition.start_level)
667 .unwrap_or(99)
668 });
669
670 for service_name in sorted_services {
671 if !visited.contains_key(&service_name) {
672 self.visit_service(&service_name, &services, &mut visited, &mut order)?;
673 }
674 }
675
676 *self.start_order.write() = order;
677 Ok(())
678 }
679
680 fn visit_service(
681 &self,
682 name: &str,
683 services: &BTreeMap<String, ServiceInfo>,
684 visited: &mut BTreeMap<String, bool>,
685 order: &mut Vec<String>,
686 ) -> Result<(), KernelError> {
687 if let Some(&in_progress) = visited.get(name) {
688 if in_progress {
689 return Err(KernelError::InvalidArgument {
690 name: "service dependency",
691 value: "circular dependency detected",
692 });
693 }
694 return Ok(()); }
696
697 visited.insert(name.into(), true);
698
699 if let Some(service) = services.get(name) {
700 for (dep_name, dep_type) in &service.definition.dependencies {
702 if matches!(dep_type, DependencyType::Requires | DependencyType::After) {
703 self.visit_service(dep_name, services, visited, order)?;
704 }
705 }
706 }
707
708 visited.insert(name.into(), false);
709 order.push(name.into());
710 Ok(())
711 }
712
713 fn check_dependencies(&self, name: &str) -> Result<(), KernelError> {
714 let services = self.services.read();
715
716 if let Some(service) = services.get(name) {
717 for (dep_name, dep_type) in &service.definition.dependencies {
718 if *dep_type == DependencyType::Requires {
719 if let Some(dep_service) = services.get(dep_name) {
720 if dep_service.state != ServiceState::Running {
721 return Err(KernelError::InvalidState {
722 expected: "running",
723 actual: "not running",
724 });
725 }
726 } else {
727 return Err(KernelError::NotFound {
728 resource: "required dependency",
729 id: 0,
730 });
731 }
732 }
733 }
734 }
735
736 Ok(())
737 }
738
739 fn get_services_for_runlevel_transition(
740 &self,
741 _from: u32,
742 to: u32,
743 start: bool,
744 ) -> Vec<String> {
745 let services = self.services.read();
746 let mut result = Vec::new();
747
748 for (name, service) in services.iter() {
749 let should_run = match to {
750 0 => false, 1 => service.definition.start_level <= 10, 2 => service.definition.start_level <= 30, 3 => service.definition.start_level <= 50, 5 => true, 6 => false, _ => service.definition.start_level <= 30,
757 };
758
759 if start && should_run && service.state != ServiceState::Running {
760 result.push(name.clone());
761 } else if !start && !should_run && service.state == ServiceState::Running {
762 result.push(name.clone());
763 }
764 }
765
766 if start {
767 let order = self.start_order.read();
769 result.sort_by_key(|name| order.iter().position(|n| n == name).unwrap_or(999));
770 } else {
771 result.reverse();
773 }
774
775 result
776 }
777
778 fn get_system_time(&self) -> u64 {
779 crate::arch::timer::get_timestamp_secs()
780 }
781}
782
783static INIT_SYSTEM: crate::sync::once_lock::OnceLock<InitSystem> =
785 crate::sync::once_lock::OnceLock::new();
786
787pub fn init() {
789 #[allow(unused_imports)]
790 use crate::println;
791
792 println!("[INIT] Creating new InitSystem...");
793 match INIT_SYSTEM.set(InitSystem::new()) {
794 Ok(()) => println!("[INIT] Init system module loaded"),
795 Err(_) => println!("[INIT] Already initialized, skipping..."),
796 }
797}
798
799pub fn try_get_init_system() -> Option<&'static InitSystem> {
803 INIT_SYSTEM.get()
804}
805
806pub fn get_init_system() -> &'static InitSystem {
811 INIT_SYSTEM
812 .get()
813 .expect("Init system not initialized: init() was not called")
814}
815
816pub fn run_init() -> ! {
818 let init_system = get_init_system();
819
820 init_system
822 .initialize()
823 .expect("Failed to initialize init system");
824
825 init_system
827 .switch_runlevel(Runlevel::Multi)
828 .expect("Failed to switch to multi-user mode");
829
830 loop {
832 let process_server = crate::services::process_server::get_process_server();
834
835 while let Ok((child_pid, exit_code)) = process_server.wait_for_child(ProcessId(1), None) {
837 init_system.handle_service_exit(child_pid, exit_code);
838 }
839
840 process_server.reap_zombies();
842
843 let wake_time = crate::arch::timer::get_timestamp_ms().saturating_add(100);
845 while crate::arch::timer::get_timestamp_ms() < wake_time {
846 #[cfg(target_arch = "x86_64")]
848 x86_64::instructions::hlt();
849
850 #[cfg(target_arch = "aarch64")]
851 unsafe {
853 core::arch::asm!("wfi", options(nomem, nostack));
854 }
855
856 #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
857 unsafe {
859 core::arch::asm!("wfi", options(nomem, nostack));
860 }
861 }
862 }
863}