Ubuntu provides all that it is needed to run on many ARM development boards but does not have ready made images for most of them.
The PINE A64-LTS uses an Allwinner A64 SoC and comes with 2 GiB of RAM. This is how installed Ubuntu Mantic on it.
U-Boot
As boot firmware the board uses U-Boot which is available as package u-boot-sunix. On an arm64 system it can easily be installed via
sudo apt-get install u-boot-sunxi
On other architectures I could find the package file in Launchpad on page https://launchpad.net/ubuntu/+source/u-boot. To download, decompress, and list included files:
wget https://launchpad.net/ubuntu/+archive/primary/+files/u-boot-sunxi_2023.07+dfsg-1ubuntu1_arm64.deb
dpkg -x u-boot-sunxi_2023.07+dfsg-1ubuntu1_arm64.deb foo
find foo
I had a look at the README:
zcat /usr/share/doc/u-boot-sunxi/README.sunxi64.gz | less
U-Boot is installed only 8 KiB after the start of SD card. A default sized GPT partition table needs 17 KiB (sic!).
Downloading the Ubuntu image
I downloaded an image from the daily build webpage and decompressed it:
$ wget https://cdimage.ubuntu.com/ubuntu-server/daily-preinstalled/current/mantic-preinstalled-server-arm64.img.xz
$ xz -d mantic-preinstalled-server-arm64.img.xz
Resizing the GPT partition table
Inspecting the partition table with gdisk confirmed the conflict with U-Boot:
$ /usr/sbin/gdisk mantic-preinstalled-server-arm64.img
GPT fdisk (gdisk) version 1.0.9
Partition table scan:
MBR: protective
BSD: not present
APM: not present
GPT: present
Found valid GPT with protective MBR; using GPT.
Command (? for help): p
Disk mantic-preinstalled-server-arm64.img: 7340032 sectors, 3.5 GiB
Sector size (logical): 512 bytes
Disk identifier (GUID): DD36A78B-3A02-415D-BF5D-FF6C31E02D2C
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 7339998
Partitions will be aligned on 2048-sector boundaries
Total free space is 4061 sectors (2.0 MiB)
Number Start (sector) End (sector) Size Code Name
1 215040 7339998 3.4 GiB 8300
14 206848 215039 4.0 MiB 8300 CIDATA
15 2048 204800 99.0 MiB EF00
Fortunately via the expert menu the GPT partition table can be resized to 56 entries which uses only 8 KiB:
Command (? for help): x
Expert command (? for help): s
Current partition table size is 128.
Enter new size (15 up, default 128): 56
Caution: The partition table size should officially be 16KB or larger,
which works out to 128 entries. In practice, smaller tables seem to
work with most OSes, but this practice is risky. I'm proceeding with
the resize, but you may want to reconsider this action and undo it.
Expert 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 mantic-preinstalled-server-arm64.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.
Flashing to SD card
Now things were ready for copying to the SD card. (As writing to the wrong drive cannot be undone I have replaced the actual drive by /dev/sdX in the listing below.)
$ sudo dd if=mantic-preinstalled-server-arm64.img of=/dev/sdX bs=1M conv=fsync
$ sudo dd conv=fsync,notrunc \
if=/usr/lib/u-boot/pine64-lts/sunxi-spl.bin \
of=/dev/sdX bs=8k seek=1
$ sudo dd conv=fsync,notrunc \
if=/usr/lib/u-boot/pine64-lts/u-boot-sunxi-with-spl.fit.itb \
of=/dev/sdX bs=8k seek=5
Adjusting the image
The image might not boot because the device-tree provided by U-Boot does not match the Linux kernel. So I mounted the image and entered it via chroot:
sudo mount /dev/sdX1 /mnt
sudo mount /dev/sdX15 /mnt/boot/efi
sudo mount dev -t devtmpfs /mnt/dev
sudo mount devpts -t devpts /mnt/dev/pts
sudo mount proc -t proc /mnt/proc
sudo mount sys -t sysfs /mnt/sys
sudo chroot /mnt
To let U-Boot find the right device-tree it must be in the dts/ directory of the EFI system partition:
# mkdir /boot/efi/dtb
# cp -R /lib/firmware/6.3.0-7-generic/device-tree/* /boot/efi/dtb/
U-Boot internally uses a variable fdtfile to identify the right device-tree file.
I don’t have a monitor attached and want to see the GRUB menu when booting and watch the kernel log on my console. To override the settings in /etc/default/grub and /etc/default/grub.d/50-cloudimg-settings.cfg I create a new configuration file. Due to its name it will be included last.
# cat > /etc/default/grub.d/99-my.cfg << EOF
GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=5
GRUB_CMDLINE_LINUX_DEFAULT="efi=debug earlyprintk"
GRUB_TERMINAL=console
EOF
# update-grub
Time to exit the chroot and unmount the SD-card:
# exit
$ sudo umount /mnt/sys
$ sudo umount /mnt/proc
$ sudo umount /mnt/dev/pts
$ sudo umount /mnt/dev
$ sudo umount /mnt/boot/efi
$ sudo umount /mnt
First boot
When booting the first time cloud-init is setting up the user ubuntu with password ubuntu. So I waited with logging in until I saw this line showing that cloud-init had finished its work:
[ 109.955627] cloud-init[1383]: Cloud-init v. 23.3.1-0ubuntu1 finished at Sun, 10 Sep 2023 10:36:43 +0000. Datasource DataSourceNoCloud [seed=/var/lib/cloud/seed/nocloud-net][dsmode=net]. Up 109.93 seconds
To add a device-tree command to grub.cfg I copied the current device-tree with flash-kernel and ran grub-update:
$ sudo flash-kernel $(uname -r)
$ sudo grub-update
The same commands will run automatically every time the kernel is updated.
Takeaways
- Ubuntu Mantic runs fine on the PINE A64-LTS
- Extra care is needed to check if the U-Boot location on disk conflicts with the partitioning scheme.
- Ubuntu images lack copies of the device-trees pre-installed in /boot/efi/dts needed for U-Boot.
- While well tuned for a workstation or server the pre-configured GRUB setup may require adjustment for users relying on a serial console.