Skip to content

Commit 64cc788

Browse files
Merge pull request #92 from FrameworkComputer/capsule-versions
Fix H2O capsule analysis
2 parents 8f718d1 + 4ba840d commit 64cc788

6 files changed

Lines changed: 41 additions & 42 deletions

File tree

README.md

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,14 @@ see the [Support Matrices](support-matrices.md).
2525
- [x] ESRT table (UEFI, Linux, FreeBSD only) (`--esrt`)
2626
- [x] SMBIOS
2727
- [x] Get firmware version from binary file
28-
- [x] Legacy EC (Intel 13th Gen and earlier) (`--ec-bin`)
29-
- [x] Zephyr EC (AMD) (`--ec-bin`)
28+
- [x] EC (Legacy and Zephyr based) (`--ec-bin`)
3029
- [x] CCG5 PD (11th Gen TigerLake) (`--pd-bin`)
31-
- [x] CCG6 PD (12th Gen AlderLake) (`--pd-bin`)
32-
- [x] CCG8 PD (Framework 16) (`--pd-bin`)
33-
- [x] HO2 BIOS Capsule (`--ho2-capsule`)
30+
- [x] CCG6 PD (Intel systems, Framework Desktop) (`--pd-bin`)
31+
- [x] CCG8 PD (AMD Laptops) (`--pd-bin`)
32+
- [x] H2O BIOS Capsule (`--h2o-capsule`)
3433
- [x] BIOS Version
3534
- [x] EC Version
36-
- [x] CCG5/CCG6 PD Version
35+
- [x] CCG5/CCG6/CCG8 PD Version
3736
- [x] UEFI Capsule (`--capsule`)
3837
- [x] Parse metadata from capsule binary
3938
- [x] Determine type (GUID) of capsule binary
@@ -54,16 +53,6 @@ see the [Support Matrices](support-matrices.md).
5453
- [x] DisplayPort Expansion Card (`--dp-hdmi-update`)
5554
- [ ] Audio Expansion Card
5655

57-
###### Firmware Update
58-
59-
Note: Use fwupd.
60-
61-
- [ ] Flash firmware
62-
- [ ] BIOS
63-
- [ ] EC
64-
- [ ] PD
65-
- [ ] Expansion Cards
66-
6756
###### System Status
6857

