#!/usr/bin/env sh # # Copyright (c) 2016 Antti Kantee # 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 OR CONTRIBUTORS 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. # # # Include given files as binary and generate constructor code # which loads said files to rumpfs. # set -eu : ${RUMPRUN_COOKFS_CC:=!LIBEXEC_CC!} : ${RUMPRUN_COOKFS_OBJCOPY:=!LIBEXEC_OBJCOPY!} : ${RUMPRUN_COOKFS_SIZE:=!LIBEXEC_SIZE!} : ${RUMPRUN_COOKFS_INCDIR:=!DESTDIR!/rumprun-!MACHINE_GNU_ARCH!/include} usage () { echo "usage: $0 [-s count] outfile directory ..." exit 1 } die () { echo ">> ERROR: $*" 2>&1 exit 1 } nuketmpdir () { nukeme="${TMPDIR}" TMPDIR='' rm -rf ${nukeme} } TMPDIR=$(mktemp -d /tmp/rumprun-cookfs.XXXXXX) trap nuketmpdir 0 INT TERM LINKPATH=${TMPDIR}/linkme LINKPATH_BIN="_binary_$(echo ${LINKPATH} | tr '/.-' '_')" STRIPCOUNT=0 while getopts "s:" opt; do case "${opt}" in s) STRIPCOUNT=${OPTARG} [ -z "$(echo ${STRIPCOUNT} | tr -d '[0-9]')" ] \ || die argument to -s must be a non-negative decimal ;; *) usage ;; esac done shift $((${OPTIND}-1)) [ $# -ge 2 ] || usage OUTFILE="$1" shift checkpaths () { stripcount=${1} shift for sd in "$@"; do arg="${sd}" oIFS="$IFS" IFS=/ set -- ${sd} IFS="$oIFS" while [ "$1" = '.' ]; do shift ; done [ $# -ge ${stripcount} ] || \ die cannot remove ${STRIPCOUNT} components from \"${arg}\" done } processfspath () { n=$1 path=$2 oIFS="$IFS" IFS=/ set -- ${path} while [ "$1" = '.' ]; do shift ; done while [ ${n} -gt 0 ]; do shift n=$((${n}-1)) done IFS="$oIFS" rpath= while [ $# -gt 0 ]; do rpath="${rpath}$1/" shift done echo ${rpath%/} | sed 's/"/\\"/g' } makedirlist () { printf 'static const char *dirlist[] = {\n' for sd in "$@"; do for d in $(find ${sd} -type d); do printf '\t"/%s",\n' $(processfspath ${STRIPCOUNT} $d) done done printf '};\n\n' } setfilevars () { case $1 in /*) fabs="$1" ;; *) fabs="$(pwd)/$1" ;; esac fn=$((${fn}+1)) rf=_rumpfs_f${fn} } processonefile () { f="$1" setfilevars "$f" ln -sf -- "${fabs}" ${LINKPATH} ${RUMPRUN_COOKFS_CC} !CFLAGS! !CPPFLAGS! -nostdlib \ !EXTRACCFLAGS! -Wl,-r,-b,binary -o ${TMPDIR}/d${fn}.o ${LINKPATH} ${RUMPRUN_COOKFS_OBJCOPY} \ --redefine-sym ${LINKPATH_BIN}_start=${rf}_start \ --redefine-sym ${LINKPATH_BIN}_size=${rf}_size \ --strip-symbol ${LINKPATH_BIN}_end \ ${TMPDIR}/d${fn}.o LSYM="${LSYM} -L ${rf}_start -L ${rf}_size" printf 'extern uint8_t %s_start, %s_size;\n' ${rf} ${rf} printf '\t{ "/%s",\n' $(processfspath ${STRIPCOUNT} "${f}") 1>&4 printf '\t { (void *)&%s_start,\n' ${rf} 1>&4 printf '\t (size_t)(uintptr_t)&%s_size} },\n' ${rf} 1>&4 } makeelfdata () { fn=0 LSYM= for sd in "$@"; do for f in $(find "${sd}" -type f); do processonefile "$f" done done printf '\n' } printhead () { printf 'static struct rumprun_extfile files[] = {\n' 1>&4 printf '#include \n\n' printf '#include \n\n' } printtail () { cat ${TMPDIR}/filelist.c printf '};\n' printf 'static void __attribute__((constructor))\n' printf 'rumpfs_externatilize(void)\n' printf '{\n\n' printf '\trumprun_platefs(dirlist, __arraycount(dirlist),\n' printf '\t files, __arraycount(files));\n' printf '}\n' } IFS=' ' checkpaths ${STRIPCOUNT} "$@" exec 3>&1 1>${TMPDIR}/constr.c 4>${TMPDIR}/filelist.c printhead makedirlist "$@" makeelfdata "$@" exec 4>&- printtail exec 1>&3 3>&- unset IFS ${RUMPRUN_COOKFS_CC} !CFLAGS! !CPPFLAGS! -I${RUMPRUN_COOKFS_INCDIR} \ -nostdlib !EXTRACCFLAGS! -Wl,-r -o ${TMPDIR}/fin.o ${TMPDIR}/d*.o ${TMPDIR}/constr.c ${RUMPRUN_COOKFS_OBJCOPY} ${LSYM} ${TMPDIR}/fin.o ${OUTFILE} totsize=$(${RUMPRUN_COOKFS_SIZE} ${OUTFILE} | awk 'NR == 2{print $4}') if [ ${totsize} -gt $((1024*1024)) ]; then echo ">> WARNING: cookfs images will be loaded into memory." 2>&1 echo ">> Maximum recommended size is 1024 kB." 2>&1 echo ">> Your image memory footprint is $((${totsize}/1024)) kB." 2>&1 fi exit 0