Skip to content

Commit

Permalink
Some improvements
Browse files Browse the repository at this point in the history
Added an async wait_event function, added get encryption status function, made some more functions use generic trait for file.
  • Loading branch information
ChocolateLoverRaj committed Jun 20, 2024
1 parent a64baa9 commit a2d5504
Show file tree
Hide file tree
Showing 15 changed files with 680 additions and 44 deletions.
591 changes: 581 additions & 10 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions crosec/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
async-std = "1.12.0"
bytemuck = { version = "1.16.0", features = ["derive"] }
clap = { version = "4.5.6", optional = true }
nix = { version = "0.27.1", features = ["ioctl"] }
Expand Down
8 changes: 4 additions & 4 deletions crosec/src/commands/fp_download.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use std::{fs::File, os::fd::AsRawFd, thread::sleep, time::Duration};
use std::{os::fd::AsRawFd, thread::sleep, time::Duration};

use bytemuck::{bytes_of, Pod, Zeroable};

use crate::ec_command::ec_command_with_dynamic_output_size;

use super::{fp_info::EcResponseFpInfo, get_protocol_info::EcResponseGetProtocolInfo, CrosEcCmd};
use super::{CrosEcCmd, fp_info::EcResponseFpInfo, get_protocol_info::EcResponseGetProtocolInfo};

