Skip to content

Commit ac83be8

Browse files
Merge pull request #30 from FrameworkComputer/flash-ec
Allow flashing EC firmware
2 parents 459323c + b96a342 commit ac83be8

File tree

11 files changed

+830
-37
lines changed

11 files changed

+830
-37
lines changed

Cargo.lock

+66
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

framework_lib/Cargo.toml

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ linux = ["linux_pio", "unix"]
1414
windows = ["std", "smbios", "dep:windows", "win_driver"]
1515
smbios = ["dep:smbios-lib"]
1616
std = ["dep:clap", "dep:clap-verbosity-flag", "dep:env_logger", "smbios-lib?/std", "dep:hidapi", "dep:rusb"]
17-
uefi = ["dep:plain", "raw_pio", "smbios", "lazy_static/spin_no_std", "dep:uefi", "dep:uefi-services"]
17+
uefi = [
18+
"dep:plain", "raw_pio", "smbios", "lazy_static/spin_no_std", "dep:uefi", "dep:uefi-services",
19+
# Otherwise I get: `LLVM ERROR: Do not know how to split the result of this operator!`
20+
# Seems to be a Ruset/LLVM bug when SSE is enabled.
21+
# See: https://github.com/rust-lang/rust/issues/61721
22+
"sha2/force-soft"
23+
]
1824

1925
# EC communication via Port I/O on Linux
2026
linux_pio = ["dep:libc"]
@@ -31,6 +37,7 @@ built = { version = "0.5", features = ["chrono", "git2"] }
3137

3238
[dependencies]
3339
lazy_static = "1.4.0"
40+
sha2 = { version = "0.10.6", default_features = false, features = [ "force-soft" ] }
3441
regex = { version = "1.10.0", default-features = false }
3542
redox_hwio = { version = "0.1.5", default_features = false }
3643
libc = { version = "0.2.137", optional = true }

framework_lib/src/chromium_ec/command.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ pub enum EcCommands {
2020
/// Command to read data from EC memory map
2121
ReadMemMap = 0x07,
2222
GetCmdVersions = 0x08,
23+
FlashInfo = 0x10,
24+
/// Write section of EC flash
25+
FlashRead = 0x11,
26+
/// Write section of EC flash
27+
FlashWrite = 0x12,
28+
/// Erase section of EC flash
29+
FlashErase = 0x13,
30+
FlashProtect = 0x15,
2331
PwmGetKeyboardBacklight = 0x0022,
2432
PwmSetKeyboardBacklight = 0x0023,
2533
I2cPassthrough = 0x9e,
@@ -85,14 +93,14 @@ impl<T: EcRequest<R>, R> EcRequestRaw<R> for T {
8593
fn command_id_u16() -> u16 {
8694
Self::command_id() as u16
8795
}
96+
fn command_version() -> u8 {
97+
Self::command_version()
98+
}
8899
}
89100

90101
pub trait EcRequestRaw<R> {
91102
fn command_id_u16() -> u16;
92-
// Can optionally override this
93-
fn command_version() -> u8 {
94-
0
95-
}
103+
fn command_version() -> u8;
96104

97105
fn format_request(&self) -> &[u8]
98106
where
@@ -152,7 +160,7 @@ pub trait EcRequestRaw<R> {
152160
let expected = response.len() != std::mem::size_of::<R>();
153161
if expected {
154162
return Err(EcError::DeviceError(format!(
155-
"Returned data size {} is not the expted size: {}",
163+
"Returned data size ({}) is not the expted size: {}",
156164
response.len(),
157165
std::mem::size_of::<R>()
158166
)));

framework_lib/src/chromium_ec/commands.rs

+94
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use core::fmt;
33
use num_derive::FromPrimitive;
44

55
use super::{command::*, input_deck::INPUT_DECK_SLOTS};
6+
#[cfg(feature = "uefi")]
7+
use core::prelude::rust_2021::derive;
68

79
#[repr(C, packed)]
810
pub struct EcRequestGetVersion {}
@@ -60,6 +62,98 @@ impl EcRequest<EcResponseGetCmdVersionsV1> for EcRequestGetCmdVersionsV1 {
6062
}
6163
}
6264

65+
pub struct EcRequestFlashInfo {}
66+
67+
#[repr(C, packed)]
68+
#[derive(Clone, Copy, Debug)]
69+
pub struct EcResponseFlashInfo {
70+
pub flash_size: u32,
71+
pub write_block_size: u32,
72+
pub erase_block_size: u32,
73+
pub protect_block_size: u32,
74+
// New fields in version 1 of the command
75+
pub write_ideal_size: u32,
76+
pub flags: u32,
77+
}
78+
79+
impl EcRequest<EcResponseFlashInfo> for EcRequestFlashInfo {
80+
fn command_version() -> u8 {
81+
1
82+
}
83+
fn command_id() -> EcCommands {
84+
EcCommands::FlashInfo
85+
}
86+
}
87+
88+
pub struct EcRequestFlashRead {
89+
pub offset: u32,
90+
pub size: u32,
91+
}
92+
93+
impl EcRequest<()> for EcRequestFlashRead {
94+
fn command_id() -> EcCommands {
95+
EcCommands::FlashRead
96+
}
97+
}
98+
99+
#[repr(C, packed)]
100+
pub struct EcRequestFlashWrite {
101+
pub offset: u32,
102+
pub size: u32,
103+
/// Dynamically sized array (data copied after this struct)
104+
pub data: [u8; 0],
105+
}
106+
impl EcRequest<()> for EcRequestFlashWrite {
107+
fn command_id() -> EcCommands {
108+
EcCommands::FlashWrite
109+
}
110+
}
111+
112+
#[repr(C, packed)]
113+
pub struct EcRequestFlashErase {
114+
pub offset: u32,
115+
pub size: u32,
116+
}
117+
118+
impl EcRequest<()> for EcRequestFlashErase {
119+
fn command_id() -> EcCommands {
120+
EcCommands::FlashErase
121+
}
122+
}
123+
124+
#[derive(Debug, PartialEq, Clone, Copy)]
125+
pub enum FlashProtectFlags {
126+
ProtectRoAtBoot = 1 << 0,
127+
ProtectRoNow = 1 << 1,
128+
ProtectAllNow = 1 << 2,
129+
ProtectGpioAsserted = 1 << 3,
130+
/// At least one flash bank is stuck and can't be unlocked
131+
ErrorStruck = 1 << 4,
132+
ErrorInconsistent = 1 << 5,
133+
ProtectAllAtBoot = 1 << 6,
134+
}
135+
136+
#[repr(C, packed)]
137+
pub struct EcRequestFlashProtect {
138+
pub mask: u32,
139+
pub flags: u32,
140+
}
141+
142+
pub struct EcResponseFlashProtect {
143+
/// Current flash protect flags
144+
pub flags: u32,
145+
/// Flags that are valid on this platform
146+
pub valid_flags: u32,
147+
/// Flags that can be currently written (depending on protection status)
148+
pub writeable_flags: u32,
149+
}
150+
151+
impl EcRequest<EcResponseFlashProtect> for EcRequestFlashProtect {
152+
fn command_id() -> EcCommands {
153+
EcCommands::FlashProtect
154+
}
155+
}
156+
63157
#[repr(C, packed)]
64158
pub struct EcRequestPwmSetKeyboardBacklight {
65159
pub percent: u8,

0 commit comments

Comments
 (0)