Skip to content

Commit

Permalink
Merge pull request #32 from FrameworkComputer/version_check
Browse files Browse the repository at this point in the history
Create version check function
  • Loading branch information
JohnAZoidberg authored Oct 21, 2024
2 parents fee9f43 + 69c97b0 commit 6fd13f2
Show file tree
Hide file tree
Showing 11 changed files with 264 additions and 12 deletions.
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,38 @@ own EC firmware and flash it.
- [x] Basic unit tests
- [x] Test parsing real binaries

## Version Check

Check if the firmware version is what you expect, returns exit code 0 on
succcess, 1 on failure.

```
# Check which devices it's available for
> ./framework_system --device
[possible values: bios, ec, pd0, pd1, rtm01, rtm23]
For more information try '--help'
# Successful compare
> ./framework_system --device bios --compare-version 03.01
Target Version "03.01"
Comparing BIOS version "03.01"
Compared version: 0
> echo $?
0
# Failed compare
> ./framework_system --device bios --compare-version 03.00
Finished dev [unoptimized + debuginfo] target(s) in 0.05s
Target Version "03.00"
Comparing BIOS version "03.01"
Compared version: 1
Error: "Fail"
> echo $?
1
```

## Debugging

To debug, increase the verbosity from the commandline with `-v`.
Expand Down
32 changes: 28 additions & 4 deletions framework_lib/src/ccgx/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
//! Interact with Infineon (formerly Cypress) PD controllers (their firmware binaries) in the CCGx series
use alloc::string::String;
use alloc::string::ToString;
#[cfg(feature = "uefi")]
use core::prelude::rust_2021::derive;
use num_derive::FromPrimitive;
use std::fmt;

use crate::chromium_ec::{CrosEc, EcResult};
use crate::smbios;
use crate::util::Platform;

use self::device::{FwMode, PdController, PdPort};