6958
All of these need EC communication support in order to work.
@@ -91,6 +80,7 @@ All of these need EC communication support in order to work.
9180
- [x] Framework Desktop (AMD Ryzen AI Max 300)
9281
- [x] Port I/O communication on Linux
9382
- [x] Port I/O communication in UEFI
83+
- [x] Port I/O communication on FreeBSD
9484
- [x] Using `cros_ec` driver in Linux kernel
9585
- [x] Using [Framework EC Windows driver](https://github.com/FrameworkComputer/crosecbus) based on [coolstar's](https://github.com/coolstar/crosecbus)
9686
- [x] Using [DHowett's Windows CrosEC driver](https://github.com/DHowett/FrameworkWindowsUtils)
@@ -183,7 +173,7 @@ Options:
183173
--ec-bin <EC_BIN> Parse versions from EC firmware binary file
184174
--capsule <CAPSULE> Parse UEFI Capsule information from binary file
185175
--dump <DUMP> Dump extracted UX capsule bitmap image to a file
186-
--ho2-capsule <HO2_CAPSULE> Parse UEFI Capsule information from binary file
176+
--h2o-capsule <H2O_CAPSULE> Parse UEFI Capsule information from binary file
187177
--intrusion Show status of intrusion switch
188178
--inputmodules Show status of the input modules (Framework 16 only)
189179
--kblight [<KBLIGHT>] Set keyboard backlight percentage or get, if no value provided

framework_lib/src/capsule_content.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::alloc::string::ToString;
88
use alloc::string::String;
99
use core::convert::TryInto;
1010

11-
use crate::ccgx::binary::{CCG5_PD_LEN, CCG6_PD_LEN};
11+
use crate::ccgx::binary::{CCG5_PD_LEN, CCG6_PD_LEN, CCG8_PD_LEN};
1212
use crate::ec_binary::EC_LEN;
1313
use crate::util;
1414

@@ -29,26 +29,25 @@ pub fn find_bios_version(data: &[u8]) -> Option<BiosCapsule> {
2929
let needle = b"$BVDT";
3030
let found = util::find_sequence(data, needle)?;
3131

32+
// One of: GFW30, HFW3T, HFW30, IFR30, KFM30, JFP30, LFK30, IFGA3, IFGP6, LFR20, LFSP0
3233
let platform_offset = found + 0xA + needle.len() - 1;
33-
let platform = std::str::from_utf8(&data[platform_offset..platform_offset + 4])
34+
let platform = std::str::from_utf8(&data[platform_offset..platform_offset + 5])
3435
.map(|x| x.to_string())
3536
.ok()?;
3637

37-
let ver_offset = found + 0xE + needle.len() - 1;
38-
let version = std::str::from_utf8(&data[ver_offset..ver_offset + 4])
38+
let ver_offset = found + 0x10 + needle.len() - 1;
39+
let version = std::str::from_utf8(&data[ver_offset..ver_offset + 5])
3940
.map(|x| x.to_string())
4041
.ok()?;
4142

4243
Some(BiosCapsule { platform, version })
4344
}
4445

4546
pub fn find_ec_in_bios_cap(data: &[u8]) -> Option<&[u8]> {
46-
let needle = b"_IFLASH_EC_IMG_";
47-
let found_iflash = util::find_sequence(data, needle)?;
48-
// The actual EC binary is a few bytes after `_IFLASH_EC_IMG_`.
49-
// Just earch for the first 4 bytes that seem to appear in all EC images.
50-
let found = util::find_sequence(&data[found_iflash..], &[0x10, 0x00, 0x00, 0xf7])?;
51-
Some(&data[found_iflash + found..found_iflash + found + EC_LEN])
47+
let needle = b"$_IFLASH_EC_IMG_";
48+
let found = util::find_sequence(data, needle)?;
49+
let ec_offset = found + 0x9 + needle.len() - 1;
50+
Some(&data[ec_offset..ec_offset + EC_LEN])
5251
}
5352

5453
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]> {
5756
// they're the same version
5857
let ccg5_needle = &[0x00, 0x20, 0x00, 0x20, 0x11, 0x00];
5958
let ccg6_needle = &[0x00, 0x40, 0x00, 0x20, 0x11, 0x00];
59+
let ccg8_needle = &[0x00, 0x80, 0x00, 0x20, 0xAD, 0x0C];
6060
if let Some(found_pd1) = util::find_sequence(data, ccg5_needle) {
6161
Some(&data[found_pd1..found_pd1 + CCG5_PD_LEN])
6262
} else if let Some(found_pd1) = util::find_sequence(data, ccg6_needle) {
6363
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])
6466
} else {
6567
None
6668
}

framework_lib/src/ccgx/binary.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ struct VersionInfo {
5353
silicon_family: u16,
5454
}
5555

56-
pub const CCG5_PD_LEN: usize = 0x2_0000;
57-
pub const CCG6_PD_LEN: usize = 0x2_0000;
56+
pub const CCG5_PD_LEN: usize = 0x20_000;
57+
pub const CCG6_PD_LEN: usize = 0x20_000;
58+
pub const CCG8_PD_LEN: usize = 0x40_000;
5859

5960
/// Information about all the firmware in a PD binary file
6061
///

