From 2d0ce0118ed8dc063dc3adf3c880d27f28d41c26 Mon Sep 17 00:00:00 2001 From: angxl x86_64 <155915830+NopAngel@users.noreply.github.com> Date: Sat, 29 Nov 2025 20:28:36 -0400 Subject: [PATCH] Add files via upload --- kernel/src/cmd/mod.rs | 144 ++++++++++++++++++++++++++++++++++++++++-- kernel/src/main.rs | 118 ++++++++++++++++++++++++++++++++-- kernel/src/rtc.rs | 84 ++++++++++++++++++++++++ 3 files changed, 333 insertions(+), 13 deletions(-) create mode 100644 kernel/src/rtc.rs diff --git a/kernel/src/cmd/mod.rs b/kernel/src/cmd/mod.rs index 9474c29..110168e 100644 --- a/kernel/src/cmd/mod.rs +++ b/kernel/src/cmd/mod.rs @@ -85,6 +85,7 @@ fn chcolor(_args: Vec<&str>) -> i32 { for arg in _args { if let Some(color) = STR_COLORS.iter().find(|&col| col.name == arg.replace("\n", "")) { new_colors.push(color.color); + } else { WRITER .lock() @@ -93,6 +94,7 @@ fn chcolor(_args: Vec<&str>) -> i32 { } } WRITER.lock().change_color(new_colors[0], new_colors[1]); + WRITER.lock().clear_screen(); 0 } else { WRITER.lock().print_colored( @@ -113,6 +115,104 @@ pub fn cmd_hist(_args: Vec<&str>) -> i32 { 0 } +// Command to shutdown the system (now public) +pub fn shutdown_command(_args: Vec<&str>) -> i32 { + println!("Shutting down system..."); + + // Legacy shutdown methods + unsafe { + // ACPI method (PM1a port) + let mut port: x86_64::instructions::port::Port = x86_64::instructions::port::Port::new(0x604); + port.write(0x2000); + + // QEMU method + let mut port: x86_64::instructions::port::Port = x86_64::instructions::port::Port::new(0x604); + port.write(0x2000); + + // Bochs method + let mut port: x86_64::instructions::port::Port = x86_64::instructions::port::Port::new(0xB004); + port.write(0x2000); + + // VirtualBox method + let mut port: x86_64::instructions::port::Port = x86_64::instructions::port::Port::new(0x4004); + port.write(0x3400); + } + + println!("Could not shutdown system via hardware."); + println!("On real systems, this would power off the machine."); + 0 +} + +// Command to reboot the system (now public) +pub fn reboot_command(_args: Vec<&str>) -> i32 { + println!("Rebooting system..."); + + // Reboot method via keyboard controller + unsafe { + use x86_64::instructions::port::Port; + + let mut port: Port = Port::new(0x64); + // Wait for buffer to be empty + for _ in 0..10000 { + if port.read() & 0x2 == 0 { + break; + } + } + port.write(0xFE); + } + + // Small delay + for _ in 0..1000000 { + x86_64::instructions::nop(); + } + + println!("Could not reboot system via hardware."); + println!("On real systems, this would restart the machine."); + 0 +} + +// Command to show current time +pub fn time_command(_args: Vec<&str>) -> i32 { + unsafe { + if let Some(rtc) = &mut crate::RTC_CONTROLLER { + let datetime = rtc.read_datetime(); + println!("Current time: {}", datetime.format_time()); + 0 + } else { + println!("Error: RTC not initialized"); + 2 + } + } +} + +// Command to show current date +pub fn date_command(_args: Vec<&str>) -> i32 { + unsafe { + if let Some(rtc) = &mut crate::RTC_CONTROLLER { + let datetime = rtc.read_datetime(); + println!("Current date: {}", datetime.format_date()); + 0 + } else { + println!("Error: RTC not initialized"); + 2 + } + } +} + +// Command to show full date and time +pub fn datetime_command(_args: Vec<&str>) -> i32 { + unsafe { + if let Some(rtc) = &mut crate::RTC_CONTROLLER { + let datetime = rtc.read_datetime(); + println!("Date and time: {}", datetime.format_full()); + 0 + } else { + println!("Error: RTC not initialized"); + 2 + } + } +} + #[cfg(debug_assertions)] fn crasher(_args: Vec<&str>) -> i32 { println!("CRASHING...\n\n"); @@ -150,12 +250,6 @@ pub const COMMAND_LIST: &[Command] = &[ doc: "display the documentation of selected command", fun: document, }, - // Command { - // name: "reinit", - // args: "", - // doc: "re-initialize the kernel", - // fun: crate::init_kernel, - // }, Command { name: "chcolor", args: "[fg] [bg]", @@ -168,6 +262,44 @@ pub const COMMAND_LIST: &[Command] = &[ doc: "display command history", fun: cmd_hist, }, + // Power management commands + Command { + name: "shutdown", + args: "", + doc: "shutdown the system", + fun: shutdown_command, + }, + Command { + name: "reboot", + args: "", + doc: "reboot the system", + fun: reboot_command, + }, + Command { + name: "poweroff", + args: "", + doc: "shutdown the system (alias for shutdown)", + fun: shutdown_command, + }, + // RTC commands + Command { + name: "time", + args: "", + doc: "show current time", + fun: time_command, + }, + Command { + name: "date", + args: "", + doc: "show current date", + fun: date_command, + }, + Command { + name: "datetime", + args: "", + doc: "show full date and time", + fun: datetime_command, + }, #[cfg(debug_assertions)] Command { name: "crash_kernel", diff --git a/kernel/src/main.rs b/kernel/src/main.rs index 3bd82a5..98ef7a9 100644 --- a/kernel/src/main.rs +++ b/kernel/src/main.rs @@ -19,6 +19,13 @@ use hlkernel::{ mod cmd; use cmd::COMMAND_LIST; +// Add RTC module +mod rtc; + +// Global variables +static mut ACPI_CONTROLLER: Option = None; +static mut RTC_CONTROLLER: Option = None; + entry_point!(kernel_main); struct RtrType { @@ -27,6 +34,88 @@ struct RtrType { color: Color, } +// Simple structure for ACPI +struct AcpiController; + +impl AcpiController { + pub unsafe fn new() -> Self { + Self + } + + pub fn shutdown(&mut self) { + // Call the public shutdown function + cmd::shutdown_command(vec![]); + } + + pub fn reboot(&mut self) { + // Call the public reboot function + cmd::reboot_command(vec![]); + } +} + +pub fn started_colors() { + WRITER.lock().print_colored( + format!("\naA"), + Color::Blue, + Color::Blue, + ); + WRITER.lock().print_colored( + format!("aA"), + Color::Pink, + Color::Pink, + ); + WRITER.lock().print_colored( + format!("aA"), + Color::Red, + Color::Red, + ); + WRITER.lock().print_colored( + format!("aA"), + Color::Green, + Color::Green, + ); + WRITER.lock().print_colored( + format!("aA"), + Color::Yellow, + Color::Yellow, + ); + WRITER.lock().print_colored( + format!("aA"), + Color::LightBlue, + Color::LightBlue, + ); + + WRITER.lock().print_colored( + format!("aA"), + Color::Magenta, + Color::Magenta, + ); + + WRITER.lock().print_colored( + format!("aA"), + Color::Cyan, + Color::Cyan, + ); + + WRITER.lock().print_colored( + format!("aA"), + Color::Brown, + Color::Brown, + ); + + WRITER.lock().print_colored( + format!("aA"), + Color::Blue, + Color::Blue, + ); + + WRITER.lock().print_colored( + format!("aA"), + Color::Blue, + Color::Blue, + ); +} + pub fn init_kernel(boot_info: &'static BootInfo) { use hlkernel::allocator; use hlkernel::mem::{self, BootInfoFrameAlloc}; @@ -43,21 +132,36 @@ pub fn init_kernel(boot_info: &'static BootInfo) { hlkernel::init(); + // Initialize ACPI controller + unsafe { + ACPI_CONTROLLER = Some(AcpiController::new()); + } + + // Initialize RTC + unsafe { + RTC_CONTROLLER = Some(rtc::Rtc::new()); + } + #[cfg(debug_assertions)] WRITER.lock().print_colored( - format!("\nHighlightOS v{} DEBUG", env!("CARGO_PKG_VERSION")), + format!("\nHighlightOS v{} *DEBUG*", env!("CARGO_PKG_VERSION")), Color::Black, Color::Yellow, ); #[cfg(not(debug_assertions))] WRITER.lock().print_colored( - format!("\nHighlightOS v{}", env!("CARGO_PKG_VERSION")), + format!("\n HighlightOS v{}", env!("CARGO_PKG_VERSION")), Color::Black, Color::Yellow, ); + WRITER.lock().print_colored( + format!("\n Documentation: https://os.adamperkowski.dev"), + Color::Cyan, + Color::Black + ); - print!("\n\nhls < "); + print!("\n\nhls > "); } fn kernel_main(boot_info: &'static BootInfo) -> ! { @@ -86,9 +190,9 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { if let Some(return_code) = RTR_LIST.iter().find(|&rtr_t| rtr_t.code == &rtr) { println!("\n > {}", req_com); WRITER.lock().print_colored( - format!("{} : {}\n\n", rtr, return_code.info), + format!("{}:{}\n\n", rtr, return_code.info), return_code.color, - Color::Black, // Color::None ?? + Color::Black, ); } else { println!("\n > {}\nreturned : {}\n", req_com, rtr); @@ -96,7 +200,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { } } else { WRITER.lock().print_colored( - format!("\n > {}\ncommand not found\n\n", input), + format!("\n > hls: command not found: {}\n", input), Color::LightRed, Color::Black, ); @@ -112,7 +216,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { } } - print!("hls < "); + print!("hls > "); } } } diff --git a/kernel/src/rtc.rs b/kernel/src/rtc.rs new file mode 100644 index 0000000..66c1124 --- /dev/null +++ b/kernel/src/rtc.rs @@ -0,0 +1,84 @@ +// src/rtc.rs +use x86_64::instructions::port::Port; + +const RTC_ADDR: u16 = 0x70; +const RTC_DATA: u16 = 0x71; + +pub struct Rtc { + addr_port: Port, + data_port: Port, +} + +#[derive(Debug, Clone, Copy)] +pub struct DateTime { + pub second: u8, + pub minute: u8, + pub hour: u8, + pub day: u8, + pub month: u8, + pub year: u8, +} + +impl Rtc { + pub unsafe fn new() -> Self { + Self { + addr_port: Port::new(RTC_ADDR), + data_port: Port::new(RTC_DATA), + } + } + + // Read from an RTC register + unsafe fn read_register(&mut self, reg: u8) -> u8 { + self.addr_port.write(reg); + self.data_port.read() + } + + // Wait for RTC to not be updating + unsafe fn wait_for_update(&mut self) { + while self.read_register(0x0A) & 0x80 != 0 {} + } + + // Read current date and time + pub unsafe fn read_datetime(&mut self) -> DateTime { + self.wait_for_update(); + + let second = self.read_register(0x00); + let minute = self.read_register(0x02); + let hour = self.read_register(0x04); + let day = self.read_register(0x07); + let month = self.read_register(0x08); + let year = self.read_register(0x09); + + // Convert from BCD to binary if necessary + let register_b = self.read_register(0x0B); + let is_bcd = register_b & 0x04 == 0; + + DateTime { + second: if is_bcd { self.bcd_to_bin(second) } else { second }, + minute: if is_bcd { self.bcd_to_bin(minute) } else { minute }, + hour: if is_bcd { self.bcd_to_bin(hour) } else { hour }, + day: if is_bcd { self.bcd_to_bin(day) } else { day }, + month: if is_bcd { self.bcd_to_bin(month) } else { month }, + year: if is_bcd { self.bcd_to_bin(year) } else { year }, + } + } + + // Convert BCD to binary + fn bcd_to_bin(&self, bcd: u8) -> u8 { + ((bcd >> 4) * 10) + (bcd & 0x0F) + } +} + +impl DateTime { + pub fn format_time(&self) -> alloc::string::String { + alloc::format!("{:02}:{:02}:{:02}", self.hour, self.minute, self.second) + } + + pub fn format_date(&self) -> alloc::string::String { + alloc::format!("{:02}/{:02}/20{:02}", self.day, self.month, self.year) + } + + pub fn format_full(&self) -> alloc::string::String { + alloc::format!("{} {}", self.format_date(), self.format_time()) + } +}