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
1 change: 1 addition & 0 deletions framework_lib/src/chromium_ec/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ pub enum EcCommands {
RebootEc = 0x00D2,
/// Get information about PD controller power
UsbPdPowerInfo = 0x0103,
GetUptimeInfo = 0x0121,
AdcRead = 0x0123,
ApReset = 0x0125,
LocateChip = 0x0126,
Expand Down
126 changes: 126 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -863,6 +863,132 @@ impl EcRequest<EcResponseUsbPdPowerInfo> for EcRequestUsbPdPowerInfo {
}
}

#[repr(usize)]
#[derive(Debug, FromPrimitive)]
pub enum EcResetFlag {
/// Other known reason
Other,
/// Reset pin asserted
ResetPin,
/// Brownout
Brownout,
/// Power-on reset
PowerOn,
/// Watchdog timer reset
Watchdog,
/// Soft reset trigger by core
Soft,
/// Wake from hibernate
Hibernate,
/// RTC alarm wake
RtcAlarm,
/// Wake pin triggered wake
WakePin,
/// Low battery triggered wake
LowBattery,
/// Jumped directly to this image
Sysjump,
/// Hard reset from software
Hard,
/// Do not power on AP
APOff,
/// Some reset flags preserved from previous boot
Preserved,
/// USB resume triggered wake
UsbResume,
/// USB Type-C debug cable
Rdd,
/// Fixed Reset Functionality
Rbox,
/// Security threat
Security,
/// AP experienced a watchdog reset
ApWatchdog,
/// Do not select RW in EFS. This enables PD in RO for Chromebox
StayInRo,
/// Jumped to this image by EFS
Efs,
/// Leave alone AP
ApIdle,
/// EC had power, then was reset
InitialPwr,
Count,
}

#[repr(u16)]
#[derive(Debug, FromPrimitive)]
pub enum ResetCause {
ResetUnknown = 0x0000,
/// Custom reason defined by a board.c or baseboard.c file
ResetBoardCustom,
/// Believe that the AP has hung
ResetHangReboot,
/// Reset by EC console command
ResetConsoleCommand,
/// Reset by EC host command
ResetHostCommand,
/// Keyboard module reset key combination
ResetKeyboardSysReset,
/// Keyboard module warm reboot
ResetKeyboardWarmBoot,
/// Debug module warm reboot
ResetDebugWarmBoot,
/// I cannot self-terminate. You must lower me into the steel
ResetApReq,
/// Reset as side-effect of startup sequence
ResetInit,
/// EC detected an AP watchdog event
ResetApWatchdog,

ShutdownPowerFail = 0x8000,
/// Forcing a shutdown as part of EC initialization
ShutdownInit,
/// Custom reason on a per-board basis.
ShutdownBoardCustom,
/// This is a reason to inhibit startup, not cause shut down.
ShutdownBatteryInhibit,
/// A power_wait_signal is being asserted
ShutdownWait,
/// Critical battery level.
ShutdownBatteryCritical,
/// Because you told me to.
ShutdownConsoleCommand,
/// Forcing a shutdown to effect entry to G3.
ShutdownG3,
/// Force shutdown due to over-temperature.
ShutdownThermal,
/// Force a chipset shutdown from the power button through EC
ShutdownButton,
}

#[repr(C)]
pub struct EcRequestGetUptimeInfo {}

#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct ApResetLogEntry {
pub reset_cause: u16,
pub reserved: u16,
pub reset_time_ms: u32,
}

#[repr(C, packed)]
#[derive(Debug)]
pub struct EcResponseGetUptimeInfo {
pub time_since_ec_boot: u32,
/// How often the AP was reset by the EC since last EC boot
/// The first AP boot may count as more than one
pub ap_resets_since_ec_boot: u32,
pub ec_reset_flags: u32,
pub recent_ap_resets: [ApResetLogEntry; 4],
}

impl EcRequest<EcResponseGetUptimeInfo> for EcRequestGetUptimeInfo {
fn command_id() -> EcCommands {
EcCommands::GetUptimeInfo
}
}

