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,14 @@
[package]
name = "amlserde"
description = "Library for serializing AML symbols"
version = "0.0.1"
authors = ["Ron Williams"]
repository = "https://gitlab.redox-os.org/redox-os/drivers"
categories = ["hardware-support"]
license = "MIT/Apache-2.0"
edition = "2021"
[dependencies]
acpi.workspace = true
serde.workspace = true
toml.workspace = true
@@ -0,0 +1,484 @@
use acpi::{
aml::{
namespace::AmlName,
object::{
FieldAccessType, FieldFlags, FieldUnit, FieldUnitKind, FieldUpdateRule, MethodFlags,
Object, ReferenceKind, WrappedObject,
},
op_region::{OpRegion, RegionSpace},
Interpreter,
},
Handle, Handler,
};
use serde::{Deserialize, Serialize};
use std::{
ops::{Deref, Shl},
str::FromStr,
sync::{
atomic::{AtomicU64, Ordering},
Arc,
},
};
#[derive(Debug, Serialize, Deserialize)]
pub struct AmlSerde {
pub name: String,
pub value: AmlSerdeValue,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeValue {
Uninitialized,
Integer(u64),
String(String),
OpRegion {
region: AmlSerdeRegionSpace,
offset: u64,
length: u64,
parent_device: String,
},
Field {
kind: AmlSerdeFieldKind,
flags: AmlSerdeFieldFlags,
offset: u64,
length: u64,
},
Device,
Event(u64),
Method {
arg_count: usize,
serialize: bool,
sync_level: u8,
},
Buffer(Vec<u8>),
BufferField {
offset: u64,
length: u64,
data: Box<AmlSerdeValue>,
},
Processor {
id: u8,
pblk_address: u32,
pblk_len: u8,
},
Mutex {
mutex: u32,
sync_level: u8,
},
Reference {
kind: AmlSerdeReferenceKind,
inner: Box<AmlSerdeValue>,
},
Package {
contents: Vec<AmlSerdeValue>,
},
PowerResource {
system_level: u8,
resource_order: u16,
},
RawDataBuffer,
ThermalZone,
Debug,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeRegionSpace {
SystemMemory,
SystemIo,
PciConfig,
EmbeddedControl,
SMBus,
SystemCmos,
PciBarTarget,
IPMI,
GeneralPurposeIo,
GenericSerialBus,
Pcc,
OemDefined(u8),
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeFieldKind {
Normal {
region: Box<AmlSerdeValue>,
},
Bank {
region: Box<AmlSerdeValue>,
bank: Box<AmlSerdeValue>,
bank_value: u64,
},
Index {
index: Box<AmlSerdeValue>,
data: Box<AmlSerdeValue>,
},
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AmlSerdeFieldFlags {
pub access_type: AmlSerdeFieldAccessType,
pub lock_rule: bool, // bit 4
pub update_rule: AmlSerdeFieldUpdateRule,
}
impl Into<u8> for AmlSerdeFieldFlags {
fn into(self) -> u8 {
// bits 0..4
(self.access_type as u8) +
// bit 4
(self.lock_rule as u8).shl(4) +
// bits 5..7
(self.update_rule as u8).shl(5)
}
}
#[derive(Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum AmlSerdeFieldAccessType {
Any = 0,
Byte = 1,
Word = 2,
DWord = 3,
QWord = 4,
Buffer = 5,
}
#[derive(Debug, Serialize, Deserialize)]
#[repr(u8)]
pub enum AmlSerdeFieldUpdateRule {
Preserve = 0,
WriteAsOnes = 1,
WriteAsZeros = 2,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum AmlSerdeReferenceKind {
RefOf,
Local,
Arg,
Index,
Named,
Unresolved,
}
impl AmlSerde {
pub fn default() -> Self {
Self {
name: "name".to_owned(),
value: AmlSerdeValue::String(String::default()),
}
}
pub fn from_aml<H: Handler>(aml_context: &Interpreter<H>, aml_name: &AmlName) -> Option<Self> {
//TODO: why does namespace.get not take a reference to aml_name
let aml_value = if let Ok(aml_value) = aml_context.namespace.lock().get(aml_name.clone()) {
aml_value
} else {
return None;
};
let value = if let Some(value) = AmlSerdeValue::from_aml_value(aml_value.deref()) {
value
} else {
return None;
};
Some(AmlSerde {
name: aml_name.to_string(),
value,
})
}
}
impl AmlSerdeValue {
pub fn default() -> Self {
AmlSerdeValue::String("".to_owned())
}
pub fn from_aml_value(aml_value: &Object) -> Option<Self> {
Some(match aml_value {
Object::Uninitialized => AmlSerdeValue::Uninitialized,
Object::Integer(n) => AmlSerdeValue::Integer(n.to_owned()),
Object::String(s) => AmlSerdeValue::String(s.to_owned()),
Object::OpRegion(region) => AmlSerdeValue::OpRegion {
region: match region.space {
RegionSpace::SystemMemory => AmlSerdeRegionSpace::SystemMemory,
RegionSpace::SystemIO => AmlSerdeRegionSpace::SystemIo,
RegionSpace::PciConfig => AmlSerdeRegionSpace::PciConfig,
RegionSpace::EmbeddedControl => AmlSerdeRegionSpace::EmbeddedControl,
RegionSpace::SmBus => AmlSerdeRegionSpace::SMBus,
RegionSpace::SystemCmos => AmlSerdeRegionSpace::SystemCmos,
RegionSpace::PciBarTarget => AmlSerdeRegionSpace::PciBarTarget,
RegionSpace::Ipmi => AmlSerdeRegionSpace::IPMI,
RegionSpace::GeneralPurposeIo => AmlSerdeRegionSpace::GeneralPurposeIo,
RegionSpace::GenericSerialBus => AmlSerdeRegionSpace::GenericSerialBus,
RegionSpace::Pcc => AmlSerdeRegionSpace::Pcc,
RegionSpace::Oem(n) => AmlSerdeRegionSpace::OemDefined(n.to_owned()),
},
offset: region.base,
length: region.length,
parent_device: region.parent_device_path.to_string(),
},
Object::FieldUnit(field) => AmlSerdeValue::Field {
kind: match &field.kind {
FieldUnitKind::Normal { region } => AmlSerdeFieldKind::Normal {
region: AmlSerdeValue::from_aml_value(region.deref()).map(Box::new)?,
},
FieldUnitKind::Bank {
region,
bank,
bank_value,
} => AmlSerdeFieldKind::Bank {
region: AmlSerdeValue::from_aml_value(region.deref()).map(Box::new)?,
bank: AmlSerdeValue::from_aml_value(bank.deref()).map(Box::new)?,
bank_value: bank_value.to_owned(),
},
FieldUnitKind::Index { index, data } => AmlSerdeFieldKind::Index {
index: AmlSerdeValue::from_aml_value(index.deref()).map(Box::new)?,
data: AmlSerdeValue::from_aml_value(data.deref()).map(Box::new)?,
},
},
flags: AmlSerdeFieldFlags {
access_type: match field.flags.access_type() {
Ok(FieldAccessType::Any) => AmlSerdeFieldAccessType::Any,
Ok(FieldAccessType::Byte) => AmlSerdeFieldAccessType::Byte,
Ok(FieldAccessType::Word) => AmlSerdeFieldAccessType::Word,
Ok(FieldAccessType::DWord) => AmlSerdeFieldAccessType::DWord,
Ok(FieldAccessType::QWord) => AmlSerdeFieldAccessType::QWord,
Ok(FieldAccessType::Buffer) => AmlSerdeFieldAccessType::Buffer,
_ => return None,
},
lock_rule: field.flags.lock_rule(),
update_rule: match field.flags.update_rule() {
FieldUpdateRule::Preserve => AmlSerdeFieldUpdateRule::Preserve,
FieldUpdateRule::WriteAsOnes => AmlSerdeFieldUpdateRule::WriteAsOnes,
FieldUpdateRule::WriteAsZeros => AmlSerdeFieldUpdateRule::WriteAsZeros,
},
},
offset: field.bit_index as u64,
length: field.bit_length as u64,
},
Object::Device => AmlSerdeValue::Device,
Object::Event(event) => AmlSerdeValue::Event(event.load(Ordering::Relaxed)),
Object::Method { flags, code: _ } => AmlSerdeValue::Method {
arg_count: flags.arg_count(),
serialize: flags.serialize(),
sync_level: flags.sync_level(),
},
//TODO: distinguish from Method?
Object::NativeMethod { f: _, flags } => AmlSerdeValue::Method {
arg_count: flags.arg_count(),
serialize: flags.serialize(),
sync_level: flags.sync_level(),
},
Object::Buffer(buffer_data) => AmlSerdeValue::Buffer(buffer_data.to_owned()),
Object::BufferField {
buffer,
offset,
length,
} => AmlSerdeValue::BufferField {
offset: offset.to_owned() as u64,
length: length.to_owned() as u64,
data: AmlSerdeValue::from_aml_value(buffer.deref()).map(Box::new)?,
},
Object::Processor {
proc_id,
pblk_address,
pblk_length,
} => AmlSerdeValue::Processor {
id: proc_id.to_owned(),
pblk_address: pblk_address.to_owned(),
pblk_len: pblk_length.to_owned(),
},
Object::Mutex { mutex, sync_level } => AmlSerdeValue::Mutex {
mutex: mutex.0,
sync_level: sync_level.to_owned(),
},
Object::Reference { kind, inner } => AmlSerdeValue::Reference {
kind: match kind {
ReferenceKind::RefOf => AmlSerdeReferenceKind::RefOf,
ReferenceKind::Local => AmlSerdeReferenceKind::Local,
ReferenceKind::Arg => AmlSerdeReferenceKind::Arg,
ReferenceKind::Index => AmlSerdeReferenceKind::Index,
ReferenceKind::Named => AmlSerdeReferenceKind::Named,
ReferenceKind::Unresolved => AmlSerdeReferenceKind::Unresolved,
},
inner: AmlSerdeValue::from_aml_value(inner.deref()).map(Box::new)?,
},
Object::Package(aml_contents) => AmlSerdeValue::Package {
contents: aml_contents
.iter()
.filter_map(|item| AmlSerdeValue::from_aml_value(item))
.collect(),
},
Object::PowerResource {
system_level,
resource_order,
} => AmlSerdeValue::PowerResource {
system_level: system_level.to_owned(),
resource_order: resource_order.to_owned(),
},
Object::RawDataBuffer => AmlSerdeValue::RawDataBuffer,
Object::ThermalZone => AmlSerdeValue::ThermalZone,
Object::Debug => AmlSerdeValue::Debug,
})
}
pub fn to_aml_object(self) -> Option<Object> {
Some(match self {
AmlSerdeValue::Uninitialized => Object::Uninitialized,
AmlSerdeValue::Integer(n) => Object::Integer(n),
AmlSerdeValue::String(s) => Object::String(s),
AmlSerdeValue::OpRegion {
region,
offset,
length,
parent_device,
} => Object::OpRegion(OpRegion {
space: match region {
AmlSerdeRegionSpace::PciConfig => RegionSpace::PciConfig,
AmlSerdeRegionSpace::EmbeddedControl => RegionSpace::EmbeddedControl,
AmlSerdeRegionSpace::SMBus => RegionSpace::SmBus,
AmlSerdeRegionSpace::SystemCmos => RegionSpace::SystemCmos,
AmlSerdeRegionSpace::PciBarTarget => RegionSpace::PciBarTarget,
AmlSerdeRegionSpace::IPMI => RegionSpace::Ipmi,
AmlSerdeRegionSpace::GeneralPurposeIo => RegionSpace::GeneralPurposeIo,
AmlSerdeRegionSpace::GenericSerialBus => RegionSpace::GenericSerialBus,
AmlSerdeRegionSpace::SystemMemory => RegionSpace::SystemMemory,
AmlSerdeRegionSpace::SystemIo => RegionSpace::SystemIO,
AmlSerdeRegionSpace::Pcc => RegionSpace::Pcc,
AmlSerdeRegionSpace::OemDefined(n) => RegionSpace::Oem(n),
},
base: offset,
length,
//
parent_device_path: AmlName::from_str(&parent_device).ok()?, // TODO: Error value hidden
}),
AmlSerdeValue::Field {
kind,
flags,
offset,
length,
} => Object::FieldUnit(FieldUnit {
kind: match kind {
AmlSerdeFieldKind::Normal { region } => FieldUnitKind::Normal {
region: region.to_aml_object()?.wrap(),
},
AmlSerdeFieldKind::Bank {
region,
bank,
bank_value,
} => FieldUnitKind::Bank {
region: region.to_aml_object()?.wrap(),
bank: bank.to_aml_object()?.wrap(),
bank_value: bank_value.to_owned(),
},
AmlSerdeFieldKind::Index { index, data } => FieldUnitKind::Index {
index: index.to_aml_object()?.wrap(),
data: data.to_aml_object()?.wrap(),
},
},
flags: FieldFlags(flags.into()),
bit_index: offset as usize,
bit_length: length as usize,
}),
AmlSerdeValue::Device => Object::Device,
AmlSerdeValue::Event(event) => Object::Event(Arc::new(AtomicU64::new(event))),
AmlSerdeValue::Method {
arg_count,
serialize,
sync_level,
} => Object::Method {
code: (return None), //TODO figure out what to do here
//TODO check specs to see if all bit patterns are allowed
flags: MethodFlags(
(arg_count as u8).clamp(0, 7)
+ (serialize as u8).shl(3)
+ sync_level.clamp(0, 15).shl(4),
),
},
//TODO: handle native method?
AmlSerdeValue::Buffer(buffer_data) => Object::Buffer(buffer_data),
AmlSerdeValue::BufferField {
data,
offset,
length,
} => Object::BufferField {
offset: offset as usize,
length: length as usize,
buffer: data.to_aml_object()?.wrap(),
},
AmlSerdeValue::Processor {
id,
pblk_address,
pblk_len,
} => Object::Processor {
proc_id: id,
pblk_address,
pblk_length: pblk_len,
},
AmlSerdeValue::Mutex { mutex, sync_level } => Object::Mutex {
mutex: Handle(mutex),
sync_level: sync_level,
},
AmlSerdeValue::Reference { kind, inner } => Object::Reference {
kind: match kind {
AmlSerdeReferenceKind::RefOf => ReferenceKind::RefOf,
AmlSerdeReferenceKind::Local => ReferenceKind::Local,
AmlSerdeReferenceKind::Arg => ReferenceKind::Arg,
AmlSerdeReferenceKind::Index => ReferenceKind::Index,
AmlSerdeReferenceKind::Named => ReferenceKind::Named,
AmlSerdeReferenceKind::Unresolved => ReferenceKind::Unresolved,
},
inner: inner.to_aml_object()?.wrap(),
},
AmlSerdeValue::Package { contents } => Object::Package(
contents
.into_iter()
.map(|item| item.to_aml_object().map(Object::wrap)) // TODO: see if errors should be ignored here
.collect::<Option<Vec<WrappedObject>>>()?,
),
AmlSerdeValue::PowerResource {
system_level,
resource_order,
} => Object::PowerResource {
system_level: system_level.to_owned(),
resource_order: resource_order.to_owned(),
},
AmlSerdeValue::RawDataBuffer => Object::RawDataBuffer,
AmlSerdeValue::ThermalZone => Object::ThermalZone,
AmlSerdeValue::Debug => Object::Debug,
})
}
}
pub mod aml_serde_name {
use acpi::aml::namespace::AmlName;
/// Add a leading backslash to make the name a valid
/// namespace reference
pub fn to_aml_format(pretty_name: &String) -> String {
format!("\\{}", pretty_name)
}
/// convert a string from AML namespace style to
/// acpi symbol style
pub fn to_symbol(aml_style_name: &String) -> String {
let mut name = aml_style_name.to_owned();
// remove leading slash
name = name.trim_start_matches("\\").to_owned();
// remove unnecessary underscores
while let Some(index) = name.find("_.") {
name.remove(index);
}
while name.len() > 0 && &name[name.len() - 1..] == "_" {
name.pop();
}
name.shrink_to_fit();
name
}
/// Convert to string and remove
/// trailing underscores from each name segment
pub fn aml_to_symbol(aml_name: &AmlName) -> String {
to_symbol(&aml_name.as_string())
}
}