milestone: desktop path Phases 1-5

Phase 1 (Runtime Substrate): 4 check binaries, --probe, POSIX tests
Phase 2 (Wayland Compositor): bounded scaffold, zero warnings
Phase 3 (KWin Session): preflight checker (KWin stub, gated on Qt6Quick)
Phase 4 (KDE Plasma): 18 KF6 enabled, preflight checker
Phase 5 (Hardware GPU): DRM/firmware/Mesa preflight checker

Build: zero warnings, all scripts syntax-clean. Oracle-verified.
This commit is contained in:
2026-04-29 09:54:06 +01:00
parent b23714f542
commit 8acc73d774
508 changed files with 76526 additions and 396 deletions
@@ -0,0 +1,26 @@
use anyhow::{Context, Result};
// TODO: Do not use target architecture to distinguish these.
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
mod x86;
/// The rtc driver runs only once, being perhaps the first of all processes that init starts (since
/// early logging benefits from knowing the time, even though this can be adjusted later once the
/// time is known). The sole job of `rtcd` is to read from the hardware real-time clock, and then
/// write the offset to the kernel.
fn main() -> Result<()> {
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
{
common::acquire_port_io_rights().context("failed to set iopl")?;
let time_s = self::x86::get_time();
let time_ns = u128::from(time_s) * 1_000_000_000;
std::fs::write("/scheme/sys/update_time_offset", &time_ns.to_ne_bytes())
.context("failed to write to time offset")?;
}
// TODO: aarch64 is currently handled in the kernel
Ok(())
}
+147
View File
@@ -0,0 +1,147 @@
// TODO: Get RTC information from acpid.
use common::io::{Io, Pio};
pub fn get_time() -> u64 {
Rtc::new().time()
}
fn cvt_bcd(value: usize) -> usize {
(value & 0xF) + ((value / 16) * 10)
}
/// RTC
pub struct Rtc {
addr: Pio<u8>,
data: Pio<u8>,
nmi: bool,
}
impl Rtc {
/// Create new empty RTC
pub fn new() -> Self {
Rtc {
addr: Pio::<u8>::new(0x70),
data: Pio::<u8>::new(0x71),
nmi: false,
}
}
/// Read
unsafe fn read(&mut self, reg: u8) -> u8 {
if self.nmi {
self.addr.write(reg & 0x7F);
} else {
self.addr.write(reg | 0x80);
}
self.data.read()
}
/// Write
#[allow(dead_code)]
unsafe fn write(&mut self, reg: u8, value: u8) {
if self.nmi {
self.addr.write(reg & 0x7F);
} else {
self.addr.write(reg | 0x80);
}
self.data.write(value);
}
/// Wait for an update, can take one second if full is specified!
unsafe fn wait(&mut self, full: bool) {
if full {
while self.read(0xA) & 0x80 != 0x80 {}
}
while self.read(0xA) & 0x80 == 0x80 {}
}
/// Get time without waiting
pub unsafe fn time_no_wait(&mut self) -> u64 {
/*let century_register = if let Some(ref fadt) = acpi::ACPI_TABLE.lock().fadt {
Some(fadt.century)
} else {
None
};*/
let mut second = self.read(0) as usize;
let mut minute = self.read(2) as usize;
let mut hour = self.read(4) as usize;
let mut day = self.read(7) as usize;
let mut month = self.read(8) as usize;
let mut year = self.read(9) as usize;
let mut century = /* TODO: Fix invalid value from VirtualBox
if let Some(century_reg) = century_register {
self.read(century_reg) as usize
} else */ {
20
};
let register_b = self.read(0xB);
if register_b & 4 != 4 {
second = cvt_bcd(second);
minute = cvt_bcd(minute);
hour = cvt_bcd(hour & 0x7F) | (hour & 0x80);
day = cvt_bcd(day);
month = cvt_bcd(month);
year = cvt_bcd(year);
century = /* TODO: Fix invalid value from VirtualBox
if century_register.is_some() {
cvt_bcd(century)
} else */ {
century
};
}
if register_b & 2 != 2 || hour & 0x80 == 0x80 {
hour = ((hour & 0x7F) + 12) % 24;
}
year += century * 100;
// Unix time from clock
let mut secs: u64 = (year as u64 - 1970) * 31_536_000;
let mut leap_days = (year as u64 - 1972) / 4 + 1;
if year % 4 == 0 && month <= 2 {
leap_days -= 1;
}
secs += leap_days * 86_400;
match month {
2 => secs += 2_678_400,
3 => secs += 5_097_600,
4 => secs += 7_776_000,
5 => secs += 10_368_000,
6 => secs += 13_046_400,
7 => secs += 15_638_400,
8 => secs += 18_316_800,
9 => secs += 20_995_200,
10 => secs += 23_587_200,
11 => secs += 26_265_600,
12 => secs += 28_857_600,
_ => (),
}
secs += (day as u64 - 1) * 86_400;
secs += hour as u64 * 3600;
secs += minute as u64 * 60;
secs += second as u64;
secs
}
/// Get time
pub fn time(&mut self) -> u64 {
loop {
unsafe {
self.wait(false);
let time = self.time_no_wait();
self.wait(false);
let next_time = self.time_no_wait();
if time == next_time {
return time;
}
}
}
}
}