From 9a282baccfda5c49b0e1cc2ac180bbde63af5d07 Mon Sep 17 00:00:00 2001
From: Daniel Schaefer <dhs@frame.work>
Date: Tue, 8 Jul 2025 19:14:16 +0800
Subject: [PATCH 1/3] try to set variable from windows

Signed-off-by: Daniel Schaefer <dhs@frame.work>
---
 framework_lib/Cargo.toml         |  1 +
 framework_lib/src/os_specific.rs | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/framework_lib/Cargo.toml b/framework_lib/Cargo.toml
index 3ba39e3d..9dbf370e 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/os_specific.rs b/framework_lib/src/os_specific.rs
index 83ae2f37..861817f5 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::System::WindowsProgramming::*};
+
 /// Sleep a number of microseconds
 pub fn sleep(micros: u64) {
     #[cfg(not(feature = "uefi"))]
@@ -19,3 +22,23 @@ pub fn sleep(micros: u64) {
         bs.stall(micros as usize);
     }
 }
+
+#[cfg(windows)]
+pub fn set_dbx() -> Option<()> {
+    set_uefi_var("dbx", "d719b2cb-3d3a-4596-a3bc-dad00e67656f", &[], 0)
+}
+
+#[cfg(windows)]
+pub fn set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Option<()> {
+    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,
+        ).ok()
+    }
+}

From 606e939c09253e8c319453325861943fb74e592f Mon Sep 17 00:00:00 2001
From: Daniel Schaefer <dhs@frame.work>
Date: Wed, 9 Jul 2025 20:44:11 +0800
Subject: [PATCH 2/3] Add --set-uefi-var

Not working yet

Signed-off-by: Daniel Schaefer <dhs@frame.work>
---
 framework_lib/src/commandline/clap_std.rs |  5 ++++
 framework_lib/src/commandline/mod.rs      | 20 +++++++++++++++
 framework_lib/src/os_specific.rs          | 31 +++++++++++++++++++----
 3 files changed, 51 insertions(+), 5 deletions(-)

diff --git a/framework_lib/src/commandline/clap_std.rs b/framework_lib/src/commandline/clap_std.rs
index a26aa4ba..0b5e6ab6 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<Option<u32>>,
 
+    /// Set UEFI variable (name, file path)
+    #[arg(long)]
+    set_uefi_var: Option<std::path::PathBuf>,
+
     /// Hash a file of arbitrary data
     #[arg(long)]
     hash: Option<std::path::PathBuf>,
@@ -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 265f6796..93851a97 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<ConsoleArg>,
     pub reboot_ec: Option<RebootEcArg>,
     pub ec_hib_delay: Option<Option<u32>>,
+    pub set_uefi_var: Option<std::path::PathBuf>,
     pub hash: Option<String>,
     pub pd_addrs: Option<(u16, u16, u16)>,
     pub pd_ports: Option<(u8, u8, u8)>,
@@ -1116,6 +1118,24 @@ 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::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 861817f5..150d0ee7 100644
--- a/framework_lib/src/os_specific.rs
+++ b/framework_lib/src/os_specific.rs
@@ -23,14 +23,27 @@ pub fn sleep(micros: u64) {
     }
 }
 
+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() -> Option<()> {
-    set_uefi_var("dbx", "d719b2cb-3d3a-4596-a3bc-dad00e67656f", &[], 0)
+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 set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Option<()> {
-    unsafe {
+    let res = unsafe {
         SetFirmwareEnvironmentVariableExW(
             // PCWSTR
             &HSTRING::from(name),
@@ -39,6 +52,14 @@ pub fn set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Op
             Some(value.as_ptr() as *const core::ffi::c_void),
             value.len() as u32,
             attributes,
-        ).ok()
-    }
+        )
+    };
+    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
 }

From b332a9b79db7a0dac403441db4e68c6796fed6f6 Mon Sep 17 00:00:00 2001
From: Daniel Schaefer <dhs@frame.work>
Date: Wed, 9 Jul 2025 20:45:58 +0800
Subject: [PATCH 3/3] wip: Also read uefi variable

Signed-off-by: Daniel Schaefer <dhs@frame.work>
---
 framework_lib/src/commandline/mod.rs |  3 +-
 framework_lib/src/os_specific.rs     | 41 +++++++++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/framework_lib/src/commandline/mod.rs b/framework_lib/src/commandline/mod.rs
index 93851a97..f6766bdd 100644
--- a/framework_lib/src/commandline/mod.rs
+++ b/framework_lib/src/commandline/mod.rs
@@ -1134,7 +1134,8 @@ pub fn run_with_args(args: &Cli, _allupdate: bool) -> i32 {
             println!("File");
             println!("  Size:       {:>20} B", data.len());
             println!("  Size:       {:>20} KB", data.len() / 1024);
-            os_specific::set_dbx(&data);
+            os_specific::get_dbx();
+            //os_specific::set_dbx(&data);
         }
     } else if args.test {
         println!("Self-Test");
diff --git a/framework_lib/src/os_specific.rs b/framework_lib/src/os_specific.rs
index 150d0ee7..ac20f7d4 100644
--- a/framework_lib/src/os_specific.rs
+++ b/framework_lib/src/os_specific.rs
@@ -4,7 +4,7 @@
 use std::{thread, time};
 
 #[cfg(windows)]
-use windows::{core::*, Win32::System::WindowsProgramming::*};
+use windows::{core::*, Win32::Foundation::*, Win32::System::WindowsProgramming::*};
 
 /// Sleep a number of microseconds
 pub fn sleep(micros: u64) {
@@ -41,6 +41,11 @@ pub fn set_dbx(data: &[u8]) -> Option<()> {
     set_uefi_var("dbx", "d719b2cb-3d3a-4596-a3bc-dad00e67656f", data, attrs)
 }
 
+#[cfg(windows)]
+pub fn get_dbx() -> Option<Vec<u8>> {
+    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 {
@@ -63,3 +68,37 @@ pub fn set_uefi_var(name: &str, guid: &str, value: &[u8], attributes: u32) -> Op
     error!("Setting UEFI variable not supported on this OS");
     None
 }
+
+#[cfg(windows)]
+pub fn get_uefi_var(name: PCWSTR, guid: PCWSTR) -> Option<Vec<u8>> {
+    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::<u8>(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<Vec<u8>> {
+    error!("Getting UEFI variable not supported on this OS");
+    None
+}
