Skip to content

Commit b03685b

Browse files
Merge pull request #28 from FrameworkComputer/reboot-ec
Add command to reboot EC, optionally to RW section
2 parents fa3ee6d + 68ad62c commit b03685b

File tree

6 files changed

+181
-4
lines changed

6 files changed

+181
-4
lines changed

framework_lib/src/chromium_ec/command.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ pub enum EcCommands {
2525
I2cPassthrough = 0x9e,
2626
ConsoleSnapshot = 0x97,
2727
ConsoleRead = 0x98,
28+
/// Force reboot, causes host reboot as well
29+
Reboot = 0xD1,
30+
/// Control EC boot
31+
RebootEc = 0xD2,
2832
/// Get information about PD controller power
2933
UsbPdPowerInfo = 0x103,
3034

framework_lib/src/chromium_ec/commands.rs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,15 @@ impl EcRequest<EcResponsePwmGetKeyboardBacklight> for EcRequestPwmGetKeyboardBac
8686
}
8787
}
8888

89+
#[repr(C, packed)]
90+
pub struct EcRequestReboot {}
91+
92+
impl EcRequest<()> for EcRequestReboot {
93+
fn command_id() -> EcCommands {
94+
EcCommands::Reboot
95+
}
96+
}
97+
8998
pub struct EcRequestConsoleSnapshot {}
9099
impl EcRequest<()> for EcRequestConsoleSnapshot {
91100
fn command_id() -> EcCommands {
@@ -111,6 +120,58 @@ impl EcRequest<()> for EcRequestConsoleRead {
111120
}
112121
}
113122

123+
#[repr(u8)]
124+
pub enum RebootEcCmd {
125+
/// Cancel a pending reboot
126+
Cancel = 0,
127+
/// Jump to RO firmware without rebooting
128+
JumpRo = 1,
129+
/// Jump to RW firmware without rebooting
130+
JumpRw = 2,
131+
/// DEPRECATED: Was jump to RW-B
132+
DeprecatedJumpToRwB = 3,
133+
/// Cold reboot of the EC. Causes host reset as well
134+
ColdReboot = 4,
135+
/// Disable jumping until the next EC reboot
136+
DisableJump = 5,
137+
/// Hibernate the EC
138+
Hibernate = 6,
139+
/// DEPRECATED: Hibernate EC and clears AP_IDLE flag.
140+
/// Use EC_REBOOT_HIBERNATE and EC_REBOOT_FLAG_CLEAR_AP_IDLE, instead.
141+
DeprecatedClearApOff = 7,
142+
/// Cold-reboot and don't boot AP
143+
ColdApOff = 8,
144+
/// Do nothing but apply the flags
145+
NoOp = 9,
146+
}
147+
148+
#[repr(u8)]
149+
pub enum RebootEcFlags {
150+
/// Default
151+
None = 0x00,
152+
DeprecatedRecoveryRequest = 0x01,
153+
/// Reboot after AP shutdown
154+
OnApShutdown = 0x02,
155+
/// Switch RW slot
156+
SwitchRwSlot = 0x04,
157+
/// Clear AP_IDLE flag
158+
ClearApidle = 0x08,
159+
}
160+
161+
pub struct EcRequestRebootEc {
162+
pub cmd: u8, /* enum RebootEcCmd */
163+
pub flags: u8,
164+
}
165+
166+
impl EcRequest<()> for EcRequestRebootEc {
167+
fn command_id() -> EcCommands {
168+
EcCommands::RebootEc
169+
}
170+
fn command_version() -> u8 {
171+
0
172+
}
173+
}
174+
114175
#[repr(C, packed)]
115176
pub struct EcRequestUsbPdPowerInfo {
116177
pub port: u8,

framework_lib/src/chromium_ec/mod.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,54 @@ impl CrosEc {
410410
.replace(|c: char| c == '\0', "");
411411
Ok(ascii)
412412
}
413+
414+
/// Instantly reboot EC and host
415+
pub fn reboot(&self) -> EcResult<()> {
416+
EcRequestReboot {}.send_command(self)
417+
}
418+
419+
pub fn reboot_ec(&self, command: RebootEcCmd) -> EcResult<()> {
420+
EcRequestRebootEc {
421+
cmd: command as u8,
422+
flags: RebootEcFlags::None as u8,
423+
}
424+
.send_command(self)
425+
}
426+
427+
pub fn jump_rw(&self) -> EcResult<()> {
428+
// Note: AP Turns off
429+
EcRequestRebootEc {
430+
cmd: RebootEcCmd::JumpRw as u8,
431+
flags: 0,
432+
// flags: RebootEcFlags::OnApShutdown as u8,
433+
}
434+
.send_command(self)
435+
}
436+
437+
pub fn jump_ro(&self) -> EcResult<()> {
438+
EcRequestRebootEc {
439+
cmd: RebootEcCmd::JumpRo as u8,
440+
flags: 0,
441+
// flags: RebootEcFlags::OnApShutdown as u8,
442+
}
443+
.send_command(self)
444+
}
445+
446+
pub fn cancel_jump(&self) -> EcResult<()> {
447+
EcRequestRebootEc {
448+
cmd: RebootEcCmd::Cancel as u8,
449+
flags: 0,
450+
}
451+
.send_command(self)
452+
}
453+
454+
pub fn disable_jump(&self) -> EcResult<()> {
455+
EcRequestRebootEc {
456+
cmd: RebootEcCmd::DisableJump as u8,
457+
flags: 0,
458+
}
459+
.send_command(self)
460+
}
413461
}
414462

415463
#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]

framework_lib/src/commandline/clap_std.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
use clap::Parser;
55

66
use crate::chromium_ec::CrosEcDriverType;
7-
use crate::commandline::{Cli, ConsoleArg, FpBrightnessArg, InputDeckModeArg};
7+
use crate::commandline::{Cli, ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg};
88

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

109+
/// Control EC RO/RW jump
110+
#[clap(value_enum)]
111+
#[arg(long)]
112+
reboot_ec: Option<RebootEcArg>,
113+
109114
/// Select which driver is used. By default portio is used
110115
#[clap(value_enum)]
111116
#[arg(long)]
@@ -154,6 +159,7 @@ pub fn parse(args: &[String]) -> Cli {
154159
fp_brightness: args.fp_brightness,
155160
kblight: args.kblight,
156161
console: args.console,
162+
reboot_ec: args.reboot_ec,
157163
driver: args.driver,
158164
test: args.test,
159165
// TODO: Set help. Not very important because Clap handles this by itself

framework_lib/src/commandline/mod.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ use crate::ccgx::{self, SiliconId::*};
3030
use crate::chromium_ec;
3131
use crate::chromium_ec::commands::DeckStateMode;
3232
use crate::chromium_ec::commands::FpLedBrightnessLevel;
33+
use crate::chromium_ec::commands::RebootEcCmd;
3334
use crate::chromium_ec::print_err;
34-
use crate::chromium_ec::EcError;
35-
use crate::chromium_ec::EcResult;
35+
use crate::chromium_ec::{EcError, EcResult};
3636
#[cfg(feature = "linux")]
3737
use crate::csme;
3838
use crate::ec_binary;
@@ -59,6 +59,16 @@ pub enum ConsoleArg {
5959
Follow,
6060
}
6161

62+
#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
63+
#[derive(Clone, Debug, PartialEq)]
64+
pub enum RebootEcArg {
65+
Reboot,
66+
JumpRo,
67+
JumpRw,
68+
CancelJump,
69+
DisableJump,
70+
}
71+
6272
#[cfg_attr(not(feature = "uefi"), derive(clap::ValueEnum))]
6373
#[derive(Clone, Copy, Debug, PartialEq)]
6474
pub enum FpBrightnessArg {
@@ -124,6 +134,7 @@ pub struct Cli {
124134
pub fp_brightness: Option<Option<FpBrightnessArg>>,
125135
pub kblight: Option<Option<u8>>,
126136
pub console: Option<ConsoleArg>,
137+
pub reboot_ec: Option<RebootEcArg>,
127138
pub help: bool,
128139
pub info: bool,
129140
// UEFI only
@@ -484,6 +495,29 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
484495
Err(err) => println!("Failed to read console: {:?}", err),
485496
},
486497
}
498+
} else if let Some(reboot_arg) = &args.reboot_ec {
499+
match reboot_arg {
500+
RebootEcArg::Reboot => match ec.reboot_ec(RebootEcCmd::ColdReboot) {
501+
Ok(_) => {}
502+
Err(err) => println!("Failed: {:?}", err),
503+
},
504+
RebootEcArg::JumpRo => match ec.jump_ro() {
505+
Ok(_) => {}
506+
Err(err) => println!("Failed: {:?}", err),
507+
},
508+
RebootEcArg::JumpRw => match ec.jump_rw() {
509+
Ok(_) => {}
510+
Err(err) => println!("Failed: {:?}", err),
511+
},
512+
RebootEcArg::CancelJump => match ec.cancel_jump() {
513+
Ok(_) => {}
514+
Err(err) => println!("Failed: {:?}", err),
515+
},
516+
RebootEcArg::DisableJump => match ec.disable_jump() {
517+
Ok(_) => {}
518+
Err(err) => println!("Failed: {:?}", err),
519+
},
520+
}
487521
} else if args.test {
488522
println!("Self-Test");
489523
let result = selftest(&ec);
@@ -655,6 +689,7 @@ Options:
655689
--fp-brightness [<VAL>]Get or set fingerprint LED brightness level [possible values: high, medium, low]
656690
--kblight [<KBLIGHT>] Set keyboard backlight percentage or get, if no value provided
657691
--console <CONSOLE> Get EC console, choose whether recent or to follow the output [possible values: recent, follow]
692+
--reboot-ec Control EC RO/RW jump [possible values: reboot, jump-ro, jump-rw, cancel-jump, disable-jump]
658693
-t, --test Run self-test to check if interaction with EC is possible
659694
-h, --help Print help information
660695
"#

framework_lib/src/commandline/uefi.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use uefi::Identify;
1212
use crate::chromium_ec::CrosEcDriverType;
1313
use crate::commandline::Cli;
1414

15-
use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg};
15+
use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg};
1616

