NixOS on ARM/Allwinner GPT Installation
This guide is intended to demonstrate how to install NixOS on an Allwinner target device, using u-boot, allowing for use of the GPT partition scheme.
The main advantage of going this way is the ability to boot using a UEFI-based bootloader from u-boot, on one single storage.
This guide uses holey, a script intended to
make this easier. A manual method using cgpt
and gdisk
will be described at
the end.
What will this do?
This will create a GPT partitioned disk with a hole between the Primary GPT header and the Primary GPT Table. The location where the Allwinner SoC looks for the bootloader falls within that hole, and this is where u-boot will be installed. Without that hole, the u-boot bootloader would be installed over the end of the Primary GPT table.
On a MBR partitioned disk, this location is at the beginning of the disk. As long as care is taken not to add a partition over it, there should be no clash.
By using a hole in the GPT, the installed firmware is more resilient to re-partitioning, as long as the GPT table is not cleared and written anew. There is no risk of overwriting the bootloader by manipulating partitions.
Preparations
You will need to boot the installation media from a different storage than the target storage (where you will install). On some, if not most, Allwinner systems, it is possible to boot from USB as long as you can boot u-boot in some manner. This means that you could flash the u-boot bootloader to an empty SD card, and boot from a USB drive containing either the UEFI iso or the SD image installer. Alternatively, some platforms will have multiple storage, and will boot from SD card before booting from the internal storage.
This is needed because the target storage will be erased, while the usual SD image from NixOS expects the user to re-use the partitions from the booted system.
Alternatively, it should be possible to install to a smaller storage, and dd
it to the internal storage and resize the partitions. Though it is untested.
Finally, it is possible to install on a USB connected storage, e.g. to another
SD card in a USB SD reader, or a specialized eMMC USB adapter.
Partitioning
Once booted to the installer system, you will need to get the holey tool.
nix-shell -p 'import (fetchTarball https://github.com/samueldr/holey/archive/master.tar.gz) {}'
This will drop you in a shell with holey available.
Create a new GPT partition table on the target drive. By default it will leave a 2MiB gap which is plenty for the default u-boot builds, with spare space for further increase in size if needed.
$ holey /dev/$DISK init
You can verify that it worked.
$ holey /dev/$DISK check Holey GPT looks fine! start size part contents 0 1 PMBR (Boot GUID: FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF) 1 1 Pri GPT header 4100 32 Pri GPT table 61071327 32 Sec GPT table 61071359 1 Sec GPT header
At that point, the GPT has been split, there is a gap between the header and the table.
You can continue either by using holey
to add partitions, or partition like
you want using tools like cfdisk
, fdisk
or gdisk
.
The next commands will prepare an ESP (EFI System Partition) and a root partition for the system. For the size of the ESP, 512MiB has been chosen, keep in mind that on ARM platforms the kernel is not compressed, and can be around 2-3 times bigger than on x86_64.
holey /dev/$DISK add esp 512 holey /dev/$DISK add linux
The last call will make the partition as big as it can fit.
Installing u-boot
This is done as usually is done.
dd if=result/u-boot-sunxi-with-spl.bin of=/dev/$DISK bs=1024 seek=8 oflag=sync
This is also how an update to u-boot would be installed.
Finishing
From here, the installation process is as usual with NixOS.
Using other tools
Create the hole using gdisk
Follows the transcript, starting from an empty disk.
$ gdisk /dev/$DISK GPT fdisk (gdisk) version 1.0.4 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present Creating new GPT entries in memory. Command (? for help): o This option deletes all partitions and creates a new protective MBR. Proceed? (Y/N): y Command (? for help): x Expert command (? for help): j Currently, main partition table begins at sector 2 and ends at sector 33 Enter new starting location (2 to 18446744073709551583; default is 2; 1 to abort): 4100 Expert command (? for help): m Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): y OK; writing new GUID partition table (GPT) to disk.img. Warning: The kernel is still using the old partition table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8) The operation has completed successfully.
Create the hole using cgpt
cgpt
is a GPT manipulation tool. We start by zeroing the GPT and
continue by creating a new partition table, then add the protective
MBR. Adding that PMBR is what is needed for the kernel and tools to
see and understand the GPT properly.
# Zeroes the GPTs, if it makes sense cgpt create -z /dev/$DISK # Creates new GPTs with space for the bootloader cgpt create -p 4100 /dev/$DISK # Creates the PMBR; also makes the GPT show up in most tools. cgpt boot -p /dev/$DISK