framework_lib/src/commandline/clap_std.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ struct ClapCli {
100100

101101
/// Parse UEFI Capsule information from binary file
102102
#[arg(long)]
103-
ho2_capsule: Option<std::path::PathBuf>,
103+
h2o_capsule: Option<std::path::PathBuf>,
104104

105105
/// Dump EC flash contents
106106
#[arg(long)]
@@ -259,8 +259,8 @@ pub fn parse(args: &[String]) -> Cli {
259259
.capsule
260260
.map(|x| x.into_os_string().into_string().unwrap()),
261261
dump: args.dump.map(|x| x.into_os_string().into_string().unwrap()),
262-
ho2_capsule: args
263-
.ho2_capsule
262+
h2o_capsule: args
263+
.h2o_capsule
264264
.map(|x| x.into_os_string().into_string().unwrap()),
265265
dump_ec_flash: args
266266
.dump_ec_flash

framework_lib/src/commandline/mod.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ pub struct Cli {
156156
pub ec_bin: Option<String>,
157157
pub capsule: Option<String>,
158158
pub dump: Option<String>,
159-
pub ho2_capsule: Option<String>,
159+
pub h2o_capsule: Option<String>,
160160
pub dump_ec_flash: Option<String>,
161161
pub flash_ec: Option<String>,
162162
pub flash_ro_ec: Option<String>,
@@ -941,7 +941,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
941941
println!("Capsule is invalid.");
942942
}
943943
}
944-
} else if let Some(capsule_path) = &args.ho2_capsule {
944+
} else if let Some(capsule_path) = &args.h2o_capsule {
945945
#[cfg(feature = "uefi")]
946946
let data = crate::uefi::fs::shell_read_file(capsule_path);
947947
#[cfg(not(feature = "uefi"))]
@@ -963,10 +963,16 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
963963
println!(" BIOS Version: {:>18}", cap.version);
964964
}
965965
if let Some(ec_bin) = find_ec_in_bios_cap(&data) {
966+
debug!("Found EC binary in BIOS capsule");
966967
analyze_ec_fw(ec_bin);
968+
} else {
969+
debug!("Didn't find EC binary in BIOS capsule");
967970
}
968971
if let Some(pd_bin) = find_pd_in_bios_cap(&data) {
972+
debug!("Found PD binary in BIOS capsule");
969973
analyze_ccgx_pd_fw(pd_bin);
974+
} else {
975+
debug!("Didn't find PD binary in BIOS capsule");
970976
}
971977
}
972978
} else if let Some(dump_path) = &args.dump_ec_flash {
@@ -1031,7 +1037,7 @@ Options:
10311037
--ec-bin <EC_BIN> Parse versions from EC firmware binary file
10321038
--capsule <CAPSULE> Parse UEFI Capsule information from binary file
10331039
--dump <DUMP> Dump extracted UX capsule bitmap image to a file
1034-
--ho2-capsule <HO2_CAPSULE> Parse UEFI Capsule information from binary file
1040+
--h2o-capsule <H2O_CAPSULE> Parse UEFI Capsule information from binary file
10351041
--dump-ec-flash <DUMP_EC_FLASH> Dump EC flash contents
10361042
--flash-ec <FLASH_EC> Flash EC with new firmware from file
10371043
--flash-ro-ec <FLASH_EC> Flash EC with new firmware from file
@@ -1289,7 +1295,7 @@ fn analyze_ccgx_pd_fw(data: &[u8]) {
12891295
ccgx::binary::print_fw(&versions.main_fw);
12901296
return;
12911297
} else {
1292-
println!("Failed to read versions")
1298+
println!("Failed to read PD versions")
12931299
}
12941300
}
12951301

@@ -1298,13 +1304,13 @@ pub fn analyze_ec_fw(data: &[u8]) {
12981304
if let Some(ver) = ec_binary::read_ec_version(data, true) {
12991305
ec_binary::print_ec_version(&ver, true);
13001306
} else {
1301-
println!("Failed to read version")
1307+
println!("Failed to read EC version")
13021308
}
13031309
// Readwrite firmware
13041310
if let Some(ver) = ec_binary::read_ec_version(data, false) {
13051311
ec_binary::print_ec_version(&ver, false);
13061312
} else {
1307-
println!("Failed to read version")
1313+
println!("Failed to read EC version")
13081314
}
13091315
}
13101316

framework_lib/src/commandline/uefi.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ pub fn parse(args: &[String]) -> Cli {
7878
flash_rw_ec: None,
7979
capsule: None,
8080
dump: None,
81-
ho2_capsule: None,
81+
h2o_capsule: None,
8282
intrusion: false,
8383
inputmodules: false,
8484
input_deck_mode: None,
@@ -374,11 +374,11 @@ pub fn parse(args: &[String]) -> Cli {
374374
None
375375
};
376376
found_an_option = true;
377-
} else if arg == "--ho2-capsule" {
378-
cli.ho2_capsule = if args.len() > i + 1 {
377+
} else if arg == "--h2o-capsule" {
378+
cli.h2o_capsule = if args.len() > i + 1 {
379379
Some(args[i + 1].clone())
380380
} else {
381-
println!("--ho2-capsule requires extra argument to denote input file");
381+
println!("--h2o-capsule requires extra argument to denote input file");
382382
None
383383
};
384384
found_an_option = true;

0 commit comments

Comments
 (0)