#[repr(C)]
#[derive(Pod, Zeroable, Clone, Copy)]
Expand All @@ -31,7 +31,7 @@ pub enum DownloadType {

/// Downloads a frame buffer from the FPMCU.
/// The downloaded data might be either the finger image or a finger template.
pub fn fp_download(
pub fn fp_download<File: AsRawFd>(
file: &mut File,
fp_info: &EcResponseFpInfo,
protocol_info: &EcResponseGetProtocolInfo,
Expand Down Expand Up @@ -101,7 +101,7 @@ impl FpTemplate {
}
}

pub fn fp_download_template(
pub fn fp_download_template<File: AsRawFd>(
file: &mut File,
fp_info: &EcResponseFpInfo,
protocol_info: &EcResponseGetProtocolInfo,
Expand Down
21 changes: 21 additions & 0 deletions crosec/src/commands/fp_get_encryption_status.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use std::os::fd::AsRawFd;
use bytemuck::{Pod, Zeroable};
use crate::commands::CrosEcCmd;
use crate::ec_command::ec_command_bytemuck;
use crate::EcCmdResult;

#[repr(u32)]
pub enum FpEncryptionStatus {
SeedSet = 0b1
}

#[derive(Pod, Zeroable, Copy, Clone)]
#[repr(C)]
pub struct EcResponseFpGetEncryptionStatus {
pub valid_flags: u32,
pub status: u32,
}

pub fn fp_get_encryption_status<File: AsRawFd>(file: &mut File) -> EcCmdResult<EcResponseFpGetEncryptionStatus> {
ec_command_bytemuck(CrosEcCmd::FpGetEncryptionStatus, 0, &(), file.as_raw_fd())
}
6 changes: 3 additions & 3 deletions crosec/src/commands/fp_info.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::{fs::File, os::fd::AsRawFd};
use std::os::fd::AsRawFd;

use bytemuck::{Pod, Zeroable};

use crate::{ec_command::ec_command_bytemuck, EcCmdResult};

use super::{
get_cmd_versions::{ec_cmd_get_cmd_versions, V1},
CrosEcCmd,
get_cmd_versions::{ec_cmd_get_cmd_versions, V1},
};

#[repr(C, align(4))]
Expand Down Expand Up @@ -41,7 +41,7 @@ impl EcResponseFpInfo {
}
}

pub fn fp_info(file: &mut File) -> EcCmdResult<EcResponseFpInfo> {
pub fn fp_info<File: AsRawFd>(file: &mut File) -> EcCmdResult<EcResponseFpInfo> {
let fd = file.as_raw_fd();
let versions = ec_cmd_get_cmd_versions(file, CrosEcCmd::FpInfo)?;
if versions & V1 == 0 {
Expand Down
2 changes: 1 addition & 1 deletion crosec/src/commands/fp_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crate::{ec_command::ec_command_bytemuck, EcCmdResult};
use super::CrosEcCmd;

/// Note that with the ChromiumOS ectool, to start enrolling, as well as continue the next step in enrolling, you do `ectool --name=cros_fp fpmode enroll`. The equivalent of this is to do `ectool fp-mode EnrollImage EnrollSession`.
#[derive(EnumString, EnumIter, IntoStaticStr, Clone, Copy)]
#[derive(EnumString, EnumIter, IntoStaticStr, Clone, Copy, Debug)]
#[cfg_attr(feature = "clap", derive(clap::ValueEnum))]
#[repr(u32)]
pub enum FpMode {
Expand Down
4 changes: 2 additions & 2 deletions crosec/src/commands/fp_set_seed.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fs::File, os::fd::AsRawFd};
use std::os::fd::AsRawFd;

use bytemuck::{Pod, Zeroable};

Expand All @@ -17,7 +17,7 @@ struct EcParamsFpSeed {
pub seed: [u8; FP_CONTEXT_TPM_BYTES],
}

pub fn fp_set_seed(file: &mut File, seed: [u8; FP_CONTEXT_TPM_BYTES]) -> EcCmdResult<()> {
pub fn fp_set_seed<File: AsRawFd>(file: &mut File, seed: [u8; FP_CONTEXT_TPM_BYTES]) -> EcCmdResult<()> {
ec_command_bytemuck(
CrosEcCmd::FpSetSeed,
0,
Expand Down
8 changes: 4 additions & 4 deletions crosec/src/commands/fp_upload_template.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use std::{fs::File, mem::offset_of, os::fd::AsRawFd};
use std::{mem::offset_of, os::fd::AsRawFd};

use bytemuck::{bytes_of, Pod, Zeroable};

use crate::{ec_command::ec_command_with_dynamic_output_size, EcCmdResult};

use super::{
fp_download::FpTemplate, fp_info::EcResponseFpInfo,
get_protocol_info::EcResponseGetProtocolInfo, CrosEcCmd,
CrosEcCmd, fp_download::FpTemplate,
fp_info::EcResponseFpInfo, get_protocol_info::EcResponseGetProtocolInfo,
};

#[derive(Pod, Zeroable, Clone, Copy)]
Expand All @@ -20,7 +20,7 @@ struct EcParamsFpTemplateWithoutData {
/// Flag in the 'size' field indicating that the full template has been sent
const FP_TEMPLATE_COMMIT: u32 = 0x80000000;

pub fn fp_upload_template(
pub fn fp_upload_template<File: AsRawFd>(
file: &mut File,
protocol_info: &EcResponseGetProtocolInfo,
fp_info: &EcResponseFpInfo,
Expand Down
3 changes: 1 addition & 2 deletions crosec/src/commands/get_cmd_versions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::fs::File;
use std::os::fd::AsRawFd;

use bytemuck::{Pod, Zeroable};
Expand Down Expand Up @@ -29,7 +28,7 @@ pub const V0: u32 = 0b001;
pub const V1: u32 = 0b010;
pub const V2: u32 = 0b100;

pub fn ec_cmd_get_cmd_versions(file: &mut File, cmd: CrosEcCmd) -> EcCmdResult<u32> {
pub fn ec_cmd_get_cmd_versions<File: AsRawFd>(file: &mut File, cmd: CrosEcCmd) -> EcCmdResult<u32> {
let fd = file.as_raw_fd();
let response: EcResponseGetCmdVersion = match ec_command_bytemuck(
CrosEcCmd::GetCmdVersions,
Expand Down
4 changes: 2 additions & 2 deletions crosec/src/commands/get_protocol_info.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{fs::File, mem::size_of, os::fd::AsRawFd};
use std::{mem::size_of, os::fd::AsRawFd};

use bytemuck::{Pod, Zeroable};

Expand Down Expand Up @@ -42,6 +42,6 @@ struct EcHostResponse {
reserved: u16,
}

pub fn get_protocol_info(file: &mut File) -> EcCmdResult<EcResponseGetProtocolInfo> {
pub fn get_protocol_info<File: AsRawFd>(file: &mut File) -> EcCmdResult<EcResponseGetProtocolInfo> {
ec_command_bytemuck(CrosEcCmd::GetProtocolInfo, 0, &(), file.as_raw_fd())
}
2 changes: 2 additions & 0 deletions crosec/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ pub enum CrosEcCmd {
FpTemplate = 0x0405,
FpStats = 0x0407,
FpSetSeed = 0x0408,
FpGetEncryptionStatus = 0x0409,
BatteryGetStatic = 0x0600,
}

pub mod board_version;
pub mod charge_control;
pub mod fp_download;
pub mod fp_info;
pub mod fp_get_encryption_status;
pub mod fp_mode;
pub mod fp_set_seed;
pub mod fp_stats;
Expand Down
28 changes: 19 additions & 9 deletions crosec/src/wait_event/event.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{
io::{self, Read},
mem::size_of,
};
use std::io;
use std::mem::size_of;
use async_std::io::ReadExt;

use bytemuck::{from_bytes, Pod, Zeroable};
use num_derive::FromPrimitive;
Expand Down Expand Up @@ -50,6 +49,7 @@ pub enum EcMkbpEventType {
OnlineCalibration,
Pchg,
}

impl EcMkbpEventType {
fn data_size(&self) -> usize {
match self {
Expand All @@ -66,17 +66,27 @@ impl EcMkbpEventType {
}
}

pub(crate) fn read<T: Read>(&self, stream: &mut T) -> io::Result<EcMkbpEvent> {
let mut event = vec![Default::default(); size_of::<Self>() + self.data_size()];
stream.read_exact(&mut event)?;
fn parse_event(&self, event: &mut Vec<u8>) -> EcMkbpEvent {
debug_assert_eq!(event[0], *self as u8);
event.remove(0);
let data = event;
Ok(match self {
match self {
EcMkbpEventType::Fingerprint => {
EcMkbpEvent::Fingerprint(from_bytes::<EcMkbpEventFingerprint>(&data).to_owned())
}
event_type => panic!("{event_type:#?} from_bytes not implemented yet"),
})
}
}

pub(crate) fn read_sync<T: std::io::Read>(&self, stream: &mut T) -> io::Result<EcMkbpEvent> {
let mut event = vec![Default::default(); size_of::<Self>() + self.data_size()];
stream.read_exact(&mut event)?;
Ok(self.parse_event(&mut event))
}

pub(crate) async fn read_async<T: async_std::io::Read + Unpin>(&self, stream: &mut T) -> io::Result<EcMkbpEvent> {
let mut event = vec![Default::default(); size_of::<Self>() + self.data_size()];
stream.read_exact(&mut event).await?;
Ok(self.parse_event(&mut event))
}
}
27 changes: 22 additions & 5 deletions crosec/src/wait_event/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
use std::{fs::File, os::fd::AsRawFd};
use std::io;
use std::os::fd::AsRawFd;

use event::{EcMkbpEvent, EcMkbpEventType};
use nix::{
libc::{ioctl, poll, pollfd},
request_code_none,
};

use event::{EcMkbpEvent, EcMkbpEventType};

use crate::CROS_EC_IOC_MAGIC;

pub mod event;
Expand All @@ -21,7 +23,7 @@ pub enum PollData {
}

/// If no timeout is specified, this function will wait for an unlimited amount of time
pub fn wait_event(
pub fn wait_event_sync<File: AsRawFd + std::io::Read>(
file: &mut File,
event_type: EcMkbpEventType,
timeout: Option<i32>,
Expand All @@ -45,12 +47,27 @@ pub fn wait_event(
match result {
0 => Ok(PollData::Timeout),
1 => match fds.revents {
POLL_IN => Ok(PollData::EventHappened(event_type.read(file).unwrap())),
POLL_IN => Ok(PollData::EventHappened(event_type.read_sync(file).unwrap())),
events => Ok(PollData::SomethingElseHappened(events)),
},
result => Err(result),
}
}
None => Ok(PollData::EventHappened(event_type.read(file).unwrap())),
None => Ok(PollData::EventHappened(event_type.read_sync(file).unwrap())),
}
}

pub async fn wait_event_async<File: AsRawFd + async_std::io::Read + Unpin>(
file: &mut File,
event_type: EcMkbpEventType,
) -> io::Result<EcMkbpEvent> {
let mask = 1 << event_type as u8;
unsafe {
ioctl(
file.as_raw_fd(),
request_code_none!(CROS_EC_IOC_MAGIC, 2),
mask,
)
};
event_type.read_async(file).await
}
11 changes: 11 additions & 0 deletions ectool/src/fp_get_encryption_status_command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use std::fs::File;
use crosec::commands::fp_get_encryption_status::{EcResponseFpGetEncryptionStatus, fp_get_encryption_status};
use crosec::CROS_FP_PATH;

pub fn fp_get_encryption_status_command() -> color_eyre::Result<()> {
let mut file = File::open(CROS_FP_PATH)?;
let EcResponseFpGetEncryptionStatus { status, valid_flags } = fp_get_encryption_status(&mut file)?;
println!("FPMCU encryption status: {status:#b}");
println!("Valid flags: {valid_flags:#b}");
Ok(())
}
8 changes: 6 additions & 2 deletions ectool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use crosec::commands::fp_mode::{fp_mode, FpMode};
use crosec::commands::fp_set_seed::{fp_set_seed, FP_CONTEXT_TPM_BYTES};
use crosec::commands::fp_stats::fp_stats;
use crosec::commands::get_protocol_info::get_protocol_info;
use crosec::wait_event::{event::EcMkbpEventType, wait_event};
use crosec::wait_event::{event::EcMkbpEventType, wait_event_sync};
use fp_download_subcommand::{fp_download_subcommand, FpDownloadSubcommand};
use fp_upload_template_command::fp_upload_template_command;
use num_traits::cast::FromPrimitive;
Expand All @@ -29,11 +29,13 @@ use crosec::{
CROS_EC_PATH, CROS_FP_PATH, EC_FAN_SPEED_ENTRIES, EC_FAN_SPEED_NOT_PRESENT,
EC_FAN_SPEED_STALLED, EC_MEM_MAP_FAN,
};
use crate::fp_get_encryption_status_command::fp_get_encryption_status_command;

mod charge_control_subcommand;
mod check_seed;
mod fp_download_subcommand;
mod fp_upload_template_command;
mod fp_get_encryption_status_command;

#[derive(Parser)]
#[command(version, about)]
Expand Down Expand Up @@ -120,6 +122,7 @@ enum Commands {
},
/// Uploads template from stdin
FpUploadTemplate,
FpGetEncryptionStatus,
}

fn main() -> Result<()> {
Expand Down Expand Up @@ -263,11 +266,12 @@ fn main() -> Result<()> {
timeout,
} => {
let mut file = File::open(device.unwrap_or_default().get_path())?;
let result = wait_event(&mut file, event_type, timeout).unwrap();
let result = wait_event_sync(&mut file, event_type, timeout).unwrap();
println!("{result:#?}");
}
Commands::FpDownload { command } => fp_download_subcommand(command)?,
Commands::FpUploadTemplate => fp_upload_template_command()?,
Commands::FpGetEncryptionStatus => fp_get_encryption_status_command()?,
}

Ok(())
Expand Down

0 comments on commit a2d5504

Please sign in to comment.