about summary refs log tree commit diff
path: root/nixos/modules/virtualisation
diff options
context:
space:
mode:
authorRaito Bezarius <masterancpp@gmail.com>2023-04-26 18:23:42 +0200
committerRaito Bezarius <masterancpp@gmail.com>2023-06-09 14:51:18 +0200
commit610f60231fde08ff5d458cfbe2f37cb9b5d70e7d (patch)
tree96a79ec83c174edc7186704099cad758ab0eb3fb /nixos/modules/virtualisation
parent0663e8287c301aca2fc155514699c9f27c67c059 (diff)
downloadnixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar.gz
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar.bz2
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar.lz
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar.xz
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.tar.zst
nixlib-610f60231fde08ff5d458cfbe2f37cb9b5d70e7d.zip
nixos/qemu-vm: introduce `virtualisation.directBoot`
As with many things, we have scenarios where we don't want to boot on a
disk / bootloader and also we don't want to boot directly.

Sometimes, we want to boot through an OptionROM of our NIC, e.g. netboot
scenarios or let the firmware decide something, e.g. UEFI PXE (or even
UEFI OptionROM!).

This is composed of:

- `directBoot.enable`: whether to direct boot or not
- `directBoot.initrd`: enable overriding the
  `config.system.build.initialRamdisk` defaults, useful for
  netbootRamdisk for example.

This makes it possible.
Diffstat (limited to 'nixos/modules/virtualisation')
-rw-r--r--nixos/modules/virtualisation/qemu-vm.nix58
1 files changed, 55 insertions, 3 deletions
diff --git a/nixos/modules/virtualisation/qemu-vm.nix b/nixos/modules/virtualisation/qemu-vm.nix
index 7d8c83ed78db..5cbc648b7a9c 100644
--- a/nixos/modules/virtualisation/qemu-vm.nix
+++ b/nixos/modules/virtualisation/qemu-vm.nix
@@ -263,7 +263,8 @@ let
         if cfg.useEFIBoot then "efi_bootloading_with_default_fs"
         else "legacy_bootloading_with_default_fs"
       else
-        "direct_boot_with_default_fs"
+        if cfg.directBoot.enable then "direct_boot_with_default_fs"
+        else "custom"
     else
       "custom";
   suggestedRootDevice = {
@@ -769,6 +770,40 @@ in
         '';
       };
 
+    virtualisation.directBoot = {
+      enable =
+        mkOption {
+          type = types.bool;
+          default = !cfg.useBootLoader;
+          defaultText = "!cfg.useBootLoader";
+          description =
+            lib.mdDoc ''
+              If enabled, the virtual machine will boot directly into the kernel instead of through a bootloader. Other relevant parameters such as the initrd are also passed to QEMU.
+
+              If you want to test netboot, consider disabling this option.
+
+              This will not boot / reboot correctly into a system that has switched to a different configuration on disk.
+
+              This is enabled by default if you don't enable bootloaders, but you can still enable a bootloader if you need.
+              Read more about this feature: <https://qemu-project.gitlab.io/qemu/system/linuxboot.html>.
+            '';
+        };
+      initrd =
+        mkOption {
+          type = types.str;
+          default = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
+          defaultText = "\${config.system.build.initialRamdisk}/\${config.system.boot.loader.initrdFile}";
+          description =
+            lib.mdDoc ''
+              In direct boot situations, you may want to influence the initrd to load
+              to use your own customized payload.
+
+              This is useful if you want to test the netboot image without
+              testing the firmware or the loading part.
+            '';
+        };
+    };
+
     virtualisation.useBootLoader =
       mkOption {
         type = types.bool;
@@ -895,6 +930,18 @@ in
               virtualisation.memorySize is above 2047, but qemu is only able to allocate 2047MB RAM on 32bit max.
             '';
           }
+          { assertion = cfg.directBoot.initrd != options.virtualisation.directBoot.initrd.default -> cfg.directBoot.enable;
+            message =
+              ''
+                You changed the default of `virtualisation.directBoot.initrd` but you are not
+                using QEMU direct boot. This initrd will not be used in your current
+                boot configuration.
+
+                Either do not mutate `virtualisation.directBoot.initrd` or enable direct boot.
+
+                If you have a more advanced usecase, please open an issue or a pull request.
+              '';
+          }
         ];
 
     warnings =
@@ -915,6 +962,11 @@ in
           Otherwise, we recommend
 
             ${opt.writableStore} = false;
+            ''
+      ++ optional (cfg.directBoot.enable && cfg.useBootLoader)
+        ''
+          You enabled direct boot and a bootloader, QEMU will not boot your bootloader, rendering
+          `useBootLoader` useless. You might want to disable one of those options.
         '';
 
     # In UEFI boot, we use a EFI-only partition table layout, thus GRUB will fail when trying to install
@@ -1036,9 +1088,9 @@ in
         alphaNumericChars = lowerChars ++ upperChars ++ (map toString (range 0 9));
         # Replace all non-alphanumeric characters with underscores
         sanitizeShellIdent = s: concatMapStrings (c: if builtins.elem c alphaNumericChars then c else "_") (stringToCharacters s);
-      in mkIf (!cfg.useBootLoader) [
+      in mkIf cfg.directBoot.enable [
         "-kernel \${NIXPKGS_QEMU_KERNEL_${sanitizeShellIdent config.system.name}:-${config.system.build.toplevel}/kernel}"
-        "-initrd ${config.system.build.toplevel}/initrd"
+        "-initrd ${cfg.directBoot.initrd}"
         ''-append "$(cat ${config.system.build.toplevel}/kernel-params) init=${config.system.build.toplevel}/init regInfo=${regInfo}/registration ${consoles} $QEMU_KERNEL_PARAMS"''
       ])
       (mkIf cfg.useEFIBoot [