1717
/// Get commandline arguments from UEFI environment
1818
pub fn get_args(boot_services: &BootServices) -> Vec<String> {
@@ -77,6 +77,7 @@ pub fn parse(args: &[String]) -> Cli {
7777
fp_brightness: None,
7878
kblight: None,
7979
console: None,
80+
reboot_ec: None,
8081
// This is the only driver that works on UEFI
8182
driver: Some(CrosEcDriverType::Portio),
8283
test: false,
@@ -216,6 +217,28 @@ pub fn parse(args: &[String]) -> Cli {
216217
None
217218
};
218219
found_an_option = true;
220+
} else if arg == "--reboot-ec" {
221+
cli.reboot_ec = if args.len() > i + 1 {
222+
let reboot_ec_arg = &args[i + 1];
223+
if reboot_ec_arg == "reboot" {
224+
Some(RebootEcArg::Reboot)
225+
} else if reboot_ec_arg == "jump-ro" {
226+
Some(RebootEcArg::JumpRo)
227+
} else if reboot_ec_arg == "jump-rw" {
228+
Some(RebootEcArg::JumpRw)
229+
} else if reboot_ec_arg == "cancel-jump" {
230+
Some(RebootEcArg::CancelJump)
231+
} else if reboot_ec_arg == "disable-jump" {
232+
Some(RebootEcArg::DisableJump)
233+
} else {
234+
println!("Invalid value for --reboot-ec: {}", reboot_ec_arg);
235+
None
236+
}
237+
} else {
238+
println!("Need to provide a value for --reboot-ec. Either `reboot`, `jump-ro`, `jump-rw`, `cancel-jump` or `disable-jump`");
239+
None
240+
};
241+
found_an_option = true;
219242
} else if arg == "-t" || arg == "--test" {
220243
cli.test = true;
221244
found_an_option = true;

0 commit comments

Comments
 (0)