Skip to content

Commit

Permalink
Merge pull request #30 from FrameworkComputer/flash-ec
Browse files Browse the repository at this point in the history
Allow flashing EC firmware
  • Loading branch information
JohnAZoidberg authored May 12, 2024
2 parents 459323c + b96a342 commit ac83be8
Show file tree
Hide file tree
Showing 11 changed files with 830 additions and 37 deletions.
66 changes: 66 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion framework_lib/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ linux = ["linux_pio", "unix"]
windows = ["std", "smbios", "dep:windows", "win_driver"]
smbios = ["dep:smbios-lib"]
std = ["dep:clap", "dep:clap-verbosity-flag", "dep:env_logger", "smbios-lib?/std", "dep:hidapi", "dep:rusb"]
uefi = ["dep:plain", "raw_pio", "smbios", "lazy_static/spin_no_std", "dep:uefi", "dep:uefi-services"]
uefi = [
"dep:plain", "raw_pio", "smbios", "lazy_static/spin_no_std", "dep:uefi", "dep:uefi-services",
# Otherwise I get: `LLVM ERROR: Do not know how to split the result of this operator!`
# Seems to be a Ruset/LLVM bug when SSE is enabled.
# See: https://github.com/rust-lang/rust/issues/61721
"sha2/force-soft"
]

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

[dependencies]
lazy_static = "1.4.0"
sha2 = { version = "0.10.6", default_features = false, features = [ "force-soft" ] }
regex = { version = "1.10.0", default-features = false }
redox_hwio = { version = "0.1.5", default_features = false }
libc = { version = "0.2.137", optional = true }
Expand Down
18 changes: 13 additions & 5 deletions framework_lib/src/chromium_ec/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ pub enum EcCommands {
/// Command to read data from EC memory map
ReadMemMap = 0x07,
GetCmdVersions = 0x08,
FlashInfo = 0x10,
/// Write section of EC flash
FlashRead = 0x11,
/// Write section of EC flash
FlashWrite = 0x12,
/// Erase section of EC flash
FlashErase = 0x13,
FlashProtect = 0x15,
PwmGetKeyboardBacklight = 0x0022,
PwmSetKeyboardBacklight = 0x0023,
I2cPassthrough = 0x9e,
Expand Down Expand Up @@ -85,14 +93,14 @@ impl<T: EcRequest<R>, R> EcRequestRaw<R> for T {
fn command_id_u16() -> u16 {
Self::command_id() as u16
}
fn command_version() -> u8 {
Self::command_version()
}
}

pub trait EcRequestRaw<R> {
fn command_id_u16() -> u16;
// Can optionally override this
fn command_version() -> u8 {
0
}
fn command_version() -> u8;

fn format_request(&self) -> &[u8]
where
Expand Down Expand Up @@ -152,7 +160,7 @@ pub trait EcRequestRaw<R> {
let expected = response.len() != std::mem::size_of::<R>();
if expected {
return Err(EcError::DeviceError(format!(
"Returned data size {} is not the expted size: {}",
"Returned data size ({}) is not the expted size: {}",
response.len(),
std::mem::size_of::<R>()
)));
Expand Down
94 changes: 94 additions & 0 deletions framework_lib/src/chromium_ec/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use core::fmt;
use num_derive::FromPrimitive;

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

#[repr(C, packed)]
pub struct EcRequestGetVersion {}
Expand Down Expand Up @@ -60,6 +62,98 @@ impl EcRequest<EcResponseGetCmdVersionsV1> for EcRequestGetCmdVersionsV1 {
}
}

pub struct EcRequestFlashInfo {}

#[repr(C, packed)]
#[derive(Clone, Copy, Debug)]
pub struct EcResponseFlashInfo {
pub flash_size: u32,
pub write_block_size: u32,
pub erase_block_size: u32,
pub protect_block_size: u32,
// New fields in version 1 of the command
pub write_ideal_size: u32,
pub flags: u32,
}

impl EcRequest<EcResponseFlashInfo> for EcRequestFlashInfo {
fn command_version() -> u8 {
1
}
fn command_id() -> EcCommands {
EcCommands::FlashInfo
}
}

pub struct EcRequestFlashRead {
pub offset: u32,
pub size: u32,
}

impl EcRequest<()> for EcRequestFlashRead {
fn command_id() -> EcCommands {
EcCommands::FlashRead
}
}

#[repr(C, packed)]
pub struct EcRequestFlashWrite {
pub offset: u32,
pub size: u32,
/// Dynamically sized array (data copied after this struct)
pub data: [u8; 0],
}
impl EcRequest<()> for EcRequestFlashWrite {
fn command_id() -> EcCommands {
EcCommands::FlashWrite
}
}

#[repr(C, packed)]
pub struct EcRequestFlashErase {
pub offset: u32,
pub size: u32,
}

impl EcRequest<()> for EcRequestFlashErase {
fn command_id() -> EcCommands {
EcCommands::FlashErase
}
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum FlashProtectFlags {
ProtectRoAtBoot = 1 << 0,
ProtectRoNow = 1 << 1,
ProtectAllNow = 1 << 2,
ProtectGpioAsserted = 1 << 3,
/// At least one flash bank is stuck and can't be unlocked
ErrorStruck = 1 << 4,
ErrorInconsistent = 1 << 5,
ProtectAllAtBoot = 1 << 6,
}

#[repr(C, packed)]
pub struct EcRequestFlashProtect {
pub mask: u32,
pub flags: u32,
}

pub struct EcResponseFlashProtect {
/// Current flash protect flags
pub flags: u32,
/// Flags that are valid on this platform
pub valid_flags: u32,
/// Flags that can be currently written (depending on protection status)
pub writeable_flags: u32,
}

impl EcRequest<EcResponseFlashProtect> for EcRequestFlashProtect {
fn command_id() -> EcCommands {
EcCommands::FlashProtect
}
}

#[repr(C, packed)]
pub struct EcRequestPwmSetKeyboardBacklight {
pub percent: u8,
Expand Down
Loading

0 comments on commit ac83be8

Please sign in to comment.