parch-riscv/mkimg

234 lines
5.8 KiB
Bash
Executable file

#!/usr/bin/bash
#
# SPDX-FileCopyrightText: 2022 Celeste Liu <CoelacanthusHex@gmail.com>
# SPDX-License-Identifier: GPL-3.0-or-later
# shellcheck disable=1091
. /usr/share/makepkg/util.sh
colorize
verbose=0
use_fixed_password=0
build_firmware=1
varbose_arg=
rootfs="parchriscv-$(date --rfc-3339=date).tar.zst"
fstype=ext4
kernel=linux
kernel_suffix=""
cmdline=""
uboot_version=v2023.10
opensbi_version=v1.3.1
show_help() {
cat << EOF
Usage: ${0##*/} [-hvfd] [-p PASSWORD] [-r ROOTFS] [-t FSTYPE] [FILENAME]
Create Parch RISC-V distro image.
FILENAME generated image file name
default: 'parchriscv-$(date --rfc-3339=date).qcow2'
unless the extension is qcow2, implies raw disk format
-h display this help and exit
-f use fixed password instead of using systemd-firstboot to ask
-d only build the disk image and omit building OpenSBI/U-Boot
-p PASSWORD set root password to PASSWORD instead of passwd in rootfs
-r ROOTFS specify rootfs file name
-t FSTYPE specify rootfs filesystem type (default: ext4)
-k KERNEL specify kernel package name (default: linux)
-c CMDLINE append CMDLINE to kernel command line
-v verbose mode
EOF
}
parse-args() {
local OPTIND=1
while getopts 'hvfdr:t:p:k:c:' opt; do
case $opt in
h) show_help
exit 0
;;
v) verbose=$((verbose+1))
varbose_arg="--verbose"
;;
f) use_fixed_password=1
;;
d) build_firmware=0
;;
p) password=$OPTARG
;;
r) rootfs=$OPTARG
;;
t) fstype=$OPTARG
;;
k) kernel=$OPTARG
;;
c) cmdline=$OPTARG
;;
*) show_help >&2
exit 1
;;
esac
done
shift "$(( OPTIND-1 ))"
filename=${1:-parchriscv-$(date --rfc-3339=date).qcow2}
}
toggle-systemd-firstboot() {
msg2 "Toggle systemd-firstboot..."
sudo rm -f mnt/etc/{machine-id,hostname,shadow}
# Mask Arch filesystem's factory to avoid the removed shadow file being copied over
sudo ln -s /dev/null mnt/etc/tmpfiles.d/arch.conf
}
use-fixed-password() {
msg2 "Using fixed password... $password"
[[ -n $password ]] && sudo usermod --root $(realpath ./mnt) --password $(openssl passwd -6 "$password") root
}
parse-args "$@"
if [ $build_firmware == 1 ]
then
msg "Building U-Boot..."
if [[ -d u-boot ]]; then
pushd u-boot
git checkout HEAD -- ':(top)'
git fetch origin
git checkout $uboot_version
popd
else
git clone --depth 1 --filter=blob:none -b $uboot_version https://github.com/u-boot/u-boot.git
fi
pushd u-boot
make \
CROSS_COMPILE=riscv64-linux-gnu- \
qemu-riscv64_smode_defconfig
./scripts/config \
-e CMD_BTRFS -e FS_BTRFS
make \
CROSS_COMPILE=riscv64-linux-gnu- \
olddefconfig
make CROSS_COMPILE=riscv64-linux-gnu-
popd
msg "Building OpenSBI..."
if [[ -d opensbi ]]; then
pushd opensbi
git checkout HEAD -- ':(top)'
git fetch origin
git checkout $opensbi_version
popd
else
git clone --depth 1 --filter=blob:none -b $opensbi_version https://github.com/riscv-software-src/opensbi
fi
pushd opensbi
# If user set it, OpenSBI will failed to build.
unset PYTHONSAFEPATH
make \
CROSS_COMPILE=riscv64-linux-gnu- \
PLATFORM=generic \
FW_PAYLOAD_PATH=../u-boot/u-boot.bin
popd
cp ./opensbi/build/platform/generic/firmware/fw_payload.bin opensbi_fw_payload.bin
fi
if [[ $filename == *.qcow2 ]]
then
msg "Create QCOW2 image..."
qemu-img create -f qcow2 "$filename" 10G
sudo modprobe nbd max_part=16 || exit 1
# Possible NBD device collision?
sudo qemu-nbd -c /dev/nbd0 "$filename"
loopdev=/dev/nbd0
else
msg "Create raw image..."
fallocate "$filename" -l 10G
loopdev=$(sudo losetup --show -P -f "$filename")
fi
msg "Partitioning..."
# FIXME: otherwise NBD device is not ready
sleep 1s
sudo parted "$loopdev" mklabel gpt mkpart "" "$fstype" 0% 100%
sudo partprobe "$loopdev"
partdev="$loopdev"p1
sudo mkfs.$fstype -L rootfs "$partdev"
sudo mkdir -p mnt
sudo mount "$partdev" mnt
sudo chown root:root mnt
uuid=$(sudo findmnt mnt -o UUID -n)
msg "Extract rootfs..."
pushd mnt
sudo bsdtar $varbose_arg -kpxf "../$rootfs"
popd
msg "Install kernel package..."
if [[ $kernel != linux ]]
then
kernel_suffix="${kernel#linux}"
echo -e "[unsupported]\nInclude = /etc/pacman.d/mirrorlist" | sudo tee -a mnt/etc/pacman.conf
fi
sudo systemd-nspawn -D mnt pacman \
--noconfirm --needed \
-Syu $kernel linux-firmware
sudo mkdir -p mnt/boot/extlinux
cat << EOF | sudo tee mnt/boot/extlinux/extlinux.conf
menu title Parch RISC-V Boot Menu
timeout 100
default linux-fallback
label linux
menu label Linux linux
kernel /boot/vmlinuz-linux$kernel_suffix
initrd /boot/initramfs-linux$kernel_suffix.img
append earlyprintk rw root=UUID=$uuid rootwait console=ttyS0,115200 $cmdline
label linux-fallback
menu label Linux linux (fallback initramfs)
kernel /boot/vmlinuz-linux$kernel_suffix
initrd /boot/initramfs-linux$kernel_suffix-fallback.img
append earlyprintk rw root=UUID=$uuid rootwait console=ttyS0,115200 $cmdline
EOF
cat << EOF | sudo tee mnt/etc/systemd/network/default.network
[Match]
Name=en*
[Network]
DHCP=yes
EOF
sudo systemd-nspawn -D mnt systemctl enable systemd-networkd.service
msg "Clean up..."
msg2 "Clean up pacman package cache..."
yes y | sudo pacman \
--sysroot ./mnt \
--sync --clean --clean
(( use_fixed_password==0 )) && toggle-systemd-firstboot || use-fixed-password
msg2 "Unmount and sync..."
sudo umount mnt
if [[ $filename == *.qcow2 ]]
then
sudo qemu-nbd -d "$loopdev"
else
sudo losetup -d "$loopdev"
fi
sudo sync