nixos: iso-image: use syslinux bootloader for USB booting support
This changes the bootloader for iso generation from Grub to syslinux. In addition this adds USB booting support, so that "dd" can be used to burn the generated ISO to USB thumbdrives instead of needing applications like UnetBootin.
This commit is contained in:
parent
9a75c1d7c8
commit
8d092270d2
@ -1,4 +1,4 @@
|
|||||||
{ stdenv, perl, cdrkit, pathsFromGraph
|
{ stdenv, perl, pathsFromGraph, xorriso, syslinux
|
||||||
|
|
||||||
, # The file name of the resulting ISO image.
|
, # The file name of the resulting ISO image.
|
||||||
isoName ? "cd.iso"
|
isoName ? "cd.iso"
|
||||||
@ -22,12 +22,18 @@
|
|||||||
, # Whether this should be an efi-bootable El-Torito CD.
|
, # Whether this should be an efi-bootable El-Torito CD.
|
||||||
efiBootable ? false
|
efiBootable ? false
|
||||||
|
|
||||||
|
, # Wheter this should be an hybrid CD (bootable from USB as well as CD).
|
||||||
|
usbBootable ? false
|
||||||
|
|
||||||
, # The path (in the ISO file system) of the boot image.
|
, # The path (in the ISO file system) of the boot image.
|
||||||
bootImage ? ""
|
bootImage ? ""
|
||||||
|
|
||||||
, # The path (in the ISO file system) of the efi boot image.
|
, # The path (in the ISO file system) of the efi boot image.
|
||||||
efiBootImage ? ""
|
efiBootImage ? ""
|
||||||
|
|
||||||
|
, # The path (outside the ISO file system) of the isohybrid-mbr image.
|
||||||
|
isohybridMbrImage ? ""
|
||||||
|
|
||||||
, # Whether to compress the resulting ISO image with bzip2.
|
, # Whether to compress the resulting ISO image with bzip2.
|
||||||
compressImage ? false
|
compressImage ? false
|
||||||
|
|
||||||
@ -38,13 +44,14 @@
|
|||||||
|
|
||||||
assert bootable -> bootImage != "";
|
assert bootable -> bootImage != "";
|
||||||
assert efiBootable -> efiBootImage != "";
|
assert efiBootable -> efiBootImage != "";
|
||||||
|
assert usbBootable -> isohybridMbrImage != "";
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
stdenv.mkDerivation {
|
||||||
name = "iso9660-image";
|
name = "iso9660-image";
|
||||||
builder = ./make-iso9660-image.sh;
|
builder = ./make-iso9660-image.sh;
|
||||||
buildInputs = [perl cdrkit];
|
buildInputs = [perl xorriso syslinux];
|
||||||
|
|
||||||
inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable;
|
inherit isoName bootable bootImage compressImage volumeID pathsFromGraph efiBootImage efiBootable isohybridMbrImage usbBootable;
|
||||||
|
|
||||||
# !!! should use XML.
|
# !!! should use XML.
|
||||||
sources = map (x: x.source) contents;
|
sources = map (x: x.source) contents;
|
||||||
|
@ -31,11 +31,20 @@ if test -n "$bootable"; then
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
bootFlags="-b $bootImage -c .boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table"
|
isoBootFlags="-eltorito-boot ${bootImage}
|
||||||
|
-eltorito-catalog .boot.cat
|
||||||
|
-no-emul-boot -boot-load-size 4 -boot-info-table"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if test -n "$usbBootable"; then
|
||||||
|
usbBootFlags="-isohybrid-mbr ${isohybridMbrImage}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test -n "$efiBootable"; then
|
if test -n "$efiBootable"; then
|
||||||
bootFlags="$bootFlags -eltorito-alt-boot -e $efiBootImage -no-emul-boot"
|
efiBootFlags="-eltorito-alt-boot
|
||||||
|
-e $efiBootImage
|
||||||
|
-no-emul-boot
|
||||||
|
-isohybrid-gpt-basdat"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
touch pathlist
|
touch pathlist
|
||||||
@ -74,18 +83,41 @@ for ((n = 0; n < ${#objects[*]}; n++)); do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
# !!! what does this do?
|
# Escape filenames that contain '='.
|
||||||
|
# TODO: Handle this properly. This fails for filenames
|
||||||
|
# that contain multiple '=' symbols.
|
||||||
cat pathlist | sed -e 's/=\(.*\)=\(.*\)=/\\=\1=\2\\=/' | tee pathlist.safer
|
cat pathlist | sed -e 's/=\(.*\)=\(.*\)=/\\=\1=\2\\=/' | tee pathlist.safer
|
||||||
|
|
||||||
|
|
||||||
mkdir -p $out/iso
|
mkdir -p $out/iso
|
||||||
genCommand="genisoimage -iso-level 4 -r -J $bootFlags -hide-rr-moved -graft-points -path-list pathlist.safer ${volumeID:+-V $volumeID}"
|
|
||||||
if test -z "$compressImage"; then
|
xorriso="xorriso
|
||||||
$genCommand -o $out/iso/$isoName
|
-as mkisofs
|
||||||
else
|
-iso-level 3
|
||||||
$genCommand | bzip2 > $out/iso/$isoName.bz2
|
-volid ${volumeID}
|
||||||
|
-appid nixos
|
||||||
|
-publisher nixos
|
||||||
|
-graft-points
|
||||||
|
-full-iso9660-filenames
|
||||||
|
${isoBootFlags}
|
||||||
|
${usbBootFlags}
|
||||||
|
${efiBootFlags}
|
||||||
|
-r
|
||||||
|
-path-list pathlist.safer
|
||||||
|
--sort-weight 0 /
|
||||||
|
--sort-weight 1 /isolinux" # Make sure isolinux is near the beginning of the ISO
|
||||||
|
|
||||||
|
$xorriso -output $out/iso/$isoName
|
||||||
|
|
||||||
|
if test -n "$usbBootable"; then
|
||||||
|
echo "Making image hybrid..."
|
||||||
|
isohybrid --uefi $out/iso/$isoName
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test -n "$compressImage"; then
|
||||||
|
echo "Compressing image..."
|
||||||
|
bzip2 $out/iso/$isoName
|
||||||
|
fi
|
||||||
|
|
||||||
mkdir -p $out/nix-support
|
mkdir -p $out/nix-support
|
||||||
echo $system > $out/nix-support/system
|
echo $system > $out/nix-support/system
|
||||||
|
@ -36,6 +36,9 @@ with lib;
|
|||||||
# EFI booting
|
# EFI booting
|
||||||
isoImage.makeEfiBootable = true;
|
isoImage.makeEfiBootable = true;
|
||||||
|
|
||||||
|
# USB booting
|
||||||
|
isoImage.makeUsbBootable = true;
|
||||||
|
|
||||||
# Add Memtest86+ to the CD.
|
# Add Memtest86+ to the CD.
|
||||||
boot.loader.grub.memtest86.enable = true;
|
boot.loader.grub.memtest86.enable = true;
|
||||||
|
|
||||||
|
@ -8,45 +8,39 @@ with lib;
|
|||||||
|
|
||||||
let
|
let
|
||||||
|
|
||||||
# The Grub image.
|
# The configuration file for syslinux.
|
||||||
grubImage = pkgs.runCommand "grub_eltorito" {}
|
baseIsolinuxCfg =
|
||||||
''
|
''
|
||||||
${pkgs.grub2}/bin/grub-mkimage -p /boot/grub -O i386-pc -o tmp biosdisk iso9660 help linux linux16 chain png jpeg echo gfxmenu reboot
|
SERIAL 0 38400
|
||||||
cat ${pkgs.grub2}/lib/grub/*/cdboot.img tmp > $out
|
UI vesamenu.c32
|
||||||
''; # */
|
MENU TITLE NixOS
|
||||||
|
MENU BACKGROUND /isolinux/background.png
|
||||||
|
|
||||||
|
LABEL boot
|
||||||
|
MENU LABEL Boot NixOS
|
||||||
|
LINUX /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
||||||
|
INITRD /boot/initrd
|
||||||
|
|
||||||
# The configuration file for Grub.
|
LABEL chain
|
||||||
grubCfg =
|
MENU LABEL Boot existing OS
|
||||||
''
|
COM32 chain.c32
|
||||||
set default=${builtins.toString config.boot.loader.grub.default}
|
APPEND hd0 0
|
||||||
set timeout=${builtins.toString config.boot.loader.grub.timeout}
|
|
||||||
|
|
||||||
if loadfont /boot/grub/unicode.pf2; then
|
LABEL reboot
|
||||||
set gfxmode=640x480
|
MENU LABEL Reboot
|
||||||
insmod gfxterm
|
COM32 reboot.c32
|
||||||
insmod vbe
|
|
||||||
terminal_output gfxterm
|
|
||||||
|
|
||||||
insmod png
|
LABEL poweroff
|
||||||
if background_image /boot/grub/splash.png; then
|
MENU LABEL Power Off
|
||||||
set color_normal=white/black
|
COM32 poweroff.c32
|
||||||
set color_highlight=black/white
|
|
||||||
else
|
|
||||||
set menu_color_normal=cyan/blue
|
|
||||||
set menu_color_highlight=white/blue
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
${config.boot.loader.grub.extraEntries}
|
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
isolinuxCfg = baseIsolinuxCfg + (optionalString config.boot.loader.grub.memtest86.enable isolinuxMemtest86Entry);
|
||||||
|
|
||||||
# The efi boot image
|
# The efi boot image
|
||||||
efiDir = pkgs.runCommand "efi-directory" {} ''
|
efiDir = pkgs.runCommand "efi-directory" {} ''
|
||||||
mkdir -p $out/efi/boot
|
mkdir -p $out/EFI/boot
|
||||||
cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/efi/boot/boot${targetArch}.efi
|
cp -v ${pkgs.gummiboot}/lib/gummiboot/gummiboot${targetArch}.efi $out/EFI/boot/boot${targetArch}.efi
|
||||||
mkdir -p $out/loader/entries
|
mkdir -p $out/loader/entries
|
||||||
echo "title NixOS LiveCD" > $out/loader/entries/nixos-livecd.conf
|
echo "title NixOS LiveCD" > $out/loader/entries/nixos-livecd.conf
|
||||||
echo "linux /boot/bzImage" >> $out/loader/entries/nixos-livecd.conf
|
echo "linux /boot/bzImage" >> $out/loader/entries/nixos-livecd.conf
|
||||||
@ -152,6 +146,22 @@ in
|
|||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
isoImage.makeUsbBootable = mkOption {
|
||||||
|
default = false;
|
||||||
|
description = ''
|
||||||
|
Whether the ISO image should be bootable from CD as well as USB.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
isoImage.splashImage = mkOption {
|
||||||
|
default = pkgs.fetchurl {
|
||||||
|
url = https://raw.githubusercontent.com/NixOS/nixos-artwork/5729ab16c6a5793c10a2913b5a1b3f59b91c36ee/ideas/grub-splash/grub-nixos-1.png;
|
||||||
|
sha256 = "43fd8ad5decf6c23c87e9026170a13588c2eba249d9013cb9f888da5e2002217";
|
||||||
|
};
|
||||||
|
description = ''
|
||||||
|
The splash image to use in the bootloader.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -166,7 +176,7 @@ in
|
|||||||
|
|
||||||
# !!! Hack - attributes expected by other modules.
|
# !!! Hack - attributes expected by other modules.
|
||||||
system.boot.loader.kernelFile = "bzImage";
|
system.boot.loader.kernelFile = "bzImage";
|
||||||
environment.systemPackages = [ pkgs.grub2 ];
|
environment.systemPackages = [ pkgs.grub2 pkgs.syslinux ];
|
||||||
|
|
||||||
# In stage 1 of the boot, mount the CD as the root FS by label so
|
# In stage 1 of the boot, mount the CD as the root FS by label so
|
||||||
# that we don't need to know its device. We pass the label of the
|
# that we don't need to know its device. We pass the label of the
|
||||||
@ -216,7 +226,7 @@ in
|
|||||||
options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
|
options = "allow_other,cow,nonempty,chroot=/mnt-root,max_files=32768,hide_meta_files,dirs=/nix/.rw-store=rw:/nix/.ro-store=ro";
|
||||||
};
|
};
|
||||||
|
|
||||||
boot.initrd.availableKernelModules = [ "squashfs" "iso9660" ];
|
boot.initrd.availableKernelModules = [ "squashfs" "iso9660" "usb-storage" ];
|
||||||
|
|
||||||
boot.initrd.kernelModules = [ "loop" ];
|
boot.initrd.kernelModules = [ "loop" ];
|
||||||
|
|
||||||
@ -236,15 +246,12 @@ in
|
|||||||
# Individual files to be included on the CD, outside of the Nix
|
# Individual files to be included on the CD, outside of the Nix
|
||||||
# store on the CD.
|
# store on the CD.
|
||||||
isoImage.contents =
|
isoImage.contents =
|
||||||
[ { source = grubImage;
|
[ { source = pkgs.substituteAll {
|
||||||
target = "/boot/grub/grub_eltorito";
|
name = "isolinux.cfg";
|
||||||
}
|
src = pkgs.writeText "isolinux.cfg-in" isolinuxCfg;
|
||||||
{ source = pkgs.substituteAll {
|
|
||||||
name = "grub.cfg";
|
|
||||||
src = pkgs.writeText "grub.cfg-in" grubCfg;
|
|
||||||
bootRoot = "/boot";
|
bootRoot = "/boot";
|
||||||
};
|
};
|
||||||
target = "/boot/grub/grub.cfg";
|
target = "/isolinux/isolinux.cfg";
|
||||||
}
|
}
|
||||||
{ source = config.boot.kernelPackages.kernel + "/bzImage";
|
{ source = config.boot.kernelPackages.kernel + "/bzImage";
|
||||||
target = "/boot/bzImage";
|
target = "/boot/bzImage";
|
||||||
@ -252,51 +259,38 @@ in
|
|||||||
{ source = config.system.build.initialRamdisk + "/initrd";
|
{ source = config.system.build.initialRamdisk + "/initrd";
|
||||||
target = "/boot/initrd";
|
target = "/boot/initrd";
|
||||||
}
|
}
|
||||||
{ source = "${pkgs.grub2}/share/grub/unicode.pf2";
|
|
||||||
target = "/boot/grub/unicode.pf2";
|
|
||||||
}
|
|
||||||
{ source = config.boot.loader.grub.splashImage;
|
|
||||||
target = "/boot/grub/splash.png";
|
|
||||||
}
|
|
||||||
{ source = config.system.build.squashfsStore;
|
{ source = config.system.build.squashfsStore;
|
||||||
target = "/nix-store.squashfs";
|
target = "/nix-store.squashfs";
|
||||||
}
|
}
|
||||||
|
{ source = "${pkgs.syslinux}/share/syslinux";
|
||||||
|
target = "/isolinux";
|
||||||
|
}
|
||||||
|
{ source = config.isoImage.splashImage;
|
||||||
|
target = "/isolinux/background.png";
|
||||||
|
}
|
||||||
] ++ optionals config.isoImage.makeEfiBootable [
|
] ++ optionals config.isoImage.makeEfiBootable [
|
||||||
{ source = efiImg;
|
{ source = efiImg;
|
||||||
target = "/boot/efi.img";
|
target = "/boot/efi.img";
|
||||||
}
|
}
|
||||||
{ source = "${efiDir}/efi";
|
{ source = "${efiDir}/EFI";
|
||||||
target = "/efi";
|
target = "/EFI";
|
||||||
}
|
}
|
||||||
{ source = "${efiDir}/loader";
|
{ source = "${efiDir}/loader";
|
||||||
target = "/loader";
|
target = "/loader";
|
||||||
}
|
}
|
||||||
] ++ mapAttrsToList (n: v: { source = v; target = "/boot/${n}"; }) config.boot.loader.grub.extraFiles;
|
];
|
||||||
|
|
||||||
# The Grub menu.
|
|
||||||
boot.loader.grub.extraEntries =
|
|
||||||
''
|
|
||||||
menuentry "NixOS ${config.system.nixosVersion} Installer" {
|
|
||||||
linux /boot/bzImage init=${config.system.build.toplevel}/init ${toString config.boot.kernelParams}
|
|
||||||
initrd /boot/initrd
|
|
||||||
}
|
|
||||||
|
|
||||||
menuentry "Boot from hard disk" {
|
|
||||||
set root=(hd0)
|
|
||||||
chainloader +1
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
boot.loader.grub.timeout = 10;
|
|
||||||
|
|
||||||
# Create the ISO image.
|
# Create the ISO image.
|
||||||
system.build.isoImage = import ../../../lib/make-iso9660-image.nix ({
|
system.build.isoImage = import ../../../lib/make-iso9660-image.nix ({
|
||||||
inherit (pkgs) stdenv perl cdrkit pathsFromGraph;
|
inherit (pkgs) stdenv perl pathsFromGraph xorriso syslinux;
|
||||||
|
|
||||||
inherit (config.isoImage) isoName compressImage volumeID contents;
|
inherit (config.isoImage) isoName compressImage volumeID contents;
|
||||||
|
|
||||||
bootable = true;
|
bootable = true;
|
||||||
bootImage = "/boot/grub/grub_eltorito";
|
bootImage = "/isolinux/isolinux.bin";
|
||||||
|
} // optionalAttrs config.isoImage.makeUsbBootable {
|
||||||
|
usbBootable = true;
|
||||||
|
isohybridMbrImage = "${pkgs.syslinux}/share/syslinux/isohdpfx.bin";
|
||||||
} // optionalAttrs config.isoImage.makeEfiBootable {
|
} // optionalAttrs config.isoImage.makeEfiBootable {
|
||||||
efiBootable = true;
|
efiBootable = true;
|
||||||
efiBootImage = "boot/efi.img";
|
efiBootImage = "boot/efi.img";
|
||||||
|
Loading…
Reference in New Issue
Block a user