2022-06-23 10:39:09 +00:00
|
|
|
{ config, lib, pkgs, mobile-nixos, utils, ... }:
|
2022-06-23 07:24:39 +00:00
|
|
|
|
2022-06-24 07:10:07 +00:00
|
|
|
with lib;
|
2022-06-23 10:39:09 +00:00
|
|
|
let
|
2022-08-01 07:23:49 +00:00
|
|
|
cfg = config.sane.image;
|
2022-06-24 07:10:07 +00:00
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
2022-08-01 21:01:46 +00:00
|
|
|
# packages whose contents should be copied directly into the /boot partition.
|
|
|
|
# e.g. EFI loaders, u-boot bootloader, etc.
|
2022-08-01 07:23:49 +00:00
|
|
|
sane.image.extraBootFiles = mkOption {
|
2022-06-24 07:10:07 +00:00
|
|
|
default = [];
|
|
|
|
type = types.listOf types.package;
|
|
|
|
};
|
2022-08-01 21:37:19 +00:00
|
|
|
# extra (empty) directories to create in the rootfs.
|
|
|
|
# for example, /var/log might be required by the boot process, so ensure it exists.
|
|
|
|
sane.image.extraDirectories = mkOption {
|
|
|
|
default = [];
|
|
|
|
type = types.listOf types.str;
|
|
|
|
};
|
2022-08-01 21:01:46 +00:00
|
|
|
|
|
|
|
# the GPT header is fixed to Logical Block Address 1,
|
|
|
|
# but we can actually put the partition entries anywhere.
|
|
|
|
# this option reserves so many bytes after LBA 1 but *before* the partition entries.
|
|
|
|
# this is not universally supported, but is an easy hack to claim space near the start
|
|
|
|
# of the disk for other purposes (e.g. firmware blobs)
|
2022-08-01 07:23:49 +00:00
|
|
|
sane.image.extraGPTPadding = mkOption {
|
2022-06-24 07:53:43 +00:00
|
|
|
default = 0;
|
2022-06-29 08:17:53 +00:00
|
|
|
# NB: rpi doesn't like non-zero values for this.
|
|
|
|
# at the same time, spinning disks REALLY need partitions to be aligned to 4KiB boundaries.
|
|
|
|
# maybe there's some imageBuilder.fileSystem type which represents empty space?
|
|
|
|
# default = 2014 * 512; # standard is to start part0 at sector 2048 (versus 34 if no padding)
|
2022-06-24 07:53:43 +00:00
|
|
|
type = types.int;
|
|
|
|
};
|
2022-08-01 21:01:46 +00:00
|
|
|
# optional space (in bytes) to leave unallocated after the GPT structure and before the first partition.
|
2022-08-01 07:23:49 +00:00
|
|
|
sane.image.firstPartGap = mkOption {
|
2022-06-29 08:17:53 +00:00
|
|
|
# align the first part to 16 MiB.
|
|
|
|
# do this by inserting a gap of 16 MiB - gptHeaderSize
|
|
|
|
# and then multiply by 1MiB and subtract 1 because mobile-nixos
|
|
|
|
# has a bug which will divide this by 1 MiB (and round up)
|
|
|
|
default = (16 * 1024 * 1024 - 34 * 512) * 1024 * 1024 - 1;
|
|
|
|
type = types.nullOr types.int;
|
|
|
|
};
|
2022-08-01 07:23:49 +00:00
|
|
|
sane.image.bootPartSize = mkOption {
|
2022-06-24 09:07:40 +00:00
|
|
|
default = 512 * 1024 * 1024;
|
|
|
|
type = types.int;
|
|
|
|
};
|
2022-06-24 07:10:07 +00:00
|
|
|
};
|
|
|
|
config = let
|
|
|
|
# return true if super starts with sub
|
|
|
|
startsWith = super: sub: (
|
|
|
|
(builtins.substring 0 (builtins.stringLength sub) super) == sub
|
|
|
|
);
|
|
|
|
# return the (string) path to get from `stem` to `path`
|
2022-08-02 23:03:32 +00:00
|
|
|
# or errors if not a sub-path
|
2022-06-24 07:10:07 +00:00
|
|
|
relPath = stem: path: (
|
|
|
|
builtins.head (builtins.match "^${stem}(.+)" path)
|
|
|
|
);
|
2022-06-23 11:48:33 +00:00
|
|
|
|
2022-06-24 07:10:07 +00:00
|
|
|
fileSystems = config.fileSystems;
|
|
|
|
bootFs = fileSystems."/boot";
|
|
|
|
nixFs = fileSystems."/nix/store" or fileSystems."/nix" or fileSystems."/";
|
|
|
|
# resolves to e.g. "nix/store", "/store" or ""
|
|
|
|
storeRelPath = relPath nixFs.mountPoint "/nix/store";
|
2022-06-23 11:48:33 +00:00
|
|
|
|
2022-06-24 07:10:07 +00:00
|
|
|
uuidFromFs = fs: builtins.head (builtins.match "/dev/disk/by-uuid/(.+)" fs.device);
|
|
|
|
vfatUuidFromFs = fs: builtins.replaceStrings ["-"] [""] (uuidFromFs fs);
|
2022-06-23 22:28:33 +00:00
|
|
|
|
2022-06-24 07:10:07 +00:00
|
|
|
fsBuilderMapBoot = {
|
|
|
|
"vfat" = pkgs.imageBuilder.fileSystem.makeESP;
|
|
|
|
};
|
|
|
|
fsBuilderMapNix = {
|
|
|
|
"ext4" = pkgs.imageBuilder.fileSystem.makeExt4;
|
|
|
|
"btrfs" = pkgs.imageBuilder.fileSystem.makeBtrfs;
|
|
|
|
};
|
|
|
|
in {
|
|
|
|
system.build.img-without-firmware = with pkgs; imageBuilder.diskImage.makeGPT {
|
|
|
|
name = "nixos";
|
|
|
|
diskID = vfatUuidFromFs bootFs;
|
|
|
|
# leave some space for firmware
|
|
|
|
# TODO: we'd prefer to turn this into a protected firmware partition, rather than reserving space in the GPT header itself
|
|
|
|
# Tow-Boot manages to do that; not sure how.
|
2022-06-24 07:53:43 +00:00
|
|
|
headerHole = cfg.extraGPTPadding;
|
2022-06-24 07:10:07 +00:00
|
|
|
partitions = [
|
2022-06-29 08:17:53 +00:00
|
|
|
(pkgs.imageBuilder.gap cfg.firstPartGap)
|
2022-06-24 07:10:07 +00:00
|
|
|
(fsBuilderMapBoot."${bootFs.fsType}" {
|
|
|
|
# fs properties
|
|
|
|
name = "ESP";
|
|
|
|
partitionID = vfatUuidFromFs bootFs;
|
|
|
|
# partition properties
|
|
|
|
partitionLabel = "EFI System";
|
|
|
|
partitionUUID = "44444444-4444-4444-4444-4444${vfatUuidFromFs bootFs}";
|
2022-06-24 09:07:40 +00:00
|
|
|
size = cfg.bootPartSize;
|
2022-05-22 05:00:38 +00:00
|
|
|
|
2022-06-24 07:10:07 +00:00
|
|
|
populateCommands = let
|
|
|
|
extras = builtins.toString (builtins.map (d: "cp -R ${d}/* ./") cfg.extraBootFiles);
|
|
|
|
in ''
|
|
|
|
echo "running installBootLoader"
|
|
|
|
${config.system.build.installBootLoader} ${config.system.build.toplevel} -d .
|
|
|
|
echo "ran installBootLoader"
|
|
|
|
${extras}
|
|
|
|
echo "copied extraBootFiles"
|
|
|
|
'';
|
|
|
|
})
|
|
|
|
(fsBuilderMapNix."${nixFs.fsType}" {
|
|
|
|
# fs properties
|
|
|
|
name = "NIXOS_SYSTEM";
|
|
|
|
partitionID = uuidFromFs nixFs;
|
|
|
|
# partition properties
|
|
|
|
partitionLabel = "Linux filesystem";
|
|
|
|
partitionUUID = uuidFromFs nixFs;
|
|
|
|
populateCommands =
|
|
|
|
let
|
|
|
|
closureInfo = buildPackages.closureInfo { rootPaths = config.system.build.toplevel; };
|
2022-08-03 00:08:26 +00:00
|
|
|
extraRelPaths = builtins.toString (builtins.map (p: "./" + builtins.toString(relPath nixFs.mountPoint p)) cfg.extraDirectories);
|
2022-06-24 07:10:07 +00:00
|
|
|
in
|
|
|
|
''
|
2022-08-01 21:37:19 +00:00
|
|
|
mkdir -p ./${storeRelPath} ${extraRelPaths}
|
2022-06-24 07:10:07 +00:00
|
|
|
echo "Copying system closure..."
|
|
|
|
while IFS= read -r path; do
|
|
|
|
echo " Copying $path"
|
|
|
|
cp -prf "$path" ./${storeRelPath}
|
|
|
|
done < "${closureInfo}/store-paths"
|
|
|
|
echo "Done copying system closure..."
|
|
|
|
cp -v ${closureInfo}/registration ./nix-path-registration
|
|
|
|
'';
|
|
|
|
})
|
|
|
|
];
|
|
|
|
};
|
|
|
|
system.build.img = lib.mkDefault config.system.build.img-without-firmware;
|
2022-05-22 05:00:38 +00:00
|
|
|
};
|
|
|
|
}
|