2
0
Fork 0

fixup! Boot from USB

This commit is contained in:
Ehmry - 2020-12-10 19:26:22 +01:00
parent 517080b3dd
commit 14a9448b79
3 changed files with 92 additions and 77 deletions

View File

@ -1,83 +1,77 @@
# Builds an ext2 image containing a populated /nix/store with the closure
# of store paths passed in the storePaths parameter, in addition to the
# contents of a directory that can be populated with commands. The
# generated image is sized to only fit its contents, with the expectation
# that a script resizes the filesystem at boot time.
{ pkgs
, lib
# List of derivations to be included
, storePaths
# Shell commands to populate the ./files directory.
# All files in that directory are copied to the root of the FS.
, populateImageCommands ? ""
, volumeLabel
, uuid ? "44444444-4444-4444-8888-888888888888"
, e2fsprogs
, libfaketime
, perl
, fakeroot
, qemu
}:
{ config, pkgs }:
let
sdClosureInfo = pkgs.buildPackages.closureInfo { rootPaths = storePaths; };
in
pkgs.stdenv.mkDerivation {
name = "ext2-fs.qcow2";
grub' = pkgs.buildPackages.grub2_efi;
sdClosureInfo = pkgs.buildPackages.closureInfo {
rootPaths = config.genode.boot.storePaths;
};
in pkgs.stdenv.mkDerivation {
name = "ext2-fs.img.zstd";
nativeBuildInputs = [ e2fsprogs.bin libfaketime perl fakeroot qemu ];
nativeBuildInputs = with pkgs.buildPackages; [
e2fsprogs.bin
grub'
libfaketime
perl
fakeroot
zstd
];
buildCommand =
''
img=temp.raw
(
mkdir -p ./files
${populateImageCommands}
)
buildCommand = ''
img=temp.raw
echo "Preparing store paths for image..."
# Create nix/store before copying path
mkdir -p ./rootImage/boot/grub ./rootImage/nix/store
# Create nix/store before copying path
mkdir -p ./rootImage/nix/store
cat <<EOF > ./rootImage/boot/grub/grub.cfg
set timeout=3
set default=0
set gfxpayload=auto
xargs -I % cp -a --reflink=auto % -t ./rootImage/nix/store/ < ${sdClosureInfo}/store-paths
(
GLOBIGNORE=".:.."
shopt -u dotglob
${config.boot.loader.grub.extraEntries}
EOF
for f in ./files/*; do
cp -a --reflink=auto -t ./rootImage/ "$f"
done
)
grub-script-check ./rootImage/boot/grub/grub.cfg
# Also include a manifest of the closures in a format suitable for nix-store --load-db
cp ${sdClosureInfo}/registration ./rootImage/nix-path-registration
xargs -I % cp -a --reflink=auto % -t ./rootImage/nix/store/ < ${sdClosureInfo}/store-paths
(
GLOBIGNORE=".:.."
shopt -u dotglob
# Make a crude approximation of the size of the target image.
# If the script starts failing, increase the fudge factors here.
numInodes=$(find ./rootImage | wc -l)
numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
echo "Creating an EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
for f in ./files/*; do
cp -a --reflink=auto -t ./rootImage/ "$f"
done
)
truncate -s $bytes $img
# Also include a manifest of the closures in a format suitable for nix-store --load-db
cp ${sdClosureInfo}/registration ./rootImage/nix-path-registration
faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext2 -L ${volumeLabel} -U ${uuid} -d ./rootImage $img
# Make a crude approximation of the size of the target image.
# If the script starts failing, increase the fudge factors here.
numInodes=$(find ./rootImage | wc -l)
numDataBlocks=$(du -s -c -B 4096 --apparent-size ./rootImage | tail -1 | awk '{ print int($1 * 1.10) }')
bytes=$((2 * 4096 * $numInodes + 4096 * $numDataBlocks))
echo "Creating an EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks)"
export EXT2FS_NO_MTAB_OK=yes
# I have ended up with corrupted images sometimes, I suspect that happens when the build machine's disk gets full during the build.
if ! fsck.ext2 -n -f $img; then
echo "--- Fsck failed for EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks) ---"
cat errorlog
return 1
fi
truncate --size=$bytes $img
echo "Resizing to minimum allowed size"
resize2fs -M $img
faketime -f "1970-01-01 00:00:01" fakeroot mkfs.ext2 -L NIXOS_GENODE -U ${config.genode.boot.storeFsUuid} -d ./rootImage $img
# And a final fsck, because of the previous truncating.
fsck.ext2 -n -f $img
export EXT2FS_NO_MTAB_OK=yes
# I have ended up with corrupted images sometimes, I suspect that happens when the build machine's disk gets full during the build.
if ! fsck.ext2 -n -f $img; then
echo "--- Fsck failed for EXT2 image of $bytes bytes (numInodes=$numInodes, numDataBlocks=$numDataBlocks) ---"
cat errorlog
return 1
fi
qemu-img convert $img $out
'';
echo "Resizing to minimum allowed size"
resize2fs -M $img
# And a final fsck, because of the previous truncating.
fsck.ext2 -n -f $img
# Compress to store
zstd --verbose --no-progress ./$img -o $out
'';
}

View File

@ -7,6 +7,17 @@ let
inherit (config.nixpkgs) system localSystem crossSystem;
inherit pkgs;
};
bootDir = pkgs.runCommand "${config.system.name}-bootdir" { } ''
mkdir $out
gz() {
gzip --keep --to-stdout "$1" > "$2"
}
gz ${pkgs.genodePackages.genodeSources}/tool/boot/bender $out/bender.gz
gz ${pkgs.genodePackages.NOVA}/hypervisor-x86_64 $out/hypervisor.gz
gz ${config.genode.boot.image}/image.elf $out/image.elf.gz
'';
in {
genode.core = {
prefix = "nova-";
@ -15,13 +26,27 @@ in {
};
genode.boot = {
initrd =
"'${pkgs.genodePackages.NOVA}/hypervisor-x86_64 arg=iommu novpid serial,${config.genode.boot.image}/image.elf'";
image =
utils.novaImage config.system.name { } config.genode.boot.configFile;
};
genode.boot.storePaths =
lib.optional (config.genode.boot.storeBackend == "usb") bootDir;
virtualisation.qemu.options =
lib.optionals (!config.virtualisation.useBootLoader) [
"-kernel '${pkgs.genodePackages.bender}/share/bender/bender'"
"-initrd '${pkgs.genodePackages.NOVA}/hypervisor-x86_64 arg=iommu logmem novpid serial,${config.genode.boot.image}/image.elf'"
];
boot.loader.grub.extraEntries = ''
menuentry 'Genode on NOVA' {
insmod multiboot2
insmod gzio
multiboot2 ${bootDir}/bender.gz serial_fallback
module2 ${bootDir}/hypervisor.gz hypervisor iommu logmem novga novpid serial
module2 ${bootDir}/image.elf.gz image.elf
}
'';
}

View File

@ -83,9 +83,9 @@ let
imap1 (idx: drive: drive // { device = driveDeviceName idx; });
efiPrefix = if (pkgs.stdenv.isi686 || pkgs.stdenv.isx86_64) then
"${pkgs.OVMF.fd}/FV/OVMF"
"${pkgs.buildPackages.OVMF.fd}/FV/OVMF"
else if pkgs.stdenv.isAarch64 then
"${pkgs.OVMF.fd}/FV/AAVMF"
"${pkgs.buildPackages.OVMF.fd}/FV/AAVMF"
else
throw "No EFI firmware available for platform";
efiFirmware = "${efiPrefix}_CODE.fd";
@ -516,10 +516,6 @@ in {
"-device usb-kbd"
"-device usb-tablet"
])
(mkIf (!cfg.useBootLoader) [
"-kernel ${config.genode.boot.kernel}"
"-initrd ${config.genode.boot.initrd}"
])
(mkIf cfg.useEFIBoot [
"-drive if=pflash,format=raw,unit=0,readonly,file=${efiFirmware}"
"-drive if=pflash,format=raw,unit=1,file=$NIX_EFI_VARS"