diff --git a/Cargo.lock b/Cargo.lock index eff80f59..5239a7c3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -205,7 +205,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -220,12 +220,6 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "core-foundation" version = "0.6.4" @@ -288,7 +282,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.114", + "syn", ] [[package]] @@ -299,20 +293,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn 2.0.114", -] - -[[package]] -name = "derive_more" -version = "0.99.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.114", + "syn", ] [[package]] @@ -333,7 +314,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -428,7 +409,7 @@ dependencies = [ "smbios-lib", "spin 0.10.0", "uefi", - "uefi-services", + "uefi-raw", "windows", "windows-version", "winreg", @@ -453,7 +434,6 @@ dependencies = [ "framework_lib", "log", "uefi", - "uefi-services", ] [[package]] @@ -512,7 +492,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -808,7 +788,7 @@ checksum = "e0c84ee7f197eca9a86c6fd6cb771e55eb991632f15f2bc3ca6ec838929e6e78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1008,7 +988,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1150,22 +1130,22 @@ dependencies = [ [[package]] name = "ptr_meta" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcada80daa06c42ed5f48c9a043865edea5dc44cbf9ac009fda3b89526e28607" +checksum = "0b9a0cf95a1196af61d4f1cbdab967179516d9a4a4312af1f31948f8f6224a79" dependencies = [ "ptr_meta_derive", ] [[package]] name = "ptr_meta_derive" -version = "0.2.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca9224df2e20e7c5548aeb5f110a0f3b77ef05f8585139b7148b59056168ed2" +checksum = "7347867d0a7e1208d93b46767be83e2b8f978c3dad35f775ac8d8847551d6fe1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] @@ -1285,7 +1265,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1394,17 +1374,6 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.114" @@ -1424,7 +1393,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1453,7 +1422,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1464,7 +1433,7 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1533,38 +1502,47 @@ dependencies = [ [[package]] name = "uefi" -version = "0.20.0" -source = "git+https://github.com/FrameworkComputer/uefi-rs?branch=merged#95165e1adde99da7a460320538d908af8b55f87f" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe9058b73ee2b6559524af9e33199c13b2485ddbf3ad1181b68051cdc50c17" dependencies = [ - "bitflags 1.3.2", - "derive_more", + "bitflags 2.10.0", + "cfg-if", "log", "ptr_meta", "ucs2", "uefi-macros", + "uefi-raw", + "uguid", ] [[package]] name = "uefi-macros" -version = "0.11.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0caeb0e7b31b9f1f347e541106be10aa8c66c76fa722a3298a4cd21433fabd4" +checksum = "4687412b5ac74d245d5bfb1733ede50c31be19bf8a4b6a967a29b451bab49e67" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn", ] [[package]] -name = "uefi-services" -version = "0.17.0" -source = "git+https://github.com/FrameworkComputer/uefi-rs?branch=merged#95165e1adde99da7a460320538d908af8b55f87f" +name = "uefi-raw" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f64fe59e11af447d12fd60a403c74106eb104309f34b4c6dbce6e927d97da9d" dependencies = [ - "cfg-if", - "log", - "uefi", + "bitflags 2.10.0", + "uguid", ] +[[package]] +name = "uguid" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8352f8c05e47892e7eaf13b34abd76a7f4aeaf817b716e88789381927f199c" + [[package]] name = "unicode-ident" version = "1.0.22" @@ -1674,7 +1652,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.114", + "syn", "wasm-bindgen-shared", ] @@ -1762,7 +1740,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -1773,7 +1751,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -2032,7 +2010,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] @@ -2060,7 +2038,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", "synstructure", ] @@ -2081,7 +2059,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", "synstructure", ] @@ -2115,11 +2093,11 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.114", + "syn", ] [[package]] name = "zmij" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea" +checksum = "94f63c051f4fe3c1509da62131a678643c5b6fbdc9273b2b79d4378ebda003d2" diff --git a/Cargo.toml b/Cargo.toml index d8108e1b..66801a46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,5 @@ default-members = [ "framework_tool", ] -[patch.crates-io] -uefi = { git = "https://github.com/FrameworkComputer/uefi-rs", branch = "merged" } -uefi-services = { git = "https://github.com/FrameworkComputer/uefi-rs", branch = "merged" } - [profile.release] lto = true diff --git a/framework_lib/Cargo.toml b/framework_lib/Cargo.toml index 0ec2e522..46286c71 100644 --- a/framework_lib/Cargo.toml +++ b/framework_lib/Cargo.toml @@ -37,8 +37,8 @@ rusb = { version = "0.9.4", optional = true } guid-create = { version = "0.5.0", default-features = false } [target.'cfg(target_os = "uefi")'.dependencies] -uefi = { version = "0.20", features = ["alloc"] } -uefi-services = "0.17" +uefi = { version = "0.36.1", features = ["alloc", "global_allocator", "panic_handler", "logger"] } +uefi-raw = "0.13" plain = "0.2.3" redox_hwio = { git = "https://github.com/FrameworkComputer/rust-hwio", branch = "freebsd", default-features = false } smbios-lib = { git = "https://github.com/FrameworkComputer/smbios-lib.git", branch = "no-std", default-features = false } diff --git a/framework_lib/src/capsule.rs b/framework_lib/src/capsule.rs index 8ded6493..d5eac38d 100644 --- a/framework_lib/src/capsule.rs +++ b/framework_lib/src/capsule.rs @@ -183,7 +183,7 @@ pub fn dump_winux_image(data: &[u8], header: &DisplayCapsule, filename: &str) { } #[cfg(feature = "uefi")] { - let ret = crate::uefi::fs::shell_write_file(filename, image); + let ret = crate::fw_uefi::fs::shell_write_file(filename, image); if let Err(err) = ret { println!("Failed to dump winux image: {:?}", err); } diff --git a/framework_lib/src/chromium_ec/mod.rs b/framework_lib/src/chromium_ec/mod.rs index 87badf52..94b8b93a 100644 --- a/framework_lib/src/chromium_ec/mod.rs +++ b/framework_lib/src/chromium_ec/mod.rs @@ -9,11 +9,11 @@ //! - `windows` - It uses [DHowett's Windows driver](https://github.com/DHowett/FrameworkWindowsUtils) use crate::ec_binary; +#[cfg(feature = "uefi")] +use crate::fw_uefi::shell_get_execution_break_flag; use crate::os_specific; use crate::power; use crate::smbios; -#[cfg(feature = "uefi")] -use crate::uefi::shell_get_execution_break_flag; use crate::util::{self, Platform}; use no_std_compat::time::Duration; diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs index f99ee257..3f78e508 100644 --- a/framework_lib/src/commandline/mod.rs +++ b/framework_lib/src/commandline/mod.rs @@ -48,6 +48,8 @@ use crate::chromium_ec::{EcError, EcResult}; use crate::csme; use crate::ec_binary; use crate::esrt; +#[cfg(feature = "uefi")] +use crate::fw_uefi::enable_page_break; #[cfg(feature = "rusb")] use crate::inputmodule::check_inputmodule_version; #[cfg(target_os = "linux")] @@ -62,8 +64,6 @@ use crate::smbios::{dmidecode_string_val, get_smbios, is_framework}; use crate::touchpad::print_touchpad_fw_ver; #[cfg(feature = "hidapi")] use crate::touchscreen; -#[cfg(feature = "uefi")] -use crate::uefi::enable_page_break; #[cfg(feature = "rusb")] use crate::usbhub::check_usbhub_version; use crate::util::{self, Config, Platform, PlatformFamily}; @@ -1022,7 +1022,7 @@ fn print_esrt() { fn flash_ec(ec: &CrosEc, ec_bin_path: &str, flash_type: EcFlashType, dry_run: bool) { #[cfg(feature = "uefi")] - let data = crate::uefi::fs::shell_read_file(ec_bin_path); + let data = crate::fw_uefi::fs::shell_read_file(ec_bin_path); #[cfg(not(feature = "uefi"))] let data: Option> = { match fs::read(ec_bin_path) { @@ -1057,7 +1057,7 @@ fn dump_ec_flash(ec: &CrosEc, dump_path: &str) { } #[cfg(feature = "uefi")] { - let ret = crate::uefi::fs::shell_write_file(dump_path, &flash_bin); + let ret = crate::fw_uefi::fs::shell_write_file(dump_path, &flash_bin); if ret.is_err() { println!("Failed to dump EC FW image."); } @@ -1122,7 +1122,7 @@ fn dump_dgpu_eeprom(ec: &CrosEc, dump_path: &str) { } #[cfg(feature = "uefi")] { - if let Err(err) = crate::uefi::fs::shell_write_file(dump_path, &flash_bin) { + if let Err(err) = crate::fw_uefi::fs::shell_write_file(dump_path, &flash_bin) { error!("Failed to dump EC FW image: {:?}", err); return; } @@ -1579,7 +1579,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { // raw_command(&args[1..]); } else if let Some(pd_bin_path) = &args.pd_bin { #[cfg(feature = "uefi")] - let data: Option> = crate::uefi::fs::shell_read_file(pd_bin_path); + let data: Option> = crate::fw_uefi::fs::shell_read_file(pd_bin_path); #[cfg(not(feature = "uefi"))] let data = match fs::read(pd_bin_path) { Ok(data) => Some(data), @@ -1598,7 +1598,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } } else if let Some(ec_bin_path) = &args.ec_bin { #[cfg(feature = "uefi")] - let data: Option> = crate::uefi::fs::shell_read_file(ec_bin_path); + let data: Option> = crate::fw_uefi::fs::shell_read_file(ec_bin_path); #[cfg(not(feature = "uefi"))] let data = match fs::read(ec_bin_path) { Ok(data) => Some(data), @@ -1617,7 +1617,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } } else if let Some(capsule_path) = &args.capsule { #[cfg(feature = "uefi")] - let data: Option> = crate::uefi::fs::shell_read_file(capsule_path); + let data: Option> = crate::fw_uefi::fs::shell_read_file(capsule_path); #[cfg(not(feature = "uefi"))] let data = match fs::read(capsule_path) { Ok(data) => Some(data), @@ -1646,7 +1646,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } } else if let Some(capsule_path) = &args.h2o_capsule { #[cfg(feature = "uefi")] - let data = crate::uefi::fs::shell_read_file(capsule_path); + let data = crate::fw_uefi::fs::shell_read_file(capsule_path); #[cfg(not(feature = "uefi"))] let data = match fs::read(capsule_path) { Ok(data) => Some(data), @@ -1699,7 +1699,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { } else if let Some(hash_file) = &args.hash { println!("Hashing file: {}", hash_file); #[cfg(feature = "uefi")] - let data = crate::uefi::fs::shell_read_file(hash_file); + let data = crate::fw_uefi::fs::shell_read_file(hash_file); #[cfg(not(feature = "uefi"))] let data = match fs::read(hash_file) { Ok(data) => Some(data), @@ -1728,7 +1728,7 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 { Some(PlatformFamily::Framework16) | None ) { #[cfg(feature = "uefi")] - let data: Option> = crate::uefi::fs::shell_read_file(gpu_descriptor_file); + let data: Option> = crate::fw_uefi::fs::shell_read_file(gpu_descriptor_file); #[cfg(not(feature = "uefi"))] let data = match fs::read(gpu_descriptor_file) { Ok(data) => Some(data), diff --git a/framework_lib/src/commandline/uefi.rs b/framework_lib/src/commandline/uefi.rs index 58490c71..19a8c019 100644 --- a/framework_lib/src/commandline/uefi.rs +++ b/framework_lib/src/commandline/uefi.rs @@ -4,9 +4,8 @@ use alloc::vec::Vec; #[allow(unused_imports)] use log::{debug, error, info, trace}; -use uefi::prelude::BootServices; -use uefi::proto::shell_params::*; -use uefi::Handle; +use uefi::boot; +use uefi::proto::shell_params::ShellParameters; use crate::chromium_ec::commands::SetGpuSerialMagic; use crate::chromium_ec::{CrosEcDriverType, HardwareDeviceType}; @@ -15,13 +14,19 @@ use crate::commandline::{Cli, LogLevel}; use super::{ConsoleArg, FpBrightnessArg, InputDeckModeArg, RebootEcArg, TabletModeArg}; /// Get commandline arguments from UEFI environment -pub fn get_args(bs: &BootServices, image_handle: Handle) -> Vec { - if let Ok(shell_params) = bs.open_protocol_exclusive::(image_handle) { - shell_params.get_args() - } else { - // No protocol found if the application wasn't executed by the shell - vec![] - } +pub fn get_args() -> Vec { + let shell_params = uefi::boot::open_protocol_exclusive::(boot::image_handle()); + let shell_params = match shell_params { + Ok(s) => s, + Err(e) => { + error!("Failed to get ShellParameters protocol"); + // TODO: Return result + // return e.status(); + return vec![]; + } + }; + let args: Vec = shell_params.args().map(|x| x.to_string()).collect(); + args } pub fn parse(args: &[String]) -> Cli { diff --git a/framework_lib/src/esrt/mod.rs b/framework_lib/src/esrt/mod.rs index 0ccc8a39..f39f49e5 100644 --- a/framework_lib/src/esrt/mod.rs +++ b/framework_lib/src/esrt/mod.rs @@ -38,6 +38,11 @@ use std::os::fd::AsRawFd; #[cfg(target_os = "freebsd")] use std::os::unix::fs::OpenOptionsExt; +#[cfg(feature = "uefi")] +use uefi::system::with_config_table; +#[cfg(feature = "uefi")] +use uefi::table::cfg::ConfigTableEntry; + pub const TGL_BIOS_GUID: GUID = GUID::build_from_components( 0xb3bdb2e4, 0xc5cb, @@ -511,22 +516,16 @@ pub const SYSTEM_RESOURCE_TABLE_GUID_BYTES: [u8; 16] = [ #[cfg(feature = "uefi")] pub fn get_esrt() -> Option { - let st = unsafe { uefi_services::system_table().as_ref() }; - let config_tables = st.config_table(); - - for table in config_tables { - // TODO: Why aren't they the same type? - //debug!("Table: {:?}", table); - let table_guid: CGuid = unsafe { std::mem::transmute(table.guid) }; - let table_guid = GUID::from(table_guid); - match table_guid { - SYSTEM_RESOURCE_TABLE_GUID => unsafe { - return esrt_from_buf(table.address as *const u8); - }, - _ => {} + with_config_table(|slice| { + for i in slice { + if i.guid == ConfigTableEntry::ESRT_GUID { + unsafe { + return esrt_from_buf(i.address as *const u8); + } + } } - } - None + None + }) } /// Parse the ESRT table buffer diff --git a/framework_lib/src/fw_uefi/fs.rs b/framework_lib/src/fw_uefi/fs.rs new file mode 100644 index 00000000..7b397c54 --- /dev/null +++ b/framework_lib/src/fw_uefi/fs.rs @@ -0,0 +1,149 @@ +use alloc::vec; +use alloc::vec::Vec; +use uefi::prelude::*; +use uefi::proto::shell::Shell; +use uefi_raw::protocol::shell::ShellProtocol; +//use uefi::proto::shell::FileOpenMode; +use core::ffi::c_void; +use core::mem::MaybeUninit; +use core::ptr::NonNull; +use uefi::Result; + +#[repr(transparent)] +#[derive(Clone, Copy, Debug)] +pub struct ShellFileHandle(NonNull); + +const FILE_MODE_READ: u64 = 0x0000000000000001; +const FILE_MODE_WRITE: u64 = 0x0000000000000002; +const FILE_MODE_CREATE: u64 = 0x8000000000000000; + +pub fn wstr(string: &str) -> Vec { + let mut wstring = vec![]; + + for c in string.chars() { + wstring.push(c as u16); + } + wstring.push(0); + + wstring +} + +pub fn shell_read_file(path: &str) -> Option> { + let handle = boot::get_handle_for_protocol::().expect("No Shell handles"); + let mut shell = + boot::open_protocol_exclusive::(handle).expect("Failed to open Shell protocol"); + let shell = unsafe { + let proto: &ShellProtocol = std::mem::transmute(shell.get().unwrap()); + proto + }; + + println!("Opened shell protocol"); + + debug_assert_eq!(shell.major_version, 2); + debug_assert_eq!(shell.minor_version, 2); + + println!( + "Shell protocol ver: {}.{}", + shell.major_version, shell.minor_version + ); + + unsafe { + let c_path = wstr(path); + let mut mode = FILE_MODE_READ; + let mut handle: MaybeUninit<*const c_void> = MaybeUninit::zeroed(); + (shell.open_file_by_name)(c_path.as_ptr(), handle.as_mut_ptr().cast(), mode); + + println!("Opened file"); + + let file_handle = handle.assume_init(); + + let mut file_size = 0; + println!("get_file_size"); + let res = (shell.get_file_size)(file_handle, &mut file_size); + // let file_size = res.unwrap(); + + let mut buffer: Vec = vec![0; file_size as usize]; + let mut read_size = file_size as usize; + println!("read_file {} bytes", file_size); + (shell.read_file)( + file_handle, + &mut read_size, + buffer.as_mut_ptr() as *mut c_void, + ); + + println!("close_file"); + + // TODO: Make it auto-close using Rust destructors + (shell.close_file)(file_handle); + + println!("Done"); + + Some(buffer) + } +} + +pub fn shell_write_file(path: &str, data: &[u8]) -> Result { + let handle = boot::get_handle_for_protocol::().expect("No Shell handles"); + let mut shell = + boot::open_protocol_exclusive::(handle).expect("Failed to open Shell protocol"); + let shell = unsafe { + let proto: &ShellProtocol = std::mem::transmute(shell.get().unwrap()); + proto + }; + + debug_assert_eq!(shell.major_version, 2); + debug_assert_eq!(shell.minor_version, 2); + + unsafe { + // let mode = FileOpenMode::Read as u64 + FileOpenMode::Write as u64 + FileOpenMode::Create as u64; + let mode = FILE_MODE_READ + FILE_MODE_WRITE + FILE_MODE_CREATE; + let c_path = wstr(path); + let mut handle: MaybeUninit<*const c_void> = MaybeUninit::zeroed(); + (shell.open_file_by_name)(c_path.as_ptr(), handle.as_mut_ptr().cast(), mode); + let file_handle = handle.assume_init(); + + //// TODO: Free file_info buffer + //let file_info = (shell.0.GetFileInfo)(file_handle); + //if file_info.is_null() { + // println!("Failed to get file info"); + // return ret; + //} + + //// Not sure if it's useful to set FileInfo + ////let mut file_info = unsafe { + //// &mut *(file_info as *mut FileInfo) + ////}; + ////println!("file_info.Size: {}", file_info.Size); + + ////if file_info.Size != 0 { + //// file_info.Size = 0; + //// let ret = (shell.0.SetFileInfo)(file_handle, file_info); + //// if ret.0 != 0 { + //// println!("Failed to set file info"); + //// return ret; + //// } + ////} + + //let mut buffer_size = data.len() as usize; + //let ret = (shell.0.WriteFile)(file_handle, &mut buffer_size, data.as_ptr()); + //if ret.0 != 0 { + // println!("Failed to write file"); + // return ret; + //} + //if buffer_size != data.len() { + // println!( + // "Failed to write whole buffer. Instead of {} wrote {} bytes.", + // data.len(), + // buffer_size + // ); + // return Status(1); + //} + + let mut read_size = data.len(); + (shell.write_file)(file_handle, &mut read_size, data.as_ptr() as *mut c_void); + + (shell.close_file)(file_handle); + + Status::SUCCESS.to_result() + } +} diff --git a/framework_lib/src/fw_uefi/mod.rs b/framework_lib/src/fw_uefi/mod.rs new file mode 100644 index 00000000..7b70608e --- /dev/null +++ b/framework_lib/src/fw_uefi/mod.rs @@ -0,0 +1,116 @@ +use alloc::vec::Vec; +use core::slice; +use uefi::system::with_config_table; +use uefi::table::cfg::ConfigTableEntry; + +#[allow(unused_imports)] +use log::{debug, error, info, trace}; +use uefi::boot; +use uefi::proto::shell::Shell; +use uefi_raw::protocol::shell::ShellProtocol; + +pub mod fs; + +/// Returns true when the execution break was requested, false otherwise +pub fn shell_get_execution_break_flag() -> bool { + let handle = boot::get_handle_for_protocol::().expect("No Shell handles"); + let shell = + boot::open_protocol_exclusive::(handle).expect("Failed to open Shell protocol"); + unsafe { + let proto: &ShellProtocol = std::mem::transmute(shell.get().unwrap()); + (proto.get_page_break)().into() + } +} + +/// Enable pagination in UEFI shell +/// +/// Pagination is handled by the UEFI shell environment automatically, whenever +/// the application prints more than fits on the screen. +pub fn enable_page_break() { + let handle = boot::get_handle_for_protocol::().expect("No Shell handles"); + let shell = + boot::open_protocol_exclusive::(handle).expect("Failed to open Shell protocol"); + unsafe { + let proto: &ShellProtocol = std::mem::transmute(shell.get().unwrap()); + (proto.enable_page_break)() + } +} + +#[repr(C, packed)] +pub struct Smbios { + pub anchor: [u8; 4], + pub checksum: u8, + pub length: u8, + pub major_version: u8, + pub minor_version: u8, + pub max_structure_size: u16, + pub revision: u8, + pub formatted: [u8; 5], + pub inter_anchor: [u8; 5], + pub inter_checksum: u8, + pub table_length: u16, + pub table_address: u32, + pub structure_count: u16, + pub bcd_revision: u8, +} + +impl Smbios { + pub fn checksum_valid(&self) -> bool { + let mut sum: u8 = self.anchor.iter().sum::(); + sum += self.checksum; + sum += self.length; + sum += self.major_version; + sum += self.minor_version; + sum += self.max_structure_size as u8; + sum += self.revision; + sum += self.formatted.iter().sum::(); + sum == 0 + } +} + +pub struct Smbios3 { + pub anchor: [u8; 5], + pub checksum: u8, + pub length: u8, + pub major_version: u8, + pub minor_version: u8, + pub docrev: u8, + pub revision: u8, + _reserved: u8, + pub table_length: u32, + pub table_address: u64, +} + +pub fn smbios_data() -> Option> { + with_config_table(|slice| { + for i in slice { + let table_data = match i.guid { + ConfigTableEntry::SMBIOS3_GUID => unsafe { + let smbios = &*(i.address as *const Smbios3); + debug!("SMBIOS3 valid: {:?}", smbios.anchor == *b"_SM3_"); + Some(slice::from_raw_parts( + smbios.table_address as *const u8, + smbios.table_length as usize, + )) + }, + ConfigTableEntry::SMBIOS_GUID => unsafe { + let smbios = &*(i.address as *const Smbios); + debug!("SMBIOS valid: {:?}", smbios.checksum_valid()); + Some(slice::from_raw_parts( + smbios.table_address as *const u8, + smbios.table_length as usize, + )) + }, + _ => None, + }; + + if let Some(data) = table_data { + // Return directly here because there is only ever the old config + // table or the new V3 config table. Never both. + return Some(data.to_vec()); + } + } + + None + }) +} diff --git a/framework_lib/src/lib.rs b/framework_lib/src/lib.rs index 1e76e724..92764319 100644 --- a/framework_lib/src/lib.rs +++ b/framework_lib/src/lib.rs @@ -32,7 +32,7 @@ pub mod usbhub; #[cfg(feature = "uefi")] #[macro_use] -extern crate uefi_services; +extern crate uefi; pub mod capsule; pub mod capsule_content; @@ -42,12 +42,12 @@ pub mod commandline; pub mod csme; pub mod ec_binary; pub mod esrt; +#[cfg(feature = "uefi")] +pub mod fw_uefi; mod os_specific; pub mod parade_retimer; pub mod power; pub mod smbios; -#[cfg(feature = "uefi")] -pub mod uefi; mod util; pub mod built_info { diff --git a/framework_lib/src/os_specific.rs b/framework_lib/src/os_specific.rs index b77deb87..3566e4c8 100644 --- a/framework_lib/src/os_specific.rs +++ b/framework_lib/src/os_specific.rs @@ -1,7 +1,8 @@ //! Helper functions that need OS/platform specific implementations +use core::time::Duration; #[cfg(not(feature = "uefi"))] -use std::{thread, time}; +use std::thread; #[cfg(feature = "uefi")] use alloc::string::{String, ToString}; @@ -38,17 +39,15 @@ pub fn get_os_version() -> String { /// Sleep a number of microseconds pub fn sleep(micros: u64) { + let duration = Duration::from_micros(micros); #[cfg(not(feature = "uefi"))] { - let duration = time::Duration::from_micros(micros); thread::sleep(duration); } #[cfg(feature = "uefi")] { // TODO: It's not recommended to use this for sleep more than 10ms // Should use a one-shot timer event - let st = unsafe { uefi_services::system_table().as_ref() }; - let bs = st.boot_services(); - bs.stall(micros as usize); + uefi::boot::stall(duration); } } diff --git a/framework_lib/src/smbios.rs b/framework_lib/src/smbios.rs index aaac1cf5..76ce335e 100644 --- a/framework_lib/src/smbios.rs +++ b/framework_lib/src/smbios.rs @@ -193,7 +193,7 @@ pub fn get_smbios() -> Option { #[cfg(feature = "uefi")] pub fn get_smbios() -> Option { trace!("get_smbios() uefi entry"); - let data = crate::uefi::smbios_data().unwrap(); + let data = crate::fw_uefi::smbios_data().unwrap(); let version = None; // TODO: Maybe add the version here let smbios = SMBiosData::from_vec_and_version(data, version); Some(smbios) diff --git a/framework_lib/src/uefi/fs.rs b/framework_lib/src/uefi/fs.rs deleted file mode 100644 index a5e2ca96..00000000 --- a/framework_lib/src/uefi/fs.rs +++ /dev/null @@ -1,132 +0,0 @@ -use alloc::vec; -use alloc::vec::Vec; -use uefi::prelude::*; -use uefi::proto::shell::FileOpenMode; -use uefi::Result; - -use super::find_shell_handle; - -pub fn wstr(string: &str) -> Vec { - let mut wstring = vec![]; - - for c in string.chars() { - wstring.push(c as u16); - } - wstring.push(0); - - wstring -} - -pub fn shell_read_file(path: &str) -> Option> { - let shell = if let Some(shell) = find_shell_handle() { - shell - } else { - println!("Failed to open Shell Protocol"); - return None; - }; - - debug_assert_eq!(shell.major_version, 2); - debug_assert_eq!(shell.minor_version, 2); - - let c_path = wstr(path); - let handle = shell.open_file_by_name(c_path.as_slice(), FileOpenMode::Read as u64); - - let handle = if let Ok(handle) = handle { - handle - } else { - println!("Failed to open file: {:?}", handle); - return None; - }; - - let handle = if let Some(handle) = handle { - handle - } else { - println!("Failed to open file: {:?}", handle); - return None; - }; - let file_handle = handle; - - let res = shell.get_file_size(file_handle); - let file_size = res.unwrap(); - - let mut buffer: Vec = vec![0; file_size as usize]; - let res = shell.read_file(file_handle, &mut buffer); - res.unwrap(); - - // TODO: Make it auto-close using Rust destructors - shell.close_file(file_handle).unwrap(); - - Some(buffer) -} - -pub fn shell_write_file(path: &str, data: &[u8]) -> Result { - let shell = if let Some(shell) = find_shell_handle() { - shell - } else { - println!("Failed to open Shell Protocol"); - return Status::LOAD_ERROR.into(); - }; - - debug_assert_eq!(shell.major_version, 2); - debug_assert_eq!(shell.minor_version, 2); - - let mode = FileOpenMode::Read as u64 + FileOpenMode::Write as u64 + FileOpenMode::Create as u64; - let c_path = wstr(path); - let handle = shell.open_file_by_name(c_path.as_slice(), mode); - let handle = if let Ok(handle) = handle { - handle - } else { - println!("Failed to open file: {:?}", handle); - return Status::LOAD_ERROR.into(); - }; - let handle = if let Some(handle) = handle { - handle - } else { - println!("Failed to open file: {:?}", handle); - return Status::LOAD_ERROR.into(); - }; - let file_handle = handle; - - //// TODO: Free file_info buffer - //let file_info = (shell.0.GetFileInfo)(file_handle); - //if file_info.is_null() { - // println!("Failed to get file info"); - // return ret; - //} - - //// Not sure if it's useful to set FileInfo - ////let mut file_info = unsafe { - //// &mut *(file_info as *mut FileInfo) - ////}; - ////println!("file_info.Size: {}", file_info.Size); - - ////if file_info.Size != 0 { - //// file_info.Size = 0; - //// let ret = (shell.0.SetFileInfo)(file_handle, file_info); - //// if ret.0 != 0 { - //// println!("Failed to set file info"); - //// return ret; - //// } - ////} - - //let mut buffer_size = data.len() as usize; - //let ret = (shell.0.WriteFile)(file_handle, &mut buffer_size, data.as_ptr()); - //if ret.0 != 0 { - // println!("Failed to write file"); - // return ret; - //} - //if buffer_size != data.len() { - // println!( - // "Failed to write whole buffer. Instead of {} wrote {} bytes.", - // data.len(), - // buffer_size - // ); - // return Status(1); - //} - - shell.write_file(file_handle, data).unwrap(); - - shell.close_file(file_handle).unwrap(); - - Status::SUCCESS.into() -} diff --git a/framework_lib/src/uefi/mod.rs b/framework_lib/src/uefi/mod.rs deleted file mode 100644 index 71d85b44..00000000 --- a/framework_lib/src/uefi/mod.rs +++ /dev/null @@ -1,179 +0,0 @@ -use alloc::vec::Vec; -use core::slice; -use uefi::table::boot::{OpenProtocolAttributes, OpenProtocolParams, ScopedProtocol, SearchType}; - -#[allow(unused_imports)] -use log::{debug, error, info, trace}; -use uefi::proto::shell::Shell; -use uefi::table::cfg::{SMBIOS3_GUID, SMBIOS_GUID}; -use uefi::table::{Boot, SystemTable}; -use uefi::Identify; - -pub mod fs; - -pub fn get_system_table() -> &'static SystemTable { - unsafe { uefi_services::system_table().as_ref() } -} - -fn find_shell_handle() -> Option> { - let st = unsafe { uefi_services::system_table().as_ref() }; - let boot_services = st.boot_services(); - let shell_handles = boot_services.locate_handle_buffer(SearchType::ByProtocol(&Shell::GUID)); - if let Ok(sh_buf) = shell_handles { - for handle in &*sh_buf { - return Some(unsafe { - boot_services - .open_protocol::( - OpenProtocolParams { - handle: *handle, - agent: boot_services.image_handle(), - controller: None, - }, - OpenProtocolAttributes::GetProtocol, - ) - .expect("Failed to open Shell handle") - }); - } - } else { - panic!("No shell handle found!"); - } - None -} - -/// Returns true when the execution break was requested, false otherwise -pub fn shell_get_execution_break_flag() -> bool { - let st = unsafe { uefi_services::system_table().as_ref() }; - let boot_services = st.boot_services(); - let shell_handles = boot_services.locate_handle_buffer(SearchType::ByProtocol(&Shell::GUID)); - if let Ok(sh_buf) = shell_handles { - for handle in &*sh_buf { - let shell_handle = unsafe { - boot_services - .open_protocol::( - OpenProtocolParams { - handle: *handle, - agent: boot_services.image_handle(), - controller: None, - }, - OpenProtocolAttributes::GetProtocol, - ) - .expect("Failed to open Shell handle") - }; - - let event = unsafe { shell_handle.execution_break.unsafe_clone() }; - return boot_services.check_event(event).unwrap(); - } - return false; - } else { - panic!("No shell handle found!"); - } -} - -/// Enable pagination in UEFI shell -/// -/// Pagination is handled by the UEFI shell environment automatically, whenever -/// the application prints more than fits on the screen. -pub fn enable_page_break() { - let st = unsafe { uefi_services::system_table().as_ref() }; - let boot_services = st.boot_services(); - let shell_handles = boot_services.locate_handle_buffer(SearchType::ByProtocol(&Shell::GUID)); - if let Ok(sh_buf) = shell_handles { - for handle in &*sh_buf { - //trace!("Calling enable_page_break"); - let shell_handle = unsafe { - boot_services - .open_protocol::( - OpenProtocolParams { - handle: *handle, - agent: boot_services.image_handle(), - controller: None, - }, - OpenProtocolAttributes::GetProtocol, - ) - .expect("Failed to open Shell handle") - }; - shell_handle.enable_page_break(); - } - } else { - panic!("No shell handle found!"); - } -} - -#[repr(C, packed)] -pub struct Smbios { - pub anchor: [u8; 4], - pub checksum: u8, - pub length: u8, - pub major_version: u8, - pub minor_version: u8, - pub max_structure_size: u16, - pub revision: u8, - pub formatted: [u8; 5], - pub inter_anchor: [u8; 5], - pub inter_checksum: u8, - pub table_length: u16, - pub table_address: u32, - pub structure_count: u16, - pub bcd_revision: u8, -} - -impl Smbios { - pub fn checksum_valid(&self) -> bool { - let mut sum: u8 = self.anchor.iter().sum::(); - sum += self.checksum; - sum += self.length; - sum += self.major_version; - sum += self.minor_version; - sum += self.max_structure_size as u8; - sum += self.revision; - sum += self.formatted.iter().sum::(); - sum == 0 - } -} - -pub struct Smbios3 { - pub anchor: [u8; 5], - pub checksum: u8, - pub length: u8, - pub major_version: u8, - pub minor_version: u8, - pub docrev: u8, - pub revision: u8, - _reserved: u8, - pub table_length: u32, - pub table_address: u64, -} - -pub fn smbios_data() -> Option> { - let st = unsafe { uefi_services::system_table().as_ref() }; - let config_tables = st.config_table(); - - for table in config_tables { - let table_data = match table.guid { - SMBIOS3_GUID => unsafe { - let smbios = &*(table.address as *const Smbios3); - debug!("SMBIOS3 valid: {:?}", smbios.anchor == *b"_SM3_"); - Some(slice::from_raw_parts( - smbios.table_address as *const u8, - smbios.table_length as usize, - )) - }, - SMBIOS_GUID => unsafe { - let smbios = &*(table.address as *const Smbios); - debug!("SMBIOS valid: {:?}", smbios.checksum_valid()); - Some(slice::from_raw_parts( - smbios.table_address as *const u8, - smbios.table_length as usize, - )) - }, - _ => None, - }; - - if let Some(data) = table_data { - // Return directly here because there is only ever the old config - // table or the new V3 config table. Never both. - return Some(data.to_vec()); - } - } - None -} diff --git a/framework_uefi/Cargo.toml b/framework_uefi/Cargo.toml index e984b1f5..0b3f2ec0 100644 --- a/framework_uefi/Cargo.toml +++ b/framework_uefi/Cargo.toml @@ -19,8 +19,7 @@ default = [ ] readonly = [ "framework_lib/readonly" ] [dependencies] -uefi = { version = "0.20", features = ["alloc"] } -uefi-services = "0.17" +uefi = { version = "0.36.1", features = ["alloc"] } log = { version = "0.4", default-features = true } [dependencies.framework_lib] diff --git a/framework_uefi/src/main.rs b/framework_uefi/src/main.rs index caeeee2e..a9e8f581 100644 --- a/framework_uefi/src/main.rs +++ b/framework_uefi/src/main.rs @@ -5,18 +5,17 @@ use log::{debug, error, info, trace}; use uefi::prelude::*; #[allow(unused_imports)] -use uefi_services::{print, println}; +use uefi::{print, println}; extern crate alloc; use framework_lib::commandline; #[entry] -fn main(image_handle: Handle, mut system_table: SystemTable) -> Status { - uefi_services::init(&mut system_table).unwrap(); - let bs = system_table.boot_services(); +fn main() -> Status { + uefi::helpers::init().unwrap(); - let args = commandline::uefi::get_args(bs, image_handle); + let args = commandline::uefi::get_args(); let args = commandline::parse(&args); if commandline::run_with_args(&args, false) == 0 { return Status::SUCCESS;