2
0
Эх сурвалжийг харах

config(qemu): preloading UEFI keys is optional

When resetting UEFI vars, add an option to preload Secure
Boot keys (previously this was always done). This allows for
the user to load their own UEFI keys.

Also update the preloaded UEFI keys to Microsoft 2023 keys.

Resolves #7005
Resolves #7257
osy 1 долоо хоног өмнө
parent
commit
862c507a26

+ 12 - 2
Configuration/UTMQemuConfigurationQEMU.swift

@@ -76,6 +76,9 @@ struct UTMQemuConfigurationQEMU: Codable {
     /// Set to a password shared with the client. Not saved.
     /// Set to a password shared with the client. Not saved.
     var spiceServerPassword: String?
     var spiceServerPassword: String?
 
 
+    /// When resetting UEFI vars, also set up Secure Boot keys
+    var hasPreloadedSecureBootKeys: Bool = false
+
     enum CodingKeys: String, CodingKey {
     enum CodingKeys: String, CodingKey {
         case hasDebugLog = "DebugLog"
         case hasDebugLog = "DebugLog"
         case hasUefiBoot = "UEFIBoot"
         case hasUefiBoot = "UEFIBoot"
@@ -188,18 +191,25 @@ extension UTMQemuConfigurationQEMU {
             // save EFI variables
             // save EFI variables
             let resourceURL = Bundle.main.url(forResource: "qemu", withExtension: nil)!
             let resourceURL = Bundle.main.url(forResource: "qemu", withExtension: nil)!
             let templateVarsURL: URL
             let templateVarsURL: URL
+            let secure = hasPreloadedSecureBootKeys ? "-secure" : ""
             if let prefix = Self.uefiImagePrefix(forArchitecture: system.architecture, isVars: true) {
             if let prefix = Self.uefiImagePrefix(forArchitecture: system.architecture, isVars: true) {
-                templateVarsURL = resourceURL.appendingPathComponent("\(prefix)-vars.fd")
+                templateVarsURL = resourceURL.appendingPathComponent("\(prefix)\(secure)-vars.fd")
             } else {
             } else {
                 throw UTMQemuConfigurationError.uefiNotSupported
                 throw UTMQemuConfigurationError.uefiNotSupported
             }
             }
             let varsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue)
             let varsURL = dataURL.appendingPathComponent(QEMUPackageFileName.efiVariables.rawValue)
-            if !fileManager.fileExists(atPath: varsURL.path) {
+            let isExisting = fileManager.fileExists(atPath: varsURL.path)
+            if !isExisting || isUefiVariableResetRequested {
                 try await Task.detached {
                 try await Task.detached {
+                    if isExisting {
+                        try FileManager.default.removeItem(at: varsURL)
+                    }
                     try FileManager.default.copyItem(at: templateVarsURL, to: varsURL)
                     try FileManager.default.copyItem(at: templateVarsURL, to: varsURL)
                     let permissions: FilePermissions = [.ownerReadWrite, .groupRead, .otherRead]
                     let permissions: FilePermissions = [.ownerReadWrite, .groupRead, .otherRead]
                     try FileManager.default.setAttributes([.posixPermissions: permissions.rawValue], ofItemAtPath: varsURL.path)
                     try FileManager.default.setAttributes([.posixPermissions: permissions.rawValue], ofItemAtPath: varsURL.path)
                 }.value
                 }.value
+                isUefiVariableResetRequested = false
+                hasPreloadedSecureBootKeys = false
             }
             }
             efiVarsURL = varsURL
             efiVarsURL = varsURL
             existing.append(varsURL)
             existing.append(varsURL)

+ 16 - 0
Platform/Shared/VMConfigQEMUView.swift

@@ -70,6 +70,14 @@ struct VMConfigQEMUView: View {
                         .help("Should be on always unless the guest cannot boot because of this.")
                         .help("Should be on always unless the guest cannot boot because of this.")
                     Toggle("TPM 2.0 Device", isOn: $config.hasTPMDevice)
                     Toggle("TPM 2.0 Device", isOn: $config.hasTPMDevice)
                         .help("TPM can be used to protect secrets in the guest operating system. Note that the host will always be able to read these secrets and therefore no expectation of physical security is provided.")
                         .help("TPM can be used to protect secrets in the guest operating system. Note that the host will always be able to read these secrets and therefore no expectation of physical security is provided.")
+                        .onChange(of: config.hasTPMDevice) { newValue in
+                            if newValue {
+                                config.isUefiVariableResetRequested = true
+                                config.hasPreloadedSecureBootKeys = true
+                            } else {
+                                config.hasPreloadedSecureBootKeys = false
+                            }
+                        }
                     Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
                     Toggle("Use Hypervisor", isOn: $config.hasHypervisor)
                         .help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.")
                         .help("Only available if host architecture matches the target. Otherwise, TCG emulation is used.")
                         .disabled(!system.architecture.hasHypervisorSupport)
                         .disabled(!system.architecture.hasHypervisorSupport)
@@ -88,6 +96,14 @@ struct VMConfigQEMUView: View {
                     Toggle("Reset UEFI Variables", isOn: $config.isUefiVariableResetRequested)
                     Toggle("Reset UEFI Variables", isOn: $config.isUefiVariableResetRequested)
                         .help("You can use this if your boot options are corrupted or if you wish to re-enroll in the default keys for secure boot.")
                         .help("You can use this if your boot options are corrupted or if you wish to re-enroll in the default keys for secure boot.")
                         .disabled(!config.hasUefiBoot)
                         .disabled(!config.hasUefiBoot)
+                    Toggle("Preload Secure Boot Keys", isOn: $config.hasPreloadedSecureBootKeys)
+                        .help("Enable Secure Boot with Microsoft UEFI keys. This is required to Secure Boot Windows.")
+                        .disabled(!config.isUefiVariableResetRequested || !config.hasTPMDevice)
+                        .onChange(of: config.isUefiVariableResetRequested) { newValue in
+                            if !newValue {
+                                config.hasPreloadedSecureBootKeys = false
+                            }
+                        }
                 }
                 }
                 DetailedSection("QEMU Machine Properties", description: "This is appended to the -machine argument.") {
                 DetailedSection("QEMU Machine Properties", description: "This is appended to the -machine argument.") {
                     DefaultTextField("", text: $config.machinePropertyOverride.bound, prompt: "Default")
                     DefaultTextField("", text: $config.machinePropertyOverride.bound, prompt: "Default")

+ 1 - 0
Platform/Shared/VMWizardState.swift

@@ -456,6 +456,7 @@ struct AlertMessage: Identifiable {
             // only change UEFI settings for Windows or Other
             // only change UEFI settings for Windows or Other
             config.qemu.hasUefiBoot = systemBootUefi
             config.qemu.hasUefiBoot = systemBootUefi
             config.qemu.hasTPMDevice = operatingSystem == .Windows && systemBootTpm
             config.qemu.hasTPMDevice = operatingSystem == .Windows && systemBootTpm
+            config.qemu.hasPreloadedSecureBootKeys = config.qemu.hasTPMDevice
         } else if legacyHardware {
         } else if legacyHardware {
             config.qemu.hasUefiBoot = false
             config.qemu.hasUefiBoot = false
             config.qemu.hasTPMDevice = false
             config.qemu.hasTPMDevice = false

+ 3 - 9
Services/UTMQemuVirtualMachine.swift

@@ -238,15 +238,9 @@ extension UTMQemuVirtualMachine {
         guard let efiVarsURL = config.qemu.efiVarsURL else {
         guard let efiVarsURL = config.qemu.efiVarsURL else {
             return
             return
         }
         }
-        var doesVarsExist = FileManager.default.fileExists(atPath: efiVarsURL.path)
-        if config.qemu.isUefiVariableResetRequested {
-            if doesVarsExist {
-                try FileManager.default.removeItem(at: efiVarsURL)
-                doesVarsExist = false
-            }
-            config.qemu.isUefiVariableResetRequested = false
-        }
-        if !doesVarsExist {
+        if !FileManager.default.fileExists(atPath: efiVarsURL.path) {
+            config.qemu.isUefiVariableResetRequested = true
+            config.qemu.hasPreloadedSecureBootKeys = config.qemu.hasTPMDevice
             _ = try await config.qemu.saveData(to: efiVarsURL.deletingLastPathComponent(), for: config.system)
             _ = try await config.qemu.saveData(to: efiVarsURL.deletingLastPathComponent(), for: config.system)
         }
         }
     }
     }

BIN
patches/data/qemu-10.0.2-utm/pc-bios/edk2-arm-secure-vars.fd.bz2


BIN
patches/data/qemu-10.0.2-utm/pc-bios/edk2-arm-vars.fd.bz2


BIN
patches/data/qemu-10.0.2-utm/pc-bios/edk2-i386-secure-vars.fd.bz2


BIN
patches/data/qemu-10.0.2-utm/pc-bios/edk2-i386-vars.fd.bz2


+ 37 - 0
patches/qemu-10.0.2-utm.patch

@@ -300,3 +300,40 @@ index 9fb9659c45..63e10cc6df 100644
  
  
  dtc = find_program('dtc', required: false)
  dtc = find_program('dtc', required: false)
 
 
+From a172998c2f8bcbd29afeb8cab9b97e43ef3a22b5 Mon Sep 17 00:00:00 2001
+From: osy <osy@turing.llc>
+Date: Sun, 10 Aug 2025 21:54:34 -0700
+Subject: [PATCH] pc-bios: use 2023 Microsoft UEFI certificates
+
+Restore non-secure vars variants as well.
+---
+ pc-bios/edk2-arm-secure-vars.fd.bz2  | Bin 0 -> 12654 bytes
+ pc-bios/edk2-arm-vars.fd.bz2         | Bin 6710 -> 595 bytes
+ pc-bios/edk2-i386-secure-vars.fd.bz2 | Bin 0 -> 12986 bytes
+ pc-bios/edk2-i386-vars.fd.bz2        | Bin 7727 -> 612 bytes
+ pc-bios/meson.build                  |   2 ++
+ 5 files changed, 2 insertions(+)
+ create mode 100644 pc-bios/edk2-arm-secure-vars.fd.bz2
+ create mode 100644 pc-bios/edk2-i386-secure-vars.fd.bz2
+
+diff --git a/pc-bios/meson.build b/pc-bios/meson.build
+index 63e10cc6df..1e1b553795 100644
+--- a/pc-bios/meson.build
++++ b/pc-bios/meson.build
+@@ -4,11 +4,13 @@ if unpack_edk2_blobs
+     'edk2-aarch64-code.fd',
+     'edk2-aarch64-secure-code.fd',
+     'edk2-arm-code.fd',
++    'edk2-arm-secure-vars.fd',
+     'edk2-arm-vars.fd',
+     'edk2-riscv-code.fd',
+     'edk2-riscv-vars.fd',
+     'edk2-i386-code.fd',
+     'edk2-i386-secure-code.fd',
++    'edk2-i386-secure-vars.fd',
+     'edk2-i386-vars.fd',
+     'edk2-x86_64-code.fd',
+     'edk2-x86_64-secure-code.fd',
+-- 
+2.41.0
+