2020–09–02:
Progress on the multi-boot image
Basic process of creating a multi-boot image is:
- Get a rootfs/bootfs contents of the given distribution (all distros I've
seen yet either have 1 or more usually two partitions, one with the system
files and one that the bootloader can easily access that contains kernel Image,
and bootloader configuration).
- Create a partition table on a multi-boot SD card with one boot partition for
p-boot and one partition per included distribution.
- Decide what root filesystem each distro supports and format the partitions
appropriately.
- Extract all the collected rootfs tarballs to the partitions.
- Boot partition needs to fit uncompressed kernels and initramfs images for
all the included distributions + some space for my own kernels, so it needs to
be at least 512MiB in size.
- Collect bootargs for all the distros and prepare a
boot.conf
file for p-boot.
- Decide on a distro that will manage the boot partition and store the p-boot
files. In my case, this will be Arch Linux ARM.
- Create a script that will mount all the partitions, so that p-boot-conf has
access to all the kernels and initramfs images and can make a boot filesystem
from this data.
At this point each distro will be bootable, but may fail if it has some
hardcoded expectations for the partition table structure, filesystem labels,
etc. This will need to be fixed manually.
Getting the rootfs tarballs
Many distros just publish a block device image. Getting the rootfs files from
the image requires mounting the filesystems contained in the image and backing
up all files with bsdtar
. Something like this can be used in
most cases:
L=`losetup -P --show -f "$1"`
BOOT_PART=1
ROOT_PART=2
mkdir -p m
mount ${L}p${ROOT_PART} m
test -n "$BOOT_PART" && mount ${L}p${BOOT_PART} m/boot
bsdtar -cvf - -C m --numeric-owner . | zstd -z -4 - > rootfs.tar.zst
test -n "$BOOT_PART" && umount m/boot
umount m
losetup -d "$L"
I excluded the distros that don't publish rootfs tarballs or block device
images, because they're too much hassle, at the moment. That is
pmOS
and nemo mobile
.
Images/tarballs can be downloaded at:
Excluded:
- nemo mobile – 0.8 image is very
outdated, current version requires some complex build process
- pmOS – requires running some
script
Partitioning
p-boot requires MBR partitions, so we need to use that with an extended
partitioning scheme, to be able to have more than 4 partitions. Creating the
partition table is quite simple. We just need to decide how much space each
distro will need. zstdcat rootfs.tar.zstd | wc -c
can give a clue.
There are some larger than 3GiB, but most fit within 2GiB, so let's create a
table like this:
At least 32GiB SD card is needed.
Warning: The following script is broken, and leads to first
two partitions overlapping. Fixes welcome. :)
sfdisk -W always /dev/mmcblk0 <<EOF
label: dos
label-id: 0x12345678
unit: sectors
sector-size: 512
4M,1020M,L,*
,4G,L
,4G,L
,21G,Ex
,3G,L
,3G,L
,3G,L
,3G,L
,3G,L
,3G,L
,,L
EOF
Filesystems
Now let's create filesystems. My kernel supports f2fs, so if I boot any of
the above distros with my kernel, I can just use f2fs everywhere.
Unfortunately, I don't know which of the above distros are able to boot from
f2fs with their own kernel.
They all probably support ext4. F2FS is much better for SD cards, though.
A conundrum :-)
After an investigation, I've decided on this layout (PARTUUIDs will be useful
later on).
The table also has the current status of the distros and their assignment to
the partitions.
/dev/mmcblk0p1: PARTUUID="12345678-01" p-boot
/dev/mmcblk0p2: PARTUUID="12345678-02" mobian (f2fs, 5.7 kernel, PP 1.0-1.2)
/dev/mmcblk0p3: PARTUUID="12345678-03" KDE neon (ext4 only, 5.7 kernel, PP 1.1 only)
/dev/mmcblk0p5: PARTUUID="12345678-05" arch (f2fs, my 5.9 kernel, , PP 1.0-1.2)
/dev/mmcblk0p6: PARTUUID="12345678-06" sxmo (ext4 only, 5.7 kernel, PP 1.1, 1.2)
/dev/mmcblk0p7: PARTUUID="12345678-07" lune (ext4 only, 5.5 kernel, PP 1.1 only)
/dev/mmcblk0p8: PARTUUID="12345678-08" maemo (ext4 only, 5.7 kernel, PP 1.0-1.2)
/dev/mmcblk0p9: PARTUUID="12345678-09" ut (ext4 only, 5.6 kernel, PP 1.1 only)
/dev/mmcblk0p10: PARTUUID="12345678-0a" sailfish (ext4 only, 5.6 kernel, some custom DTB with partial support for up to PP 1.2)
/dev/mmcblk0p11: PARTUUID="12345678-0b" pureos (f2fs, 5.8 kernel, PP 1.0-1.2)
The status is not great, only maybe 3 distros really support PinePhone 1.2,
and only one uses a kernel that's not EOLed upstream. Triste!
Anyway, this leads to:
for bd in /dev/mmcblk0p{3,6,7,8,9,10}
do
mkfs.ext4 $bd
done
for bd in /dev/mmcblk0p{2,5,11}
do
mkfs.f2fs $bd
done
After this we can just mount all the partitions one by one and extract the
prepared rootfs contents there, with:
mount /dev/mmcblk0p# /mnt
bsdtar -xp --numeric-owner -C /mnt -f rootfs.tar.zst
umount /mnt
That's about it for today. I'll do first boot tests in the following days,
and you can look forward to a bootloader setup guide. :)