#[repr(C, packed)]
pub struct EcRequestAdcRead {
/// ADC Channel, specific to each mainboard schematic
Expand Down
44 changes: 44 additions & 0 deletions framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use crate::smbios;
use crate::uefi::shell_get_execution_break_flag;
use crate::util::{self, Platform};

use no_std_compat::time::Duration;

use log::Level;
use num_derive::FromPrimitive;

Expand Down Expand Up @@ -1670,6 +1672,48 @@ impl CrosEc {
}
Ok(())
}

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());
println!("EC Uptime");
println!(
" Time since EC Boot: {}",
util::format_duration(&t_since_boot)
);
println!(" AP Resets since EC Boot: {}", {
res.ap_resets_since_ec_boot
});
println!(" EC Reset Flags");
for flag in 0..(EcResetFlag::Count as usize) {
if ((1 << flag) & res.ec_reset_flags) > 0 {
// Safe to unwrap unless coding mistake
println!(
" {:?}",
<EcResetFlag as FromPrimitive>::from_usize(flag).unwrap()
);
}
}
println!(" Recent AP Resets");
for reset in res.recent_ap_resets {
if reset.reset_time_ms == 0 {
// Empty entry
continue;
}
let reset_time = Duration::from_millis(reset.reset_time_ms.into());
println!(
" Reset Time: {}",
util::format_duration(&reset_time)
);
let reset_cause: Option<ResetCause> = FromPrimitive::from_u16(reset.reset_cause);
if let Some(cause) = reset_cause {
println!(" Cause: {:?}", cause);
} else {
println!(" Cause: Unknown");
}
}
Ok(())
}
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
Expand Down
4 changes: 4 additions & 0 deletions framework_lib/src/commandline/clap_std.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,9 @@ struct ClapCli {
#[arg(long)]
ec_hib_delay: Option<Option<u32>>,

#[arg(long)]
uptimeinfo: bool,

/// Hash a file of arbitrary data
#[arg(long)]
hash: Option<std::path::PathBuf>,
Expand Down Expand Up @@ -454,6 +457,7 @@ pub fn parse(args: &[String]) -> Cli {
console: args.console,
reboot_ec: args.reboot_ec,
ec_hib_delay: args.ec_hib_delay,
uptimeinfo: args.uptimeinfo,
hash: args.hash.map(|x| x.into_os_string().into_string().unwrap()),
driver: args.driver,
pd_addrs,
Expand Down
4 changes: 4 additions & 0 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ pub struct Cli {
pub console: Option<ConsoleArg>,
pub reboot_ec: Option<RebootEcArg>,
pub ec_hib_delay: Option<Option<u32>>,
pub uptimeinfo: bool,
pub hash: Option<String>,
pub pd_addrs: Option<(u16, u16, u16)>,
pub pd_ports: Option<(u8, u8, u8)>,
Expand Down Expand Up @@ -295,6 +296,7 @@ pub fn parse(args: &[String]) -> Cli {
console: cli.console,
reboot_ec: cli.reboot_ec,
// ec_hib_delay
uptimeinfo: cli.uptimeinfo,
hash: cli.hash,
pd_addrs: cli.pd_addrs,
pd_ports: cli.pd_ports,
Expand Down Expand Up @@ -1174,6 +1176,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
print_err(ec.set_ec_hib_delay(*delay));
}
print_err(ec.get_ec_hib_delay());
} else if args.uptimeinfo {
print_err(ec.get_uptime_info());
} else if args.test {
println!("Self-Test");
let result = selftest(&ec);
Expand Down
6 changes: 5 additions & 1 deletion framework_lib/src/commandline/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub fn parse(args: &[String]) -> Cli {
console: None,
reboot_ec: None,
ec_hib_delay: None,
uptimeinfo: false,
hash: None,
// This is the only driver that works on UEFI
driver: Some(CrosEcDriverType::Portio),
Expand Down Expand Up @@ -476,7 +477,7 @@ pub fn parse(args: &[String]) -> Cli {
None
};
found_an_option = true;
} else if arg == "--reboot-ec" {
} else if arg == "--ec-hib-delay" {
cli.ec_hib_delay = if args.len() > i + 1 {
if let Ok(delay) = args[i + 1].parse::<u32>() {
if delay == 0 {
Expand All @@ -493,6 +494,9 @@ pub fn parse(args: &[String]) -> Cli {
Some(None)
};
found_an_option = true;
} else if arg == "--uptimeinfo" {
cli.uptimeinfo = true;
found_an_option = true;
} else if arg == "-t" || arg == "--test" {
cli.test = true;
found_an_option = true;
Expand Down
9 changes: 9 additions & 0 deletions framework_lib/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ use spin::{Mutex, MutexGuard};
#[cfg(not(feature = "uefi"))]
use std::sync::{Arc, Mutex, MutexGuard};

use no_std_compat::time::Duration;

use crate::smbios;

#[derive(Debug, PartialEq, Clone, Copy)]
Expand Down Expand Up @@ -264,3 +266,10 @@ pub fn assert_win_len<N: Num + std::fmt::Debug + Ord + NumCast + Copy>(left: N,
#[cfg(not(windows))]
assert_eq!(left, right);
}

pub fn format_duration(duration: &Duration) -> String {
let hours = duration.as_secs() / 3600;
let minutes = (duration.as_secs() % 3600) / 60;
let seconds = duration.as_secs() % 60;
format!("{:02}h {:02}m {:02}s", hours, minutes, seconds)
}