diff --git a/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml b/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml index ef6835b..818f681 100644 --- a/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml +++ b/org.jdrupes.vmoperator.runner.qemu/config-sample.yaml @@ -36,11 +36,11 @@ # Whether to provide a software TPM (defaults to false) # "useTpm": false - # How to boot: + # How to boot (see https://github.com/mnlipp/VM-Operator/blob/main/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml): # * bios - # * uefi - # * secure - # "bootMode": "uefi" + # * uefi[-4m] + # * secure[-4m] + # "firmware": "uefi" # When terminating, a graceful powerdown is attempted. If it # doesn't succeed within the given timeout (seconds) SIGTERM diff --git a/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml b/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml index c7dfa3e..70de565 100644 --- a/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml +++ b/org.jdrupes.vmoperator.runner.qemu/resources/org/jdrupes/vmoperator/runner/qemu/defaults.yaml @@ -1,12 +1,33 @@ -# Candidate paths for code and templates for firmware rom and flash +# Candidate paths for code and templates for firmware rom and vars "firmware": - "rom": - - "/usr/share/OVMF/OVMF_CODE.fd" - - "/usr/share/edk2/x64/OVMF_CODE.fd" - "flash": - - "/usr/share/edk2/ovmf/OVMF_VARS.fd" - - "/usr/share/edk2/x64/OVMF_CODE.fd" + "bios": + "rom": [] + "vars": [] + "uefi": + "rom": + - "/usr/share/edk2/ovmf/OVMF_CODE.fd" + - "/usr/share/edk2/x64/OVMF_CODE.fd" + "vars": + - "/usr/share/edk2/ovmf/OVMF_VARS.fd" + - "/usr/share/edk2/x64/OVMF_VARS.fd" + "uefi-4m": + "rom": + - "/usr/share/edk2/ovmf-4m/OVMF_CODE.fd" + - "/usr/share/edk2/x64/OVMF_CODE.4m.fd" + "vars": + - "/usr/share/edk2/ovmf-4m/OVMF_VARS.fd" + - "/usr/share/edk2/x64/OVMF_VARS.4m.fd" "secure": - "flash": + "rom": - "/usr/share/edk2/ovmf/OVMF_CODE.secboot.fd" - "/usr/share/edk2/x64/OVMF_CODE.secboot.fd" + "vars": + - "/usr/share/edk2/ovmf/OVMF_VARS.secboot.fd" + - "/usr/share/edk2/x64/OVMF_VARS.fd" + "secure-4m": + "rom": + - "/usr/share/edk2/ovmf-4m/OVMF_CODE.secboot.fd" + - "/usr/share/edk2/x64/OVMF_CODE.secboot.4m.fd" + "vars": + - "/usr/share/edk2/ovmf-4m/OVMF_CODE.secboot.fd" + - "/usr/share/edk2/x64/OVMF_VARS.4m.fd" diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java index 127a057..5c1791a 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Configuration.java @@ -34,9 +34,6 @@ class Configuration implements Dto { @SuppressWarnings("PMD.FieldNamingConventions") protected final Logger logger = Logger.getLogger(getClass().getName()); - public static final Object BOOT_MODE_UEFI = "uefi"; - public static final Object BOOT_MODE_SECURE = "secure"; - public String dataDir; public String runtimeDir; public String template; @@ -44,7 +41,7 @@ class Configuration implements Dto { public Path swtpmSocket; public Path monitorSocket; public Path firmwareRom; - public Path firmwareFlash; + public Path firmwareVars; @SuppressWarnings("PMD.ShortVariable") public Vm vm; @@ -56,7 +53,7 @@ class Configuration implements Dto { public String name; public String uuid; public boolean useTpm; - public String bootMode = "uefi"; + public String firmware = "uefi"; public String maximumRam; public String currentRam; public String cpuModel = "host"; diff --git a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java index 7dabad4..23b7ecc 100644 --- a/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java +++ b/org.jdrupes.vmoperator.runner.qemu/src/org/jdrupes/vmoperator/runner/qemu/Runner.java @@ -47,8 +47,6 @@ import org.apache.commons.cli.CommandLineParser; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; -import static org.jdrupes.vmoperator.runner.qemu.Configuration.BOOT_MODE_SECURE; -import static org.jdrupes.vmoperator.runner.qemu.Configuration.BOOT_MODE_UEFI; import org.jdrupes.vmoperator.runner.qemu.StateController.State; import org.jdrupes.vmoperator.util.ExtendedObjectWrapper; import org.jgrapes.core.Channel; @@ -151,7 +149,7 @@ public class Runner extends Component { private static final String DEFAULT_TEMPLATE = "Standard-VM-latest.ftl.yaml"; private static final String SAVED_TEMPLATE = "VM.ftl.yaml"; - private static final String FW_FLASH = "fw-flash.fd"; + private static final String FW_VARS = "fw-vars.fd"; private final ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); private final JsonNode defaults; @@ -255,8 +253,9 @@ public class Runner extends Component { @SuppressWarnings({ "PMD.CognitiveComplexity", "PMD.DataflowAnomalyAnalysis" }) private void setFirmwarePaths() throws IOException { + JsonNode firmware = defaults.path("firmware").path(config.vm.firmware); // Get file for firmware ROM - JsonNode codePaths = defaults.path("firmware").path("rom"); + JsonNode codePaths = firmware.path("rom"); for (var p : codePaths) { var path = Path.of(p.asText()); if (Files.exists(path)) { @@ -264,24 +263,14 @@ public class Runner extends Component { break; } } - // Get file for firmware flash, if necessary - config.firmwareFlash = Path.of(config.dataDir, FW_FLASH); - if (!Files.exists(config.firmwareFlash)) { - JsonNode srcPaths = null; - if (BOOT_MODE_UEFI.equals(config.vm.bootMode)) { - srcPaths = defaults.path("firmware").path("flash"); - } else if (BOOT_MODE_SECURE.equals(config.vm.bootMode)) { - srcPaths = defaults.path("firmware") - .path("secure").path("flash"); - } - // If UEFI boot, srcPaths != null - if (srcPaths != null) { - for (var p : srcPaths) { - var path = Path.of(p.asText()); - if (Files.exists(path)) { - Files.copy(path, config.firmwareFlash); - break; - } + // Get file for firmware vars, if necessary + config.firmwareVars = Path.of(config.dataDir, FW_VARS); + if (!Files.exists(config.firmwareVars)) { + for (var p : firmware.path("vars")) { + var path = Path.of(p.asText()); + if (Files.exists(path)) { + Files.copy(path, config.firmwareVars); + break; } } } @@ -304,8 +293,10 @@ public class Runner extends Component { // Configure data model var model = new HashMap(); model.put("runtimeDir", config.runtimeDir); - model.put("firmwareRom", config.firmwareRom.toString()); - model.put("firmwareFlash", config.firmwareFlash.toString()); + model.put("firmwareRom", Optional.ofNullable(config.firmwareRom) + .map(Object::toString).orElse(null)); + model.put("firmwareVars", Optional.ofNullable(config.firmwareVars) + .map(Object::toString).orElse(null)); model.put("vm", config.vm); // Combine template and data and parse result diff --git a/org.jdrupes.vmoperator.runner.qemu/templates/Standard-VM-latest.ftl.yaml b/org.jdrupes.vmoperator.runner.qemu/templates/Standard-VM-latest.ftl.yaml index e576c8d..c236eeb 100644 --- a/org.jdrupes.vmoperator.runner.qemu/templates/Standard-VM-latest.ftl.yaml +++ b/org.jdrupes.vmoperator.runner.qemu/templates/Standard-VM-latest.ftl.yaml @@ -44,8 +44,8 @@ # For smm=on see https://scumjr.github.io/2016/01/04/playing-with-smm-and-qemu/. # Configure ROM/EEPROM for UEFI. - [ "-machine", "pc-q35-7.0,usb=off,vmport=off,dump-guest-core=off\ - <#if vm.bootMode == "secure">,smm=on\ - <#if vm.bootMode != "bios">,pflash0=fw-rom-device\ + <#if vm.firmware?starts_with("secure")>,smm=on\ + <#if firmwareRom??>,pflash0=fw-rom-device\ ,pflash1=fw-eeprom-device,memory-backend=pc.ram,hpet=off" ] # * https://bugzilla.redhat.com/show_bug.cgi?id=1170533, may be unnecessary - [ "-global", "ICH9-LPC.disable_s3=1" ] @@ -54,17 +54,21 @@ # -global driver=cfi.pflash01,property=secure,value=on # -object '{"qom-type":"secret","id":"masterKey0","format":"raw","file":"/var/local/qemu/master-key.aes"}' # {{- end }} - <#if vm.bootMode != "bios"> + <#if firmwareRom??> # * Provide ROM/EEPROM devices (instead of built-in BIOS) - [ "-blockdev", "node-name=fw-rom-file,driver=file,cache.direct=on,\ filename=${ firmwareRom },auto-read-only=true,discard=unmap" ] - [ "-blockdev", "node-name=fw-rom-device,driver=raw,\ read-only=true,file=fw-rom-file" ] - [ "-blockdev", "node-name=fw-eeprom-file,driver=file,cache.direct=on,\ - filename=${ firmwareFlash },auto-read-only=true,discard=unmap" ] + filename=${ firmwareVars },auto-read-only=true,discard=unmap" ] - [ "-blockdev", "node-name=fw-eeprom-device,driver=raw,\ read-only=false,file=fw-eeprom-file" ] - + + # https://wiki.debian.org/SecureBoot/VirtualMachine + <#if vm.firmware?starts_with("secure")> + - [ "-global", "driver=cfi.pflash01,property=secure,value=on" ] + # * Provide RAM - [ "-object", "memory-backend-ram,id=pc.ram,\ size=${ vm.maximumRam!"1G" }" ]