Skip to content

Commit

Permalink
Merge pull request #28 from FrameworkComputer/reboot-ec
Browse files Browse the repository at this point in the history
Add command to reboot EC, optionally to RW section
  • Loading branch information
JohnAZoidberg authored Apr 30, 2024
2 parents fa3ee6d + 68ad62c commit b03685b
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 4 deletions.
4 changes: 4 additions & 0 deletions framework_lib/src/chromium_ec/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub enum EcCommands {
I2cPassthrough = 0x9e,
ConsoleSnapshot = 0x97,
ConsoleRead = 0x98,
/// Force reboot, causes host reboot as well
Reboot = 0xD1,
/// Control EC boot
RebootEc = 0xD2,
/// Get information about PD controller power
UsbPdPowerInfo = 0x103,

Expand Down
61 changes: 61 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,15 @@ impl EcRequest<EcResponsePwmGetKeyboardBacklight> for EcRequestPwmGetKeyboardBac
}
}

#[repr(C, packed)]
pub struct EcRequestReboot {}

impl EcRequest<()> for EcRequestReboot {
fn command_id() -> EcCommands {
EcCommands::Reboot
}
}

pub struct EcRequestConsoleSnapshot {}
impl EcRequest<()> for EcRequestConsoleSnapshot {
fn command_id() -> EcCommands {
Expand All @@ -111,6 +120,58 @@ impl EcRequest<()> for EcRequestConsoleRead {
}
}

#[repr(u8)]
pub enum RebootEcCmd {
/// Cancel a pending reboot
Cancel = 0,
/// Jump to RO firmware without rebooting
JumpRo = 1,
/// Jump to RW firmware without rebooting
JumpRw = 2,
/// DEPRECATED: Was jump to RW-B
DeprecatedJumpToRwB = 3,
/// Cold reboot of the EC. Causes host reset as well
ColdReboot = 4,
/// Disable jumping until the next EC reboot
DisableJump = 5,
/// Hibernate the EC
Hibernate = 6,
/// DEPRECATED: Hibernate EC and clears AP_IDLE flag.
/// Use EC_REBOOT_HIBERNATE and EC_REBOOT_FLAG_CLEAR_AP_IDLE, instead.
DeprecatedClearApOff = 7,
/// Cold-reboot and don't boot AP
ColdApOff = 8,
/// Do nothing but apply the flags
NoOp = 9,
}

#[repr(u8)]
pub enum RebootEcFlags {
/// Default
None = 0x00,
DeprecatedRecoveryRequest = 0x01,
/// Reboot after AP shutdown
OnApShutdown = 0x02,
/// Switch RW slot
SwitchRwSlot = 0x04,
/// Clear AP_IDLE flag
ClearApidle = 0x08,
}

pub struct EcRequestRebootEc {
pub cmd: u8, /* enum RebootEcCmd */
pub flags: u8,
}

impl EcRequest<()> for EcRequestRebootEc {
fn command_id() -> EcCommands {
EcCommands::RebootEc
}
fn command_version() -> u8 {
0
}
}

#[repr(C, packed)]
pub struct EcRequestUsbPdPowerInfo {
pub port: u8,
Expand Down
48 changes: 48 additions & 0 deletions framework_lib/src/chromium_ec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,54 @@ impl CrosEc {
.replace(|c: char| c == '\0', "");
Ok(ascii)
}

/// Instantly reboot EC and host
pub fn reboot(&self) -> EcResult<()> {
EcRequestReboot {}.send_command(self)
}

pub fn reboot_ec(&self, command: RebootEcCmd) -> EcResult<()> {
EcRequestRebootEc {
cmd: command as u8,
flags: RebootEcFlags::None as u8,
}
.send_command(self)
}

pub fn jump_rw(&self) -> EcResult<()> {
// Note: AP Turns off
EcRequestRebootEc {
cmd: RebootEcCmd::JumpRw as u8,
flags: 0,
// flags: RebootEcFlags::OnApShutdown as u8,
}
.send_command(self)
}

pub fn jump_ro(&self) -> EcResult<()> {
EcRequestRebootEc {
cmd: RebootEcCmd::JumpRo as u8,
flags: 0,
// flags: RebootEcFlags::OnApShutdown as u8,
}
.send_command(self)
}

pub fn cancel_jump(&self) -> EcResult<()> {
EcRequestRebootEc {
cmd: RebootEcCmd::Cancel as u8,
flags: 0,
}
.send_command(self)
}

pub fn disable_jump(&self) -> EcResult<()> {
EcRequestRebootEc {
cmd: RebootEcCmd::DisableJump as u8,
flags: 0,
}
.send_command(self)
}
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
Expand Down
8 changes: 7 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,7 @@
use clap::Parser;

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

/// Swiss army knife for Framework laptops
#[derive(Parser)]
Expand Down Expand Up @@ -106,6 +106,11 @@ struct ClapCli {
#[arg(long)]
console: Option<ConsoleArg>,

/// Control EC RO/RW jump
#[clap(value_enum)]
#[arg(long)]
reboot_ec: Option<RebootEcArg>,

/// Select which driver is used. By default portio is used
#[clap(value_enum)]
#[arg(long)]
Expand Down Expand Up @@ -154,6 +159,7 @@ pub fn parse(args: &[String]) -> Cli {
fp_brightness: args.fp_brightness,
kblight: args.kblight,
console: args.console,
reboot_ec: args.reboot_ec,
driver: args.driver,
test: args.test,
// TODO: Set help. Not very important because Clap handles this by itself
Expand Down
39 changes: 37 additions & 2 deletions framework_lib/src/commandline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ use crate::ccgx::{self, SiliconId::*};
use crate::chromium_ec;
use crate::chromium_ec::commands::DeckStateMode;
use crate::chromium_ec::commands::FpLedBrightnessLevel;
use crate::chromium_ec::commands::RebootEcCmd;
use crate::chromium_ec::print_err;
use crate::chromium_ec::EcError;
use crate::chromium_ec::EcResult;
use crate::chromium_ec::{EcError, EcResult};
#[cfg(feature = "linux")]
use crate::csme;
use crate::ec_binary;
Expand All @@ -59,6 +59,16 @@ pub enum ConsoleArg {
Follow,
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
#[derive(Clone, Debug, PartialEq)]
pub enum RebootEcArg {
Reboot,
JumpRo,
JumpRw,
CancelJump,
DisableJump,
}

#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum FpBrightnessArg {
Expand Down Expand Up @@ -124,6 +134,7 @@ pub struct Cli {
pub fp_brightness: Option<Option<FpBrightnessArg>>,
pub kblight: Option<Option<u8>>,
pub console: Option<ConsoleArg>,
pub reboot_ec: Option<RebootEcArg>,
pub help: bool,
pub info: bool,
// UEFI only
Expand Down Expand Up @@ -484,6 +495,29 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
Err(err) => println!("Failed to read console: {:?}", err),
},
}
} else if let Some(reboot_arg) = &args.reboot_ec {
match reboot_arg {
RebootEcArg::Reboot => match ec.reboot_ec(RebootEcCmd::ColdReboot) {
Ok(_) => {}
Err(err) => println!("Failed: {:?}", err),
},
RebootEcArg::JumpRo => match ec.jump_ro() {
Ok(_) => {}
Err(err) => println!("Failed: {:?}", err),
},
RebootEcArg::JumpRw => match ec.jump_rw() {
Ok(_) => {}
Err(err) => println!("Failed: {:?}", err),
},
RebootEcArg::CancelJump => match ec.cancel_jump() {
Ok(_) => {}
Err(err) => println!("Failed: {:?}", err),
},
RebootEcArg::DisableJump => match ec.disable_jump() {
Ok(_) => {}
Err(err) => println!("Failed: {:?}", err),
},
}
} else if args.test {
println!("Self-Test");
let result = selftest(&ec);
Expand Down Expand Up @@ -655,6 +689,7 @@ Options:
--fp-brightness [<VAL>]Get or set fingerprint LED brightness level [possible values: high, medium, low]
--kblight [<KBLIGHT>] Set keyboard backlight percentage or get, if no value provided
--console <CONSOLE> Get EC console, choose whether recent or to follow the output [possible values: recent, follow]
--reboot-ec Control EC RO/RW jump [possible values: reboot, jump-ro, jump-rw, cancel-jump, disable-jump]
-t, --test Run self-test to check if interaction with EC is possible
-h, --help Print help information
"#
Expand Down
25 changes: 24 additions & 1 deletion framework_lib/src/commandline/uefi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use uefi::Identify;
use crate::chromium_ec::CrosEcDriverType;
use crate::commandline::Cli;

use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg};
use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg};

/// Get commandline arguments from UEFI environment
pub fn get_args(boot_services: &BootServices) -> Vec<String> {
Expand Down Expand Up @@ -77,6 +77,7 @@ pub fn parse(args: &[String]) -> Cli {
fp_brightness: None,
kblight: None,
console: None,
reboot_ec: None,
// This is the only driver that works on UEFI
driver: Some(CrosEcDriverType::Portio),
test: false,
Expand Down Expand Up @@ -216,6 +217,28 @@ pub fn parse(args: &[String]) -> Cli {
None
};
found_an_option = true;
} else if arg == "--reboot-ec" {
cli.reboot_ec = if args.len() > i + 1 {
let reboot_ec_arg = &args[i + 1];
if reboot_ec_arg == "reboot" {
Some(RebootEcArg::Reboot)
} else if reboot_ec_arg == "jump-ro" {
Some(RebootEcArg::JumpRo)
} else if reboot_ec_arg == "jump-rw" {
Some(RebootEcArg::JumpRw)
} else if reboot_ec_arg == "cancel-jump" {
Some(RebootEcArg::CancelJump)
} else if reboot_ec_arg == "disable-jump" {
Some(RebootEcArg::DisableJump)
} else {
println!("Invalid value for --reboot-ec: {}", reboot_ec_arg);
None
}
} else {
println!("Need to provide a value for --reboot-ec. Either `reboot`, `jump-ro`, `jump-rw`, `cancel-jump` or `disable-jump`");
None
};
found_an_option = true;
} else if arg == "-t" || arg == "--test" {
cli.test = true;
found_an_option = true;
Expand Down

0 comments on commit b03685b

Please sign in to comment.