From 6b5f6387a6c184258010cda2fad69066a749e949 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Thu, 27 Mar 2025 05:12:24 -0700 Subject: [PATCH 1/2] chromium_ec: Add host command to read board ID This command is not present on all systems, it was only recently added to our main branch and will be slowly backported. Signed-off-by: Daniel Schaefer --- framework_lib/src/chromium_ec/command.rs | 2 ++ framework_lib/src/chromium_ec/commands.rs | 36 +++++++++++++++++++++++ framework_lib/src/chromium_ec/mod.rs | 16 ++++++++++ 3 files changed, 54 insertions(+) diff --git a/framework_lib/src/chromium_ec/command.rs b/framework_lib/src/chromium_ec/command.rs index 696c1529..07bf4d36 100644 --- a/framework_lib/src/chromium_ec/command.rs +++ b/framework_lib/src/chromium_ec/command.rs @@ -110,6 +110,8 @@ pub enum EcCommands { GetGpuPcie = 0x3E1E, /// Set gpu bay serial and program structure ProgramGpuEeprom = 0x3E1F, + /// Read board ID of specific ADC channel + ReadBoardId = 0x3E26, } pub trait EcRequest { diff --git a/framework_lib/src/chromium_ec/commands.rs b/framework_lib/src/chromium_ec/commands.rs index e5798069..2a22b891 100644 --- a/framework_lib/src/chromium_ec/commands.rs +++ b/framework_lib/src/chromium_ec/commands.rs @@ -1658,3 +1658,39 @@ impl EcRequest for EcRequestSetGpuSerial { EcCommands::ProgramGpuEeprom } } + +#[repr(u8)] +#[derive(Debug, Clone, Copy)] +pub enum BoardIdType { + /// Mainboard - any system + Mainboard = 0, + /// Power button board - Framework 12 + PowerButtonBoard = 1, + /// Touchpad - Framework 12, 13, 16 + Touchpad = 2, + /// Audio Board - Framework 12, 13 + AudioBoard = 3, + /// dGPU board - Framework 16 + DGpu0 = 4, + /// dGPU board - Framework 16 + DGpu1 = 5, +} + +#[repr(C, packed)] +pub struct EcRequestReadBoardId { + /// See BoardIdType + pub board_id_type: u8, +} + +#[repr(C, packed)] +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub struct EcResponseReadBoardId { + /// Board ID: -1 invalid, 0–14 valid, 15 not present + pub board_id: i8, +} + +impl EcRequest for EcRequestReadBoardId { + fn command_id() -> EcCommands { + EcCommands::ReadBoardId + } +} diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index 94997bab..4fae5bbc 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -1740,6 +1740,22 @@ impl CrosEc { Ok(()) } + pub fn read_board_id_hc(&self, board_id_type: BoardIdType) -> EcResult> { + let res = EcRequestReadBoardId { + board_id_type: board_id_type as u8, + } + .send_command(self)?; + match res.board_id { + -1 => Err(EcError::DeviceError(format!( + "Failed to read Board ID {:?}", + board_id_type + ))), + 15 => Ok(None), + 0..=14 => Ok(Some(res.board_id as u8)), + n => Err(EcError::DeviceError(format!("Invalid Board ID {}", n))), + } + } + pub fn get_uptime_info(&self) -> EcResult<()> { let res = EcRequestGetUptimeInfo {}.send_command(self)?; let t_since_boot = Duration::from_millis(res.time_since_ec_boot.into()); From 49155629b2d746583afb28246e013c430e99d6c4 Mon Sep 17 00:00:00 2001 From: Daniel Schaefer Date: Tue, 18 Nov 2025 19:51:41 +0800 Subject: [PATCH 2/2] --boardid: Print all available board IDs Using a native host command to get the ID from the EC instead of having the sotware measure ADC and evaluate the host command. This is better because the ADC values represent different board IDs on different platforms (Microchip vs Nuvoton based ECs) > sudo framework_tool --boardid Board IDs Mainboard: Ok(Some(6)) PowerButton: Err(Response(InvalidResponse)) Touchpad: Ok(Some(7)) AudioBoard: Ok(Some(7)) dGPU0: Err(Response(InvalidCommand)) dGPU1: Err(Response(InvalidCommand)) ``` Signed-off-by: Daniel Schaefer --- EXAMPLES.md | 20 ++++++++++++++ framework_lib/src/commandline/clap_std.rs | 5 ++++ framework_lib/src/commandline/mod.rs | 33 +++++++++++++++++++++++ framework_lib/src/commandline/uefi.rs | 4 +++ 4 files changed, 62 insertions(+) diff --git a/EXAMPLES.md b/EXAMPLES.md index 8cf74a0d..420d06e8 100644 --- a/EXAMPLES.md +++ b/EXAMPLES.md @@ -380,6 +380,26 @@ Positions: Pos 4: GenericC ``` +### Checking board ID + +Most inputdeck checking is implemented by Board ID. To read those directly for +debugging low level issues, use the `--boardid` command. +This host command was added recently is not available on every system yet. + +``` +# Example on Framework Laptop 13 +# Touchpad Board ID is only present on Laptop 12 +# dGPU Board IDs are only present on Laptop 16 +> framework_tool --boardid +Board IDs + Mainboard: Ok(Some(6)) + PowerButton: Err(Response(InvalidResponse)) + Touchpad: Ok(Some(7)) + AudioBoard: Ok(Some(7)) + dGPU0: Err(Response(InvalidCommand)) + dGPU1: Err(Response(InvalidCommand)) +``` + ## Check temperatures and fan speed ``` diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index a2727903..3952675e 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -273,6 +273,10 @@ struct ClapCli { #[arg(long)] test_retimer: bool, + /// Print all board IDs + #[arg(long)] + boardid: bool, + /// Force execution of an unsafe command - may render your hardware unbootable! #[arg(long, short)] force: bool, @@ -472,6 +476,7 @@ pub fn parse(args: &[String]) -> Cli { pd_ports, test: args.test, test_retimer: args.test_retimer, + boardid: args.boardid, dry_run: args.dry_run, force: args.force, // TODO: Set help. Not very important because Clap handles this by itself diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 98de02b5..b7924778 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -35,6 +35,7 @@ use crate::ccgx::device::{FwMode, PdController, PdPort}; use crate::ccgx::hid::{check_ccg_fw_version, find_devices, DP_CARD_PID, HDMI_CARD_PID}; use crate::ccgx::{self, MainPdVersions, PdVersions, SiliconId::*}; use crate::chromium_ec; +use crate::chromium_ec::commands::BoardIdType; use crate::chromium_ec::commands::DeckStateMode; use crate::chromium_ec::commands::FpLedBrightnessLevel; use crate::chromium_ec::commands::RebootEcCmd; @@ -192,6 +193,7 @@ pub struct Cli { pub driver: Option, pub test: bool, pub test_retimer: bool, + pub boardid: bool, pub dry_run: bool, pub force: bool, pub intrusion: bool, @@ -279,6 +281,7 @@ pub fn parse(args: &[String]) -> Cli { driver: cli.driver, test: cli.test, test_retimer: cli.test_retimer, + boardid: cli.boardid, dry_run: cli.dry_run, // force intrusion: cli.intrusion, @@ -1487,6 +1490,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { if let Err(err) = selftest_retimer(&ec) { println!(" Failed: {:?}", err); } + } else if args.boardid { + print_board_ids(&ec); } else if args.power { return power::get_and_print_power_info(&ec); } else if args.thermal { @@ -1850,6 +1855,34 @@ fn hash(data: &[u8]) { util::print_buffer(sha512); } +fn print_board_ids(ec: &CrosEc) { + println!("Board IDs"); + println!( + " Mainboard: {:?}", + ec.read_board_id_hc(BoardIdType::Mainboard) + ); + println!( + " PowerButton: {:?}", + ec.read_board_id_hc(BoardIdType::PowerButtonBoard) + ); + println!( + " Touchpad: {:?}", + ec.read_board_id_hc(BoardIdType::Touchpad) + ); + println!( + " AudioBoard: {:?}", + ec.read_board_id_hc(BoardIdType::AudioBoard) + ); + println!( + " dGPU0: {:?}", + ec.read_board_id_hc(BoardIdType::DGpu0) + ); + println!( + " dGPU1: {:?}", + ec.read_board_id_hc(BoardIdType::DGpu1) + ); +} + fn selftest(ec: &CrosEc) -> Option<()> { if let Some(platform) = smbios::get_platform() { println!(" SMBIOS Platform: {:?}", platform); diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index cb2b4c5d..58490c71 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -87,6 +87,7 @@ pub fn parse(args: &[String]) -> Cli { pd_ports: None, test: false, test_retimer: false, + boardid: false, dry_run: false, force: false, help: false, @@ -511,6 +512,9 @@ pub fn parse(args: &[String]) -> Cli { } else if arg == "-t" || arg == "--test-retimer" { cli.test_retimer = true; found_an_option = true; + } else if arg == "--boardid" { + cli.boardid = true; + found_an_option = true; } else if arg == "-f" || arg == "--force" { cli.force = true; found_an_option = true;