Skip to content
Snippets Groups Projects
mkimage.sh 5.25 KiB
#!/bin/bash

set -x
set -e

# make sure build tools are installed
DEPS="mmdebstrap genext2fs e2fsprogs binfmt-support git mount arch-test qemu-user-static parted"
if [ "$(dpkg-query --showformat '${db:Status-Status}\n' --show $DEPS | sort -u)" != "installed" ]; then
	echo "Not all dependencies of this script are installed."
	echo "Run the following command to install them:"
	echo
	echo "    sudo apt install $DEPS"
	exit 1
fi
if dpkg --compare-versions "$(dpkg-query --showformat='${Version}\n' --show mmdebstrap)" lt "0.8.4-1"; then
	echo "mmdebstrap version must be >= 0.8.4-1"
	exit 1
fi
if dpkg --compare-versions "$(dpkg-query --showformat='${Version}\n' --show genext2fs)" lt "1.5.0-2"; then
	echo "genext2fs version must be >= 1.5.0-2"
	exit 1
fi

# if we are in a git repository and if SOURCE_DATE_EPOCH is not set, use the
# timestamp of the latest git commit
if [ -z ${SOURCE_DATE_EPOCH+x} ] && git -C . rev-parse 2>/dev/null; then
	SOURCE_DATE_EPOCH=$(git log -1 --format=%ct)
else
	SOURCE_DATE_EPOCH=$(date +%s)
fi
export SOURCE_DATE_EPOCH

# /tmp might be too small for the full system, so we set a different TMPDIR
export TMPDIR="$(pwd)"

# We need a separate partition for /boot for two reasons:
#
# 1) To boot encrypted NVMe
# 2) If we boot a system that is not on the SD-Card (even unencrypted) then we
#    need to mount the partition containing kernel, initrd and dtb. If /boot is
#    not in its own partition, then mounting that partition to /boot will
#    result in the files being in /boot/boot. So we need to create a partition
#    where kernel, initrd and dtb are at the root of the partition. Otherwise
#    we cannot upgrade the kernel from the booted system.

# debian-installer chooses 999424 sectors (= 488MB) by default
BOOTSIZE=488
ROOTSIZE=2048

# download u-boot v3 from CI
/usr/lib/apt/apt-helper download-file https://source.mnt.re/reform/reform-boundary-uboot/-/jobs/artifacts/v3/raw/flash.bin\?job\=build flash.bin

# build the debian userland and configure it
./mkuserland.sh

# Rescue System ---------------------------------------------------------

mmtarfilter --path-exclude='*' --path-include=/boot --path-include='/boot/*' --strip-components=2 < target-userland.tar \
	| genext2fs --block-size 1024 --size-in-blocks $((BOOTSIZE*1024)) --bytes-per-inode 16384 --tarball - boot.img
dd if=boot.img of=reform-rescue-system.img seek=1 bs=4194304
rm boot.img
mmtarfilter --path-exclude='/boot/*' < target-userland.tar \
	| genext2fs --block-size 1024 --size-in-blocks $((ROOTSIZE*1024)) --bytes-per-inode 16384 --tarball - root.img
dd if=root.img of=reform-rescue-system.img seek=$((((BOOTSIZE+4)*1024*1024)/4194304)) bs=4194304
rm root.img
dd if=/dev/zero bs=512 count=1 >> reform-rescue-system.img
/sbin/parted -s reform-rescue-system.img "mklabel msdos"
# reproducible disk signature
printf mntr | dd of=reform-rescue-system.img seek=440 bs=1 conv=notrunc
/sbin/parted -s reform-rescue-system.img "mkpart primary ext4 4MiB $((BOOTSIZE+4))MiB"
/sbin/parted -s reform-rescue-system.img "mkpart primary ext4 $((BOOTSIZE+4))MiB $((BOOTSIZE+ROOTSIZE+4))MiB"
/sbin/parted -s reform-rescue-system.img print

# install u-boot for i.MX8MQ
dd if=./flash.bin of=reform-rescue-system.img conv=notrunc bs=1k seek=33

echo Reform Rescue System Image created: reform-rescue-system.img
# Full System -----------------------------------------------------------

# chroot into the userland and add extra applications
./mkuserland3.sh

ROOTSIZE=9000

if [ $(id -u) -eq 0 ]; then
	# genext2fs is very slow so if we run this script as root, we give up
	# on reproducibility in favor of creating the image faster
	mkdir target-userland
	tar --directory target-userland --xattrs --xattrs-include='*' --extract --file target-userland-full.tar
	/sbin/mke2fs -v -L 'MNTREFORMBOOT' -N 0 -E offset=4194304 -d target-userland/boot -t ext2 reform-system.img ${BOOTSIZE}M
	rm -rf target-userland/boot/*
	/sbin/mke2fs -v -L 'MNTREFORMROOT' -N 0 -O 64bit -E offset=$(((BOOTSIZE+4)*1024*1024)) -d target-userland -m 5 -r 1 -t ext4 reform-system.img ${ROOTSIZE}M
	rm -rf target-userland
else
	# if we don't run as root, use the slow (but bit-by-bit reproducible)
	# genext2fs instead
	mmtarfilter --path-exclude='*' --path-include=/boot --path-include='/boot/*' --strip-components=2 < target-userland-full.tar \
		| genext2fs --block-size 1024 --size-in-blocks $((BOOTSIZE*1024)) --bytes-per-inode 16384 --tarball - boot.img
	dd if=boot.img of=reform-system.img seek=1 bs=4194304
	rm boot.img
	mmtarfilter --path-exclude='/boot/*' < target-userland-full.tar \
		| genext2fs --block-size 1024 --size-in-blocks $((ROOTSIZE*1024)) --bytes-per-inode 16384 --tarball - root.img
	dd if=root.img of=reform-system.img seek=$((((BOOTSIZE+4)*1024*1024)/4194304)) bs=4194304
	rm root.img
fi
dd if=/dev/zero bs=512 count=1 >> reform-system.img
/sbin/parted -s reform-system.img "mklabel msdos"
# reproducible disk signature
printf mntr | dd of=reform-system.img seek=440 bs=1 conv=notrunc
/sbin/parted -s reform-system.img "mkpart primary ext4 4MiB $((BOOTSIZE+4))MiB"
/sbin/parted -s reform-system.img "mkpart primary ext4 $((BOOTSIZE+4))MiB $((BOOTSIZE+ROOTSIZE+4))MiB"
/sbin/parted -s reform-system.img print

# install u-boot for i.MX8MQ
dd if=./flash.bin of=reform-system.img conv=notrunc bs=1k seek=33
rm flash.bin

echo Reform Full System Image created: reform-system.img