Skip to content

Add support for Framework 2nd Gen Event platforms #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Feb 28, 2025
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