buildfloppies.sh revision 1.12.20.1 1 #!/bin/sh
2 #
3 # $NetBSD: buildfloppies.sh,v 1.12.20.1 2008/06/02 13:21:12 mjf 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 ${PAX} -O -w -b8k ${files} >> ${floppy} || exit 1
101 # XXX: use pax metafile and set perms?
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