diff --git a/framework_lib/Cargo.toml b/framework_lib/Cargo.toml index 3ba39e3..9dbf370 100644 --- a/framework_lib/Cargo.toml +++ b/framework_lib/Cargo.toml @@ -70,6 +70,7 @@ features = [ "Win32_System_IO", "Win32_System_Ioctl", "Win32_System_SystemServices", + "Win32_System_WindowsProgramming", # For HID devices "Win32_Devices_DeviceAndDriverInstallation", "Win32_Devices_HumanInterfaceDevice", diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs index a26aa4b..0b5e6ab 100644 --- a/framework_lib/src/commandline/clap_std.rs +++ b/framework_lib/src/commandline/clap_std.rs @@ -240,6 +240,10 @@ struct ClapCli { #[arg(long)] ec_hib_delay: Option>, + /// Set UEFI variable (name, file path) + #[arg(long)] + set_uefi_var: Option, + /// Hash a file of arbitrary data #[arg(long)] hash: Option, @@ -450,6 +454,7 @@ pub fn parse(args: &[String]) -> Cli { console: args.console, reboot_ec: args.reboot_ec, ec_hib_delay: args.ec_hib_delay, + set_uefi_var: args.set_uefi_var, hash: args.hash.map(|x| x.into_os_string().into_string().unwrap()), driver: args.driver, pd_addrs, diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index 265f679..f6766bd 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -49,6 +49,7 @@ use crate::ec_binary; use crate::esrt; #[cfg(feature = "rusb")] use crate::inputmodule::check_inputmodule_version; +use crate::os_specific; use crate::power; use crate::smbios; use crate::smbios::ConfigDigit0; @@ -204,6 +205,7 @@ pub struct Cli { pub console: Option, pub reboot_ec: Option, pub ec_hib_delay: Option>, + pub set_uefi_var: Option, pub hash: Option, pub pd_addrs: Option<(u16, u16, u16)>, pub pd_ports: Option<(u8, u8, u8)>, @@ -1116,6 +1118,25 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { print_err(ec.set_ec_hib_delay(*delay)); } print_err(ec.get_ec_hib_delay()); + } else if let Some(filepath) = &args.set_uefi_var { + #[cfg(feature = "uefi")] + let data = crate::uefi::fs::shell_read_file(filepath); + #[cfg(not(feature = "uefi"))] + let data = match fs::read(filepath) { + Ok(data) => Some(data), + // TODO: Perhaps a more user-friendly error + Err(e) => { + println!("Error {:?}", e); + None + } + }; + if let Some(data) = data { + println!("File"); + println!(" Size: {:>20} B", data.len()); + println!(" Size: {:>20} KB", data.len() / 1024); + os_specific::get_dbx(); + //os_specific::set_dbx(&data); + } } else if args.test { println!("Self-Test"); let result = selftest(&ec); diff --git a/framework_lib/src/os_specific.rs b/framework_lib/src/os_specific.rs index 83ae2f3..ac20f7d 100644 --- a/framework_lib/src/os_specific.rs +++ b/framework_lib/src/os_specific.rs @@ -3,6 +3,9 @@ #[cfg(not(feature = "uefi"))] use std::{thread, time}; +#[cfg(windows)] +use windows::{core::*, Win32::Foundation::*, Win32::System::WindowsProgramming::*}; + /// Sleep a number of microseconds pub fn sleep(micros: u64) { #[cfg(not(feature = "uefi"))] @@ -19,3 +22,83 @@ pub fn sleep(micros: u64) { bs.stall(micros as usize); } } + +pub const EFI_VARIABLE_NON_VOLATILE: u32 = 0x00000001; +pub const EFI_VARIABLE_BOOTSERVICE_ACCESS: u32 = 0x00000002; +pub const EFI_VARIABLE_RUNTIME_ACCESS: u32 = 0x00000004; +//pub const EFI_VARIABLE_HARDWARE_ERROR_RECORD: u32 = 0x00000008; +pub const EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS: u32 = 0x00000010; +//pub const EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS: u32 = 0x00000020; +pub const EFI_VARIABLE_APPEND_WRITE: u32 = 0x00000040; + +#[cfg(windows)] +pub fn set_dbx(data: &[u8]) -> Option<()> { + let attrs = EFI_VARIABLE_NON_VOLATILE + | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS + | EFI_VARIABLE_APPEND_WRITE; + set_uefi_var("dbx", "d719b2cb-3d3a-4596-a3bc-dad00e67656f", data, attrs) +} + +#[cfg(windows)] +pub fn get_dbx() -> Option> { + get_uefi_var(w!("dbx"), w!("d719b2cb-3d3a-4596-a3bc-dad00e67656f")) +} + +#[cfg(windows)] +pub fn set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Option<()> { + let res = unsafe { + SetFirmwareEnvironmentVariableExW( + // PCWSTR + &HSTRING::from(name), + // PCWSTR + &HSTRING::from(guid), + Some(value.as_ptr() as *const core::ffi::c_void), + value.len() as u32, + attributes, + ) + }; + println!("{:?}", res); + res.ok() +} + +#[cfg(not(windows))] +pub fn set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Option<()> { + error!("Setting UEFI variable not supported on this OS"); + None +} + +#[cfg(windows)] +pub fn get_uefi_var(name: PCWSTR, guid: PCWSTR) -> Option> { + let mut data = [0; 1024]; + let mut attributes: u32 = 0; + let (res, error) = unsafe { + let res = GetFirmwareEnvironmentVariableExW( + // PCWSTR + //&HSTRING::from(name), + name, + // PCWSTR + //&HSTRING::from(guid), + guid, + Some(data.as_mut_ptr() as *mut core::ffi::c_void), + data.len() as u32, + Some(&mut attributes), + ); + let error = GetLastError(); + (res, error) + }; + + //let data = std::slice::from_raw_parts::(credentials_ptr as _, count as usize); + + println!("Res: {:?}", res); + println!("LastError: {:?}", error); + println!("Data: {:X?}", data); + Some(vec![]) +} + +#[cfg(not(windows))] +pub fn get_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Option> { + error!("Getting UEFI variable not supported on this OS"); + None +}