From 0a9e298a30cf5028ecdc65b4a8d215674dbb4440 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 15 Sep 2026 12:03:04 +0200 Subject: [PATCH 1/2] Add support for CCG6 CFP binaries Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/binary.rs | 96 +++++++++++++++++++++- framework_lib/src/ccgx/mod.rs | 3 + framework_lib/src/commandline/mod.rs | 2 +- framework_lib/test_bins/dahlia-0.0.0A.bin | Bin 0 -> 131072 bytes 4 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 framework_lib/test_bins/dahlia-0.0.0A.bin diff --git a/framework_lib/src/ccgx/binary.rs b/framework_lib/src/ccgx/binary.rs index 98d44a3..717840e 100644 --- a/framework_lib/src/ccgx/binary.rs +++ b/framework_lib/src/ccgx/binary.rs @@ -112,10 +112,11 @@ fn read_metadata( SiliconFamily::Ccg5 | SiliconFamily::Ccg6Adl | SiliconFamily::Ccg6 => { parse_metadata_cyacd(&buffer) } - SiliconFamily::Ccg8D | SiliconFamily::Ccg8S | SiliconFamily::Ccg8Cfp => { - parse_metadata_cyacd2(&buffer) - .map(|(fw_row_start, fw_size)| (fw_row_start / (flash_row_size as u32), fw_size)) - } + SiliconFamily::Ccg8D + | SiliconFamily::Ccg8S + | SiliconFamily::Ccg6Cfp + | SiliconFamily::Ccg8Cfp => parse_metadata_cyacd2(&buffer) + .map(|(fw_row_start, fw_size)| (fw_row_start / (flash_row_size as u32), fw_size)), } } @@ -181,6 +182,7 @@ pub fn read_versions(file_buffer: &[u8], ccgx: SiliconFamily) -> Option (SMALL_ROW, 0x1FE, 0x1FD), SiliconFamily::Ccg8D => (LARGE_ROW, 0x3FE, 0x3FF), SiliconFamily::Ccg8S => (LARGE_ROW, 0x3FE, 0x3FF), + SiliconFamily::Ccg6Cfp => (LARGE_ROW, 0x1FE, 0x1FF), SiliconFamily::Ccg8Cfp => (LARGE_ROW, 0x1FE, 0x1FF), }; let backup_fw = read_version(file_buffer, flash_row_size, f1_metadata_row, ccgx)?; @@ -223,12 +225,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_some()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -289,12 +293,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_some()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -355,12 +361,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_some()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -421,12 +429,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_some()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -487,12 +497,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_some()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -553,12 +565,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_some()); assert!(ccg8s_ver.is_some()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -619,12 +633,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_some()); assert!(ccg8s_ver.is_some()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -685,12 +701,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_some()); assert!(ccg8s_ver.is_some()); + assert!(ccg6cfp_ver.is_none()); assert!(ccg8cfp_ver.is_none()); assert_eq!( @@ -751,12 +769,14 @@ mod tests { let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); assert!(ccg3_ver.is_none()); assert!(ccg5_ver.is_none()); assert!(ccg6_ver.is_none()); assert!(ccg8d_ver.is_none()); assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_some()); assert!(ccg8cfp_ver.is_some()); assert_eq!( @@ -805,4 +825,72 @@ mod tests { }) ); } + + #[test] + fn can_parse_ccg8_binary_dahlia() { + let mut pd_bin_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + pd_bin_path.push("test_bins/dahlia-0.0.0A.bin"); + + let data = fs::read(pd_bin_path).unwrap(); + let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); + let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); + let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); + let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); + let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); + let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); + let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); + assert!(ccg3_ver.is_none()); + assert!(ccg5_ver.is_none()); + assert!(ccg6_ver.is_none()); + assert!(ccg8d_ver.is_none()); + assert!(ccg8s_ver.is_none()); + assert!(ccg6cfp_ver.is_some()); + assert!(ccg8cfp_ver.is_some()); + + assert_eq!( + ccg8cfp_ver, + Some({ + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E03, + base_version: BaseVersion { + major: 3, + minor: 9, + patch: 0, + build_number: 826, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 116, + size: 82160, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E03, + base_version: BaseVersion { + major: 3, + minor: 9, + patch: 0, + build_number: 826, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 7, + size: 24832, + row_size: 0x100, + }, + } + }) + ); + } } diff --git a/framework_lib/src/ccgx/mod.rs b/framework_lib/src/ccgx/mod.rs index 99b3ad8..6f4fe67 100644 --- a/framework_lib/src/ccgx/mod.rs +++ b/framework_lib/src/ccgx/mod.rs @@ -111,6 +111,9 @@ pub enum SiliconFamily { Ccg6 = 0x30A0, Ccg8D = 0x3580, Ccg8S = 0x3581, + /// CCG6xF_CFP, e.g. CYPD6229 + Ccg6Cfp = 0x3E03, + /// CCG8xF_CFP, e.g. CYPD8229 Ccg8Cfp = 0x3E81, } diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 0fb317d..ba9576c 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -2623,7 +2623,7 @@ fn analyze_ccgx_pd_fw(data: &[u8]) { println!("FW 2"); ccgx::binary::print_fw(&versions.main_fw); } else if let Some(versions) = ccgx::binary::read_versions(data, Ccg8Cfp) { - println!("Detected CCG8 CFP firmware"); + println!("Detected CCG6/CCG8 CFP firmware"); println!("FW 1"); ccgx::binary::print_fw(&versions.backup_fw); diff --git a/framework_lib/test_bins/dahlia-0.0.0A.bin b/framework_lib/test_bins/dahlia-0.0.0A.bin new file mode 100644 index 0000000000000000000000000000000000000000..e6c95ad3ad79c4b0f3bdc3734bb378e61e49e74b GIT binary patch literal 131072 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 Date: Wed, 16 Sep 2026 08:08:38 +0200 Subject: [PATCH 2/2] pd-test: Extract checking chip logic Signed-off-by: Daniel Schaefer --- framework_lib/src/ccgx/binary.rs | 1087 ++++++++++++-------------- framework_lib/src/commandline/mod.rs | 60 +- 2 files changed, 509 insertions(+), 638 deletions(-) diff --git a/framework_lib/src/ccgx/binary.rs b/framework_lib/src/ccgx/binary.rs index 717840e..799e9b3 100644 --- a/framework_lib/src/ccgx/binary.rs +++ b/framework_lib/src/ccgx/binary.rs @@ -162,6 +162,15 @@ fn read_version( let fw_silicon_id = version_info.silicon_id.get(); let fw_silicon_family = version_info.silicon_family.get(); + if fw_silicon_family != ccgx as u16 { + trace!( + "Silicon family mismatch. Expected {:#06x}, binary has {:#06x}", + ccgx as u16, + fw_silicon_family + ); + return None; + } + Some(PdFirmware { silicon_id: fw_silicon_id, silicon_family: fw_silicon_family, @@ -214,72 +223,83 @@ mod tests { use std::fs; use std::path::PathBuf; + /// Find the silicon family whose parameters match this binary + fn detect_family(data: &[u8]) -> Option<(SiliconFamily, PdFirmwareFile)> { + let families = [ + SiliconFamily::Ccg3, + SiliconFamily::Ccg5, + SiliconFamily::Ccg6Adl, + SiliconFamily::Ccg6, + SiliconFamily::Ccg8D, + SiliconFamily::Ccg8S, + SiliconFamily::Ccg6Cfp, + SiliconFamily::Ccg8Cfp, + ]; + let mut found = None; + for family in families { + if let Some(versions) = read_versions(data, family) { + assert!( + found.is_none(), + "{:?} matched but so did an earlier family", + family + ); + found = Some((family, versions)); + } + } + found + } + #[test] fn can_parse_ccg3_binary() { let mut pd_bin_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); pd_bin_path.push("test_bins/dp-pd-3.0.17.100.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_some()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg3_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11AD, - silicon_family: 0x1D00, - base_version: BaseVersion { - major: 3, - minor: 0, - patch: 17, - build_number: 100, - }, - app_version: AppVersion { - application: Application::AA, - major: 0, - minor: 0, - circuit: 2, - }, - start_row: 48, - size: 58624, - row_size: 128, - }, - main_fw: PdFirmware { - silicon_id: 0x11AD, - silicon_family: 0x1D00, - base_version: BaseVersion { - major: 3, - minor: 0, - patch: 17, - build_number: 100, - }, - app_version: AppVersion { - application: Application::AA, - major: 0, - minor: 0, - circuit: 2, - }, - start_row: 512, - size: 58624, - row_size: 128, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg3); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11AD, + silicon_family: 0x1D00, + base_version: BaseVersion { + major: 3, + minor: 0, + patch: 17, + build_number: 100, + }, + app_version: AppVersion { + application: Application::AA, + major: 0, + minor: 0, + circuit: 2, + }, + start_row: 48, + size: 58624, + row_size: 128, + }, + main_fw: PdFirmware { + silicon_id: 0x11AD, + silicon_family: 0x1D00, + base_version: BaseVersion { + major: 3, + minor: 0, + patch: 17, + build_number: 100, + }, + app_version: AppVersion { + application: Application::AA, + major: 0, + minor: 0, + circuit: 2, + }, + start_row: 512, + size: 58624, + row_size: 128, + }, + } + }); } #[test] @@ -288,66 +308,51 @@ mod tests { pd_bin_path.push("test_bins/tgl-pd-3.8.0.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_some()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg5_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11B1, - silicon_family: 0x2100, - base_version: BaseVersion { - major: 3, - minor: 4, - patch: 0, - build_number: 2575, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 3, - minor: 8, - circuit: 0, - }, - start_row: 163, - size: 88832, - row_size: 256, - }, - main_fw: PdFirmware { - silicon_id: 0x11B1, - silicon_family: 0x2100, - base_version: BaseVersion { - major: 3, - minor: 4, - patch: 0, - build_number: 2575, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 3, - minor: 8, - circuit: 0, - }, - start_row: 20, - size: 36352, - row_size: 256, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg5); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11B1, + silicon_family: 0x2100, + base_version: BaseVersion { + major: 3, + minor: 4, + patch: 0, + build_number: 2575, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 3, + minor: 8, + circuit: 0, + }, + start_row: 163, + size: 88832, + row_size: 256, + }, + main_fw: PdFirmware { + silicon_id: 0x11B1, + silicon_family: 0x2100, + base_version: BaseVersion { + major: 3, + minor: 4, + patch: 0, + build_number: 2575, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 3, + minor: 8, + circuit: 0, + }, + start_row: 20, + size: 36352, + row_size: 256, + }, + } + }); } #[test] @@ -356,66 +361,51 @@ mod tests { pd_bin_path.push("test_bins/adl-pd-0.1.33.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_some()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg6_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 4, - patch: 0, - build_number: 425, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 1, - circuit: 33, - }, - start_row: 22, - size: 12160, - row_size: 128, - }, - main_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 4, - patch: 0, - build_number: 425, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 1, - circuit: 33, - }, - start_row: 118, - size: 49408, - row_size: 128, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg6Adl); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 4, + patch: 0, + build_number: 425, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 1, + circuit: 33, + }, + start_row: 22, + size: 12160, + row_size: 128, + }, + main_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 4, + patch: 0, + build_number: 425, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 1, + circuit: 33, + }, + start_row: 118, + size: 49408, + row_size: 128, + }, + } + }); } #[test] @@ -424,66 +414,51 @@ mod tests { pd_bin_path.push("test_bins/mtl-pd-0.0.A.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_some()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg6_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 6, - patch: 0, - build_number: 115, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0A, - }, - start_row: 10, - size: 12288, - row_size: 128, - }, - main_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 6, - patch: 0, - build_number: 115, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0A, - }, - start_row: 112, - size: 47744, - row_size: 128, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg6Adl); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 6, + patch: 0, + build_number: 115, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 10, + size: 12288, + row_size: 128, + }, + main_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 6, + patch: 0, + build_number: 115, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 112, + size: 47744, + row_size: 128, + }, + } + }); } #[test] @@ -492,66 +467,51 @@ mod tests { pd_bin_path.push("test_bins/dogwood-pd-0.0E.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_some()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg6_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 159, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0E, - }, - start_row: 10, - size: 9344, - row_size: 128, - }, - main_fw: PdFirmware { - silicon_id: 0x11C0, - silicon_family: 0x3000, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 159, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0E, - }, - start_row: 112, - size: 50816, - row_size: 128, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg6Adl); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 159, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0E, + }, + start_row: 10, + size: 9344, + row_size: 128, + }, + main_fw: PdFirmware { + silicon_id: 0x11C0, + silicon_family: 0x3000, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 159, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0E, + }, + start_row: 112, + size: 50816, + row_size: 128, + }, + } + }); } #[test] @@ -560,66 +520,51 @@ mod tests { pd_bin_path.push("test_bins/fl16-pd-0.0.03.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_some()); - assert!(ccg8s_ver.is_some()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg8d_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3580, - base_version: BaseVersion { - major: 3, - minor: 6, - patch: 0, - build_number: 160, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 3, - }, - start_row: 290, - size: 111536, - row_size: 0x100, - }, - main_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3580, - base_version: BaseVersion { - major: 3, - minor: 6, - patch: 0, - build_number: 160, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 3, - }, - start_row: 29, - size: 42312, - row_size: 0x100, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg8D); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3580, + base_version: BaseVersion { + major: 3, + minor: 6, + patch: 0, + build_number: 160, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 3, + }, + start_row: 290, + size: 111536, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3580, + base_version: BaseVersion { + major: 3, + minor: 6, + patch: 0, + build_number: 160, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 3, + }, + start_row: 29, + size: 42312, + row_size: 0x100, + }, + } + }); } #[test] @@ -628,66 +573,51 @@ mod tests { pd_bin_path.push("test_bins/fl16-ai300-pd-0.0.22.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_some()); - assert!(ccg8s_ver.is_some()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg8d_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3580, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 407, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x22, - }, - start_row: 290, - size: 129912, - row_size: 0x100, - }, - main_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3580, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 407, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x22, - }, - start_row: 29, - size: 42816, - row_size: 0x100, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg8D); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3580, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 407, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x22, + }, + start_row: 290, + size: 129912, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3580, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 407, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x22, + }, + start_row: 29, + size: 42816, + row_size: 0x100, + }, + } + }); } #[test] @@ -696,66 +626,51 @@ mod tests { pd_bin_path.push("test_bins/gn22-pd-0.0.22.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_some()); - assert!(ccg8s_ver.is_some()); - assert!(ccg6cfp_ver.is_none()); - assert!(ccg8cfp_ver.is_none()); - - assert_eq!( - ccg8s_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3581, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 407, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x22, - }, - start_row: 290, - size: 126700, - row_size: 0x100, - }, - main_fw: PdFirmware { - silicon_id: 0x11C5, - silicon_family: 0x3581, - base_version: BaseVersion { - major: 3, - minor: 7, - patch: 0, - build_number: 407, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x22, - }, - start_row: 29, - size: 41588, - row_size: 0x100, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg8S); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3581, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 407, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x22, + }, + start_row: 290, + size: 126700, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11C5, + silicon_family: 0x3581, + base_version: BaseVersion { + major: 3, + minor: 7, + patch: 0, + build_number: 407, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x22, + }, + start_row: 29, + size: 41588, + row_size: 0x100, + }, + } + }); } #[test] @@ -764,133 +679,103 @@ mod tests { pd_bin_path.push("test_bins/sakura-pd-1.0.0A.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_some()); - assert!(ccg8cfp_ver.is_some()); - - assert_eq!( - ccg8cfp_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11CE, - silicon_family: 0x3E81, - base_version: BaseVersion { - major: 3, - minor: 8, - patch: 0x50, - build_number: 10, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 1, - minor: 0, - circuit: 0x0A, - }, - start_row: 108, - size: 79092, - row_size: 0x100, - }, - main_fw: PdFirmware { - silicon_id: 0x11CE, - silicon_family: 0x3E81, - base_version: BaseVersion { - major: 3, - minor: 8, - patch: 0x50, - build_number: 10, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 1, - minor: 0, - circuit: 0x0A, - }, - start_row: 7, - size: 24120, - row_size: 0x100, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg8Cfp); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E81, + base_version: BaseVersion { + major: 3, + minor: 8, + patch: 0x50, + build_number: 10, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 1, + minor: 0, + circuit: 0x0A, + }, + start_row: 108, + size: 79092, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E81, + base_version: BaseVersion { + major: 3, + minor: 8, + patch: 0x50, + build_number: 10, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 1, + minor: 0, + circuit: 0x0A, + }, + start_row: 7, + size: 24120, + row_size: 0x100, + }, + } + }); } #[test] - fn can_parse_ccg8_binary_dahlia() { + fn can_parse_ccg6_binary_dahlia() { let mut pd_bin_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); pd_bin_path.push("test_bins/dahlia-0.0.0A.bin"); let data = fs::read(pd_bin_path).unwrap(); - let ccg3_ver = read_versions(&data, SiliconFamily::Ccg3); - let ccg5_ver = read_versions(&data, SiliconFamily::Ccg5); - let ccg6_ver = read_versions(&data, SiliconFamily::Ccg6); - let ccg8d_ver = read_versions(&data, SiliconFamily::Ccg8D); - let ccg8s_ver = read_versions(&data, SiliconFamily::Ccg8S); - let ccg6cfp_ver = read_versions(&data, SiliconFamily::Ccg6Cfp); - let ccg8cfp_ver = read_versions(&data, SiliconFamily::Ccg8Cfp); - assert!(ccg3_ver.is_none()); - assert!(ccg5_ver.is_none()); - assert!(ccg6_ver.is_none()); - assert!(ccg8d_ver.is_none()); - assert!(ccg8s_ver.is_none()); - assert!(ccg6cfp_ver.is_some()); - assert!(ccg8cfp_ver.is_some()); - - assert_eq!( - ccg8cfp_ver, - Some({ - PdFirmwareFile { - backup_fw: PdFirmware { - silicon_id: 0x11CE, - silicon_family: 0x3E03, - base_version: BaseVersion { - major: 3, - minor: 9, - patch: 0, - build_number: 826, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0A, - }, - start_row: 116, - size: 82160, - row_size: 0x100, - }, - main_fw: PdFirmware { - silicon_id: 0x11CE, - silicon_family: 0x3E03, - base_version: BaseVersion { - major: 3, - minor: 9, - patch: 0, - build_number: 826, - }, - app_version: AppVersion { - application: Application::Notebook, - major: 0, - minor: 0, - circuit: 0x0A, - }, - start_row: 7, - size: 24832, - row_size: 0x100, - }, - } - }) - ); + let (family, versions) = detect_family(&data).unwrap(); + assert_eq!(family, SiliconFamily::Ccg6Cfp); + + assert_eq!(versions, { + PdFirmwareFile { + backup_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E03, + base_version: BaseVersion { + major: 3, + minor: 9, + patch: 0, + build_number: 826, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 116, + size: 82160, + row_size: 0x100, + }, + main_fw: PdFirmware { + silicon_id: 0x11CE, + silicon_family: 0x3E03, + base_version: BaseVersion { + major: 3, + minor: 9, + patch: 0, + build_number: 826, + }, + app_version: AppVersion { + application: Application::Notebook, + major: 0, + minor: 0, + circuit: 0x0A, + }, + start_row: 7, + size: 24832, + row_size: 0x100, + }, + } + }); } } diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index ba9576c..9d4d005 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -2608,44 +2608,30 @@ fn me_info(verbose: bool, dump_path: Option<&str>) { } fn analyze_ccgx_pd_fw(data: &[u8]) { - if let Some(versions) = ccgx::binary::read_versions(data, Ccg3) { - println!("Detected CCG3 firmware"); - println!("FW 1"); - ccgx::binary::print_fw(&versions.backup_fw); - - println!("FW 2"); - ccgx::binary::print_fw(&versions.main_fw); - } else if let Some(versions) = ccgx::binary::read_versions(data, Ccg8D) { - println!("Detected CCG8D/CCG8S firmware"); - println!("FW 1"); - ccgx::binary::print_fw(&versions.backup_fw); - - println!("FW 2"); - ccgx::binary::print_fw(&versions.main_fw); - } else if let Some(versions) = ccgx::binary::read_versions(data, Ccg8Cfp) { - println!("Detected CCG6/CCG8 CFP firmware"); - println!("FW 1"); - ccgx::binary::print_fw(&versions.backup_fw); - - println!("FW 2"); - ccgx::binary::print_fw(&versions.main_fw); - } else if let Some(versions) = ccgx::binary::read_versions(data, Ccg5) { - println!("Detected CCG5 firmware"); - println!("FW 1"); - ccgx::binary::print_fw(&versions.backup_fw); - - println!("FW 2"); - ccgx::binary::print_fw(&versions.main_fw); - } else if let Some(versions) = ccgx::binary::read_versions(data, Ccg6) { - println!("Detected CCG6 firmware"); - println!("FW 1 (Backup)"); - ccgx::binary::print_fw(&versions.backup_fw); - - println!("FW 2 (Main)"); - ccgx::binary::print_fw(&versions.main_fw); - } else { - println!("Failed to read PD versions") + // Each silicon family validates the family field in the binary, so at most + // one of these can match + let families = [ + (Ccg3, "CCG3"), + (Ccg5, "CCG5"), + (Ccg6Adl, "CCG6"), + (Ccg6, "CCG6"), + (Ccg8D, "CCG8D"), + (Ccg8S, "CCG8S"), + (Ccg6Cfp, "CCG6 CFP"), + (Ccg8Cfp, "CCG8 CFP"), + ]; + for (family, name) in families { + if let Some(versions) = ccgx::binary::read_versions(data, family) { + println!("Detected {} firmware", name); + println!("FW 1"); + ccgx::binary::print_fw(&versions.backup_fw); + + println!("FW 2"); + ccgx::binary::print_fw(&versions.main_fw); + return; + } } + println!("Failed to read PD versions") } pub fn analyze_ec_fw(data: &[u8]) {