#!/bin/sh #- # Copyright (c) 2017 Google # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #- readonly PROGNAME=$(basename "$0") readonly ARCH=$(uname -m) readonly REQTOOLS="xbps-install xbps-reconfigure tar xz" # This source pulls in all the functions from lib.sh. This set of # functions makes it much easier to work with chroots and abstracts # away all the problems with running binaries with QEMU. # shellcheck source=./lib.sh . ./lib.sh # Die is a function provided in lib.sh which handles the cleanup of # the mounts and removal of temporary directories if the running # program exists unexpectedly. trap 'die "Interrupted! exiting..."' INT TERM HUP # Even though we only support really one target for most of these # architectures this lets us refer to these quickly and easily by # XBPS_ARCH. This makes it a lot more obvious what is happening later # in the script, and it makes it easier to consume the contents of # these down the road in later scripts. usage() { cat <<_EOF Usage: $PROGNAME [options] Supported platforms: i686, x86_64, GCP, dockstar, bananapi, beaglebone, cubieboard2, cubietruck, odroid-c2, odroid-u2, rpi, rpi2 (armv7), rpi3 (aarch64), usbarmory, ci20 Options -b Set an alternative base-system package (defaults to base-system) -p Additional packages to install into the rootfs (separated by blanks) -k Call "cmd " after building the rootfs -c Set XBPS cache directory (defaults to \$PWD/xbps-cachedir-) -C Full path to the XBPS configuration file -r Set XBPS repository (may be set multiple times) -h Show this help -V Show version _EOF } # ######################################## # SCRIPT EXECUTION STARTS HERE # ######################################## BASEPKG=base-system while getopts "b:p:k:c:C:r:h:V" opt; do case $opt in b) BASEPKG="$OPTARG" ;; p) EXTRA_PKGS="$OPTARG" ;; k) POST_CMD="$OPTARG" ;; c) XBPS_CACHEDIR="--cachedir=$OPTARG" ;; C) XBPS_CONFFILE="-C $OPTARG" ;; r) XBPS_REPOSITORY="$XBPS_REPOSITORY --repository=$OPTARG" ;; h) usage; exit 0 ;; V) echo "$PROGNAME @@MKLIVE_VERSION@@"; exit 0 ;; esac done shift $((OPTIND - 1)) PLATFORM="$1" BASE_TARBALL="$2" # This is an aweful hack since the script isn't using privesc # mechanisms selectively. This is a TODO item. if [ "$(id -u)" -ne 0 ]; then die "need root perms to continue, exiting." fi # Before going any further, check that the tools that are needed are # present. If we delayed this we could check for the QEMU binary, but # its a reasonable tradeoff to just bail out now. check_tools # Most platforms have a base system package that includes specific # packages for bringing up the hardware. In the case of the cloud # platforms the base package includes the components needed to inject # SSH keys and user accounts. The base platform packages are always # noarch though, so we strip off the -musl extention if it was # provided. case "$PLATFORM" in bananapi*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; beaglebone*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; cubieboard2*|cubietruck*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; dockstar*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; odroid-u2*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; odroid-c2*) PKGS="$BASEPKG ${PLATFORM%-musl}-base" ;; rpi3*) PKGS="$BASEPKG rpi3-base" ;; rpi2*) PKGS="$BASEPKG rpi-base" ;; rpi*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; usbarmory*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; ci20*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; i686*) PKGS="$BASEPKG" ;; x86_64*) PKGS="$BASEPKG" ;; GCP*) PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; *) die "$PROGNAME: invalid platform!";; esac # Check if we should be using the -musl variant if [ -z "${BASE_TARBALL##*-musl-*}" ] ; then PLATFORM="${PLATFORM}-musl" fi # Derive the target architecture using the static map set_target_arch_from_platform # Append any additional packages if they were requested if [ -z "$EXTRA_PKGS" ] ; then PKGS="$PKGS $EXTRA_PKGS" fi # We need to operate on a tempdir, if this fails to create, it is # absolutely crucial to bail out so that we don't hose the system that # is running the script. ROOTFS=$(mktemp -d) || die "failed to create tempdir, exiting..." # Now that we have a directory for the ROOTFS, we can expand the # existing base filesystem into the directory info_msg "Expanding base tarball $BASE_TARBALL into $ROOTFS for $PLATFORM build." tar xf "$BASE_TARBALL" -C "$ROOTFS" # This will install, but not configure, the packages specified by # $PKGS. After this step we will do an xbps-reconfigure -f $PKGS # under the correct architecture to ensure the system is setup # correctly. run_cmd_target "xbps-install -S $XBPS_CONFFILE $XBPS_CACHEDIR $XBPS_REPOSITORY -r $ROOTFS -y $PKGS" # Now that the packages are installed, we need to chroot in and # reconfigure. This needs to be done as the right architecture. # Since this is the only thing we're doing in the chroot, we clean up # right after. run_cmd_chroot "$ROOTFS" "xbps-reconfigure -a" cleanup_chroot # The cache isn't that useful since by the time the ROOTFS will be # used it is likely to be out of date. Rather than shipping it around # only for it to be out of date, we remove it now. rm -rf "$ROOTFS/var/cache/*" 2>/dev/null # Finally we can compress the tarball, the name will include the # platform and the date on which the tarball was built. tarball=void-${PLATFORM}-ROOTFS-$(date '+%Y%m%d').tar.xz run_cmd "tar -cp --posix --xattrs -C $ROOTFS . | xz -T0 -9 > $tarball " # Now that we have the tarball we don't need the rootfs anymore, so we # can get rid of it. rm -rf "$ROOTFS" # Last thing to do before closing out is to let the user know that # this succeeded. This also ensures that there's something visible # that the user can look for at the end of the script, which can make # it easier to see what's going on if something above failed. info_msg "Successfully created $tarball ($PLATFORM)"