Advanced OS Customizations & Bootloaders

Hands-on Lab: Crafting a Multi-Boot Android/Linux System with Systemd-boot UKI

Google AdSense Native Placement - Horizontal Top-Post banner

Introduction

The modern computing landscape often demands flexibility, especially when juggling development, productivity, and mobile environments. While dual-booting Linux alongside Windows is commonplace, integrating Android-x86 into a multi-boot setup, particularly with advanced bootloader technologies, presents unique challenges and opportunities. This hands-on lab delves into creating a robust multi-boot system featuring Android and Linux, leveraging the power and simplicity of Systemd-boot and the efficiency of Unified Kernel Images (UKIs).

Traditional multi-booting often relies on complex GRUB configurations or separate boot entries managed by the UEFI firmware. Systemd-boot, an EFI boot manager, offers a streamlined, native UEFI approach, especially when paired with UKIs. UKIs encapsulate the kernel, initial ramdisk, kernel command line, and other metadata into a single EFI executable, simplifying the boot process and improving security.

Understanding UKI and Systemd-boot

What is a Unified Kernel Image (UKI)?

A UKI is a self-contained EFI executable that combines all necessary components for a kernel to boot: the kernel image itself, the initial RAM disk (initramfs), the kernel command line parameters, and optionally, a splash image or signed kernel modules. By consolidating these elements, a UKI eliminates the need for the bootloader to locate and load multiple files, making the boot process faster, more atomic, and less prone to misconfiguration. It’s particularly beneficial for secure boot environments as the entire UKI can be signed.

Why Systemd-boot?

Systemd-boot (formerly Gummiboot) is a simple, UEFI-native boot manager. It’s designed to be minimalistic and efficient, directly loading EFI executables. Its simplicity is a significant advantage: it avoids the complexity of scripting languages found in bootloaders like GRUB, relying instead on straightforward configuration files. For UKIs, Systemd-boot is an ideal partner, as it can directly execute the UKI EFI file, streamlining the entire boot chain.

Prerequisites

  • A device with UEFI firmware.
  • An existing Linux installation (e.g., Arch Linux, Debian, Fedora) with an EFI System Partition (ESP).
  • An Android-x86 or similar x86-compatible Android distribution ISO.
  • Basic familiarity with Linux command-line tools.
  • Disk partitioning tools (fdisk, gparted).
  • EFI utilities (efibootmgr, bootctl).
  • Kernel image manipulation tools (objcopy).
  • An internet connection for package installation.

Preparing the System

Partitioning Strategy

A well-organized disk layout is crucial. We recommend the following partition scheme:

  • EFI System Partition (ESP): /dev/sdX1 (e.g., 512MB, FAT32, mounted at /boot or /efi)
  • Linux Root Partition: /dev/sdX2 (e.g., ext4)
  • Android Root Partition: /dev/sdX3 (e.g., ext4 or f2fs, for Android-x86 installation)

Ensure your existing Linux installation’s ESP is large enough (at least 512MB is recommended). If you’re starting from scratch, use fdisk or gparted to set up your partitions:

# Example fdisk commands (replace /dev/sda with your disk)fdisk /dev/sda# g (create new GPT partition table)# n (new partition), 1 (partition number), default (first sector), +512M (size) -> Type 1 (EFI System)# n (new partition), 2, default, +50G -> Type 20 (Linux filesystem)# n (new partition), 3, default, +30G -> Type 20 (Linux filesystem)# w (write changes)mkfs.fat -F 32 /dev/sda1mkfs.ext4 /dev/sda2mkfs.ext4 /dev/sda3 # Or mkfs.f2fs /dev/sda3 for Android

Installing Linux (Reference)

Assume you have a working Linux installation. Crucially, ensure your kernel and initramfs generation tools are properly configured. For Arch Linux, this often involves mkinitcpio.

Crafting the Linux UKI

Here, we’ll create a UKI for your existing Linux installation. We’ll use objcopy to combine components.

Kernel Command Line

Create a file, e.g., /tmp/linux_cmdline.txt, with your desired kernel parameters. This usually includes the root partition, read/write access, and potentially other boot options.

