Mic92 / nixos-aarch64-images

Build NixOS images for various ARM single computer boards
79 stars 20 forks source link

Pass calculated size to sfdisk arguments #12

Closed FPtje closed 1 year ago

FPtje commented 1 year ago

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 by build-image.py.

Setup

My setup is as follows:

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:

manifest.json ```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 } } } ```

The problem

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.

Mic92 commented 1 year ago

Thanks. Finally merged in https://github.com/Mic92/nixos-aarch64-images/pull/13