Expand Down Expand Up @@ -102,7 +106,7 @@ pub enum SiliconId {
Ccg8 = 0x3580,
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct BaseVersion {
/// Major part of the version. X of X.Y.Z.BB
pub major: u8,
Expand Down Expand Up @@ -138,15 +142,15 @@ impl From<u32> for BaseVersion {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Application {
Notebook,
Monitor,
AA,
Invalid,
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct AppVersion {
pub application: Application,
/// Major part of the version. X of X.Y.Z
Expand Down Expand Up @@ -185,7 +189,7 @@ impl From<u32> for AppVersion {
}
}

#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct ControllerVersion {
pub base: BaseVersion,
pub app: AppVersion,
Expand All @@ -199,6 +203,26 @@ pub struct ControllerFirmwares {
pub main_fw: ControllerVersion,
}

impl ControllerFirmwares {
pub fn active_fw(&self) -> ControllerVersion {
match self.active_fw {
FwMode::MainFw => self.main_fw,
FwMode::BackupFw => self.backup_fw,
FwMode::BootLoader => self.bootloader,
}
}

pub fn active_fw_ver(&self) -> String {
let active = self.active_fw();
// On 11th Gen we modified base version instead of app version
if let Some(Platform::IntelGen11) = smbios::get_platform() {
active.base.to_string()
} else {
active.app.to_string()
}
}
}

#[derive(Debug, PartialEq)]
pub struct PdVersions {
pub controller01: ControllerFirmwares,
Expand Down
13 changes: 13 additions & 0 deletions framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,19 @@ pub enum CrosEcDriverType {
Windows,
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
#[derive(Clone, Debug, Copy, PartialEq)]
pub enum HardwareDeviceType {
BIOS,
EC,
PD0,
PD1,
RTM01,
RTM23,
AcLeft,
AcRight,
}

impl CrosEcDriver for CrosEc {
fn read_memory(&self, offset: u16, length: u16) -> Option<Vec<u8>> {
if !smbios::is_framework() {
Expand Down
15 changes: 14 additions & 1 deletion framework_lib/src/commandline/clap_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
use clap::Parser;

use crate::chromium_ec::CrosEcDriverType;
use crate::commandline::{Cli, ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg};
use crate::commandline::{
Cli, ConsoleArg, FpBrightnessArg, HardwareDeviceType, InputDeckModeArg, RebootEcArg,
};

/// Swiss army knife for Framework laptops
#[derive(Parser)]
Expand All @@ -25,6 +27,15 @@ struct ClapCli {
#[arg(long)]
esrt: bool,

// Device type to compare_version string with version string on device
#[clap(value_enum)]
#[arg(long)]
device: Option<HardwareDeviceType>,

// version to compare with
#[arg(long)]
compare_version: Option<String>,

/// Show current power status of battery and AC (Add -vv for more details)
#[arg(long)]
power: bool,
Expand Down Expand Up @@ -198,6 +209,8 @@ pub fn parse(args: &[String]) -> Cli {
versions: args.versions,
version: args.version,
esrt: args.esrt,
device: args.device,
compare_version: args.compare_version,
power: args.power,
thermal: args.thermal,
sensors: args.sensors,
Expand Down
126 changes: 124 additions & 2 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! Can be easily re-used from any OS or UEFI shell.
//! We have implemented both in the `framework_tool` and `framework_uefi` crates.
use alloc::format;
use alloc::string::String;
use alloc::string::ToString;
use alloc::vec::Vec;
Expand Down Expand Up @@ -54,7 +55,7 @@ use sha2::{Digest, Sha256, Sha384, Sha512};
//use smbioslib::*;
use smbioslib::{DefinedStruct, SMBiosInformation};

use crate::chromium_ec::{CrosEc, CrosEcDriverType};
use crate::chromium_ec::{CrosEc, CrosEcDriverType, HardwareDeviceType};

#[cfg(feature = "uefi")]
use core::prelude::rust_2021::derive;
Expand Down Expand Up @@ -120,6 +121,8 @@ pub struct Cli {
pub versions: bool,
pub version: bool,
pub esrt: bool,
pub device: Option<HardwareDeviceType>,
pub compare_version: Option<String>,
pub power: bool,
pub thermal: bool,
pub sensors: bool,
Expand Down Expand Up @@ -506,6 +509,119 @@ fn dump_ec_flash(ec: &CrosEc, dump_path: &str) {
}
}

fn compare_version(device: Option<HardwareDeviceType>, version: String, ec: &CrosEc) -> i32 {
println!("Target Version {:?}", version);

if let Some(smbios) = get_smbios() {
let bios_entries = smbios.collect::<SMBiosInformation>();
let bios = bios_entries.get(0).unwrap();

if device == Some(HardwareDeviceType::BIOS) {
println!("Comparing BIOS version {:?}", bios.version().to_string());
if version.to_uppercase() == bios.version().to_string().to_uppercase() {
return 0;
} else {
return 1;
}
}
}

match device {
Some(HardwareDeviceType::EC) => {
let ver = print_err(ec.version_info()).unwrap_or_else(|| "UNKNOWN".to_string());
println!("Comparing EC version {:?}", ver);

if ver.contains(&version) {
return 0;
} else {
return 1;
}
}
Some(HardwareDeviceType::PD0) => {
if let Ok(pd_versions) = ccgx::get_pd_controller_versions(ec) {
let ver = pd_versions.controller01.active_fw_ver();
println!("Comparing PD0 version {:?}", ver);

if ver.contains(&version) {
return 0;
} else {
return 1;
}
}
}
Some(HardwareDeviceType::PD1) => {
if let Ok(pd_versions) = ccgx::get_pd_controller_versions(ec) {
let ver = pd_versions.controller23.active_fw_ver();
println!("Comparing PD1 version {:?}", ver);

if ver.contains(&version) {
return 0;
} else {
return 1;
}
}
}
Some(HardwareDeviceType::AcLeft) => {
if let Ok((_right, left)) = power::is_charging(ec) {
let ver = format!("{}", left as i32);
println!("Comparing AcLeft {:?}", ver);
if ver == version {
return 0;
} else {
return 1;
}
} else {
error!("Failed to get charging information");
// Not charging is the safe default
return 1;
}
}
Some(HardwareDeviceType::AcRight) => {
if let Ok((right, _left)) = power::is_charging(ec) {
let ver = format!("{}", right as i32);
println!("Comparing AcRight {:?}", ver);
if ver == version {
return 0;
} else {
return 1;
}
} else {
error!("Failed to get charging information");
// Not charging is the safe default
return 1;
}
}
_ => {}
}

if let Some(esrt) = esrt::get_esrt() {
for entry in &esrt.entries {
match entry.fw_class {
esrt::TGL_RETIMER01_GUID | esrt::ADL_RETIMER01_GUID | esrt::RPL_RETIMER01_GUID => {
if device == Some(HardwareDeviceType::RTM01) {
println!("Comparing RTM01 version {:?}", entry.fw_version.to_string());

if entry.fw_version.to_string().contains(&version) {
return 0;
}
}
}
esrt::TGL_RETIMER23_GUID | esrt::ADL_RETIMER23_GUID | esrt::RPL_RETIMER23_GUID => {
if device == Some(HardwareDeviceType::RTM23) {
println!("Comparing RTM23 version {:?}", entry.fw_version.to_string());
if entry.fw_version.to_string().contains(&version) {
return 0;
}
}
}
_ => {}
}
}
}

1
}

pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
#[cfg(feature = "uefi")]
{
Expand Down Expand Up @@ -563,6 +679,10 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
print_tool_version();
} else if args.esrt {
print_esrt();
} else if let Some(compare_version_ver) = &args.compare_version {
let compare_ret = compare_version(args.device, compare_version_ver.to_string(), &ec);
println!("Comparison Result: {}", compare_ret);
return compare_ret;
} else if args.intrusion {
println!("Chassis status:");
if let Some(status) = print_err(ec.get_intrusion_status()) {
Expand Down Expand Up @@ -653,7 +773,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
return 1;
}
} else if args.power {
power::get_and_print_power_info(&ec);
return power::get_and_print_power_info(&ec);
} else if args.thermal {
power::print_thermal(&ec);
} else if args.sensors {
Expand Down Expand Up @@ -835,6 +955,8 @@ Options:
--versions List current firmware versions
--version Show tool version information (Add -vv for more detailed information)
--esrt Display the UEFI ESRT table
--device <DEVICE> Device used to compare firmware version [possible values: bios, ec, pd0, pd1, rtm01, rtm23]
--compare-version Version string used to match firmware version (use with --device)
--power Show current power status (battery and AC)
--thermal Print thermal information (Temperatures and Fan speed)
--sensors Print sensor information (ALS, G-Sensor)
Expand Down
Loading

0 comments on commit 6fd13f2

Please sign in to comment.