diff --git a/README.md b/README.md index 1c454543..28a10603 100644 --- a/README.md +++ b/README.md @@ -25,15 +25,14 @@ 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] HO2 BIOS Capsule (`--ho2-capsule`) + - [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 - - [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 @@ -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) @@ -182,7 +172,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/capsule_content.rs b/framework_lib/src/capsule_content.rs index ca9d9ec6..81199bda 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; @@ -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()?; @@ -43,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]> { @@ -57,10 +56,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/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 01a40fe5..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,10 +954,16 @@ 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"); 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 { @@ -1022,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 @@ -1280,7 +1286,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") } } @@ -1289,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;