#!/bin/bash
create_loop() {
local loop_device=$(losetup -f)
if [ ! -b "$loop_device" ]; then
local major=$(grep loop /proc/devices | cut -c3)
local number="$(echo "$loop_device" | grep -Eo '[0-9]+' | tail -n1)"
mknod $loop_device b $major $number
fi
losetup -P $loop_device "${1}"
echo $loop_device
}
make_bootable() {
cgpt add -i 2 -S 1 -T 5 -P 10 -l kernel $1
}
partition_disk() {
local image_path=$(realpath -m "${1}")
local bootloader_size="$2"
local rootfs_name="$3"
(
echo g
echo n
echo
echo
echo +1M
echo n
echo
echo
echo +32M
echo t
echo
echo FE3A2A5D-4F32-41A7-B725-ACCC3285A309
echo n
echo
echo
echo "+${bootloader_size}M"
echo t
echo
echo 3CB8E202-3B7E-47DD-8A3C-7FF2A13CFCEC
echo n
echo
echo
echo
echo x
echo n
echo
echo "shimboot_rootfs:$rootfs_name"
echo r
echo w
) | fdisk $image_path > /dev/null
}
safe_mount() {
local source="$1"
local dest="$2"
local opts="$3"
umount $dest 2> /dev/null || /bin/true
rm -rf $dest
mkdir -p $dest
if [ "$opts" ]; then
mount $source $dest -o $opts
else
mount $source $dest
fi
}
create_partitions() {
local image_loop=$(realpath -m "${1}")
local kernel_path=$(realpath -m "${2}")
local is_luks="${3}"
local crypt_password="${4}"
mkfs.ext4 "${image_loop}p1"
dd if=$kernel_path of="${image_loop}p2" bs=1M oflag=sync
make_bootable $image_loop
mkfs.ext2 "${image_loop}p3"
if [ "$is_luks" ]; then
echo "$crypt_password" | cryptsetup luksFormat "${image_loop}p4"
echo "$crypt_password" | cryptsetup luksOpen "${image_loop}p4" rootfs
mkfs.ext4 /dev/mapper/rootfs
else
mkfs.ext4 "${image_loop}p4"
fi
}
populate_partitions() {
local image_loop=$(realpath -m "${1}")
local bootloader_dir=$(realpath -m "${2}")
local rootfs_dir=$(realpath -m "${3}")
local quiet="$4"
local luks_enabled="$5"
local git_tag="$(git tag -l --contains HEAD)"
local git_hash="$(git rev-parse --short HEAD)"
local stateful_mount=/tmp/shim_stateful
safe_mount "${image_loop}p1" $stateful_mount
mkdir -p $stateful_mount/dev_image/etc/
mkdir -p $stateful_mount/dev_image/factory/sh
touch $stateful_mount/dev_image/etc/lsb-factory
umount $stateful_mount
local bootloader_mount="/tmp/shim_bootloader"
safe_mount "${image_loop}p3" "$bootloader_mount"
cp -arv $bootloader_dir/* "$bootloader_mount"
if [ ! "$git_tag" ]; then
printf "$git_hash" > "$bootloader_mount/opt/.shimboot_version_dev"
fi
umount "$bootloader_mount"
local rootfs_mount=/tmp/new_rootfs
if [ "$luks_enabled" ]; then
safe_mount /dev/mapper/rootfs $rootfs_mount
else
safe_mount "${image_loop}p4" $rootfs_mount
fi
if [ "$quiet" ]; then
cp -ar $rootfs_dir/* $rootfs_mount
else
copy_progress $rootfs_dir $rootfs_mount
fi
umount $rootfs_mount
if [ "$luks_enabled" ]; then
cryptsetup close rootfs
fi
}
create_image() {
local image_path=$(realpath -m "${1}")
local bootloader_size="$2"
local rootfs_size="$3"
local rootfs_name="$4"
local total_size=$((1 + 32 + $bootloader_size + $rootfs_size))
rm -rf "${image_path}"
fallocate -l "${total_size}M" "${image_path}"
partition_disk $image_path $bootloader_size $rootfs_name
}
patch_initramfs() {
local initramfs_path=$(realpath -m $1)
rm "${initramfs_path}/init" -f
cp -r bootloader/* "${initramfs_path}/"
find ${initramfs_path}/bin -name "*" -exec chmod +x {} \;
}
clean_loops() {
local loop_devices="$(losetup -a | awk -F':' {'print $1'})"
for loop_device in $loop_devices; do
local mountpoints="$(cat /proc/mounts | grep "$loop_device")"
if [ ! "$mountpoints" ]; then
losetup -d $loop_device
fi
done
}
copy_progress() {
local source="$1"
local destination="$2"
local total_bytes="$(du -sb "$source" | cut -f1)"
mkdir -p "$destination"
tar -cf - -C "${source}" . | pv -f -s $total_bytes | tar -xf - -C "${destination}"
}