Skip to content

Commit f236866

Browse files
committed
--capsule: Find any number of PD binaries in capsule
The PDs may not be all the same version, so we should show them all. Signed-off-by: Daniel Schaefer <dhs@frame.work>
1 parent cf6813c commit f236866

3 files changed

Lines changed: 57 additions & 19 deletions

File tree

framework_lib/src/capsule_content.rs

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use crate::alloc::string::ToString;
88
use alloc::string::String;
9+
use alloc::vec::Vec;
910
use core::convert::TryInto;
1011

1112
use crate::ccgx::binary::{CCG5_PD_LEN, CCG6_PD_LEN, CCG8_PD_LEN};
@@ -51,19 +52,38 @@ pub fn find_ec_in_bios_cap(data: &[u8]) -> Option<&[u8]> {
5152
}
5253

5354
pub fn find_pd_in_bios_cap(data: &[u8]) -> Option<&[u8]> {
54-
// Just search for the first couple of bytes in PD binaries
55-
// TODO: There's a second one but unless the capsule is bad, we can assume
56-
// they're the same version
57-
let ccg5_needle = &[0x00, 0x20, 0x00, 0x20, 0x11, 0x00];
58-
let ccg6_needle = &[0x00, 0x40, 0x00, 0x20, 0x11, 0x00];
59-
let ccg8_needle = &[0x00, 0x80, 0x00, 0x20, 0xAD, 0x0C];
60-
if let Some(found_pd1) = util::find_sequence(data, ccg5_needle) {
61-
Some(&data[found_pd1..found_pd1 + CCG5_PD_LEN])
62-
} else if let Some(found_pd1) = util::find_sequence(data, ccg6_needle) {
63-
Some(&data[found_pd1..found_pd1 + CCG6_PD_LEN])
64-
} else if let Some(found_pd1) = util::find_sequence(data, ccg8_needle) {
65-
Some(&data[found_pd1..found_pd1 + CCG8_PD_LEN])
66-
} else {
67-
None
55+
find_all_pds_in_bios_cap(data).into_iter().next()
56+
}
57+
58+
/// PD binary signatures and their corresponding lengths
59+
const CCG5_NEEDLE: &[u8] = &[0x00, 0x20, 0x00, 0x20, 0x11, 0x00];
60+
const CCG6_NEEDLE: &[u8] = &[0x00, 0x40, 0x00, 0x20, 0x11, 0x00];
61+
const CCG8_NEEDLE: &[u8] = &[0x00, 0x80, 0x00, 0x20, 0xAD, 0x0C];
62+
63+
/// Find all PD firmware binaries embedded in a BIOS capsule
64+
pub fn find_all_pds_in_bios_cap(data: &[u8]) -> Vec<&[u8]> {
65+
let mut results = Vec::new();
66+
67+
// Search for CCG5 PDs
68+
for offset in util::find_all_sequences(data, CCG5_NEEDLE) {
69+
if offset + CCG5_PD_LEN <= data.len() {
70+
results.push(&data[offset..offset + CCG5_PD_LEN]);
71+
}
6872
}
73+
74+
// Search for CCG6 PDs
75+
for offset in util::find_all_sequences(data, CCG6_NEEDLE) {
76+
if offset + CCG6_PD_LEN <= data.len() {
77+
results.push(&data[offset..offset + CCG6_PD_LEN]);
78+
}
79+
}
80+
81+
// Search for CCG8 PDs
82+
for offset in util::find_all_sequences(data, CCG8_NEEDLE) {
83+
if offset + CCG8_PD_LEN <= data.len() {
84+
results.push(&data[offset..offset + CCG8_PD_LEN]);
85+
}
86+
}
87+
88+
results
6989
}

framework_lib/src/commandline/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use crate::built_info;
2828
use crate::camera::check_camera_version;
2929
use crate::capsule;
3030
use crate::capsule_content::{
31-
find_bios_version, find_ec_in_bios_cap, find_pd_in_bios_cap, find_retimer_version,
31+
find_all_pds_in_bios_cap, find_bios_version, find_ec_in_bios_cap, find_retimer_version,
3232
};
3333
use crate::ccgx::device::{FwMode, PdController, PdPort};
3434
#[cfg(feature = "hidapi")]
@@ -1691,9 +1691,10 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
16911691
println!("Embedded EC");
16921692
analyze_ec_fw(ec_bin);
16931693
}
1694-
if let Some(pd_bin) = find_pd_in_bios_cap(&data) {
1694+
let pd_bins = find_all_pds_in_bios_cap(&data);
1695+
for (i, pd_bin) in pd_bins.iter().enumerate() {
16951696
found_any = true;
1696-
println!("Embedded PD");
1697+
println!("Embedded PD {}", i + 1);
16971698
analyze_ccgx_pd_fw(pd_bin);
16981699
}
16991700
if !found_any {
@@ -2436,8 +2437,9 @@ pub fn analyze_capsule(data: &[u8]) -> Option<capsule::EfiCapsuleHeader> {
24362437
println!(" RW Version: {:>18}", ver.version);
24372438
}
24382439
}
2439-
if let Some(pd_bin) = find_pd_in_bios_cap(data) {
2440-
println!("Embedded PD");
2440+
let pd_bins = find_all_pds_in_bios_cap(data);
2441+
for (i, pd_bin) in pd_bins.iter().enumerate() {
2442+
println!("Embedded PD {}", i + 1);
24412443
analyze_ccgx_pd_fw(pd_bin);
24422444
}
24432445
}

framework_lib/src/util.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,22 @@ pub fn find_sequence(haystack: &[u8], needle: &[u8]) -> Option<usize> {
258258
.position(|window| window == needle)
259259
}
260260

261+
/// Find all occurrences of a sequence of bytes in a long slice of bytes
262+
pub fn find_all_sequences(haystack: &[u8], needle: &[u8]) -> Vec<usize> {
263+
let mut results = Vec::new();
264+
let mut pos = 0;
265+
while pos + needle.len() <= haystack.len() {
266+
if let Some(offset) = find_sequence(&haystack[pos..], needle) {
267+
let absolute_pos = pos + offset;
268+
results.push(absolute_pos);
269+
pos = absolute_pos + needle.len();
270+
} else {
271+
break;
272+
}
273+
}
274+
results
275+
}
276+
261277
/// Assert length of an EC response from the windows driver
262278
/// It's always 20 more than expected. TODO: Figure out why
263279
pub fn assert_win_len<N: Num + std::fmt::Debug + Ord + NumCast + Copy>(left: N, right: N) {

0 commit comments

Comments
 (0)