I have been using Fedora Server as the operating system for my x86_64 home servers over an extended period. However, last year, I decided to phase out my older, power-hungry x86_64 servers and transitioned to ARM Single Board Computers (SBCs). This transition proved to be successful in terms of efficiency and performance. Regrettably, Fedora Server does not offer official support for a wide range of ARM SBCs available in the market. Nevertheless, it is relatively straightforward to tailor the official ARM image to ensure compatibility with these ARM SBCs. This article aims to provide a guide on how to customize the Fedora Server image to work seamlessly with ARM SBCs.

To successful booting the Fedora Server image on ARM SBCs, the following prerequisites must be prepared:

  1. A functional U-Boot binary specific to the ARM SBC model in use.
  2. A functional Device Tree Binary (DTB) file also tailored to the ARM SBC model.

Once these essentials are in place, we can proceed with the customization of the Fedora Server image using the following commands:

#!/bin/bash

# Parse named arguments
while getopts "i:o:u:d:s:f:" opt; do
  case "$opt" in
    i) input_file="$OPTARG" ;;
    o) output_file="$OPTARG" ;;
    u) uboot_file="$OPTARG" ;;
    d) dtb_file="$OPTARG" ;;
    s) seek="$OPTARG" ;;
    f) folder="$OPTARG" ;;
    \?) echo "Usage: $0 -i <input_image_file> -o <output_image_file> -u <uboot_file> -s <seek> [-d <dtb_file>] [-f <folder>]"
        exit 1
        ;;
  esac
done

# Check if required arguments are provided
if [ -z "$input_file" ] || [ -z "$output_file" ] || [ -z "$uboot_file"  ] || [ -z "$seek"  ]; then
  echo "Usage: $0 -i <input_image_file> -o <output_image_file> -u <uboot_file> -s <seek> [-d <dtb_file>] [-f <folder>]"
  exit 1
fi

# Copy the original image
cp "$input_file" "$output_file"

# Append 1GiB of zeroes to the end of the image
dd if=/dev/zero bs=1M count=1024 >> "$output_file"

# Move the rootfs partition to the end of the image
echo "+1024MiB" | sfdisk --move-data "$output_file" -N 3

# Move the /boot partition so there is 512MiB freespace after it
echo "+512MiB" | sfdisk --move-data "$output_file" -N 2

# Extend the /boot partition
echo ", +" | sfdisk -N 2 "$output_file"

# Move the /boot/efi partition so it starts from 16MiB
echo "+16MiB" | sfdisk --move-data "$output_file" -N 1
# Extend the /boot/efi partition
echo ", +" | sfdisk -N 1 "$output_file"

# Set up a loop device for the image file
loop_device=$(sudo losetup --find --show -Pf "$output_file")

# Write the u-boot bootloader to the image file
sudo dd if="$uboot_file" of="$loop_device" bs=1K seek=$seek

# If a dtb_file is provided, copy it to the first partition of the image
if [ -n "$dtb_file" ]; then
  sudo mount "${loop_device}p1" /mnt
  sudo mkdir -p /mnt/${folder}
  sudo cp "$dtb_file" /mnt/${folder}/
  sudo umount /mnt
fi

# Clean up by removing the loop device
sudo losetup -d "$loop_device"

The script is designed to take the Fedora Server image as its input and generate a new image that incorporates the U-Boot bootloader and DTB binary, thereby facilitating the compatibility of the image with ARM SBCs. The script offers several configurable options to tailor the customization process:

  • -i <input file>: Specifies the input image file.
  • -o <output file>: Specifies the output image file.
  • -u <u-boot file>: Specifies the U-Boot binary file.
  • -d <dtb file>: Specifies the DTB binary file.
  • -s <sector offset>: Defines the sector offset for the image.
  • -f <flash type>: Specifies the flash type, with options including ‘allwinner,’ ‘amlogic,’ and ‘rockchip.’

It’s worth noting that the script has undergone rigorous testing with allwinner and rockchip boards, demonstrating its effectiveness in these scenarios. However, it is expected to function reliably with other board models as well, provided the correct sector offset and flash type are specified.

For allwinner boards, the recommended configuration is as follows:

-s 8 -f allwinner

When working with rockchip boards, the following configuration is advised:

-s 32 -f rockchip

Additionally, the script includes functionality to resize the /boot/efi and /boot partitions to 1GiB and 1.5GiB, respectively. Furthermore, it allocates 16MiB of space at the beginning of the image to accommodate the U-Boot bootloader.