diff options
Diffstat (limited to 'nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix')
-rw-r--r-- | nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix | 157 |
1 files changed, 98 insertions, 59 deletions
diff --git a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix index 6d0a11b7491f..f9cbafc28657 100644 --- a/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixpkgs/nixos/modules/installer/cd-dvd/iso-image.nix @@ -22,8 +22,8 @@ let (option: '' menuentry '${defaults.name} ${ # Name appended to menuentry defaults to params if no specific name given. - option.name or (if option ? params then "(${option.params})" else "") - }' ${if option ? class then " --class ${option.class}" else ""} { + option.name or (optionalString (option ? params) "(${option.params})") + }' ${optionalString (option ? class) " --class ${option.class}"} { linux ${defaults.image} \''${isoboot} ${defaults.params} ${ option.params or "" } @@ -35,24 +35,29 @@ let ; /** - * Given a `config`, builds the default options. + * Builds the default options. */ - buildMenuGrub2 = config: - buildMenuAdditionalParamsGrub2 config "" - ; + buildMenuGrub2 = buildMenuAdditionalParamsGrub2 ""; + + targetArch = + if config.boot.loader.grub.forcei686 then + "ia32" + else + pkgs.stdenv.hostPlatform.efiArch; /** - * Given a `config` and params to add to `params`, build a set of default options. + * Given params to add to `params`, build a set of default options. * Use this one when creating a variant (e.g. hidpi) */ - buildMenuAdditionalParamsGrub2 = config: additional: + buildMenuAdditionalParamsGrub2 = additional: let finalCfg = { - name = "NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}"; + name = "${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel}"; params = "init=${config.system.build.toplevel}/init ${additional} ${toString config.boot.kernelParams}"; image = "/boot/${config.system.boot.loader.kernelFile}"; initrd = "/boot/initrd"; }; + in menuBuilderGrub2 finalCfg @@ -65,18 +70,24 @@ let ; # Timeout in syslinux is in units of 1/10 of a second. - # 0 is used to disable timeouts. + # null means max timeout (35996, just under 1h in 1/10 seconds) + # 0 means disable timeout syslinuxTimeout = if config.boot.loader.timeout == null then - 0 + 35996 else - max (config.boot.loader.timeout * 10) 1; + config.boot.loader.timeout * 10; - - max = x: y: if x > y then x else y; + # Timeout in grub is in seconds. + # null means max timeout (infinity) + # 0 means disable timeout + grubEfiTimeout = if config.boot.loader.timeout == null then + -1 + else + config.boot.loader.timeout; # The configuration file for syslinux. - # Notes on syslinux configuration and UNetbootin compatiblity: + # Notes on syslinux configuration and UNetbootin compatibility: # * Do not use '/syslinux/syslinux.cfg' as the path for this # configuration. UNetbootin will not parse the file and use it as-is. # This results in a broken configuration if the partition label does @@ -98,35 +109,35 @@ let DEFAULT boot LABEL boot - MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} + MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} LINUX /boot/${config.system.boot.loader.kernelFile} APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} INITRD /boot/${config.system.boot.loader.initrdFile} # A variant to boot with 'nomodeset' LABEL boot-nomodeset - MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset) + MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (nomodeset) LINUX /boot/${config.system.boot.loader.kernelFile} APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} nomodeset INITRD /boot/${config.system.boot.loader.initrdFile} # A variant to boot with 'copytoram' LABEL boot-copytoram - MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram) + MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (copytoram) LINUX /boot/${config.system.boot.loader.kernelFile} APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} copytoram INITRD /boot/${config.system.boot.loader.initrdFile} # A variant to boot with verbose logging to the console LABEL boot-debug - MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug) + MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (debug) LINUX /boot/${config.system.boot.loader.kernelFile} APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} loglevel=7 INITRD /boot/${config.system.boot.loader.initrdFile} # A variant to boot with a serial console enabled LABEL boot-serial - MENU LABEL NixOS ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8) + MENU LABEL ${config.isoImage.prependToMenuLabel}${config.system.nixos.distroName} ${config.system.nixos.label}${config.isoImage.appendToMenuLabel} (serial console=ttyS0,115200n8) LINUX /boot/${config.system.boot.loader.kernelFile} APPEND init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams} console=ttyS0,115200n8 INITRD /boot/${config.system.boot.loader.initrdFile} @@ -281,7 +292,7 @@ let if serial; then set with_serial=yes ;fi export with_serial clear - set timeout=10 + set timeout=${toString grubEfiTimeout} # This message will only be viewable when "gfxterm" is not used. echo "" @@ -314,16 +325,16 @@ let # Menu entries # - ${buildMenuGrub2 config} + ${buildMenuGrub2} submenu "HiDPI, Quirks and Accessibility" --class hidpi --class submenu { ${grubMenuCfg} submenu "Suggests resolution @720p" --class hidpi-720p { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "video=1280x720@60"} + ${buildMenuAdditionalParamsGrub2 "video=1280x720@60"} } submenu "Suggests resolution @1080p" --class hidpi-1080p { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "video=1920x1080@60"} + ${buildMenuAdditionalParamsGrub2 "video=1920x1080@60"} } # If we boot into a graphical environment where X is autoran @@ -331,7 +342,7 @@ let # to disable this. submenu "Disable display-manager" --class quirk-disable-displaymanager { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "systemd.mask=display-manager.service"} + ${buildMenuAdditionalParamsGrub2 "systemd.mask=display-manager.service"} } # Some laptop and convertibles have the panel installed in an @@ -340,29 +351,29 @@ let submenu "" {return} submenu "Rotate framebuffer Clockwise" --class rotate-90cw { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:1"} + ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:1"} } submenu "Rotate framebuffer Upside-Down" --class rotate-180 { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:2"} + ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:2"} } submenu "Rotate framebuffer Counter-Clockwise" --class rotate-90ccw { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "fbcon=rotate:3"} + ${buildMenuAdditionalParamsGrub2 "fbcon=rotate:3"} } # As a proof of concept, mainly. (Not sure it has accessibility merits.) submenu "" {return} submenu "Use black on white" --class accessibility-blakconwhite { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "vt.default_red=0xFF,0xBC,0x4F,0xB4,0x56,0xBC,0x4F,0x00,0xA1,0xCF,0x84,0xCA,0x8D,0xB4,0x84,0x68 vt.default_grn=0xFF,0x55,0xBA,0xBA,0x4D,0x4D,0xB3,0x00,0xA0,0x8F,0xB3,0xCA,0x88,0x93,0xA4,0x68 vt.default_blu=0xFF,0x58,0x5F,0x58,0xC5,0xBD,0xC5,0x00,0xA8,0xBB,0xAB,0x97,0xBD,0xC7,0xC5,0x68"} + ${buildMenuAdditionalParamsGrub2 "vt.default_red=0xFF,0xBC,0x4F,0xB4,0x56,0xBC,0x4F,0x00,0xA1,0xCF,0x84,0xCA,0x8D,0xB4,0x84,0x68 vt.default_grn=0xFF,0x55,0xBA,0xBA,0x4D,0x4D,0xB3,0x00,0xA0,0x8F,0xB3,0xCA,0x88,0x93,0xA4,0x68 vt.default_blu=0xFF,0x58,0x5F,0x58,0xC5,0xBD,0xC5,0x00,0xA8,0xBB,0xAB,0x97,0xBD,0xC7,0xC5,0x68"} } # Serial access is a must! submenu "" {return} submenu "Serial console=ttyS0,115200n8" --class serial { ${grubMenuCfg} - ${buildMenuAdditionalParamsGrub2 config "console=ttyS0,115200n8"} + ${buildMenuAdditionalParamsGrub2 "console=ttyS0,115200n8"} } } @@ -416,7 +427,7 @@ let echo "Usage size: $usage_size" echo "Image size: $image_size" truncate --size=$image_size "$out" - faketime "2000-01-01 00:00:00" mkfs.vfat -i 12345678 -n EFIBOOT "$out" + mkfs.vfat --invariant -i 12345678 -n EFIBOOT "$out" # Force a fixed order in mcopy for better determinism, and avoid file globbing for d in $(find EFI -type d | sort); do @@ -431,22 +442,6 @@ let fsck.vfat -vn "$out" ''; # */ - # Name used by UEFI for architectures. - targetArch = - if pkgs.stdenv.isi686 || config.boot.loader.grub.forcei686 then - "ia32" - else if pkgs.stdenv.isx86_64 then - "x64" - else if pkgs.stdenv.isAarch32 then - "arm" - else if pkgs.stdenv.isAarch64 then - "aa64" - else - throw "Unsupported architecture"; - - # Syslinux (and isolinux) only supports x86-based architectures. - canx86BiosBoot = pkgs.stdenv.hostPlatform.isx86; - in { @@ -454,13 +449,15 @@ in isoImage.isoName = mkOption { default = "${config.isoImage.isoBaseName}.iso"; + type = lib.types.str; description = lib.mdDoc '' Name of the generated ISO image file. ''; }; isoImage.isoBaseName = mkOption { - default = "nixos"; + default = config.system.nixos.distroId; + type = lib.types.str; description = lib.mdDoc '' Prefix of the name of the generated ISO image file. ''; @@ -468,6 +465,7 @@ in isoImage.compressImage = mkOption { default = false; + type = lib.types.bool; description = lib.mdDoc '' Whether the ISO image should be compressed using {command}`zstd`. @@ -475,12 +473,13 @@ in }; isoImage.squashfsCompression = mkOption { - default = with pkgs.stdenv.targetPlatform; "xz -Xdict-size 100% " + default = with pkgs.stdenv.hostPlatform; "xz -Xdict-size 100% " + lib.optionalString isx86 "-Xbcj x86" # Untested but should also reduce size for these platforms + lib.optionalString isAarch "-Xbcj arm" + lib.optionalString (isPower && is32bit && isBigEndian) "-Xbcj powerpc" + lib.optionalString (isSparc) "-Xbcj sparc"; + type = lib.types.str; description = lib.mdDoc '' Compression settings to use for the squashfs nix store. ''; @@ -489,6 +488,7 @@ in isoImage.edition = mkOption { default = ""; + type = lib.types.str; description = lib.mdDoc '' Specifies which edition string to use in the volume ID of the generated ISO image. @@ -498,6 +498,7 @@ in isoImage.volumeID = mkOption { # nixos-$EDITION-$RELEASE-$ARCH default = "nixos${optionalString (config.isoImage.edition != "") "-${config.isoImage.edition}"}-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}"; + type = lib.types.str; description = lib.mdDoc '' Specifies the label or volume ID of the generated ISO image. Note that the label is used by stage 1 of the boot process to @@ -528,6 +529,7 @@ in isoImage.includeSystemBuildDependencies = mkOption { default = false; + type = lib.types.bool; description = lib.mdDoc '' Set this option to include all the needed sources etc in the image. It significantly increases image size. Use that when @@ -537,15 +539,35 @@ in ''; }; + isoImage.makeBiosBootable = mkOption { + # Before this option was introduced, images were BIOS-bootable if the + # hostPlatform was x86-based. This option is enabled by default for + # backwards compatibility. + # + # Also note that syslinux package currently cannot be cross-compiled from + # non-x86 platforms, so the default is false on non-x86 build platforms. + default = pkgs.stdenv.buildPlatform.isx86 && pkgs.stdenv.hostPlatform.isx86; + defaultText = lib.literalMD '' + `true` if both build and host platforms are x86-based architectures, + e.g. i686 and x86_64. + ''; + type = lib.types.bool; + description = lib.mdDoc '' + Whether the ISO image should be a BIOS-bootable disk. + ''; + }; + isoImage.makeEfiBootable = mkOption { default = false; + type = lib.types.bool; description = lib.mdDoc '' - Whether the ISO image should be an efi-bootable volume. + Whether the ISO image should be an EFI-bootable volume. ''; }; isoImage.makeUsbBootable = mkOption { default = false; + type = lib.types.bool; description = lib.mdDoc '' Whether the ISO image should be bootable from CD as well as USB. ''; @@ -581,7 +603,7 @@ in isoImage.syslinuxTheme = mkOption { default = '' - MENU TITLE NixOS + MENU TITLE ${config.system.nixos.distroName} MENU RESOLUTION 800 600 MENU CLEAR MENU ROWS 6 @@ -610,8 +632,22 @@ in ''; }; + isoImage.prependToMenuLabel = mkOption { + default = ""; + type = types.str; + example = "Install "; + description = lib.mdDoc '' + The string to prepend before the menu label for the NixOS system. + This will be directly prepended (without whitespace) to the NixOS version + string, like for example if it is set to `XXX`: + + `XXXNixOS 99.99-pre666` + ''; + }; + isoImage.appendToMenuLabel = mkOption { default = " Installer"; + type = types.str; example = " Live System"; description = lib.mdDoc '' The string to append after the menu label for the NixOS system. @@ -676,6 +712,11 @@ in config = { assertions = [ { + # Syslinux (and isolinux) only supports x86-based architectures. + assertion = config.isoImage.makeBiosBootable -> pkgs.stdenv.hostPlatform.isx86; + message = "BIOS boot is only supported on x86-based architectures."; + } + { assertion = !(stringLength config.isoImage.volumeID > 32); # https://wiki.osdev.org/ISO_9660#The_Primary_Volume_Descriptor # Volume Identifier can only be 32 bytes @@ -688,14 +729,12 @@ in } ]; - boot.loader.grub.version = 2; - # Don't build the GRUB menu builder script, since we don't need it # here and it causes a cyclic dependency. boot.loader.grub.enable = false; environment.systemPackages = [ grubPkgs.grub2 grubPkgs.grub2_efi ] - ++ optional canx86BiosBoot pkgs.syslinux + ++ optional (config.isoImage.makeBiosBootable) pkgs.syslinux ; # In stage 1 of the boot, mount the CD as the root FS by label so @@ -746,7 +785,7 @@ in { source = pkgs.writeText "version" config.system.nixos.label; target = "/version.txt"; } - ] ++ optionals canx86BiosBoot [ + ] ++ optionals (config.isoImage.makeBiosBootable) [ { source = config.isoImage.splashImage; target = "/isolinux/background.png"; } @@ -773,7 +812,7 @@ in { source = config.isoImage.efiSplashImage; target = "/EFI/boot/efi-background.png"; } - ] ++ optionals (config.boot.loader.grub.memtest86.enable && canx86BiosBoot) [ + ] ++ optionals (config.boot.loader.grub.memtest86.enable && config.isoImage.makeBiosBootable) [ { source = "${pkgs.memtest86plus}/memtest.bin"; target = "/boot/memtest.bin"; } @@ -788,10 +827,10 @@ in # Create the ISO image. system.build.isoImage = pkgs.callPackage ../../../lib/make-iso9660-image.nix ({ inherit (config.isoImage) isoName compressImage volumeID contents; - bootable = canx86BiosBoot; + bootable = config.isoImage.makeBiosBootable; bootImage = "/isolinux/isolinux.bin"; - syslinux = if canx86BiosBoot then pkgs.syslinux else null; - } // optionalAttrs (config.isoImage.makeUsbBootable && canx86BiosBoot) { + syslinux = if config.isoImage.makeBiosBootable then pkgs.syslinux else null; + } // optionalAttrs (config.isoImage.makeUsbBootable && config.isoImage.makeBiosBootable) { usbBootable = true; isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin"; } // optionalAttrs config.isoImage.makeEfiBootable { |