pub use super::common::Env; use crate::ffi::{OsStr, OsString}; use crate::io; pub fn env() -> Env { let env = uefi_env::get_all().expect("not supported on this platform"); Env::new(env) } pub fn getenv(key: &OsStr) -> Option { uefi_env::get(key) } pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> { uefi_env::set(key, val) } pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> { uefi_env::unset(key) } mod uefi_env { use crate::ffi::{OsStr, OsString}; use crate::io; use crate::os::uefi::ffi::OsStringExt; use crate::ptr::NonNull; use crate::sys::{helpers, unsupported_err}; pub(crate) fn get(key: &OsStr) -> Option { let shell = helpers::open_shell()?; let mut key_ptr = helpers::os_string_to_raw(key)?; unsafe { get_raw(shell, key_ptr.as_mut_ptr()) } } pub(crate) fn set(key: &OsStr, val: &OsStr) -> io::Result<()> { let mut key_ptr = helpers::os_string_to_raw(key) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; let mut val_ptr = helpers::os_string_to_raw(val) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; unsafe { set_raw(key_ptr.as_mut_ptr(), val_ptr.as_mut_ptr()) } } pub(crate) fn unset(key: &OsStr) -> io::Result<()> { let mut key_ptr = helpers::os_string_to_raw(key) .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid key"))?; unsafe { set_raw(key_ptr.as_mut_ptr(), crate::ptr::null_mut()) } } pub(crate) fn get_all() -> io::Result> { let shell = helpers::open_shell().ok_or(unsupported_err())?; let mut vars = Vec::new(); let val = unsafe { ((*shell.as_ptr()).get_env)(crate::ptr::null_mut()) }; if val.is_null() { return Ok(vars); } let mut start = 0; // UEFI Shell returns all keys separated by NULL. // End of string is denoted by two NULLs for i in 0.. { if unsafe { *val.add(i) } == 0 { // Two NULL signal end of string if i == start { break; } let key = OsString::from_wide(unsafe { crate::slice::from_raw_parts(val.add(start), i - start) }); // SAFETY: val.add(start) is always NULL terminated let val = unsafe { get_raw(shell, val.add(start)) } .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "invalid value"))?; vars.push((key, val)); start = i + 1; } } Ok(vars) } unsafe fn get_raw( shell: NonNull, key_ptr: *mut r_efi::efi::Char16, ) -> Option { let val = unsafe { ((*shell.as_ptr()).get_env)(key_ptr) }; helpers::os_string_from_raw(val) } unsafe fn set_raw( key_ptr: *mut r_efi::efi::Char16, val_ptr: *mut r_efi::efi::Char16, ) -> io::Result<()> { let shell = helpers::open_shell().ok_or(unsupported_err())?; let r = unsafe { ((*shell.as_ptr()).set_env)(key_ptr, val_ptr, r_efi::efi::Boolean::FALSE) }; if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } } }