From 3c719ced1c4ec5337b3caabd92ae58f26deed58b Mon Sep 17 00:00:00 2001 From: Andreas Grapentin Date: Thu, 1 Feb 2018 10:54:30 +0100 Subject: [PATCH] booting linux-libre --- README | 37 +++++++++++++++++------ create.sh | 18 +++++------ src/stage1.sh | 34 +++++++++++---------- src/stage2.sh | 51 +++++++++++++++++-------------- src/stage3.sh | 68 ++++++++++++++++++++--------------------- start.sh | 84 +++++++++++++++++++++++++++++---------------------- 6 files changed, 164 insertions(+), 128 deletions(-) diff --git a/README b/README index ac9dd06..b9c8ce5 100644 --- a/README +++ b/README @@ -3,14 +3,19 @@ parabola-arm-imagebuilder ========================= this is a collection of scripts creating parabola arm images for use with qemu -with the goal of building parabola arm packages on these machines. +with the original goal of building parabola arm packages on these machines. +Development focus has since shifted towards creating parabola-arm release +tarballs. to create a new virtual machine, run $> sudo ./create.sh -the creation script makes use of several files and packages present on already -setup parabola development machines. if your setup is different, you might -have to modify the scripts accordingly. +optionally, to create a new virtual machine with a packaging environment, run: + $> DEVSETUP=1 sudo ./create.sh + +the packaging environment setup script makes use of several files and packages +present on already setup parabola development machines. if your setup is +different, you might have to modify src/stage3.sh accordingly. Places the scripts check the host machine for configuration files are: /etc/makepkg.conf - for PACKAGER and GPGKEY @@ -20,7 +25,7 @@ The scripts assume that the following programs are available and in $PATH: qemu-img, qemu-system-arm wget parted - mkfs.vfat, mkfs.ext4 + mkfs.vfat, mkfs.ext4, mkswap bsdtar scp, ssh, ssh-keygen pacman @@ -30,7 +35,21 @@ The scripts also assume that you like vim :) to open a shell into the created machine, run $> ./start.sh [path to created image] -you are logged in as user parabola with password parabola. passwordless sudo is -setup and the package tree and a build chroot are prepared. have fun. also -check out the .bashrc of the parabola user in the created virtual machine, for -batch build integration based on task-spooler. +the start.sh script assumes that you want a throwaway session, so it will start +the virtual machine in snapshot mode and drop you into an ssh session. Once you +exit that session, the machine is shutdown and changes made to the image are +discarded. This behavior can be changed using the following environment +variables: + + FOREGROUND : set this to 1 to start a qemu serial connection instead of a ssh + session. Useful to capture boot output. + + PERSISTENT : set this to 1 to make persistent changes to the image that are + not discarded on shutdown. + +The username and password for the created image is parabola:parabola, or +root:parabola respectively. If a packaging environment is setup, the system is +configured for passwordless sudo for the parabola user and the package tree and +a build chroot are prepared. have fun. also check out the .bashrc of the +parabola user in the created virtual machine, for batch build integration based +on task-spooler. diff --git a/create.sh b/create.sh index 36fbaf6..a089e2f 100755 --- a/create.sh +++ b/create.sh @@ -27,15 +27,15 @@ die() { echo "$*" 1>&2 ; exit 1; } [ $(id -u) -ne 0 ] && die "must be root" [ -z "${SUDO_USER:-}" ] && die "SUDO_USER not set" -export OUTFILE=${OUTFILE:-armv7h.img} -export SIZE=${SIZE:-64G} -export ARCHTARBALL=${ARCHTARBALL:-ArchLinuxARM-armv7-latest.tar.gz} +export OUTFILE="${OUTFILE:-armv7h.img}" +export SIZE="${SIZE:-64G}" +export ARCHTARBALL="${ARCHTARBALL:-ArchLinuxARM-armv7-latest.tar.gz}" export _builddir=build -mkdir -p $_builddir -chown $SUDO_USER $_builddir +mkdir -p "$_builddir" +chown $SUDO_USER "$_builddir" -export _outfile=$_builddir/$(basename $OUTFILE) +export _outfile="$_builddir/$(basename "$OUTFILE")" # prepare the empty image ./src/stage0.sh @@ -48,11 +48,11 @@ export _outfile=$_builddir/$(basename $OUTFILE) ./src/stage2.sh # setup package development environment -./src/stage3.sh +[ -n "${DEVSETUP:-}" ] && ./src/stage3.sh # cleanup chown $SUDO_USER $_outfile -mv -v $_outfile $OUTFILE -rm -rf $_builddir +mv -v "$_outfile" "$OUTFILE" +rm -rf "$_builddir" echo "all done :)" diff --git a/src/stage1.sh b/src/stage1.sh index 5e8960f..3de1f2c 100755 --- a/src/stage1.sh +++ b/src/stage1.sh @@ -20,8 +20,10 @@ set -eu -# setup an available loop device -_loopdev=$(losetup -f --show $_outfile) +_bootdir="$_builddir/boot" +_rootdir="$_builddir/root" + +_loopdev=$(losetup -f --show "$_outfile") # setup an error exit handler for cleanup function cleanup { @@ -30,8 +32,8 @@ function cleanup { umount $_loopdev$part || true done losetup -d $_loopdev || true - rm -rf $_builddir/boot $_builddir/root - rm -f $_outfile + rm -rf "$_bootdir" "$_rootdir" + rm -f "$_outfile" } trap cleanup ERR @@ -56,16 +58,16 @@ mkswap ${_loopdev}p2 mkfs.ext4 ${_loopdev}p3 # install the base image -mkdir -p $_builddir/boot -mkdir $_builddir/root -mount ${_loopdev}p1 $_builddir/boot -mount ${_loopdev}p3 $_builddir/root -bsdtar -vxpf $ARCHTARBALL -C $_builddir/root +mkdir -p "$_bootdir" +mkdir -p "$_rootdir" +mount ${_loopdev}p1 "$_bootdir" +mount ${_loopdev}p3 "$_rootdir" +bsdtar -vxpf $ARCHTARBALL -C "$_rootdir" sync # fill the boot partition and create fstab -mv -v $_builddir/root/boot/* $_builddir/boot -cat >> $_builddir/root/etc/fstab << EOF +mv -v "$_rootdir"/boot/* "$_bootdir" +cat >> "$_rootdir"/etc/fstab << EOF /dev/mmcblk0p1 /boot vfat defaults 0 0 /dev/mmcblk0p2 none swap defaults 0 0 EOF @@ -74,16 +76,16 @@ EOF mkdir -p keys test -f keys/id_rsa || ssh-keygen -N '' -f keys/id_rsa chown $SUDO_USER keys/id_rsa* -mkdir -m 700 $_builddir/root/root/.ssh -install -m 600 -o 0 -g 0 keys/id_rsa.pub $_builddir/root/root/.ssh/authorized_keys +mkdir -m 700 "$_rootdir"/root/.ssh +install -m 600 -o 0 -g 0 keys/id_rsa.pub "$_rootdir"/root/.ssh/authorized_keys # create and install ssh host keys for cipher in dsa ecdsa ed25519 rsa; do if [ ! -f keys/ssh_host_${cipher}_key ]; then ssh-keygen -N '' -t ${cipher} -f keys/ssh_host_${cipher}_key fi - install -m 600 -o 0 -g 0 keys/ssh_host_${cipher}_key $_builddir/root/etc/ssh - install -m 644 -o 0 -g 0 keys/ssh_host_${cipher}_key.pub $_builddir/root/etc/ssh + install -m 600 -o 0 -g 0 keys/ssh_host_${cipher}_key "$_rootdir"/etc/ssh + install -m 644 -o 0 -g 0 keys/ssh_host_${cipher}_key.pub "$_rootdir"/etc/ssh done # tie up any loose ends @@ -91,4 +93,4 @@ for part in p1 p3; do umount $_loopdev$part done losetup -d $_loopdev -rm -rf $_builddir/boot $_builddir/root +rm -rf "$_bootdir" "$_rootdir" diff --git a/src/stage2.sh b/src/stage2.sh index 5dbabe4..c46b281 100755 --- a/src/stage2.sh +++ b/src/stage2.sh @@ -20,26 +20,26 @@ set -eu -_scriptfile=$_builddir/migrate.sh -_pidfile=$_builddir/qemu.pid +_scriptfile="$_builddir"/migrate.sh +_pidfile="$_builddir"/qemu-$$.pid +_bootdir="$_builddir"/boot-$$ _loopdev=$(sudo losetup -f --show $_outfile) -_bootdir=.boot # register cleanup handler to stop the started VM function cleanup { - test -f $_pidfile && (kill -9 $(cat $_pidfile) || true) - rm -f $_pidfile + test -f "$_pidfile" && (kill -9 $(cat "$_pidfile") || true) + rm -f "$_pidfile" umount ${_loopdev}p1 losetup -d $_loopdev - rm -rf $_bootdir - rm -f $_scriptfile + rm -rf "$_bootdir" + rm -f "$_scriptfile" } trap cleanup ERR # create the migration script, adapted from # https://wiki.parabola.nu/Migration_from_Arch_ARM -cat > $_scriptfile << 'EOF' +cat > "$_scriptfile" << 'EOF' #!/bin/bash set -eu @@ -80,32 +80,39 @@ pacman --noconfirm -S pacman mv /etc/pacman.conf{.pacnew,} pacman --noconfirm -Syuu pacman --noconfirm -S your-freedom - -# FIXME: we should install the linux-libre kernel, but it won't boot in qemu yet -# yes | pacman -S linux-libre +yes | pacman -S linux-libre # cleanup users userdel -r alarm useradd -mU parabola echo 'parabola:parabola' | chpasswd +echo 'root:parabola' | chpasswd + +# cleanup hostname +echo "parabola-arm" > /etc/hostname + +# enable UTF-8 locale +sed -i 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen +locale-gen +sed -i 's/LANG.*/LANG=en_US.UTF-8/' /etc/locale.conf EOF -chmod +x $_scriptfile +chmod +x "$_scriptfile" # start the VM -mkdir -p $_bootdir +mkdir -p "$_bootdir" mount ${_loopdev}p1 $_bootdir QEMU_AUDIO_DRV=none qemu-system-arm \ -M vexpress-a9 \ -m 1G \ - -dtb $_bootdir/dtbs/vexpress-v2p-ca9.dtb \ - -kernel $_bootdir/zImage \ + -dtb "$_bootdir"/dtbs/vexpress-v2p-ca9.dtb \ + -kernel "$_bootdir"/zImage \ --append "root=/dev/mmcblk0p3 rw roottype=ext4 console=ttyAMA0" \ - -drive if=sd,driver=raw,cache=writeback,file=$_outfile \ + -drive if=sd,driver=raw,cache=writeback,file="$_outfile" \ -display none \ -net user,hostfwd=tcp::2022-:22 \ -net nic \ -daemonize \ - -pidfile $_pidfile + -pidfile "$_pidfile" # wait for ssh to be up while ! ssh -p 2022 -i keys/id_rsa root@localhost -o StrictHostKeyChecking=no true 2>/dev/null; do @@ -113,16 +120,14 @@ while ! ssh -p 2022 -i keys/id_rsa root@localhost -o StrictHostKeyChecking=no tr done && echo # copy and execute the migration script -scp -P 2022 -i keys/id_rsa $_scriptfile root@localhost: -ssh -p 2022 -i keys/id_rsa root@localhost "./$(basename $_scriptfile)" +scp -P 2022 -i keys/id_rsa "$_scriptfile" root@localhost: +ssh -p 2022 -i keys/id_rsa root@localhost "./$(basename "$_scriptfile")" # stop the VM ssh -p 2022 -i keys/id_rsa root@localhost "nohup shutdown -h now &>/dev/null & exit" -while kill -0 $(cat $_pidfile) 2> /dev/null; do echo -n . && sleep 5; done && echo -rm -f $_pidfile +while kill -0 $(cat "$_pidfile") 2> /dev/null; do echo -n . && sleep 5; done && echo # cleanup umount ${_loopdev}p1 losetup -d $_loopdev -rm -rf $_bootdir -rm $_scriptfile +rm -rf "$_bootdir" "$_scriptfile" "$_pidfile" diff --git a/src/stage3.sh b/src/stage3.sh index 442c7a0..d3dfdb8 100755 --- a/src/stage3.sh +++ b/src/stage3.sh @@ -20,26 +20,26 @@ set -eu -_scriptfile=$_builddir/migrate.sh -_pidfile=$_builddir/qemu.pid +_scriptfile="$_builddir"/migrate.sh +_pidfile="$_builddir"/qemu-$$.pid +_bootdir="$_builddir"/boot-$$ -_loopdev=$(sudo losetup -f --show $_outfile) -_bootdir=.boot +_loopdev=$(sudo losetup -f --show "$_outfile") # register cleanup handler to stop the started VM function cleanup { - test -f $_pidfile && (kill -9 $(cat $_pidfile) || true) - rm -f $_pidfile + test -f "$_pidfile" && (kill -9 $(cat "$_pidfile") || true) + rm -f "$_pidfile" umount ${_loopdev}p1 losetup -d $_loopdev - rm -rf $_bootdir - rm -f $_scriptfile + rm -rf "$_bootdir" + rm -f "$_scriptfile" } trap cleanup ERR # create the package build preparation script, adapted from # https://wiki.parabola.nu/Package_maintainer_guide -(source /etc/makepkg.conf && cat > $_scriptfile << EOF +(source /etc/makepkg.conf && cat > "$_scriptfile" << EOF #!/bin/bash set -eu @@ -115,30 +115,33 @@ alias tspc='while tsp | grep -q running; do tsp -c; done' alias librecommit='if tsp | grep " \$(pwd)\\$" >/dev/null; then tspr; fi && git commit -m "\$(pwd | rev | cut -d"/" -f1-2 | rev): updated to \$(bash -c "source PKGBUILD && echo \\\$pkgver")"' IEOF - -# enable UTF-8 locale -sed -i 's/#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen -locale-gen -sed -i 's/LANG.*/LANG=en_US.UTF-8/' /etc/locale.conf EOF ) -chmod +x $_scriptfile +chmod +x "$_scriptfile" # start the VM -mkdir -p $_bootdir -mount ${_loopdev}p1 $_bootdir +mkdir -p "$_bootdir" +mount ${_loopdev}p1 "$_bootdir" +_board="vexpress-a9" +_cpu="cortex-a9" +_memory="1G" +_kernel="$_bootdir"/vmlinuz-linux-libre +_dtb="$_bootdir"/dtbs/linux-libre/vexpress-v2p-ca9.dtb +_initrd="$_bootdir"/initramfs-linux-libre.img QEMU_AUDIO_DRV=none qemu-system-arm \ - -M vexpress-a9 \ - -m 1G \ - -dtb $_bootdir/dtbs/vexpress-v2p-ca9.dtb \ - -kernel $_bootdir/zImage \ + -M $_board \ + -cpu $_cpu \ + -m $_memory \ + -kernel "$_kernel" \ + -dtb "$_dtb" \ + -initrd "$_initrd" \ --append "root=/dev/mmcblk0p3 rw roottype=ext4 console=ttyAMA0" \ - -drive if=sd,driver=raw,cache=writeback,file=$_outfile \ + -drive if=sd,driver=raw,cache=writeback,file="$_outfile" \ -display none \ -net user,hostfwd=tcp::2022-:22 \ -net nic \ -daemonize \ - -pidfile $_pidfile + -pidfile "$_pidfile" # wait for ssh to be up while ! ssh -p 2022 -i keys/id_rsa root@localhost -o StrictHostKeyChecking=no true 2>/dev/null; do @@ -146,24 +149,19 @@ while ! ssh -p 2022 -i keys/id_rsa root@localhost -o StrictHostKeyChecking=no tr done && echo # copy the current users keys to the VM -scp -rP 2022 -i keys/id_rsa $(sudo -iu $SUDO_USER pwd)/.gnupg root@localhost:/home/parabola/ -scp -rP 2022 -i keys/id_rsa $(sudo -iu $SUDO_USER pwd)/.ssh root@localhost:/home/parabola/ -scp -rP 2022 -i keys/id_rsa $(sudo -iu $SUDO_USER pwd)/.gitconfig root@localhost:/home/parabola/ +scp -rP 2022 -i keys/id_rsa "$(sudo -iu $SUDO_USER pwd)"/.gnupg root@localhost:/home/parabola/ +scp -rP 2022 -i keys/id_rsa "$(sudo -iu $SUDO_USER pwd)"/.ssh root@localhost:/home/parabola/ +scp -rP 2022 -i keys/id_rsa "$(sudo -iu $SUDO_USER pwd)"/.gitconfig root@localhost:/home/parabola/ # copy and execute the migration script -scp -P 2022 -i keys/id_rsa $_scriptfile root@localhost: -ssh -p 2022 -i keys/id_rsa root@localhost "./$(basename $_scriptfile)" - -# open a shell for debugging -# ssh -p 2022 -i keys/id_rsa root@localhost +scp -P 2022 -i keys/id_rsa "$_scriptfile" root@localhost: +ssh -p 2022 -i keys/id_rsa root@localhost "./$(basename "$_scriptfile")" # stop the VM ssh -p 2022 -i keys/id_rsa root@localhost "nohup shutdown -h now &>/dev/null & exit" -while kill -0 $(cat $_pidfile) 2> /dev/null; do echo -n . && sleep 5; done && echo -rm -f $_pidfile +while kill -0 $(cat "$_pidfile") 2> /dev/null; do echo -n . && sleep 5; done && echo # cleanup umount ${_loopdev}p1 losetup -d $_loopdev -rm -rf $_bootdir -rm $_scriptfile +rm -rf "$_bootdir" "$_scriptfile" "$_pidfile" diff --git a/start.sh b/start.sh index a1124a9..2a83232 100755 --- a/start.sh +++ b/start.sh @@ -21,62 +21,74 @@ set -eu _builddir=build -mkdir -p $_builddir +mkdir -p "$_builddir" _imagefile=$1 -_pidfile=$_builddir/qemu-$$.pid -_bootdir=$_builddir/boot-$$ +_pidfile="$_builddir"/qemu-$$.pid +_bootdir="$_builddir"/boot-$$ -_loopdev=$(sudo losetup -f --show $_imagefile) +_loopdev=$(sudo losetup -f --show "$_imagefile") sudo partprobe $_loopdev -_localport=$((2022 + $(find $_builddir -iname 'qemu-*.pid' | wc -l))) -touch $_pidfile +touch "$_pidfile" # register a cleanup error handler function cleanup { - test -f $_pidfile && (sudo kill -9 $(cat $_pidfile) || true) - rm -f $_pidfile + test -f "$_pidfile" && (sudo kill -9 $(cat "$_pidfile") || true) + rm -f "$_pidfile" sudo umount ${_loopdev}p1 sudo losetup -d $_loopdev - rm -rf $_bootdir + rm -rf "$_bootdir" } trap cleanup ERR # start the VM -mkdir -p $_bootdir -sudo mount ${_loopdev}p1 $_bootdir -# FIXME: archlinuxarm rust will SIGILL on cortex-a9 cpus, using cortex-a15 for now +mkdir -p "$_bootdir" +sudo mount ${_loopdev}p1 "$_bootdir" +_board="vexpress-a9" +# FIXME: archlinuxarm rust SIGILLs on cortex-a9 cpus, using cortex-a15 for now +_cpu="cortex-a15" +_memory="1G" +_snapshot="" +[ -z "${PERSISTENT:-}" ] && _snapshot="-snapshot" +_daemonize="-nographic -serial mon:stdio" +[ -z "${FOREGROUND:-}" ] && _daemonize="-daemonize -pidfile \"$_pidfile\" -net user,hostfwd=tcp::2022-:22 -net nic -display none" +if [ -f "$_bootdir"/zImage ]; then + _kernel="$_bootdir"/zImage + _dtb="$_bootdir"/dtbs/vexpress-v2p-ca9.dtb + _initrd="$_bootdir"/initramfs-linux.img +else + _kernel="$_bootdir"/vmlinuz-linux-libre + _dtb="$_bootdir"/dtbs/linux-libre/vexpress-v2p-ca9.dtb + _initrd="$_bootdir"/initramfs-linux-libre.img +fi QEMU_AUDIO_DRV=none qemu-system-arm \ - -M vexpress-a9 \ - -cpu cortex-a15 \ - -m 1G \ - -dtb $_bootdir/dtbs/vexpress-v2p-ca9.dtb \ - -kernel $_bootdir/zImage \ + -M $_board \ + -cpu $_cpu \ + -m $_memory \ + -kernel "$_kernel" \ + -dtb "$_dtb" \ + -initrd "$_initrd" \ --append "root=/dev/mmcblk0p3 rw roottype=ext4 console=ttyAMA0" \ - -drive if=sd,driver=raw,cache=writeback,file=$_imagefile \ - -display none \ - -net user,hostfwd=tcp::$_localport-:22 \ - -net nic \ - -daemonize \ - -snapshot \ - -pidfile $_pidfile - + -drive if=sd,driver=raw,cache=writeback,file="$_imagefile" \ + $_daemonize \ + $_snapshot +if [ -z "${FOREGROUND:-}" ]; then # wait for ssh to be up -_sshopts="-o StrictHostKeyChecking=no -o ConnectTimeout=5" -while ! ssh -p $_localport -i keys/id_rsa root@localhost $_sshopts true 2>/dev/null; do - echo -n . && sleep 5 -done && echo + _sshopts="-o StrictHostKeyChecking=no -o ConnectTimeout=5" + while ! ssh -p 2022 -i keys/id_rsa root@localhost $_sshopts true 2>/dev/null; do + echo -n . && sleep 5 + done && echo -# open a session -ssh -p $_localport -i keys/id_rsa parabola@localhost + # open a session + ssh -p 2022 -i keys/id_rsa parabola@localhost -# shutdown the VM -ssh -p $_localport -i keys/id_rsa root@localhost "nohup shutdown -h now &>/dev/null & exit" -while sudo kill -0 $(cat $_pidfile) 2> /dev/null; do echo -n . && sleep 5; done && echo -rm -f $_pidfile + # shutdown the VM + ssh -p 2022 -i keys/id_rsa root@localhost "nohup shutdown -h now &>/dev/null & exit" + while sudo kill -0 $(cat "$_pidfile") 2> /dev/null; do echo -n . && sleep 5; done && echo +fi # cleanup sudo umount ${_loopdev}p1 sudo losetup -d $_loopdev -rm -rf $_bootdir +rm -rf "$_bootdir" "$_pidfile"