modules/image.nix: remove dependency on mobile-nixos
the images build, but i have not tried booting them
This commit is contained in:
@@ -39,7 +39,6 @@ let
|
||||
"linux-postmarketos-allwinner"
|
||||
"linux-postmarketos-exynos5"
|
||||
"linux-postmarketos-pinephonepro"
|
||||
"mobile-nixos"
|
||||
"nixpkgs-bootstrap"
|
||||
"nixpkgs-wayland"
|
||||
"sops-nix"
|
||||
|
@@ -23,12 +23,6 @@ in
|
||||
default = [];
|
||||
type = types.listOf types.package;
|
||||
};
|
||||
# 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;
|
||||
};
|
||||
|
||||
# the GPT header is fixed to Logical Block Address 1,
|
||||
# but we can actually put the partition entries anywhere.
|
||||
@@ -47,9 +41,7 @@ in
|
||||
sane.image.firstPartGap = mkOption {
|
||||
# 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;
|
||||
default = 16 * 1024 * 1024 - 34 * 512;
|
||||
type = types.nullOr types.int;
|
||||
};
|
||||
sane.image.platformPartSize = mkOption {
|
||||
@@ -107,91 +99,276 @@ in
|
||||
uuidFromFs = fs: builtins.head (builtins.match "/dev/disk/by-uuid/(.+)" fs.device);
|
||||
vfatUuidFromFs = fs: builtins.replaceStrings ["-"] [""] (uuidFromFs fs);
|
||||
|
||||
fsBuilderMapBoot = {
|
||||
"vfat" = pkgs.mobile-nixos.imageBuilder.fileSystem.makeESP;
|
||||
};
|
||||
fsBuilderMapNix = {
|
||||
"ext4" = pkgs.mobile-nixos.imageBuilder.fileSystem.makeExt4;
|
||||
"btrfs" = pkgs.mobile-nixos.imageBuilder.fileSystem.makeBtrfs;
|
||||
};
|
||||
# TODO: consolidate bootFsImg, nixFsImg builders; split into separate file?
|
||||
|
||||
bootFsImg = fsBuilderMapBoot."${bootFs.fsType}" {
|
||||
# fs properties
|
||||
name = "ESP";
|
||||
bootFsImg = pkgs.runCommandNoCC "ESP" {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
dosfstools
|
||||
libfaketime
|
||||
mtools
|
||||
];
|
||||
partitionID = vfatUuidFromFs bootFs;
|
||||
size = cfg.bootPartSize;
|
||||
sectorSize = cfg.sectorSize;
|
||||
# partition properties
|
||||
partitionLabel = "EFI System";
|
||||
partitionType = "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"; # "EFI"
|
||||
partitionUUID = "44444444-4444-4444-4444-4444${vfatUuidFromFs bootFs}";
|
||||
size = cfg.bootPartSize;
|
||||
inherit (cfg) sectorSize;
|
||||
blockSize = cfg.sectorSize; # has to be a multiple of sectorSize
|
||||
} ''
|
||||
# hoisted (in simplified form) from pkgs.mobile-nixos.imageBuilder.fileSystem.makeESP
|
||||
mkdir -p $out
|
||||
mkdir -p files
|
||||
|
||||
populateCommands = let
|
||||
extras = builtins.toString (builtins.map (d: "cp -R ${d}/* ./") cfg.extraBootFiles);
|
||||
in ''
|
||||
(
|
||||
cd files
|
||||
echo "running installBootLoader"
|
||||
${config.boot.loader.generic-extlinux-compatible.populateCmd} -c ${config.system.build.toplevel} -d .
|
||||
echo "ran installBootLoader"
|
||||
${extras}
|
||||
for d in ${lib.escapeShellArgs cfg.extraBootFiles}; do
|
||||
cp -R $d/* ./
|
||||
done
|
||||
echo "copied extraBootFiles"
|
||||
'';
|
||||
};
|
||||
nixFsImg = fsBuilderMapNix."${nixFs.fsType}" {
|
||||
)
|
||||
|
||||
(
|
||||
set -x
|
||||
truncate -s $size "$out/partition.img"
|
||||
)
|
||||
|
||||
echo " -> Making filesystem"
|
||||
faketime -f "1970-01-01 00:00:01" mkfs.vfat \
|
||||
-F 32 \
|
||||
-S "$sectorSize" \
|
||||
-i "$partitionID" \
|
||||
-n "$partName" \
|
||||
"$out/partition.img"
|
||||
|
||||
echo " -> Copying files"
|
||||
(
|
||||
cd files
|
||||
for f in ./* ./.*; do
|
||||
if [[ "$f" != "./." && "$f" != "./.." ]]; then
|
||||
faketime -f "1970-01-01 00:00:01" \
|
||||
mcopy -psv -i "$out/partition.img" "$f" ::
|
||||
fi
|
||||
done
|
||||
)
|
||||
|
||||
echo " -> Checking filesystem"
|
||||
fsck.vfat -vn "$out/partition.img"
|
||||
|
||||
cat >> $out/layout.json <<EOF
|
||||
{
|
||||
"partitionType": "$partitionType",
|
||||
"partitionUUID": "$partitionUUID",
|
||||
"partitionLabel": "$partitionLabel"
|
||||
}
|
||||
EOF
|
||||
'';
|
||||
|
||||
nixFsImg = pkgs.runCommandNoCC "NIXOS_SYSTEM" {
|
||||
# fs properties
|
||||
name = "NIXOS_SYSTEM";
|
||||
nativeBuildInputs = with pkgs; [ btrfs-progs ];
|
||||
blockSize = cfg.sectorSize;
|
||||
partitionID = uuidFromFs nixFs;
|
||||
# partition properties
|
||||
partitionLabel = "Linux filesystem";
|
||||
partitionType = "0FC63DAF-8483-4772-8E79-3D69D8477DE4"; # "Linux filesystem data"
|
||||
partitionUUID = uuidFromFs nixFs;
|
||||
# inherit (cfg) sectorSize; # imageBuilder only supports sectorSize for vfat. btrfs defaults to a 4096B sector size, somehow it abstracts over the drive's sector size?
|
||||
} ''
|
||||
# hoisted (in simplified form) from pkgs.mobile-nixos.imageBuilder.fileSystem.makeBtrfs
|
||||
sum-lines() {
|
||||
local acc=0
|
||||
while read -r number; do
|
||||
acc=$(( $acc + $number))
|
||||
done
|
||||
|
||||
populateCommands = let
|
||||
closureInfo = pkgs.buildPackages.closureInfo { rootPaths = config.system.build.toplevel; };
|
||||
extraRelPaths = builtins.toString (builtins.map (p: "./" + builtins.toString(relPath nixFs.mountPoint p)) cfg.extraDirectories);
|
||||
in ''
|
||||
mkdir -p ./${storeRelPath} ${extraRelPaths}
|
||||
echo "$acc"
|
||||
}
|
||||
|
||||
compute-minimal-size() {
|
||||
local size=0
|
||||
(
|
||||
cd files
|
||||
# Size rounded in blocks. This assumes all files are to be rounded to a
|
||||
# multiple of blockSize.
|
||||
# Use of `--apparent-size` is to ensure we don't get the block size of the underlying FS.
|
||||
# Use of `--block-size` is to get *our* block size.
|
||||
size=$(find . ! -type d -print0 | du --files0-from=- --apparent-size --block-size "$blockSize" | cut -f1 | sum-lines)
|
||||
echo "Reserving $size sectors for files..." 1>&2
|
||||
|
||||
# Adds one blockSize per directory, they do take some place, in the end.
|
||||
local directories=$(find . -type d | wc -l)
|
||||
echo "Reserving $directories sectors for directories..." 1>&2
|
||||
)
|
||||
|
||||
size=$(( $directories + $size ))
|
||||
size=$(( $size * $blockSize))
|
||||
echo "$size"
|
||||
}
|
||||
|
||||
mkdir -p $out
|
||||
mkdir -p files
|
||||
|
||||
(
|
||||
cd files
|
||||
mkdir -p ./${storeRelPath}
|
||||
echo "Copying system closure..."
|
||||
while IFS= read -r path; do
|
||||
echo " Copying $path"
|
||||
cp -prf "$path" ./${storeRelPath}
|
||||
done < "${closureInfo}/store-paths"
|
||||
done < "${pkgs.buildPackages.closureInfo { rootPaths = config.system.build.toplevel; }}/store-paths"
|
||||
echo "Done copying system closure..."
|
||||
cp -v ${closureInfo}/registration ./nix-path-registration
|
||||
'';
|
||||
};
|
||||
img = (pkgs.mobile-nixos.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.
|
||||
headerHole = cfg.extraGPTPadding;
|
||||
partitions = [
|
||||
(pkgs.mobile-nixos.imageBuilder.gap cfg.firstPartGap)
|
||||
] ++ lib.optionals (cfg.platformPartSize != null) [
|
||||
{
|
||||
name = "kernel"; #< TODO: is it safe to rename this?
|
||||
filename = "${config.system.build.platformPartition}";
|
||||
# from: <https://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format>
|
||||
partitionType = "FE3A2A5D-4F32-41A7-B725-ACCC3285A309";
|
||||
length = cfg.platformPartSize;
|
||||
}
|
||||
)
|
||||
|
||||
(
|
||||
size=$(compute-minimal-size)
|
||||
|
||||
set -x
|
||||
truncate -s $size "$out/partition.img"
|
||||
)
|
||||
|
||||
(
|
||||
cd files
|
||||
set -x
|
||||
mkfs.btrfs \
|
||||
-r . \
|
||||
-L "$partName" \
|
||||
-U "$partitionID" \
|
||||
--shrink \
|
||||
"$out/partition.img"
|
||||
)
|
||||
|
||||
cat >> $out/layout.json <<EOF
|
||||
{
|
||||
"partitionType": "$partitionType",
|
||||
"partitionUUID": "$partitionUUID",
|
||||
"partitionLabel": "$partitionLabel"
|
||||
}
|
||||
EOF
|
||||
'';
|
||||
|
||||
platformFsImg = pkgs.runCommandNoCC "kernel" {
|
||||
filename = "${config.system.build.platformPartition}";
|
||||
partSize = cfg.platformPartSize;
|
||||
partImage = config.system.build.platformPartition;
|
||||
# from: <https://www.chromium.org/chromium-os/chromiumos-design-docs/disk-format>
|
||||
partitionType = "FE3A2A5D-4F32-41A7-B725-ACCC3285A309"; # "ChromeOS Kernel"
|
||||
partitionLabel = "kernel"; #< TODO: is it safe to rename this?
|
||||
} ''
|
||||
mkdir $out
|
||||
truncate -s $partSize $out/partition.img
|
||||
dd if=$partImage of=$out/partition.img bs=512
|
||||
# TODO: assert that the `dd` command didn't overflow the allocated partition space
|
||||
cat >> $out/layout.json <<EOF
|
||||
{
|
||||
"partitionType": "$partitionType",
|
||||
"partitionUUID": "$partitionUUID",
|
||||
"partitionLabel": "$partitionLabel"
|
||||
}
|
||||
EOF
|
||||
'';
|
||||
|
||||
img = pkgs.runCommandNoCC "nixos" {
|
||||
nativeBuildInputs = with pkgs; [
|
||||
jq
|
||||
vboot_reference
|
||||
];
|
||||
partitions = lib.optionals (cfg.platformPartSize != null) [
|
||||
platformFsImg
|
||||
] ++ [
|
||||
bootFsImg
|
||||
nixFsImg
|
||||
];
|
||||
}) // {
|
||||
firstPartGap = cfg.firstPartGap;
|
||||
sectorSize = cfg.sectorSize;
|
||||
passthru = {
|
||||
inherit bootFsImg nixFsImg;
|
||||
};
|
||||
};
|
||||
} ''
|
||||
# hoisted (in simplified form) from pkgs.mobile-nixos.imageBuilder.diskImage.makeGPT
|
||||
roundUp() {
|
||||
# adjusts $1 upward until it's a multiple of $2.
|
||||
local inp=$1
|
||||
local mult=$2
|
||||
if (($inp % $mult)); then
|
||||
echo $(( $mult + $inp / $mult * $mult ))
|
||||
else
|
||||
echo $inp
|
||||
fi
|
||||
}
|
||||
getPartSize() {
|
||||
local partImg="$1/partition.img"
|
||||
local partSize=$(($(du --apparent-size -B 512 "$partImg" | awk '{ print $1 }') * 512))
|
||||
echo $(roundUp $partSize $mb)
|
||||
}
|
||||
mb=$((1024*1024))
|
||||
|
||||
mkdir -p $out
|
||||
|
||||
# 34 is the base GPT header size, as added to -p by cgpt.
|
||||
gptSize=$((34*512))
|
||||
part0Start=$(( $gptSize + $firstPartGap ))
|
||||
|
||||
(
|
||||
# solve for the size of the disk image
|
||||
echo "planned disk layout:"
|
||||
echo "- 0 -> primary GPT header"
|
||||
totalSize=$part0Start
|
||||
for part in $partitions; do
|
||||
echo "- $totalSize -> $part"
|
||||
partSize=$(getPartSize $part)
|
||||
totalSize=$(( $totalSize + $partSize ))
|
||||
done
|
||||
echo "- $totalSize -> secondary GPT header"
|
||||
totalSize=$(( $totalSize + $gptSize ))
|
||||
echo "- $totalSize -> end of disk"
|
||||
|
||||
truncate -s $totalSize $out/disk.img
|
||||
# Zeroes the GPT
|
||||
cgpt create -z $out/disk.img
|
||||
# Create the GPT with space if desired
|
||||
cgpt create -p 0 $out/disk.img
|
||||
# Add the PMBR
|
||||
cgpt boot -p $out/disk.img
|
||||
)
|
||||
|
||||
(
|
||||
partStart=$part0Start
|
||||
for part in $partitions; do
|
||||
partSize=$(getPartSize $part)
|
||||
partitionType=$(jq -r .partitionType $part/layout.json)
|
||||
partitionUUID=$(jq -r .partitionUUID $part/layout.json)
|
||||
partitionLabel=$(jq -r .partitionLabel $part/layout.json)
|
||||
|
||||
(
|
||||
set -x
|
||||
cgpt add \
|
||||
-b "$(( $partStart / $sectorSize ))" \
|
||||
-s "$(( $partSize / $sectorSize ))" \
|
||||
-t "$partitionType" \
|
||||
-u "$partitionUUID" \
|
||||
-l "$partitionLabel" \
|
||||
$out/disk.img
|
||||
dd conv=notrunc if=$part/partition.img of=$out/disk.img \
|
||||
seek=$(( $partStart / $sectorSize)) count=$(( $partSize / $sectorSize )) bs=$sectorSize
|
||||
)
|
||||
|
||||
partStart=$(( $partStart + $partSize ))
|
||||
done
|
||||
)
|
||||
|
||||
echo "disk image created:"
|
||||
ls -lh $out/disk.img
|
||||
cgpt show $out/disk.img
|
||||
'';
|
||||
in
|
||||
{
|
||||
system.build.img = pkgs.runCommand "nixos-with-bootloader" {
|
||||
system.build.img = pkgs.runCommandNoCC "nixos-with-bootloader" {
|
||||
preferLocalBuild = true;
|
||||
passthru = {
|
||||
inherit bootFsImg nixFsImg;
|
||||
withoutBootloader = img; #< XXX: this derivation places the image at $out/nixos.img
|
||||
withoutBootloader = img; #< XXX: this derivation places the image at $out/disk.img
|
||||
};
|
||||
} (
|
||||
if cfg.installBootloader == null then ''
|
||||
|
@@ -1,19 +0,0 @@
|
||||
{ pkgs
|
||||
, fetchFromGitHub
|
||||
}:
|
||||
let
|
||||
src = fetchFromGitHub {
|
||||
owner = "nixos";
|
||||
repo = "mobile-nixos";
|
||||
# XXX: commit `0f3ac0bef1aea70254a3bae35e3cc2561623f4c1`
|
||||
# replaces the imageBuilder with a "new implementation from celun" and wildly breaks my use.
|
||||
# pinning to d25d3b... is equivalent to holding at 2023-09-15
|
||||
rev = "d25d3b87e7f300d8066e31d792337d9cd7ecd23b";
|
||||
hash = "sha256-MiVokKlpcJmfoGuWAMeW1En7gZ5hk0rCQArYm6P9XCc=";
|
||||
};
|
||||
overlay = import "${src}/overlay/overlay.nix";
|
||||
final = pkgs.extend overlay;
|
||||
in src.overrideAttrs (base: {
|
||||
# passthru only mobile-nixos' own packages -- not the whole nixpkgs-with-mobile-nixos-as-overlay:
|
||||
passthru = base.passthru // (overlay final pkgs);
|
||||
})
|
Reference in New Issue
Block a user