echo "root=UUID=your-linux-root-uuid-here rw quiet loglevel=3" > /tmp/linux_cmdline.txt

Replace your-linux-root-uuid-here with the actual UUID of your Linux root partition, obtainable via blkid.

Initramfs Generation

Ensure your initramfs includes necessary modules for your hardware and filesystems. For Arch Linux with mkinitcpio:

mkinitcpio -p linux # This generates /boot/initramfs-linux.img

Assembling the UKI

Now, combine the kernel, initramfs, and command line into a single EFI executable. Assuming your kernel is at /boot/vmlinuz-linux:

objcopy --add-section .cmdline=/tmp/linux_cmdline.txt --change-section-vma .cmdline=0x30000 --add-section .initrd=/boot/initramfs-linux.img --change-section-vma .initrd=0x4000000 /boot/vmlinuz-linux /boot/efi/EFI/Linux/arch-uki.efi

Note the large VMA for .initrd to ensure it doesn’t overlap with the kernel or cmdline sections. You might need to adjust paths based on your distribution.

Integrating Android-x86

This is where it gets interesting. Android-x86 distributions typically use a GRUB-based boot process. We need to extract its kernel and initrd and then craft our own UKI.

Android-x86 Installation

Install Android-x86 onto its dedicated partition (e.g., /dev/sdX3). During installation, choose to install GRUB, but *not* to modify the ESP if your Linux Systemd-boot is already set up. If you’re okay with it, let it install GRUB to the Android partition’s boot sector, but we won’t be using it for UKI.

Extracting Android Kernel/Initrd

After installation, mount your Android partition:

mount /dev/sdX3 /mnt/android

Navigate to /mnt/android. You’ll typically find the kernel image (e.g., /mnt/android/kernel) and the initial ramdisk (e.g., /mnt/android/initrd.img or /mnt/android/initrd.img-x.x.x). Copy these to a temporary location on your Linux system, e.g., /tmp/android_kernel and /tmp/android_initrd.img.

Android Kernel Command Line

Android-x86 requires specific boot parameters. Create /tmp/android_cmdline.txt:

echo "root=/dev/sdX3 androidboot.selinux=permissive SRC=/android-x86 quiet" > /tmp/android_cmdline.txt

Replace /dev/sdX3 with your Android partition’s device name or UUID. SRC=/android-x86 is often critical for Android-x86 to find its root filesystem.

Crafting the Android UKI

Now, combine the Android kernel, initrd, and command line:

objcopy --add-section .cmdline=/tmp/android_cmdline.txt --change-section-vma .cmdline=0x30000 --add-section .initrd=/tmp/android_initrd.img --change-section-vma .initrd=0x4000000 /tmp/android_kernel /boot/efi/EFI/Android/android-x86-uki.efi

Systemd-boot Configuration

With both UKIs created, we need to configure Systemd-boot to recognize them.

Mounting ESP

Ensure your EFI System Partition is mounted correctly, usually at /boot or /efi:

mount /dev/sdX1 /boot/efi # If not already mounted

Boot Loader Setup

If Systemd-boot isn’t already installed, install it:

bootctl install

Creating Loader Entries

Systemd-boot uses simple .conf files in /boot/efi/loader/entries/ to define boot entries. Create directories for your UKIs if they don’t exist, e.g., /boot/efi/EFI/Linux/ and /boot/efi/EFI/Android/.

For Linux (/boot/efi/loader/entries/linux.conf):

title    Arch Linux UKIefi     /EFI/Linux/arch-uki.efi

Since the command line is embedded in the UKI, no options line is needed here.

For Android (/boot/efi/loader/entries/android.conf):

title    Android-x86 UKIefi     /EFI/Android/android-x86-uki.efi

Default Boot Entry (Optional)

You can set a default boot entry by modifying /boot/efi/loader/loader.conf:

default  linux.conf#timeout  5

Testing and Troubleshooting

Reboot your system. You should be presented with the Systemd-boot menu, listing both

Android Mobile Specs & Compare Directory

Are you researching mobile hardware properties, processor SoCs, GPU chipsets, or RAM configurations? Access our complete specs catalog to compare up to 5 devices side-by-side!

Compare Devices Specs →
Google AdSense Inline Placement - Content Footer banner