This fixes a bug I encountered while using this script against a custom image based on nixpkgs/nixos/modules/installer/sd-card/sd-image-aarch64.nix. Specifically, the Linux partition on the original image was larger than what ended up being created by build-image.py.
Setup
My setup is as follows:
RockPro64, 4GB, using an SD card for the OS
nixpkgs on revision 5dc7114b7b256d217fe7752f1614be2514e61bb8, a nixpkgs-unstable commit from 2022-11-25
The original sd-image-aarch64.nix generated image (config.system.build.sdImage) looks like this:
Name
Start
blocks
(empty)
0
16384
U-Boot
16384
61440
Linux
77824
14275544
The manifest passed to the build-image.py is as follows:
The actual image built by build-image.py looks like this:
Name
Start
blocks
(empty)
0
64
idbloader
64
16320
U-Boot
16384
16384
Linux
32768
14275544 14274560
Struck through is the partition size one would expect, and besides it is the actual partition size. It's a difference of 984 blocks.
This leads to an image that properly starts U-Boot, before failing on an fsck.ext4 check of the Linux partition. This first reports that the partition is the wrong size. Ignoring that error causes boot to fail due to a corrupt filesystem.
For reference, here is the full log of the image build:
Full command log
```
nix-repl> :b packages.falco-rockpro64-image-test
image> patching sources
image> configuring
image> no configure script, doing nothing
image> building
image> /nix/store/ar1dn2gsijf52wqcxyfg57kbvzp6vypm-build-image.py /nix/store/3a552vwb7vgmmc8j8fwmdwy17f4jzrqh-manifest.json /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image
image> sfdisk /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image <<'EOF'
image> label: gpt
image> unit: sectors
image> first-lba: 64
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="idbloader", start=0x40, size=0x3fc0, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4"
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="uboot", start=0x4000, size=0x4000, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4"
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="nixos", start=0x8000, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4", attrs="LegacyBIOSBootable"
image> EOF
image> Checking that no-one is using this disk right now ... OK
image> Disk /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: 6.82 GiB, 7325872640 bytes, 14308345 sectors
image> Units: sectors of 1 * 512 = 512 bytes
image> Sector size (logical/physical): 512 bytes / 512 bytes
image> I/O size (minimum/optimal): 512 bytes / 512 bytes
image> >>> Script header accepted.
image> >>> Script header accepted.
image> >>> Script header accepted.
image> >>> Created a new GPT disklabel (GUID: F88ED0DE-F46A-F743-BE9B-ED2980CEB17C).
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image1: Created a new partition 1 of type 'Linux filesystem' and of size 8 MiB.
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image2: Created a new partition 2 of type 'Linux filesystem' and of size 8 MiB.
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image3: Created a new partition 3 of type 'Linux filesystem' and of size 6.8 GiB.
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image4: Done.
image> New situation:
image> Disklabel type: gpt
image> Disk identifier: F88ED0DE-F46A-F743-BE9B-ED2980CEB17C
image> Device Start End Sectors Size Type
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image1 64 16383 16320 8M Linu
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image2 16384 32767 16384 8M Linu
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image3 32768 14307327 14274560 6.8G Linu
image> The partition table has been altered.
image> Syncing disks.
image> $ dd if=/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/idbloader.img of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=0 seek=32768 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=8355840
image> 0+1 records in
image> 0+1 records out
image> 172032 bytes (172 kB, 168 KiB) copied, 0.00817264 s, 21.0 MB/s
image> $ dd if=/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/u-boot.itb of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=0 seek=8388608 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=8388608
image> 0+1 records in
image> 0+1 records out
image> 1034128 bytes (1.0 MB, 1010 KiB) copied, 0.0148625 s, 69.6 MB/s
image> $ dd if=/nix/store/92ilkjr42nif1cczxrlla8m1jv0jpd3h-falco-rockpro64.img of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=39845888 seek=16777216 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=7309078528 (14275544 sectors)
image> 7230980096 bytes (7.2 GB, 6.7 GiB) copied, 35 s, 207 MB/s7309078528 bytes (7.3 GB, 6.8 GiB) copied, 35.3169 s, 207 MB/s
image> 435+1 records in
image> 435+1 records out
image> 7309078528 bytes (7.3 GB, 6.8 GiB) copied, 35.3632 s, 207 MB/s
image> $ sfdisk --verify /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image
image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image:
image> No errors detected.
image> Header version: 1.0
image> Using 3 out of 128 partitions.
image> A total of 984 free sectors is available in 1 segment.
image> buildPhase completed in 35 seconds
image> post-installation fixup
This derivation produced the following outputs:
out -> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image
```
Why this fixes the problem
I'm not entirely sure. It seems that everything up to the call to subprocess.run(["sfdisk"... has the correct size information for all partitions. However, since the Linux partition's size is not explicitly passed in the layout argument to sfdisk, sfdisk is left to guess its size. I suppose it does this based on the size of the image file, leading it to have the wrong guess.
Either way, explicitly passing the size of the partition does the trick.
Description
This fixes a bug I encountered while using this script against a custom image based on
nixpkgs/nixos/modules/installer/sd-card/sd-image-aarch64.nix
. Specifically, the Linux partition on the original image was larger than what ended up being created bybuild-image.py
.Setup
My setup is as follows:
5dc7114b7b256d217fe7752f1614be2514e61bb8
, a nixpkgs-unstable commit from 2022-11-25The original
sd-image-aarch64.nix
generated image (config.system.build.sdImage
) looks like this:The manifest passed to the
build-image.py
is as follows:
```json { "firstLba": 64, "format": "gpt", "partitions": { "idbloader": { "attrs": null, "name": "idbloader", "size": 16320, "source": "/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/idbloader.img", "start": 64, "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", "useBootPartition": false }, "nixos": { "attrs": "LegacyBIOSBootable", "name": "nixos", "size": null, "source": "/nix/store/92ilkjr42nif1cczxrlla8m1jv0jpd3h-falco-rockpro64.img", "start": 32768, "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", "useBootPartition": true }, "uboot": { "attrs": null, "name": "uboot", "size": 16384, "source": "/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/u-boot.itb", "start": 16384, "type": "0FC63DAF-8483-4772-8E79-3D69D8477DE4", "useBootPartition": false } } } ```manifest.json
The problem
The actual image built by
build-image.py
looks like this:1427554414274560Struck through is the partition size one would expect, and besides it is the actual partition size. It's a difference of
984
blocks.This leads to an image that properly starts U-Boot, before failing on an
fsck.ext4
check of the Linux partition. This first reports that the partition is the wrong size. Ignoring that error causes boot to fail due to a corrupt filesystem.For reference, here is the full log of the image build:
Full command log
``` nix-repl> :b packages.falco-rockpro64-image-test image> patching sources image> configuring image> no configure script, doing nothing image> building image> /nix/store/ar1dn2gsijf52wqcxyfg57kbvzp6vypm-build-image.py /nix/store/3a552vwb7vgmmc8j8fwmdwy17f4jzrqh-manifest.json /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image image> sfdisk /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image <<'EOF' image> label: gpt image> unit: sectors image> first-lba: 64 image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="idbloader", start=0x40, size=0x3fc0, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="uboot", start=0x4000, size=0x4000, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4" image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: name="nixos", start=0x8000, type="0FC63DAF-8483-4772-8E79-3D69D8477DE4", attrs="LegacyBIOSBootable" image> EOF image> Checking that no-one is using this disk right now ... OK image> Disk /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: 6.82 GiB, 7325872640 bytes, 14308345 sectors image> Units: sectors of 1 * 512 = 512 bytes image> Sector size (logical/physical): 512 bytes / 512 bytes image> I/O size (minimum/optimal): 512 bytes / 512 bytes image> >>> Script header accepted. image> >>> Script header accepted. image> >>> Script header accepted. image> >>> Created a new GPT disklabel (GUID: F88ED0DE-F46A-F743-BE9B-ED2980CEB17C). image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image1: Created a new partition 1 of type 'Linux filesystem' and of size 8 MiB. image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image2: Created a new partition 2 of type 'Linux filesystem' and of size 8 MiB. image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image3: Created a new partition 3 of type 'Linux filesystem' and of size 6.8 GiB. image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image4: Done. image> New situation: image> Disklabel type: gpt image> Disk identifier: F88ED0DE-F46A-F743-BE9B-ED2980CEB17C image> Device Start End Sectors Size Type image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image1 64 16383 16320 8M Linu image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image2 16384 32767 16384 8M Linu image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image3 32768 14307327 14274560 6.8G Linu image> The partition table has been altered. image> Syncing disks. image> $ dd if=/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/idbloader.img of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=0 seek=32768 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=8355840 image> 0+1 records in image> 0+1 records out image> 172032 bytes (172 kB, 168 KiB) copied, 0.00817264 s, 21.0 MB/s image> $ dd if=/nix/store/q4589qfnlsaajhzjn9332g6133lcq82g-uboot-rockpro64-rk3399_defconfig-2022.10/u-boot.itb of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=0 seek=8388608 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=8388608 image> 0+1 records in image> 0+1 records out image> 1034128 bytes (1.0 MB, 1010 KiB) copied, 0.0148625 s, 69.6 MB/s image> $ dd if=/nix/store/92ilkjr42nif1cczxrlla8m1jv0jpd3h-falco-rockpro64.img of=/nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image skip=39845888 seek=16777216 status=progress iflag=direct,count_bytes,skip_bytes oflag=direct,seek_bytes bs=16M conv=fsync,notrunc count=7309078528 (14275544 sectors) image> 7230980096 bytes (7.2 GB, 6.7 GiB) copied, 35 s, 207 MB/s7309078528 bytes (7.3 GB, 6.8 GiB) copied, 35.3169 s, 207 MB/s image> 435+1 records in image> 435+1 records out image> 7309078528 bytes (7.3 GB, 6.8 GiB) copied, 35.3632 s, 207 MB/s image> $ sfdisk --verify /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image image> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image: image> No errors detected. image> Header version: 1.0 image> Using 3 out of 128 partitions. image> A total of 984 free sectors is available in 1 segment. image> buildPhase completed in 35 seconds image> post-installation fixup This derivation produced the following outputs: out -> /nix/store/n99v22pqj13g9jnq7y1ma63kh98j3cdx-image ```Why this fixes the problem
I'm not entirely sure. It seems that everything up to the call to
subprocess.run(["sfdisk"...
has the correct size information for all partitions. However, since the Linux partition's size is not explicitly passed in thelayout
argument tosfdisk
,sfdisk
is left to guess its size. I suppose it does this based on the size of the image file, leading it to have the wrong guess.Either way, explicitly passing the size of the partition does the trick.