Home | History | Annotate | Line # | Download | only in embedded
mkimage revision 1.8
      1  1.1       agc #! /bin/sh
      2  1.1       agc 
      3  1.8  jmcneill # $NetBSD: mkimage,v 1.8 2013/01/14 12:12:19 jmcneill Exp $
      4  1.1       agc 
      5  1.1       agc # Copyright (c) 2012 Alistair Crooks <agc (at] NetBSD.org>
      6  1.1       agc # All rights reserved.
      7  1.1       agc #
      8  1.1       agc # Redistribution and use in source and binary forms, with or without
      9  1.1       agc # modification, are permitted provided that the following conditions
     10  1.1       agc # are met:
     11  1.1       agc # 1. Redistributions of source code must retain the above copyright
     12  1.1       agc #    notice, this list of conditions and the following disclaimer.
     13  1.1       agc # 2. Redistributions in binary form must reproduce the above copyright
     14  1.1       agc #    notice, this list of conditions and the following disclaimer in the
     15  1.1       agc #    documentation and/or other materials provided with the distribution.
     16  1.1       agc #
     17  1.1       agc # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     18  1.1       agc # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     19  1.1       agc # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     20  1.1       agc # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     21  1.1       agc # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     22  1.1       agc # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23  1.1       agc # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  1.1       agc # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25  1.1       agc # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     26  1.1       agc # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27  1.1       agc #
     28  1.1       agc 
     29  1.1       agc # find next available vnd, from kre
     30  1.1       agc next_avail ()
     31  1.1       agc {
     32  1.1       agc 	local dev="$1"
     33  1.1       agc 	local N=$(( ${#dev} + 1 ))
     34  1.1       agc 	local unit units
     35  1.1       agc 
     36  1.1       agc 	units=$(
     37  1.1       agc 		sysctl -n hw.disknames		|
     38  1.1       agc 			tr ' ' '\012'		|
     39  1.1       agc 			grep '^'"${dev}"'[0-9]'	|
     40  1.1       agc 			sort -n -k 1.$N			)
     41  1.1       agc 
     42  1.1       agc 	test -z "${units}" && {
     43  1.1       agc 		test -e "/dev/${dev}0a" || {
     44  1.1       agc 			echo >&2 "No ${dev}s available!"
     45  1.1       agc 			return 1
     46  1.1       agc 		}
     47  1.1       agc 		echo "${dev}0"
     48  1.1       agc 		return
     49  1.1       agc 	}
     50  1.1       agc 
     51  1.1       agc 	N=0
     52  1.1       agc 	for unit in ${units}
     53  1.1       agc 	do
     54  1.1       agc 		if [ "${unit}" = "${dev}${N}" ]
     55  1.1       agc 		then
     56  1.1       agc 			N=$(( N + 1 ))
     57  1.1       agc 		else
     58  1.1       agc 			echo "${dev}${N}"
     59  1.1       agc 			return
     60  1.1       agc 		fi
     61  1.1       agc 	done
     62  1.1       agc 
     63  1.1       agc 	test -e /dev/"${dev}${N}a" || {
     64  1.1       agc 		echo >&2 "All ${dev}s in use"
     65  1.1       agc 		return 1
     66  1.1       agc 	}
     67  1.1       agc 
     68  1.1       agc 	echo "${dev}${N}"
     69  1.1       agc }
     70  1.1       agc 
     71  1.1       agc # find the size of the gzipped files in a .tgz archive
     72  1.1       agc sizeone() {
     73  1.4  christos 	if [ ! -f "$1" ]
     74  1.4  christos 	then
     75  1.4  christos 		echo "$PROG: Missing set $1" 1>&2
     76  1.4  christos 		echo 0
     77  1.4  christos 		return;
     78  1.4  christos 	fi
     79  1.1       agc         case "$1" in 
     80  1.1       agc         *.tgz|*.tar.gz)
     81  1.1       agc                 tar tvzf "$1" | awk '{ tot += $5 } END { print tot }'
     82  1.1       agc                 ;;
     83  1.1       agc         *.tbz|*.tar.bz2)
     84  1.1       agc                 tar tvjf "$1" | awk '{ tot += $5 } END { print tot }' 
     85  1.1       agc                 ;;
     86  1.1       agc         *)
     87  1.1       agc                 echo 0
     88  1.1       agc                 ;; 
     89  1.1       agc         esac
     90  1.1       agc }
     91  1.1       agc 
     92  1.4  christos usage() {
     93  1.4  christos 	cat << EOF 1>&2
     94  1.4  christos Usage: $PROG [-S <setsdir>] [-c <custom-files-dir>] [-h <host-arch>] [-s <size>]
     95  1.4  christos EOF
     96  1.4  christos exit 1
     97  1.4  christos }
     98  1.4  christos 
     99  1.4  christos finish() {
    100  1.4  christos     cleanup
    101  1.4  christos     ${sudo} umount ${mnt}
    102  1.4  christos     ${sudo} vnconfig -u ${vnddev}
    103  1.4  christos }
    104  1.4  christos 
    105  1.4  christos DIR="$(dirname "$0")"
    106  1.4  christos PROG="$(basename "$0")"
    107  1.2       agc bar="==="
    108  1.4  christos sudo=
    109  1.7  christos mnt="${TMPDIR:-/tmp}/image.$$"
    110  1.4  christos src="/usr/src"
    111  1.4  christos obj="/usr/obj"
    112  1.4  christos 
    113  1.4  christos # First pass for options to get the host
    114  1.4  christos OPTS="S:c:h:s:x"
    115  1.4  christos while getopts "$OPTS" f
    116  1.4  christos do
    117  1.4  christos 	case $f in
    118  1.4  christos 	h)	h="$OPTARG";;
    119  1.4  christos 	*)	;;
    120  1.4  christos 	esac
    121  1.4  christos done
    122  1.4  christos 
    123  1.4  christos if [ -z "$h" ]
    124  1.4  christos then
    125  1.4  christos 	usage
    126  1.4  christos fi
    127  1.4  christos 
    128  1.5  christos if [ ! -f "${DIR}/conf/${h}.conf" ]
    129  1.4  christos then
    130  1.5  christos 	echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2
    131  1.4  christos 	exit 1
    132  1.4  christos fi
    133  1.4  christos 
    134  1.5  christos . "${DIR}/conf/${h}.conf"
    135  1.4  christos 
    136  1.4  christos OPTIND=1
    137  1.4  christos while getopts "$OPTS" f
    138  1.4  christos do
    139  1.4  christos 	case $f in
    140  1.4  christos 	S)	setsdir="$OPTARG";;
    141  1.4  christos 	c)	custom="$OPTARG";;
    142  1.4  christos 	h)	;;
    143  1.4  christos 	s)	size="$OPTARG";;
    144  1.4  christos 	x)	set -x;;
    145  1.6  christos 	*)	usage;;
    146  1.1       agc 	esac
    147  1.1       agc done
    148  1.1       agc 
    149  1.8  jmcneill trap finish 0 1 2 3 15
    150  1.8  jmcneill 
    151  1.4  christos shift $(( "$OPTIND" - 1 ))
    152  1.4  christos if [ -n "$1" ]; then
    153  1.1       agc 	# take the next argument as being the image name
    154  1.1       agc 	image="$1"
    155  1.1       agc 	shift
    156  1.1       agc fi
    157  1.1       agc 
    158  1.1       agc total=0
    159  1.1       agc for s in ${sets}; do
    160  1.4  christos 	one="$(sizeone ${setsdir}/${s}.tgz)"
    161  1.4  christos 	total=$(( ${total} +  ${one} ))
    162  1.1       agc done
    163  1.2       agc # calculate size of custom files
    164  1.2       agc custsize=0
    165  1.2       agc if [ -d "${custom}" ]; then
    166  1.2       agc 	custsize=$(ls -lR "${custom}" | awk 'NF == 9 { tot += $5 } END { print tot }')
    167  1.2       agc fi
    168  1.4  christos total=$(( ( ( ${total} + ${custsize} ) / 1000000 ) + ${overhead} ))
    169  1.1       agc if [ $size -eq 0 ]; then
    170  1.1       agc         # auto-size the pkgs fs
    171  1.1       agc         size=${total}
    172  1.1       agc else
    173  1.1       agc         # check that we've been given enough space
    174  1.1       agc         if [ ${total} -gt ${size} ]; then
    175  1.4  christos                 echo "$PROG: Given size is ${size} MB, but we need ${total} MB" >&2
    176  1.1       agc                 exit 1
    177  1.1       agc         fi
    178  1.1       agc fi
    179  1.1       agc 
    180  1.1       agc echo "${bar} making a new ${size} MB image in ${image} ${bar}"
    181  1.4  christos dd if=/dev/zero of=${image} bs=1m count=${size} conv=sparse
    182  1.1       agc 
    183  1.1       agc vnddev=$(next_avail vnd)
    184  1.1       agc echo "${bar} mounting image via vnd ${vnddev} ${bar}"
    185  1.2       agc ${sudo} vnconfig ${vnddev} ${image}
    186  1.4  christos ${sudo} mkdir -p ${mnt}
    187  1.4  christos make_filesystems
    188  1.4  christos 
    189  1.4  christos ${sudo} mkdir -p ${mnt}/etc ${mnt}/dev
    190  1.1       agc 
    191  1.1       agc echo "${bar} installing sets ${bar}"
    192  1.4  christos (cd ${mnt} &&
    193  1.1       agc 	for s in ${sets}; do
    194  1.4  christos 		if [ -f "${s}" ]; then
    195  1.4  christos 			echo ${s}
    196  1.4  christos 			${sudo} tar xpzf ${setsdir}/${s}.tgz
    197  1.4  christos 		fi
    198  1.1       agc 	done
    199  1.1       agc )
    200  1.1       agc 
    201  1.1       agc echo "${bar} performing customisations ${bar}"
    202  1.1       agc 
    203  1.4  christos make_fstab
    204  1.1       agc 
    205  1.4  christos ${sudo} cat > ${mnt}/etc/rc.conf << EOF
    206  1.1       agc #
    207  1.1       agc # see rc.conf(5) for more information.
    208  1.1       agc #
    209  1.1       agc # Use program=YES to enable program, NO to disable it. program_flags are
    210  1.1       agc # passed to the program on the command line.
    211  1.1       agc #
    212  1.1       agc 
    213  1.1       agc # Load the defaults in from /etc/defaults/rc.conf (if it's readable).
    214  1.1       agc # These can be overridden below.
    215  1.1       agc #
    216  1.1       agc if [ -r /etc/defaults/rc.conf ]; then
    217  1.1       agc         . /etc/defaults/rc.conf
    218  1.1       agc fi
    219  1.1       agc 
    220  1.1       agc # If this is not set to YES, the system will drop into single-user mode.
    221  1.1       agc #
    222  1.1       agc rc_configured=YES
    223  1.1       agc 
    224  1.4  christos hostname=${h}
    225  1.1       agc 
    226  1.4  christos EOF
    227  1.1       agc 
    228  1.4  christos customize
    229  1.1       agc 
    230  1.1       agc for d in ${specialdirs}; do
    231  1.4  christos 	${sudo} mkdir -p ${mnt}/${d}
    232  1.1       agc done
    233  1.1       agc 
    234  1.4  christos if [ \( -n "${custom}" \) -a \( -d "${custom}" \) ]; then
    235  1.2       agc 	echo "${bar} user customisations from files in ${custom} ${bar}"
    236  1.4  christos 	(cd ${custom} && ${sudo} pax -rwpe . ${mnt})
    237  1.2       agc fi
    238  1.1       agc 
    239  1.1       agc exit 0
    240