From 95cbdc3cc091b33b22ace0a5bbcb627c767549a1 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 24 Mar 2025 23:13:42 +0800 Subject: [PATCH 1/5] ccgx: Extract CCG8 PD version from capsule ``` > framework_tool --ho2-capsule Framework_Laptop_13_Ryzen7040_capsule_signed_allsku_3.08.cap [...] Detected CCG8 firmware FW 1 Silicon ID: 0x11c5 Silicon Family: 0x3580 Version: 0.0.1C Base Ver: 3.7.0.0D0 Row size: 256 B Start Row: 290 Rows: 474 Size: 121444 B Size: 118 KB FW 2 Silicon ID: 0x11c5 Silicon Family: 0x3580 Version: 0.0.1C Base Ver: 3.7.0.0D0 Row size: 256 B Start Row: 29 Rows: 175 Size: 45024 B Size: 43 KB ``` Signed-off-by: Daniel Schaefer --- README.md | 2 +- framework_lib/src/capsule_content.rs | 5 ++++- framework_lib/src/ccgx/binary.rs | 5 +++-- framework_lib/src/commandline/mod.rs | 5 ++++- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1c454543..88b90844 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ see the [Support Matrices](support-matrices.md). - [x] HO2 BIOS Capsule (`--ho2-capsule`) - [x] BIOS Version - [x] EC Version - - [x] CCG5/CCG6 PD Version + - [x] CCG5/CCG6/CCG8 PD Version - [x] UEFI Capsule (`--capsule`) - [x] Parse metadata from capsule binary - [x] Determine type (GUID) of capsule binary diff --git a/framework_lib/src/capsule_content.rs b/framework_lib/src/capsule_content.rs index ca9d9ec6..cceb7ed1 100644 --- a/framework_lib/src/capsule_content.rs +++ b/framework_lib/src/capsule_content.rs @@ -8,7 +8,7 @@ use crate::alloc::string::ToString; use alloc::string::String; use core::convert::TryInto; -use crate::ccgx::binary::{CCG5_PD_LEN, CCG6_PD_LEN}; +use crate::ccgx::binary::{CCG5_PD_LEN, CCG6_PD_LEN, CCG8_PD_LEN}; use crate::ec_binary::EC_LEN; use crate::util; @@ -57,10 +57,13 @@ pub fn find_pd_in_bios_cap(data: &[u8]) -> Option<&[u8]> { // they're the same version let ccg5_needle = &[0x00, 0x20, 0x00, 0x20, 0x11, 0x00]; let ccg6_needle = &[0x00, 0x40, 0x00, 0x20, 0x11, 0x00]; + let ccg8_needle = &[0x00, 0x80, 0x00, 0x20, 0xAD, 0x0C]; if let Some(found_pd1) = util::find_sequence(data, ccg5_needle) { Some(&data[found_pd1..found_pd1 + CCG5_PD_LEN]) } else if let Some(found_pd1) = util::find_sequence(data, ccg6_needle) { Some(&data[found_pd1..found_pd1 + CCG6_PD_LEN]) + } else if let Some(found_pd1) = util::find_sequence(data, ccg8_needle) { + Some(&data[found_pd1..found_pd1 + CCG8_PD_LEN]) } else { None } diff --git a/framework_lib/src/ccgx/binary.rs b/framework_lib/src/ccgx/binary.rs index acb9c51a..09c16855 100644 --- a/framework_lib/src/ccgx/binary.rs +++ b/framework_lib/src/ccgx/binary.rs @@ -53,8 +53,9 @@ struct VersionInfo { silicon_family: u16, } -pub const CCG5_PD_LEN: usize = 0x2_0000; -pub const CCG6_PD_LEN: usize = 0x2_0000; +pub const CCG5_PD_LEN: usize = 0x20_000; +pub const CCG6_PD_LEN: usize = 0x20_000; +pub const CCG8_PD_LEN: usize = 0x40_000; /// Information about all the firmware in a PD binary file /// diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 01a40fe5..d08a6dc7 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -957,7 +957,10 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { analyze_ec_fw(ec_bin); } if let Some(pd_bin) = find_pd_in_bios_cap(&data) { + debug!("Found PD binary in BIOS capsule"); analyze_ccgx_pd_fw(pd_bin); + } else { + debug!("Didn't find PD binary in BIOS capsule"); } } } else if let Some(dump_path) = &args.dump_ec_flash { @@ -1280,7 +1283,7 @@ fn analyze_ccgx_pd_fw(data: &[u8]) { ccgx::binary::print_fw(&versions.main_fw); return; } else { - println!("Failed to read versions") + println!("Failed to read PD versions") } } From 12b39558618469dd79444ec16dfeb13f3c0c71fe Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 24 Mar 2025 23:27:15 +0800 Subject: [PATCH 2/5] capsule: Fix reading BIOS platform and version Can't believe it has never been correct... ``` > framework_tool --ho2-capsule Framework_Laptop_13_12th_Gen_Intel_Core_capsule_signed_allsku_3.09.cap File Size: 36130244 B Size: 35283 KB BIOS Platform: HFW30 BIOS Version: 03.09 [...] > framework_tool --ho2-capsule Framework_Laptop_13_Ryzen7040_capsule_signed_allsku_3.08.cap File Size: 36129956 B Size: 35283 KB BIOS Platform: JFP30 BIOS Version: 03.08 [...] ``` Signed-off-by: Daniel Schaefer --- framework_lib/src/capsule_content.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/framework_lib/src/capsule_content.rs b/framework_lib/src/capsule_content.rs index cceb7ed1..5dfe5241 100644 --- a/framework_lib/src/capsule_content.rs +++ b/framework_lib/src/capsule_content.rs @@ -29,13 +29,14 @@ pub fn find_bios_version(data: &[u8]) -> Option { let needle = b"$BVDT"; let found = util::find_sequence(data, needle)?; + // One of: GFW30, HFW3T, HFW30, IFR30, KFM30, JFP30, LFK30, IFGA3, IFGP6, LFR20, LFSP0 let platform_offset = found + 0xA + needle.len() - 1; - let platform = std::str::from_utf8(&data[platform_offset..platform_offset + 4]) + let platform = std::str::from_utf8(&data[platform_offset..platform_offset + 5]) .map(|x| x.to_string()) .ok()?; - let ver_offset = found + 0xE + needle.len() - 1; - let version = std::str::from_utf8(&data[ver_offset..ver_offset + 4]) + let ver_offset = found + 0x10 + needle.len() - 1; + let version = std::str::from_utf8(&data[ver_offset..ver_offset + 5]) .map(|x| x.to_string()) .ok()?; From 721a938bbb8b54f75cc8471df418c9beb512a0f8 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 24 Mar 2025 23:33:38 +0800 Subject: [PATCH 3/5] It's H2O, not HO2 Signed-off-by: Daniel Schaefer --- README.md | 4 ++-- framework_lib/src/commandline/clap_std.rs | 6 +++--- framework_lib/src/commandline/mod.rs | 13 ++++++++----- framework_lib/src/commandline/uefi.rs | 8 ++++---- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 88b90844..f9089bb6 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ see the [Support Matrices](support-matrices.md). - [x] CCG5 PD (11th Gen TigerLake) (`--pd-bin`) - [x] CCG6 PD (12th Gen AlderLake) (`--pd-bin`) - [x] CCG8 PD (Framework 16) (`--pd-bin`) - - [x] HO2 BIOS Capsule (`--ho2-capsule`) + - [x] H2O BIOS Capsule (`--h2o-capsule`) - [x] BIOS Version - [x] EC Version - [x] CCG5/CCG6/CCG8 PD Version @@ -182,7 +182,7 @@ Options: --ec-bin Parse versions from EC firmware binary file --capsule Parse UEFI Capsule information from binary file --dump Dump extracted UX capsule bitmap image to a file - --ho2-capsule Parse UEFI Capsule information from binary file + --h2o-capsule Parse UEFI Capsule information from binary file --intrusion Show status of intrusion switch --inputmodules Show status of the input modules (Framework 16 only) --kblight [] Set keyboard backlight percentage or get, if no value provided diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index 96249b8e..f9299e6d 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -100,7 +100,7 @@ struct ClapCli { /// Parse UEFI Capsule information from binary file #[arg(long)] - ho2_capsule: Option, + h2o_capsule: Option, /// Dump EC flash contents #[arg(long)] @@ -259,8 +259,8 @@ pub fn parse(args: &[String]) -> Cli { .capsule .map(|x| x.into_os_string().into_string().unwrap()), dump: args.dump.map(|x| x.into_os_string().into_string().unwrap()), - ho2_capsule: args - .ho2_capsule + h2o_capsule: args + .h2o_capsule .map(|x| x.into_os_string().into_string().unwrap()), dump_ec_flash: args .dump_ec_flash diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index d08a6dc7..c42d97d9 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -152,7 +152,7 @@ pub struct Cli { pub ec_bin: Option, pub capsule: Option, pub dump: Option, - pub ho2_capsule: Option, + pub h2o_capsule: Option, pub dump_ec_flash: Option, pub flash_ec: Option, pub flash_ro_ec: Option, @@ -932,7 +932,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { println!("Capsule is invalid."); } } - } else if let Some(capsule_path) = &args.ho2_capsule { + } else if let Some(capsule_path) = &args.h2o_capsule { #[cfg(feature = "uefi")] let data = crate::uefi::fs::shell_read_file(capsule_path); #[cfg(not(feature = "uefi"))] @@ -954,7 +954,10 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { println!(" BIOS Version: {:>18}", cap.version); } if let Some(ec_bin) = find_ec_in_bios_cap(&data) { + debug!("Found EC binary in BIOS capsule"); analyze_ec_fw(ec_bin); + } else { + debug!("Didn't find EC binary in BIOS capsule"); } if let Some(pd_bin) = find_pd_in_bios_cap(&data) { debug!("Found PD binary in BIOS capsule"); @@ -1025,7 +1028,7 @@ Options: --ec-bin Parse versions from EC firmware binary file --capsule Parse UEFI Capsule information from binary file --dump Dump extracted UX capsule bitmap image to a file - --ho2-capsule Parse UEFI Capsule information from binary file + --h2o-capsule Parse UEFI Capsule information from binary file --dump-ec-flash Dump EC flash contents --flash-ec Flash EC with new firmware from file --flash-ro-ec Flash EC with new firmware from file @@ -1292,13 +1295,13 @@ pub fn analyze_ec_fw(data: &[u8]) { if let Some(ver) = ec_binary::read_ec_version(data, true) { ec_binary::print_ec_version(&ver, true); } else { - println!("Failed to read version") + println!("Failed to read EC version") } // Readwrite firmware if let Some(ver) = ec_binary::read_ec_version(data, false) { ec_binary::print_ec_version(&ver, false); } else { - println!("Failed to read version") + println!("Failed to read EC version") } } diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index ce350868..261720fc 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -78,7 +78,7 @@ pub fn parse(args: &[String]) -> Cli { flash_rw_ec: None, capsule: None, dump: None, - ho2_capsule: None, + h2o_capsule: None, intrusion: false, inputmodules: false, input_deck_mode: None, @@ -374,11 +374,11 @@ pub fn parse(args: &[String]) -> Cli { None }; found_an_option = true; - } else if arg == "--ho2-capsule" { - cli.ho2_capsule = if args.len() > i + 1 { + } else if arg == "--h2o-capsule" { + cli.h2o_capsule = if args.len() > i + 1 { Some(args[i + 1].clone()) } else { - println!("--ho2-capsule requires extra argument to denote input file"); + println!("--h2o-capsule requires extra argument to denote input file"); None }; found_an_option = true; From f8a80adad9268a55d03e82700e0e31dc0722a47b Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 24 Mar 2025 23:44:48 +0800 Subject: [PATCH 4/5] capsule: Fix EC version detection for Zephyr based Now it can work for both legacy and zephyr based ECs. Tested on Intel 12th gen, AMD Ryzen 7040, AMD Ryzen AI 300, Framework Desktop. ``` > framework_tool --h2o-capsule Framework_Laptop_13_Ryzen7040_capsule_signed_allsku_3.08.cap [...] EC Type: RO Version: azalea_v3.4.113382-ec:ec916d,os RollbackVer: 0 Platform: azalea Version: 3.4.113382 Commit: ec916d Size: 258048 B Size: 252 KB EC Type: RW Version: azalea_v3.4.113382-ec:ec916d,os RollbackVer: 0 Platform: azalea Version: 3.4.113382 Commit: ec916d Size: 258048 B Size: 252 KB [...] ``` Signed-off-by: Daniel Schaefer --- framework_lib/src/capsule_content.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/framework_lib/src/capsule_content.rs b/framework_lib/src/capsule_content.rs index 5dfe5241..81199bda 100644 --- a/framework_lib/src/capsule_content.rs +++ b/framework_lib/src/capsule_content.rs @@ -44,12 +44,10 @@ pub fn find_bios_version(data: &[u8]) -> Option { } pub fn find_ec_in_bios_cap(data: &[u8]) -> Option<&[u8]> { - let needle = b"_IFLASH_EC_IMG_"; - let found_iflash = util::find_sequence(data, needle)?; - // The actual EC binary is a few bytes after `_IFLASH_EC_IMG_`. - // Just earch for the first 4 bytes that seem to appear in all EC images. - let found = util::find_sequence(&data[found_iflash..], &[0x10, 0x00, 0x00, 0xf7])?; - Some(&data[found_iflash + found..found_iflash + found + EC_LEN]) + let needle = b"$_IFLASH_EC_IMG_"; + let found = util::find_sequence(data, needle)?; + let ec_offset = found + 0x9 + needle.len() - 1; + Some(&data[ec_offset..ec_offset + EC_LEN]) } pub fn find_pd_in_bios_cap(data: &[u8]) -> Option<&[u8]> { From 4ba840d437e78847498cd1b816555a220b285db2 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Mon, 24 Mar 2025 23:47:28 +0800 Subject: [PATCH 5/5] README: Update to latest status Signed-off-by: Daniel Schaefer --- README.md | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index f9089bb6..28a10603 100644 --- a/README.md +++ b/README.md @@ -25,11 +25,10 @@ see the [Support Matrices](support-matrices.md). - [x] ESRT table (UEFI, Linux, FreeBSD only) (`--esrt`) - [x] SMBIOS - [x] Get firmware version from binary file - - [x] Legacy EC (Intel 13th Gen and earlier) (`--ec-bin`) - - [x] Zephyr EC (AMD) (`--ec-bin`) + - [x] EC (Legacy and Zephyr based) (`--ec-bin`) - [x] CCG5 PD (11th Gen TigerLake) (`--pd-bin`) - - [x] CCG6 PD (12th Gen AlderLake) (`--pd-bin`) - - [x] CCG8 PD (Framework 16) (`--pd-bin`) + - [x] CCG6 PD (Intel systems, Framework Desktop) (`--pd-bin`) + - [x] CCG8 PD (AMD Laptops) (`--pd-bin`) - [x] H2O BIOS Capsule (`--h2o-capsule`) - [x] BIOS Version - [x] EC Version @@ -53,16 +52,6 @@ see the [Support Matrices](support-matrices.md). - [x] DisplayPort Expansion Card (`--dp-hdmi-update`) - [ ] Audio Expansion Card -###### Firmware Update - -Note: Use fwupd. - -- [ ] Flash firmware - - [ ] BIOS - - [ ] EC - - [ ] PD - - [ ] Expansion Cards - ###### System Status All of these need EC communication support in order to work. @@ -90,6 +79,7 @@ All of these need EC communication support in order to work. - [x] Framework Desktop (AMD Ryzen AI Max 300) - [x] Port I/O communication on Linux - [x] Port I/O communication in UEFI +- [x] Port I/O communication on FreeBSD - [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)