Home | History | Annotate | Line # | Download | only in common
buildfloppies.sh revision 1.15
      1 #!/bin/sh
      2 #
      3 # $NetBSD: buildfloppies.sh,v 1.15 2008/11/10 02:10:52 dogcow Exp $
      4 #
      5 # Copyright (c) 2002-2003 The NetBSD Foundation, Inc.
      6 # All rights reserved.
      7 #
      8 # This code is derived from software contributed to The NetBSD Foundation
      9 # by Luke Mewburn of Wasabi Systems.
     10 #
     11 # Redistribution and use in source and binary forms, with or without
     12 # modification, are permitted provided that the following conditions
     13 # are met:
     14 # 1. Redistributions of source code must retain the above copyright
     15 #    notice, this list of conditions and the following disclaimer.
     16 # 2. Redistributions in binary form must reproduce the above copyright
     17 #    notice, this list of conditions and the following disclaimer in the
     18 #    documentation and/or other materials provided with the distribution.
     19 #
     20 # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22 # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23 # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30 # POSSIBILITY OF SUCH DAMAGE.
     31 #
     32 
     33 # set defaults
     34 #
     35 : ${PAX=pax}
     36 prog=${0##*/}
     37 
     38 
     39 usage()
     40 {
     41 	cat 1>&2 << _USAGE_
     42 Usage: ${prog} [-i instboot] [-m max] [-p] [-s suffix] base size file [...]
     43 	-i instboot	run instboot to install a bootstrap on @IMAGE@
     44 	-m max		maximum number of floppies to build
     45 	-p		pad last floppy to floppy size
     46 	-s suffix	suffix for floppies
     47 	base		basename of generated floppies
     48 	size		size of a floppy in 512 byte blocks
     49 	file [...]	file(s) to build
     50 _USAGE_
     51 	exit 1
     52 }
     53 
     54 plural()
     55 {
     56 	[ $1 -ne 1 ] && echo "s"
     57 }
     58 
     59 roundup()
     60 {
     61 	echo $(( ( $1 + $2 - 1 ) / ( $2 ) ))
     62 }
     63 
     64 
     65 #	parse and check arguments
     66 #
     67 
     68 while getopts i:m:ps: opt; do
     69 	case ${opt} in
     70 	i)
     71 		instboot=${OPTARG} ;;
     72 	m)
     73 		maxdisks=${OPTARG} ;;
     74 	p)
     75 		pad=1 ;;
     76 	s)
     77 		suffix=${OPTARG} ;;
     78 	\?|*)
     79 		usage
     80 		;;
     81 	esac
     82 done
     83 
     84 shift $(( ${OPTIND} - 1 ))
     85 [ $# -lt 3 ] && usage
     86 floppybase=$1
     87 floppysize=$2
     88 shift 2
     89 files=$*
     90 
     91 #	setup temp file, remove existing images
     92 #
     93 floppy=floppy.$$.tar
     94 trap "rm -f ${floppy}" 0 1 2 3			# EXIT HUP INT QUIT
     95 rm -f ${floppybase}?${suffix}
     96 
     97 #	create tar file
     98 #
     99 dd if=/dev/zero of=${floppy} bs=8k count=1 2>/dev/null
    100 (printf "/set uid=0 gid=0\n. type=dir\n"; for f in ${files}; do printf "%s\n" $f; done) | \
    101 ${PAX} -O -w -b8k -M >> ${floppy} || exit 1
    102 if [ -n "$instboot" ]; then
    103 	instboot=$( echo $instboot | sed -e s/@IMAGE@/${floppy}/ )
    104 	echo "Running instboot: ${instboot}"
    105 	eval ${instboot} || exit 1
    106 fi
    107 
    108 #	check size against available number of disks
    109 #
    110 set -- $(ls -ln $floppy)
    111 bytes=$5
    112 blocks=$(roundup ${bytes} 512)
    113 	# when calculating numdisks, take into account:
    114 	#	a) the image already has an 8K tar header prepended
    115 	#	b) each floppy needs an 8K tar volume header
    116 numdisks=$(roundup ${blocks}-16 ${floppysize}-16)
    117 if [ -z "${maxdisks}" ]; then
    118 	maxdisks=${numdisks}
    119 fi
    120 
    121 #	Try to accurately summarise free space
    122 #
    123 msg=
    124 # First floppy has 8k boot code, the rest an 8k 'multivolume header'
    125 # Each file has a 512 byte header and is rounded to a multiple of 512
    126 # The archive ends with two 512 byte blocks of zeros
    127 # The output file is then rounded up to a multiple of 8k
    128 free_space=$(($maxdisks * ($floppysize - 16) * 512 - 512 * 2))
    129 for file in $files; do
    130 	set -- $(ls -ln $file)
    131 	file_bytes=$5
    132 	pad_bytes=$(($(roundup $file_bytes 512) * 512 - $file_bytes))
    133 	[ "$file_bytes" != 0 -o "$file" = "${file#USTAR.volsize.}" ] &&
    134 		msg="$msg $file $pad_bytes,"
    135 	free_space=$(($free_space - 512 - $file_bytes - $pad_bytes))
    136 done
    137 echo "Free space in last tar block:$msg"
    138 
    139 if [ ${numdisks} -gt ${maxdisks} ]; then
    140 	# Add in the size of the last item (we really want the kernel) ...
    141 	excess=$(( 0 - $free_space + $pad_bytes))
    142 	echo 1>&2 \
    143 	    "$prog: Image is ${excess} bytes ($(( ${excess} / 1024 )) KB)"\
    144 	    "too big to fit on ${maxdisks} disk"$(plural ${maxdisks})
    145 	exit 1
    146 fi
    147 
    148 padto=$(( ${floppysize} * ${maxdisks} ))
    149 if [ -n "${pad}" ]; then
    150 	echo \
    151 	    "Writing $(( ${padto} * 512 )) bytes ($(( ${padto} / 2 )) KB)" \
    152 	    "on ${numdisks} disk"$(plural ${numdisks})"," \
    153 	    "padded by ${free_space} bytes" \
    154 	    "($(( ${free_space} / 1024 )) KB)"
    155 else
    156 	echo "Writing ${bytes} bytes ($(( ${blocks} / 2 )) KB)"\
    157 	    "on ${numdisks} disk"$(plural ${numdisks})"," \
    158 	    "free space ${free_space} bytes" \
    159 	    "($(( ${free_space} / 1024 )) KB)"
    160 fi
    161 
    162 #	write disks
    163 #
    164 curdisk=1
    165 image=
    166 seek=0
    167 skip=0
    168 floppysize8k=$(( ${floppysize} / 16 ))
    169 while [ ${curdisk} -le ${numdisks} ]; do
    170 	image="${floppybase}${curdisk}${suffix}"
    171 	echo "Creating disk ${curdisk} to ${image}"
    172 	if [ ${curdisk} -eq 1 ]; then
    173 		: > ${image}
    174 	else
    175 		echo USTARFS ${curdisk} > ${image}
    176 	fi
    177 	count=$(( ${floppysize8k} - ${seek} ))
    178 	dd bs=8k conv=sync seek=${seek} skip=${skip} count=${count} \
    179 	    if=${floppy} of=${image} 2>/dev/null
    180 
    181 	curdisk=$(( ${curdisk} + 1 ))
    182 	skip=$(( $skip + $count ))
    183 	seek=1
    184 done
    185 
    186 #	pad last disk if necessary
    187 #
    188 if [ -n "${pad}" ]; then
    189 	dd if=$image of=$image conv=notrunc conv=sync bs=${floppysize}b count=1
    190 fi
    191 
    192 
    193 #	final status
    194 #
    195 echo "Final result:"
    196 ls -l ${floppybase}?${suffix}
    197 
    198 exit 0
    199