Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
792 changes: 277 additions & 515 deletions Cargo.lock

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions EXAMPLES_ADVANCED.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,50 @@ Keyboard backlight: 0%
Keyboard backlight: 0%
```

## Battery

### Smart Battery

Get smart battery information by talking to the battery directly through SMBUS.

Allows unsealing the battery and reading privileged registers - this needs the
secret key and is not available to end-users. Implemented for Framework
internal analysis of RMA units.
End-users, please press enter to skip unseal key.

```
> sudo framework_tool --smartbattery
Enter unseal key in hex (e.g. 04143672), or press enter to skip:
Device Name: FRANEDA
Manuf Name: ATC
Serial Num: 0188
Manuf Date: 2025-11-27
Chemistry: LION
FW Version: Device=0x0045 FW=09.03 Build=0x4900
Mode: 0x6001
Temperature: 32.6C
Voltage: 17.719V
Cell 1: 4.430V
Cell 2: 4.429V
Cell 3: 4.431V
Cell 4: 4.428V
Current: 0.000A (avg 0.000A)
Charge: 98% (4776 / 4920 mAh)
Design: 4640mAh @ 15.640V
Bat Status: 0x00E0 [FC (Fully Charged), DSG (Discharging), INIT (Initialization)]
Cycle Count: 76

=== Battery Health Analysis ===

Status: HEALTHY
No issues detected. Battery is operating normally.

Summary:
Cycle count: 76
Capacity: 4920 / 4640 mAh (106%)
Current cell balance: 3mV spread
```

## PD

### Check PD state
Expand Down
6 changes: 5 additions & 1 deletion framework_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ built = { version = "0.8", features = ["chrono", "git2"] }
[dependencies]
lazy_static = "1.4.0"
dmidecode = { version = "1", default-features = false }
sha1 = { version = "0.10.6", default-features = false }
sha2 = { version = "0.10.8", default-features = false, features = [ "force-soft" ] }
regex = { version = "1.11.1", default-features = false }
num = { version = "0.4", default-features = false }
Expand All @@ -45,6 +46,7 @@ uefi-raw = "0.13"
plain = "0.2.3"

[target.'cfg(windows)'.dependencies]
rand = { version = "0.9", default-features = false, features = ["std", "std_rng", "thread_rng"] }
wmi = "~0.17.3"
env_logger = "0.11"
clap = { version = "4.5", features = ["derive", "cargo"] }
Expand All @@ -56,8 +58,9 @@ winreg = "0.55.0"
nvml-wrapper = { version = "0.11.0", optional = true }

[target.'cfg(unix)'.dependencies]
rand = { version = "0.9", default-features = false, features = ["std", "std_rng", "thread_rng"] }
libc = "0.2.155"
nix = { version = "0.30", features = ["ioctl", "user"] }
nix = { version = "0.30", features = ["ioctl", "user", "term"] }
env_logger = "0.11"
clap = { version = "4.5", features = ["derive", "cargo"] }
clap-num = { version = "1.2.0" }
Expand All @@ -81,6 +84,7 @@ features = [
"Win32_Devices_Properties",
"Win32_Storage_EnhancedStorage",
"Win32_System_Threading",
"Win32_System_Console",
"Win32_UI_Shell_PropertiesSystem"
]

13 changes: 13 additions & 0 deletions framework_lib/src/commandline/clap_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! This way we can use it in the regular OS commandline tool on Linux and Windows,
//! as well as on the UEFI shell tool.
use std::io;
use std::path::PathBuf;

use clap::builder::TypedValueParser;
use clap::error::ErrorKind;
Expand Down Expand Up @@ -53,6 +54,14 @@ struct ClapCli {
#[arg(long)]
power: bool,

/// Show detailed smart battery information, or load from dump file
#[arg(long, value_name = "FILE")]
smartbattery: Option<Option<PathBuf>>,

/// Authenticate smart battery (requires unseal and auth keys)
#[arg(long)]
smartbattery_auth: bool,

/// Print thermal information (Temperatures and Fan speed)
#[arg(long)]
thermal: bool,
Expand Down Expand Up @@ -495,6 +504,10 @@ pub fn parse(args: &[String]) -> Cli {
device: args.device,
compare_version: args.compare_version,
power: args.power,
smartbattery: args
.smartbattery
.map(|opt| opt.map(|x| x.into_os_string().into_string().unwrap())),
smartbattery_auth: args.smartbattery_auth,
thermal: args.thermal,
sensors: args.sensors,
fansetduty,
Expand Down
31 changes: 31 additions & 0 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ use crate::nvme;
use crate::os_specific;
use crate::parade_retimer;
use crate::power;
#[cfg(not(feature = "uefi"))]
use crate::smart_battery::SmartBattery;
use crate::smbios;
use crate::smbios::ConfigDigit0;
use crate::smbios::{get_smbios, is_framework};
Expand Down Expand Up @@ -186,6 +188,8 @@ pub struct Cli {
pub device: Option<HardwareDeviceType>,
pub compare_version: Option<String>,
pub power: bool,
pub smartbattery: Option<Option<String>>,
pub smartbattery_auth: bool,
pub thermal: bool,
pub sensors: bool,
pub fansetduty: Option<(Option<u32>, u32)>,
Expand Down Expand Up @@ -1593,6 +1597,33 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
print_board_ids(&ec);
} else if args.power {
return power::get_and_print_power_info(&ec);
} else if let Some(smartbattery_arg) = &args.smartbattery {
#[cfg(not(feature = "uefi"))]
{
use crate::smart_battery::{display_battery_data, BatteryData};
use std::path::Path;

match smartbattery_arg {
Some(file_path) => {
// Load from file
match BatteryData::read_from_file(Path::new(file_path)) {
Ok(data) => display_battery_data(&data),
Err(e) => eprintln!("Failed to read battery dump: {}", e),
}
}
None => {
// Read from actual battery
let bat = SmartBattery::new();
print_err(bat.dump_data(&ec));
}
}
}
} else if args.smartbattery_auth {
#[cfg(not(feature = "uefi"))]
{
let bat = SmartBattery::new();
print_err(bat.interactive_authenticate(&ec));
}
} else if args.thermal {
power::print_thermal(&ec);
} else if args.sensors {
Expand Down
2 changes: 2 additions & 0 deletions framework_lib/src/commandline/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub fn parse(args: &[String]) -> Cli {
device: None,
compare_version: None,
power: false,
smartbattery: None,
smartbattery_auth: false,
thermal: false,
sensors: false,
fansetduty: None,
Expand Down
2 changes: 2 additions & 0 deletions framework_lib/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ pub mod fw_uefi;
mod os_specific;
pub mod parade_retimer;
pub mod power;
#[cfg(not(feature = "uefi"))]
pub mod smart_battery;
pub mod smbios;
mod util;

Expand Down
Loading
Loading