Skip to content

Instantly share code, notes, and snippets.

@ociaw
Last active June 8, 2024 02:12
Show Gist options
  • Select an option

  • Save ociaw/2ac8711d4aa6685808fbd910490d9bc2 to your computer and use it in GitHub Desktop.

Select an option

Save ociaw/2ac8711d4aa6685808fbd910490d9bc2 to your computer and use it in GitHub Desktop.
Fixed Fedora ARM Install script (arm-image-installer) - added support for partition suffix in the format `-partX`
#!/usr/bin/sh
# Copyright (C) 2014-2024 Red Hat Inc.
# SPDX-License-Identifier: GPL-2.0+
# Automate Media Creation for Fedora ARM
# Current version
VERSION=4.1
# usage message
usage() {
echo "
Usage: $(basename ${0}) <options>
--image=IMAGE - xz compressed image file name
--media=DEVICE - media device file (/dev/[sdX|mmcblkX])
Optional
--addconsole - Add system console kernel parameter for the target
--addkey - /path/to/ssh-public-key
--args - Optional kernel parameters listed in quotes
--norootpass - Remove the root password
--relabel - SELinux relabel root filesystem on first boot
--resizefs - Resize root filesystem to fill media device
--showboot - Show boot messages, removes 'rhgb quiet' from kargs
--sysrq - Enable System Request debugging of the kernel
--target=TARGET - target board for uboot
-y - Assumes yes, will not wait for confirmation
Help
--supported - List of hardware we support writing out boot firmware
--version - Display version and exit
Example: $(basename ${0}) --image=Fedora-Rawhide.xz --target=pine64_plus --media=/dev/mmcblk0
"
}
# Set some global variables for the command directory, target board directory,
# and valid targets.
DIR=$(dirname $0)
if [ -d "/usr/share/arm-image-installer/boards.d" ]; then
BOARDDIR="/usr/share/arm-image-installer/boards.d"
DOC_DIR="/usr/share/doc/arm-image-installer/"
else
DIR=$(dirname $0)
BOARDDIR="${DIR}/boards.d"
DOC_DIR="${DIR}/"
fi
# Return help for no args
if [ $# -eq 0 ]; then
usage
exit 0
fi
# check the args
while [ $# -gt 0 ]; do
case $1 in
--debug)
set -x
;;
-h|--help)
usage
exit 0
;;
--target*)
if echo $1 | grep '=' >/dev/null ; then
TARGET=$(echo $1 | sed 's/^--target=//')
elif [ -n "$2" ]; then
TARGET=$2
shift
else
echo "$(basename ${0}): Error - '--target' expects an argument"
usage
exit 1
fi
;;
--image*)
if echo $1 | grep '=' >/dev/null ; then
IMAGE=$(echo $1 | sed 's/^--image=//')
elif [ -n "$2" ]; then
IMAGE=$2
shift
else
echo "$(basename ${0}): Error - '--image' expects an argument"
usage
exit 1
fi
;;
--media*)
if echo $1 | grep '=' >/dev/null ; then
MEDIA=$(echo $1 | sed 's/^--media=//')
elif [ -n "$2" ]; then
MEDIA=$2
shift
else
echo "$(basename ${0}): Error - '--media' expects an argument"
usage
exit 1
fi
;;
--addkey*)
if echo $1 | grep '=' >/dev/null ; then
SSH_KEY=$(echo $1 | sed 's/^--addkey=//')
elif [ -n "$2" ]; then
SSH_KEY=$2
shift
else
echo "$(basename ${0}): Error - '--addkey' expects an argument"
usage
exit 1
fi
;;
--selinux*)
if echo $1 | grep '=' >/dev/null ; then
SELINUX=$(echo $1 | sed 's/^--selinux=//')
elif [ -n "$2" ]; then
SELINUX=$2
shift
else
echo "$(basename ${0}): Error - '--selinux' expects an argument"
usage
exit 1
fi
;;
--args*)
if echo $1 | grep '=' >/dev/null ; then
OPT_ARGS=$(echo $1 | sed 's/^--args=//')
elif [ -n "$2" ]; then
OPT_ARGS=$2
shift
else
echo "$(basename ${0}): Error - '--args' expects an argument"
usage
exit 1
fi
;;
--norootpass)
NOROOTPASS=1
;;
--sysrq)
SYSRQ=1
;;
--resizefs)
RESIZEFS=1
;;
--addconsole)
CONSOLE=1
;;
--blacklistvc4)
FIX_RPI=1
;;
--supported)
cat $DOC_DIR/SUPPORTED-BOARDS
exit 0
;;
--relabel)
RELABEL=1
;;
--showboot)
SHOWBOOT=1
;;
--version)
echo "$(basename ${0})-$VERSION"
exit 0
;;
-y)
NOASK=1
;;
*)
echo "$(basename ${0}): Error - ${1}"
usage
exit 1
;;
esac
shift
done
contains() {
string="$1"
substring="$2"
if test "${string#*$substring}" != "$string"; then
return 0 # $substring is in $string
else
return 1 # $substring is not in $string
fi
}
# ensure sudo user
if [ "$(whoami)" != "root" ]; then
echo "Error: This script requires 'sudo' privileges in order to write to disk & mount media."
exit 1
fi
# check to make sure populated
if [ "$MEDIA" = "" ]; then
usage
exit 1
fi
ROOTDISK="$(mount | grep "on / " | awk '{printf $1"\n"}')"
case "$ROOTDISK" in
*nvme*)
ROOTDISK="$(echo $ROOTDISK | head -c 10)"
;;
*sd*)
ROOTDISK="$(echo $ROOTDISK | head -c 8)"
;;
esac
if [ "$MEDIA" = "$ROOTDISK" ]; then
echo ""
echo " ***********************************************************"
echo " ** WARNING: You have requested the image be written to sda."
echo " ** $ROOTDISK is mounted as the root filesystem of the host."
echo " ***********************************************************"
echo " ** Do you wish to continue? (type 'yes' to continue)"
echo " ***********************************************************"
# wait for agreement
printf " = Continue? "
read AGREE
if [ "$(echo ${AGREE} | tr '[:lower:]' '[:upper:]')" != "YES" ]; then
echo "User exit, no image written."
exit 0
fi
fi
# check for boards
if [ "$TARGET" != "" ] && ! [ -e "${BOARDDIR}/${TARGET}" ]; then
echo "Error: You must choose a supported board or none at all."
usage
exit 1
fi
# image exists
if [ ! -f "$IMAGE" ] && [ "$IMAGE" != "" ]; then
echo "Error: $IMAGE not found! Please choose an existing image."
exit 1
fi
# device exists
if [ ! -e "$MEDIA" ]; then
echo "Error: $MEDIA not found! Please choose an existing device."
exit 1
fi
# Last chance to back out
echo ""
echo "====================================================="
# check to see if host system uses LVM and VG named fedora for root
# if writing the aarch64 server image rename to fedora-server
if [ -b /dev/fedora/root ] && [ "$(echo $IMAGE|awk '/aarch64/ && /Server/')" != "" ]; then
echo "**************************************************"
echo "= NOTE: This host system uses the same VG name as "
echo "= the AArch64 disk image. To avoid issues, the VG "
echo "= on the image will be renamed to 'fedora-server'."
echo "**************************************************"
RENAME_LVM="1"
fi
# Image if included
if [ "$IMAGE" != "" ]; then
echo "= Selected Image: "
echo "= $IMAGE"
fi
echo "= Selected Media : $MEDIA"
# target hardware platform
if [ "$TARGET" != "" ]; then
echo "= U-Boot Target : $TARGET"
fi
# SE Linux On/Off
if [ "$SELINUX" != "" ]; then
echo "= SELINUX = $SELINUX"
fi
if [ "$RELABEL" != "" ]; then
echo "= SELinux relabel will be completed on first boot."
fi
# Remove root password
if [ "$NOROOTPASS" != "" ]; then
echo "= Root Password will be removed."
fi
# Enable System Request debugging of the kernel
if [ "$SYSRQ" != "" ]; then
echo "= System Request debugging of the kernel will be enabled."
fi
# Resize root filesystem to fill media device
if [ "$RESIZEFS" != "" ]; then
echo "= Root partition will be resized"
fi
# Console to be added
if [ "$CONSOLE" != "" ]; then
# don't add a console param for target none
if echo "$TARGET" | grep -q 'none'; then
CONSOLE=0
else
echo "= Console for $TARGET will be added."
fi
fi
# User ssh key
if [ "$SSH_KEY" != "" ]; then
echo "= SSH Public Key $SSH_KEY will be added."
fi
# show boot messages
if [ "$SHOWBOOT" != "" ]; then
echo "= Boot messages will be shown onscreen."
fi
echo "= Version: $VERSION"
echo "====================================================="
echo " "
echo "*****************************************************"
echo "*****************************************************"
echo "******** WARNING! ALL DATA WILL BE DESTROYED ********"
echo "*****************************************************"
echo "*****************************************************"
if [ "$NOASK" != 1 ]; then
echo " "
echo " Type 'YES' to proceed, anything else to exit now "
echo " "
# wait for agreement
printf "= Proceed? "
read PROCEED
if [ "$(echo ${PROCEED} | tr '[:lower:]' '[:upper:]')" != "YES" ]; then
echo "User exit, no image written."
exit 0
fi
fi
# umount before starting
umount $MEDIA* > /dev/null 2>&1
if [ "$(fdisk -l $MEDIA | grep LVM)" != "" ] ; then
vgchange -a n "$(pvs 2> /dev/null | grep $MEDIA | awk '{print $2}')" > /dev/null 2>&1
fi
# Write the disk image to media
if [ "$IMAGE" != "" ]; then
echo "= Writing: "
echo "= $IMAGE "
echo "= To: $MEDIA ...."
xzcat $IMAGE | dd of=$MEDIA oflag=direct bs=4M status=progress iflag=fullblock; sync; sleep 3
echo "= Writing image complete!"
fi
# check to see how many partitions on the image
partprobe "$MEDIA"
get_lvm_name () {
if [ "$(fdisk -l $MEDIA | grep LVM)" != "" ] ; then
LVM_NAME=$(pvs --devices $ROOTPART 2> /dev/null | grep $MEDIA | awk '{print $2}')
fi
}
add_bls_parameter()
{
for bls in /tmp/boot/loader/entries/*.conf; do
sed -i "s|options|& $1|" ${bls}
done
}
add_kernel_parameter () {
if [ -f /tmp/boot/extlinux/extlinux.conf ]; then
sed -i "s|append|& $1 |" /tmp/boot/extlinux/extlinux.conf
elif [ -f /tmp/fw/EFI/fedora/grub.cfg ]; then
sed -i "s|GRUB_CMDLINE_LINUX=\"|& $1 |" ${PREFIX}/etc/default/grub
if [ -f /tmp/fw/EFI/fedora/grubenv ]; then
sed -i "s|kernelopts=|& $1 |" /tmp/fw/EFI/fedora/grubenv
else
add_bls_parameter "$1"
fi
fi
}
if [ -e "$MEDIA"-part5 ]; then
export FIRMPART="${MEDIA}-part1"
BOOTPART="${MEDIA}-part2"
ROOTPART="${MEDIA}-part5"
PARTNUM=5
elif [ -e "$MEDIA"-part4 ]; then
export FIRMPART="${MEDIA}-part1"
BOOTPART="${MEDIA}-part2"
ROOTPART="${MEDIA}-part4"
PARTNUM=4
elif [ -e "$MEDIA"-part3 ]; then
export FIRMPART="${MEDIA}-part1"
BOOTPART="${MEDIA}-part2"
ROOTPART="${MEDIA}-part3"
PARTNUM=3
elif [ -e "$MEDIA"p5 ]; then
export FIRMPART="${MEDIA}p1"
BOOTPART="${MEDIA}p2"
ROOTPART="${MEDIA}p5"
PARTNUM=5
elif [ -e "$MEDIA"p4 ]; then
export FIRMPART="${MEDIA}p1"
BOOTPART="${MEDIA}p2"
ROOTPART="${MEDIA}p4"
PARTNUM=4
elif [ -e "$MEDIA"p3 ]; then
export FIRMPART="${MEDIA}p1"
BOOTPART="${MEDIA}p2"
ROOTPART="${MEDIA}p3"
PARTNUM=3
elif [ -e "$MEDIA"5 ]; then
export FIRMPART="${MEDIA}1"
BOOTPART="${MEDIA}2"
ROOTPART="${MEDIA}5"
PARTNUM=5
elif [ -e "$MEDIA"4 ]; then
export FIRMPART="${MEDIA}1"
BOOTPART="${MEDIA}2"
ROOTPART="${MEDIA}4"
PARTNUM=4
else
export FIRMPART="${MEDIA}1"
BOOTPART="${MEDIA}2"
ROOTPART="${MEDIA}3"
PARTNUM=3
fi
FS_TYPE=$(blkid "$ROOTPART" -s TYPE -o value)
if [ "$FS_TYPE" = "LVM2_member" ]; then FS_TYPE="xfs"; fi
if [ "$FS_TYPE" = "btrfs" ]; then
BTRFS=1
fi
# resize root filesystem before mounting
if [ "$RESIZEFS" != "" ]; then
echo "= Resizing $MEDIA ...."
sync
count=0
if [ "$PARTNUM" = "4" ] || [ "$PARTNUM" = "5" ]; then
echo ", +" | sfdisk -N "4" "$MEDIA"
while [ $? != '0' ]; do
sleep 5
echo ", +" | sfdisk -N "4" "$MEDIA"
count=$((count + 1))
if [ $count -gt 5 ]; then
echo "= Partition Resize Failed."
continue
fi
done
partprobe "$MEDIA"
if [ "$PARTNUM" = "5" ]; then
echo ", +" | sfdisk -N "$PARTNUM" "$MEDIA"
while [ $? != '0' ]; do
sleep 5
echo ", +" | sfdisk -N "$PARTNUM" "$MEDIA"
count=$((count + 1))
if [ $count -gt 5 ]; then
echo "= Partition Resize Failed."
continue
fi
done
fi
partprobe "$MEDIA"
fi
if [ "$PARTNUM" = "3" ]; then
if [ "$RENAME_LVM" = "1" ]; then
# rename VG if host system uses conflicting names
LVM_UUID=$(pvs --devices $ROOTPART -o +vguuid | grep $MEDIA | awk '{print $7}')
vgrename --devices $ROOTPART $LVM_UUID fedora-server
LVM_NAME=fedora-server
fi
get_lvm_name
vgchange --devices $ROOTPART -a n $LVM_NAME > /dev/null 2>&1
echo ", +" | sfdisk -N "$PARTNUM" "$MEDIA"
while [ $? != '0' ]; do
sleep 5
echo ", +" | sfdisk -N "$PARTNUM" "$MEDIA"
count=$((count + 1))
if [ $count -gt 5 ]; then
echo "= Partition Resize Failed."
continue
fi
done
sleep 5
partprobe "$MEDIA"
if [ "$LVM_NAME" != "" ]; then
vgchange --devices $ROOTPART -a y $LVM_NAME > /dev/null 2>&1
pvresize --devices $ROOTPART "$ROOTPART"
lvextend --devices $ROOTPART -l +100%FREE /dev/$LVM_NAME/root
ROOTLV="/dev/$LVM_NAME/root"
fi
fi
if [ "$FS_TYPE" = "xfs" ] && [ "$LVM_NAME" != "" ]; then
mkdir /tmp/root > /dev/null 2>&1
mount "$ROOTLV" /tmp/root > /dev/null 2>&1
xfs_growfs /tmp/root
elif [ "$FS_TYPE" = "btrfs" ]; then
mkdir /tmp/root > /dev/null 2>&1
mount "$ROOTPART" /tmp/root > /dev/null 2>&1
btrfs filesystem resize max /tmp/root
elif [ "$FS_TYPE" = "ext4" ]; then
fsck.ext4 -fy "$ROOTPART"
resize2fs "$ROOTPART"
fi
fi
sleep 5
get_lvm_name
if [ "$RENAME_LVM" = "1" ] && [ "$LVM_NAME" != "fedora-server" ]; then
# rename VG if host system uses conflicting names
LVM_UUID=$(pvs --devices $ROOTPART -o +vguuid | grep $MEDIA | awk '{print $7}')
vgrename --devices $ROOTPART $LVM_UUID fedora-server
LVM_NAME=fedora-server
fi
# make temp mount points
mkdir /tmp/boot /tmp/root /tmp/fw > /dev/null 2>&1
mount "$BOOTPART" /tmp/boot > /dev/null 2>&1
if [ $? -ne 0 ]; then
echo "Error: mount $BOOTPART /tmp/boot failed"
exit 1
fi
mount "$FIRMPART" /tmp/fw
if [ $? -ne 0 ]; then
echo "Error: mount $FIRMPART /tmp/fw failed"
exit 1
fi
if [ "$RESIZEFS" = "" ]; then
get_lvm_name
vgchange --devices $ROOTPART -a y $LVM_NAME > /dev/null 2>&1
fi
if [ "$(grep /tmp/root /proc/mounts)" = "" ]; then
if [ "$LVM_NAME" != "" ]; then
mount "/dev/$LVM_NAME/root" /tmp/root > /dev/null 2>&1
else
mount "$ROOTPART" /tmp/root
fi
fi
if [ "$(echo $IMAGE | grep IoT)" != "" ]; then
IOT_IMAGE="1"
OSTREE_ROOT_HOME="/tmp/root/ostree/deploy/fedora-iot/var/roothome"
OSTREE_PREFIX="/tmp/root/ostree/deploy/fedora-iot/deploy/*/"
fi
# fix up grub.cfg to reflect the new vg name
if [ "$RENAME_LVM" != "" ]; then
if [ -f /tmp/boot/loader/entries/*.conf ] && [ -f /tmp/boot/grub2/grub.cfg ]; then
sed -i 's|/dev/mapper/fedora-root|/dev/mapper/fedora--server-root|g; s|rd.lvm.lv=fedora/root|rd.lvm.lv=fedora-server/root|g' /tmp/boot/loader/entries/*.conf
sed -i 's|/dev/mapper/fedora-root|/dev/mapper/fedora--server-root|g; s|rd.lvm.lv=fedora/root|rd.lvm.lv=fedora-server/root|g' /tmp/boot/grub2/grub.cfg
fi
fi
if [ "$IOT_IMAGE" = "1" ]; then
# dd doesnt support wildcards, echo to expand
PREFIX=$(echo $OSTREE_PREFIX)
elif [ "$BTRFS" = "1" ]; then
PREFIX="/tmp/root/root/"
else
PREFIX=/tmp/root
fi
# determine uboot and write to disk
if [ "$TARGET" != "" ]; then
if echo "$TARGET" | grep -q 'rpi[34]' || [ "$TARGET" = "beagleplay" ]; then
. "${BOARDDIR}/${TARGET}"
elif [ -d "${PREFIX}/usr/share/uboot/${TARGET}" ]; then
. "${BOARDDIR}/${TARGET}"
else
echo "= No U-Boot files found for $TARGET."
fi
else
echo "= No U-boot will be written."
TARGET="board"
fi
# turn off selinux
if [ "$SELINUX" != "" ]; then
if [ "$(echo ${SELINUX} | tr '[:lower:]' '[:upper:]')" = "OFF" ]; then
echo "= Turning SELinux off ..."
sed -i 's/SELINUX=enforcing/SELINUX=permissive/' ${PREFIX}/etc/selinux/config
# turn on selinux
elif [ "$(echo ${SELINUX} | tr '[:lower:]' '[:upper:]')" = "ON" ]; then
echo "= Turning SELinux on ..."
sed -i 's/SELINUX=permissive/SELINUX=enforcing/' ${PREFIX}/etc/selinux/config
fi
fi
# Remove root password
if [ "$NOROOTPASS" = "1" ]; then
echo "= Removing the root password."
sed -i 's/root:x:/root::/' ${PREFIX}/etc/passwd
fi
# Enable System Request debugging of the kernel
if [ "$SYSRQ" != "" ]; then
echo "= Enabling System Request debugging of the kernel."
cat >> ${PREFIX}/etc/sysctl.d/arm-image-installer-sysrq.conf <<-EOH
# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 1
EOH
fi
# Add ssh key to the image
if [ "$SSH_KEY" != "" ]; then
if [ -f $SSH_KEY ]; then
echo "= Adding SSH key to authorized keys."
if [ "$IOT_IMAGE" = "1" ]; then
mkdir $OSTREE_ROOT_HOME/.ssh/ > /dev/null 2>&1
cat $SSH_KEY >> $OSTREE_ROOT_HOME/.ssh/authorized_keys
chmod -R u=rwX,o=,g= $OSTREE_ROOT_HOME/.ssh/
else
mkdir ${PREFIX}/root/.ssh/ > /dev/null 2>&1
cat $SSH_KEY >> ${PREFIX}/root/.ssh/authorized_keys
chmod -R u=rwX,o=,g= ${PREFIX}/root/.ssh/
fi
else
echo "= SSH key $SSH_KEY : Not Found!"
echo "= WARNING: No SSH Key Added."
fi
fi
# Add console
if [ "$CONSOLE" = "1" ]; then
if [ "$SYSCON" = "" ]; then
SYSCON="ttyS0,115200"
echo "= No console listed for $TARGET, adding default $SYSCON ."
fi
echo "= Adding console $SYSCON to kernel parameters ..."
add_kernel_parameter "console=$SYSCON console=tty0"
if echo "$TARGET" | grep -q 'rpi[34]'; then
sed -i "s|# enable_uart=1|enable_uart=1|" /tmp/fw/config.txt
fi
fi
# check if host system has selinux disabled, if it does autorelabel is required
if [ "$(getenforce)" = "Disabled" ]; then
echo "= NOTE: System Relabel required on first boot."
RELABEL="1"
fi
# touch /.autorelabel
if [ "$RELABEL" != "" ]; then
if [ "$IOT_IMAGE" = "1" ]; then
echo "= SELinux relabel not supported on IoT images."
else
echo "= Touch /.autorelabel on rootfs."
touch ${PREFIX}/.autorelabel
fi
fi
# add option kernel parameters
if [ "$OPT_ARGS" != "" ] ; then
echo "= Adding optional kernel parameters for $TARGET : "
echo "= Parameter: $OPT_ARGS"
add_kernel_parameter "$OPT_ARGS"
fi
# remove quiet from kargs
if [ "$SHOWBOOT" != "" ]; then
sed -i 's|rhgb quiet ||g' /tmp/boot/loader/entries/*.conf
fi
sync
umount /tmp/root $BOOTPART $FIRMPART > /dev/null 2>&1
if [ "$LVM_NAME" != "" ]; then
vgchange --devices $ROOTPART -a n $LVM_NAME > /dev/null 2>&1
fi
rmdir /tmp/root /tmp/boot /tmp/fw > /dev/null 2>&1
if [ "$URL" != "" ]; then
echo
echo "= NOTE"
echo "= Additional instructions for $TARGET can be found at:"
echo "= $URL "
echo
fi
echo ""
echo "= Installation Complete! Insert into the $TARGET and boot."
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment