Skip to content
18 changes: 9 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,12 +82,16 @@ All of these need EC communication support in order to work.

###### Communication with Embedded Controller

- [x] Framework Laptop 12 (Intel 13th Gen)
- [x] Framework Laptop 13 (Intel 11-13th Gen)
- [x] Framework Laptop 13 (AMD Ryzen)
- [x] Framework Laptop 16 (AMD Ryzen)
- [x] Framework Laptop 13 (AMD Ryzen 7080)
- [x] Framework Laptop 13 (AMD Ryzen AI 300)
- [x] Framework Laptop 16 (AMD Ryzen 7080)
- [x] Framework Desktop (AMD Ryzen AI Max 300)
- [x] Port I/O communication on Linux
- [x] Port I/O communication on UEFI
- [x] Port I/O communication in UEFI
- [x] Using `cros_ec` driver in Linux kernel
- [x] Using [Framework EC Windows driver](https://github.com/FrameworkComputer/crosecbus) based on [coolstar's](https://github.com/coolstar/crosecbus)
- [x] Using [DHowett's Windows CrosEC driver](https://github.com/DHowett/FrameworkWindowsUtils)

## Prerequisites
Expand All @@ -99,8 +103,8 @@ will install the right toolchain and version for this project.

MSRV (Minimum Supported Rust Version):

- 1.61 for Linux/Windows
- 1.68 for UEFI
- 1.74 for Linux/Windows
- 1.74 for UEFI

```sh
# Running linter
Expand Down Expand Up @@ -131,10 +135,6 @@ ls -l framework_uefi/build/x86_64-unknown-uefi/boot.efi
Building on Windows or in general with fewer features:

```ps1
# Because we're fetching a private dependency from git, it might be necessary
# to force cargo to use the git commandline. In powershell run:
$env:CARGO_NET_GIT_FETCH_WITH_CLI='true'

# Build the library and tool
cargo build --no-default-features --features "windows"

Expand Down
4 changes: 2 additions & 2 deletions framework_lib/src/audio_card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ enum CapeCommand {
GetVersion = 0x0103,
}

#[repr(packed)]
#[repr(C, packed)]
#[derive(Clone, Copy)]
struct CapeMessage {
_len: i16,
Expand All @@ -25,7 +25,7 @@ struct CapeMessage {
data: [u32; CAPE_DATA_LEN],
}

#[repr(packed)]
#[repr(C, packed)]
#[derive(Clone, Copy)]
struct HidCapeMessage {
_report_id: u16,
Expand Down
2 changes: 1 addition & 1 deletion framework_lib/src/ccgx/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const FW_VERSION_OFFSET: usize = 0xE0;
const SMALL_ROW: usize = 0x80;
const LARGE_ROW: usize = 0x100;

#[repr(packed)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct VersionInfo {
base_version: u32,
Expand Down
30 changes: 26 additions & 4 deletions framework_lib/src/ccgx/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,20 @@ impl PdPort {
(Platform::GenericFramework((left, _), _, _), PdPort::Left01) => *left,
(Platform::GenericFramework((_, right), _, _), PdPort::Right23) => *right,
// Framework AMD Platforms (CCG8)
(Platform::Framework13Amd | Platform::Framework16, PdPort::Left01) => 0x42,
(Platform::Framework13Amd | Platform::Framework16, PdPort::Right23) => 0x40,
(
Platform::Framework13Amd7080
| Platform::Framework13AmdAi300
| Platform::Framework16Amd7080,
PdPort::Left01,
) => 0x42,
(
Platform::Framework13Amd7080
| Platform::Framework13AmdAi300
| Platform::Framework16Amd7080,
PdPort::Right23,
) => 0x40,
// TODO: It only has a single PD controller
(Platform::FrameworkDesktopAmdAiMax300, _) => 0x08,
// Framework Intel Platforms (CCG5 and CCG6)
(_, PdPort::Left01) => 0x08,
(_, PdPort::Right23) => 0x40,
Expand All @@ -64,13 +76,23 @@ impl PdPort {
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Left01) => 6,
(Platform::IntelGen12 | Platform::IntelGen13, PdPort::Right23) => 7,
(
Platform::Framework13Amd | Platform::Framework16 | Platform::IntelCoreUltra1,
Platform::Framework13Amd7080
| Platform::Framework16Amd7080
| Platform::IntelCoreUltra1
| Platform::Framework13AmdAi300
| Platform::Framework12IntelGen13,
PdPort::Left01,
) => 1,
(
Platform::Framework13Amd | Platform::Framework16 | Platform::IntelCoreUltra1,
Platform::Framework13Amd7080
| Platform::Framework16Amd7080
| Platform::IntelCoreUltra1
| Platform::Framework13AmdAi300
| Platform::Framework12IntelGen13,
PdPort::Right23,
) => 2,
// TODO: It only has a single PD controller
(Platform::FrameworkDesktopAmdAiMax300, _) => 1,
// (_, _) => Err(EcError::DeviceError(format!(
// "Unsupported platform: {:?} {:?}",
// platform, self
Expand Down
2 changes: 1 addition & 1 deletion framework_lib/src/ccgx/hid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const FW2_START: usize = 0x0200;
const FW1_METADATA: usize = 0x03FF;
const FW2_METADATA: usize = 0x03FE;

#[repr(packed)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct HidFirmwareInfo {
report_id: u8,
Expand Down
4 changes: 2 additions & 2 deletions framework_lib/src/ccgx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CCG3_METADATA_OFFSET: usize = 0x40;
const METADATA_MAGIC: u16 = u16::from_le_bytes([b'Y', b'C']); // CY (Cypress)
const CCG8_METADATA_MAGIC: u16 = u16::from_le_bytes([b'F', b'I']); // IF (Infineon)

#[repr(packed)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct CyAcdMetadata {
/// Offset 00: Single Byte FW Checksum
Expand Down Expand Up @@ -64,7 +64,7 @@ struct CyAcdMetadata {
}

// TODO: Would be nice to check the checksums
#[repr(packed)]
#[repr(C, packed)]
#[derive(Debug, Copy, Clone)]
struct CyAcd2Metadata {
/// Offset 00: App Firmware Start
Expand Down
8 changes: 7 additions & 1 deletion framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,15 @@ pub fn has_mec() -> bool {
return has_mec;
}

// TODO: Should turn this around
!matches!(
smbios::get_platform().unwrap(),
Platform::Framework13Amd | Platform::Framework16 | Platform::IntelCoreUltra1
Platform::Framework13Amd7080
| Platform::Framework16Amd7080
| Platform::IntelCoreUltra1
| Platform::Framework13AmdAi300
| Platform::Framework12IntelGen13
| Platform::FrameworkDesktopAmdAiMax300
)
}

Expand Down
2 changes: 1 addition & 1 deletion framework_lib/src/esrt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ pub fn match_guid_kind(guid: &Guid) -> FrameworkGuidKind {
}
}

#[repr(packed)]
#[repr(C, packed)]
struct _Esrt {
resource_count: u32,
resource_count_max: u32,
Expand Down
42 changes: 38 additions & 4 deletions framework_lib/src/power.rs
Original file line number Diff line number Diff line change
Expand Up @@ -214,20 +214,54 @@ pub fn print_thermal(ec: &CrosEc) {
println!(" F75303_DDR: {:>4}", TempSensor::from(temps[2]));
println!(" Battery: {:>4}", TempSensor::from(temps[3]));
println!(" PECI: {:>4}", TempSensor::from(temps[4]));
println!(" F57397_VCCGT: {:>4}", TempSensor::from(temps[5]));
if matches!(
platform,
Some(Platform::IntelGen12) | Some(Platform::IntelGen13)
) {
println!(" F57397_VCCGT: {:>4}", TempSensor::from(temps[5]));
}
}
Some(Platform::Framework13Amd | Platform::Framework16) => {

Some(Platform::IntelCoreUltra1) => {
println!(" F75303_Local: {:>4}", TempSensor::from(temps[0]));
println!(" F75303_CPU: {:>4}", TempSensor::from(temps[1]));
println!(" Battery: {:>4}", TempSensor::from(temps[2]));
println!(" F75303_DDR: {:>4}", TempSensor::from(temps[3]));
println!(" PECI: {:>4}", TempSensor::from(temps[4]));
}

Some(Platform::Framework12IntelGen13) => {
println!(" F75303_CPU: {:>4}", TempSensor::from(temps[0]));
println!(" F75303_Skin: {:>4}", TempSensor::from(temps[1]));
println!(" F75303_Local: {:>4}", TempSensor::from(temps[2]));
println!(" Battery: {:>4}", TempSensor::from(temps[3]));
println!(" PECI: {:>4}", TempSensor::from(temps[4]));
}

Some(
Platform::Framework13Amd7080
| Platform::Framework13AmdAi300
| Platform::Framework16Amd7080,
) => {
println!(" F75303_Local: {:>4}", TempSensor::from(temps[0]));
println!(" F75303_CPU: {:>4}", TempSensor::from(temps[1]));
println!(" F75303_DDR: {:>4}", TempSensor::from(temps[2]));
println!(" APU: {:>4}", TempSensor::from(temps[3]));
if matches!(platform, Some(Platform::Framework16)) {
if matches!(platform, Some(Platform::Framework16Amd7080)) {
println!(" dGPU VR: {:>4}", TempSensor::from(temps[4]));
println!(" dGPU VRAM: {:>4}", TempSensor::from(temps[5]));
println!(" dGPU AMB: {:>4}", TempSensor::from(temps[6]));
println!(" dGPU temp: {:>4}", TempSensor::from(temps[7]));
}
}

Some(Platform::FrameworkDesktopAmdAiMax300) => {
println!(" F75303_APU: {:>4}", TempSensor::from(temps[0]));
println!(" F75303_DDR: {:>4}", TempSensor::from(temps[1]));
println!(" F75303_AMB: {:>4}", TempSensor::from(temps[2]));
println!(" APU: {:>4}", TempSensor::from(temps[3]));
}

_ => {
println!(" Temp 0: {:>4}", TempSensor::from(temps[0]));
println!(" Temp 1: {:>4}", TempSensor::from(temps[1]));
Expand Down Expand Up @@ -495,7 +529,7 @@ pub fn get_pd_info(ec: &CrosEc, ports: u8) -> Vec<EcResult<UsbPdPowerInfo>> {
}

pub fn get_and_print_pd_info(ec: &CrosEc) {
let fl16 = Some(crate::util::Platform::Framework16) == get_platform();
let fl16 = Some(crate::util::Platform::Framework16Amd7080) == get_platform();
let ports = 4; // All our platforms have 4 PD ports so far
let infos = get_pd_info(ec, ports);
for (port, info) in infos.iter().enumerate().take(ports.into()) {
Expand Down
11 changes: 7 additions & 4 deletions framework_lib/src/smbios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub struct Smbios3 {
}

#[cfg(target_os = "freebsd")]
#[repr(packed)]
#[repr(C, packed)]
pub struct Smbios {
pub anchor: [u8; 4],
pub checksum: u8,
Expand Down Expand Up @@ -262,10 +262,13 @@ pub fn get_platform() -> Option<Platform> {
"Laptop" => Some(Platform::IntelGen11),
"Laptop (12th Gen Intel Core)" => Some(Platform::IntelGen12),
"Laptop (13th Gen Intel Core)" => Some(Platform::IntelGen13),
"Laptop 13 (AMD Ryzen 7040Series)" => Some(Platform::Framework13Amd),
"Laptop 13 (AMD Ryzen 7040 Series)" => Some(Platform::Framework13Amd),
"Laptop 13 (AMD Ryzen 7040Series)" => Some(Platform::Framework13Amd7080),
"Laptop 13 (AMD Ryzen 7040 Series)" => Some(Platform::Framework13Amd7080),
"Laptop 13 (AMD Ryzen AI 300 Series)" => Some(Platform::Framework13AmdAi300),
"Laptop 12 (13th Gen Intel Core)" => Some(Platform::Framework12IntelGen13),
"Laptop 13 (Intel Core Ultra Series 1)" => Some(Platform::IntelCoreUltra1),
"Laptop 16 (AMD Ryzen 7040 Series)" => Some(Platform::Framework16),
"Laptop 16 (AMD Ryzen 7040 Series)" => Some(Platform::Framework16Amd7080),
"Desktop (AMD Ryzen AI Max 300 Series)" => Some(Platform::FrameworkDesktopAmdAiMax300),
_ => None,
};

Expand Down
2 changes: 1 addition & 1 deletion framework_lib/src/uefi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub fn enable_page_break() {
}
}

#[repr(packed)]
#[repr(C, packed)]
pub struct Smbios {
pub anchor: [u8; 4],
pub checksum: u8,
Expand Down
14 changes: 10 additions & 4 deletions framework_lib/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ use crate::smbios;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum Platform {
/// Framework 12
Framework12IntelGen13,
/// Framework 13 - Intel 11th Gen, Codenamed TigerLake
IntelGen11,
/// Framework 13 - Intel 11th Gen, Codenamed AlderLake
Expand All @@ -25,10 +27,14 @@ pub enum Platform {
IntelGen13,
/// Framework 13 - Intel Core Ultra Series 1, Codenamed MeteorLake
IntelCoreUltra1,
/// Framework 13 - AMD Ryzen
Framework13Amd,
/// Framework 16
Framework16,
/// Framework 13 - AMD Ryzen 7080 Series
Framework13Amd7080,
/// Framework 13 - AMD Ryzen AI 300 Series
Framework13AmdAi300,
/// Framework 16 - AMD Ryzen 7080 Series
Framework16Amd7080,
/// Framework Desktop - AMD Ryzen AI Max 300
FrameworkDesktopAmdAiMax300,
/// Generic Framework device
/// pd_addrs, pd_ports, has_mec
GenericFramework((u16, u16), (u8, u8), bool),
Expand Down