diff --git a/lib.sh.in b/lib.sh.in index 727b376..3399830 100644 --- a/lib.sh.in +++ b/lib.sh.in @@ -213,12 +213,15 @@ register_binfmt() { fi } +set_cachedir() { + # The package artifacts are cacheable, but they need to be isolated + # from the host cache. + : "${XBPS_CACHEDIR:=--cachedir=$PWD/xbps-cache/${XBPS_TARGET_ARCH}}" +} + # These should all resolve even if they won't have the appropriate # repodata files for the selected architecture. : "${XBPS_REPOSITORY:=--repository=http://repo.voidlinux.eu/current \ --repository=http://repo.voidlinux.eu/current/musl \ --repository=http://repo.voidlinux.eu/current/aarch64}" -# The package artifacts are cacheable, but they need to be isolated -# from the host cache. -: "${XBPS_CACHEDIR:=--cachedir=$PWD/xbps-cache/${XBPS_TARGET_ARCH}}" diff --git a/mkplatformfs.sh.in b/mkplatformfs.sh.in new file mode 100644 index 0000000..5086d76 --- /dev/null +++ b/mkplatformfs.sh.in @@ -0,0 +1,177 @@ +#!/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*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + beaglebone*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + cubieboard2*|cubietruck*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + dockstar*) XBPS_TARGET_ARCH="armv5tel"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + odroid-u2*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + odroid-c2*) XBPS_TARGET_ARCH="aarch64"; PKGS="$BASEPKG ${PLATFORM%-musl}-base" ;; + rpi3*) XBPS_TARGET_ARCH="aarch64"; PKGS="$BASEPKG rpi3-base" ;; + rpi2*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG rpi-base" ;; + rpi*) XBPS_TARGET_ARCH="armv6l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + usbarmory*) XBPS_TARGET_ARCH="armv7l"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + ci20*) XBPS_TARGET_ARCH="mipsel"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + i686*) XBPS_TARGET_ARCH="i686"; PKGS="$BASEPKG" ;; + x86_64*) XBPS_TARGET_ARCH="x86_64"; PKGS="$BASEPKG" ;; + GCP*) XBPS_TARGET_ARCH="x86_64"; PKGS="$BASEPKG ${PLATFORM%-*}-base" ;; + *) die "$PROGNAME: invalid platform!";; +esac + +# Check if we should be using the -musl variant +if [ -z "${BASE_TARBALL##*-musl-*}" ] ; then + XBPS_TARGET_ARCH="${XBPS_TARGET_ARCH}-musl" + PLATFORM="${PLATFORM}-musl" +fi + +# 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)" diff --git a/mkrootfs.sh.in b/mkrootfs.sh.in index 35d1b01..bcba40f 100644 --- a/mkrootfs.sh.in +++ b/mkrootfs.sh.in @@ -83,6 +83,9 @@ done shift $((OPTIND - 1)) XBPS_TARGET_ARCH="$1" +# Set the XBPS cache +set_cachedir + # 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