1#!/bin/sh 2# 3# Copyright (c) 2005 Poul-Henning Kamp All rights reserved. 4# Copyright (c) 2016 M. Warner Losh <imp@FreeBSD.org> 5# 6# 7# Redistribution and use in source and binary forms, with or without 8# modification, are permitted provided that the following conditions 9# are met: 10# 1. Redistributions of source code must retain the above copyright 11# notice, this list of conditions and the following disclaimer. 12# 2. Redistributions in binary form must reproduce the above copyright 13# notice, this list of conditions and the following disclaimer in the 14# documentation and/or other materials provided with the distribution. 15# 16# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26# SUCH DAMAGE. 27# 28# 29 30# Media geometry, only relevant if bios doesn't understand LBA. 31[ -n "$NANO_SECTS" ] || NANO_SECTS=63 32[ -n "$NANO_HEADS" ] || NANO_HEADS=16 33 34# Functions and variable definitions used by the legacy nanobsd 35# image building system. 36 37calculate_partitioning() { 38 echo $NANO_MEDIASIZE $NANO_IMAGES \ 39 $NANO_SECTS $NANO_HEADS \ 40 $NANO_CODESIZE $NANO_CONFSIZE $NANO_DATASIZE | 41 awk ' 42 { 43 # size of cylinder in sectors 44 cs = $3 * $4 45 46 # number of full cylinders on media 47 cyl = int ($1 / cs) 48 49 if ($7 > 0) { 50 # size of data partition in full cylinders 51 dsl = int (($7 + cs - 1) / cs) 52 } else { 53 dsl = 0; 54 } 55 56 # size of config partition in full cylinders 57 csl = int (($6 + cs - 1) / cs) 58 59 # size of image partition(s) in full cylinders 60 if ($5 == 0) { 61 isl = int ((cyl - dsl - csl) / $2) 62 } else { 63 isl = int (($5 + cs - 1) / cs) 64 } 65 66 # First image partition start at second track 67 print $3, isl * cs - $3, 1 68 c = isl * cs; 69 70 # Second image partition (if any) also starts offset one 71 # track to keep them identical. 72 if ($2 > 1) { 73 print $3 + c, isl * cs - $3, 2 74 c += isl * cs; 75 } 76 77 # Config partition starts at cylinder boundary. 78 print c, csl * cs, 3 79 c += csl * cs 80 81 # Data partition (if any) starts at cylinder boundary. 82 if ($7 > 0) { 83 print c, dsl * cs, 4 84 } else if ($7 < 0 && $1 > c) { 85 print c, $1 - c, 4 86 } else if ($1 < c) { 87 print "Disk space overcommitted by", \ 88 c - $1, "sectors" > "/dev/stderr" 89 exit 2 90 } 91 } 92 ' > ${NANO_LOG}/_.partitioning 93} 94 95_xxx_adjust_code_size() 96{ 97 # XXX adjust the CODE_SIZE value by rounding it up to 98 # a bsize of 32768 (DFL_BLKSIZE). 99 # Otherwise makefs -s will fail because of the guard 100 # introduced in 5ad283b3c60d. 101 codesize=$1 102 bsize=32768 103 echo $(( ((codesize + (bsize - 1)) / bsize) * bsize )) 104} 105 106create_code_slice() { 107 pprint 2 "build code slice" 108 pprint 3 "log: ${NANO_OBJ}/_.cs" 109 110 ( 111 IMG=${NANO_DISKIMGDIR}/_.disk.image 112 MNT=${NANO_OBJ}/_.mnt 113 mkdir -p ${MNT} 114 CODE_SIZE=`head -n 1 ${NANO_LOG}/_.partitioning | awk '{ print $2 }'` 115 116 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 117 MD=`mdconfig -a -t swap -s ${CODE_SIZE} -x ${NANO_SECTS} \ 118 -y ${NANO_HEADS}` 119 else 120 echo "Creating md backing file..." 121 rm -f ${IMG} 122 dd if=/dev/zero of=${IMG} seek=${CODE_SIZE} count=0 123 MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ 124 -y ${NANO_HEADS}` 125 fi 126 127 trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT 128 129 gpart create -s bsd "${MD}" 130 gpart add -t freebsd-ufs -b 16 "${MD}" 131 if [ -f ${NANO_WORLDDIR}/boot/boot ]; then 132 echo "Making bootable partition" 133 gpart bootcode -b ${NANO_WORLDDIR}/boot/boot ${MD} 134 else 135 echo "Partition will not be bootable" 136 fi 137 gpart list ${MD} 138 139 # Create first image 140 populate_slice /dev/${MD}${NANO_PARTITION_ROOT} ${NANO_WORLDDIR} ${MNT} "${NANO_ROOT}" 141 mount /dev/${MD}a ${MNT} 142 echo "Generating mtree..." 143 ( cd ${MNT} && mtree -c ) > ${NANO_OBJ}/_.mtree 144 ( cd ${MNT} && du -k ) > ${NANO_OBJ}/_.du 145 nano_umount ${MNT} 146 147 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 148 echo "Writing out _.disk.image..." 149 dd conv=sparse if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.image bs=64k 150 fi 151 mdconfig -d -u $MD 152 153 trap - 1 2 15 EXIT 154 155 ) > ${NANO_OBJ}/_.cs 2>&1 156} 157 158_create_code_slice() { 159 pprint 2 "build code slice" 160 pprint 3 "log: ${NANO_OBJ}/_.cs" 161 162 ( 163 IMG=${NANO_DISKIMGDIR}/_.disk.image 164 CODE_SIZE=$(head -n 1 "${NANO_LOG}/_.partitioning" | awk '{ print $2 }') 165 CODE_SIZE=$(_xxx_adjust_code_size "$CODE_SIZE") 166 167 echo "Writing code image..." 168 if [ -f "${NANO_WORLDDIR}/boot/boot" ]; then 169 echo "Making bootable partition" 170 bootcode="-b ${NANO_WORLDDIR}/boot/boot" 171 else 172 echo "Partition will not be bootable" 173 fi 174 nano_makefs "-DxZ ${NANO_MAKEFS} -o minfree=0,optimization=space" \ 175 "${NANO_METALOG}" "${CODE_SIZE}" "${NANO_OBJ}/_.disk.part" \ 176 "${NANO_WORLDDIR}" 177 mkimg -s bsd \ 178 ${bootcode} \ 179 -p freebsd-ufs:="${NANO_OBJ}/_.disk.part" \ 180 -o "${NANO_DISKIMGDIR}/_.disk.image" 181 rm -f "${NANO_OBJ}/_.disk.part" 182 183 ) > ${NANO_OBJ}/_.cs 2>&1 184} 185 186create_diskimage() { 187 pprint 2 "build diskimage" 188 pprint 3 "log: ${NANO_OBJ}/_.di" 189 190 ( 191 192 IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} 193 MNT=${NANO_OBJ}/_.mnt 194 mkdir -p ${MNT} 195 196 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 197 MD=`mdconfig -a -t swap -s ${NANO_MEDIASIZE} -x ${NANO_SECTS} \ 198 -y ${NANO_HEADS}` 199 else 200 echo "Creating md backing file..." 201 rm -f ${IMG} 202 dd if=/dev/zero of=${IMG} seek=${NANO_MEDIASIZE} count=0 203 MD=`mdconfig -a -t vnode -f ${IMG} -x ${NANO_SECTS} \ 204 -y ${NANO_HEADS}` 205 fi 206 207 awk ' 208 BEGIN { 209 # Create MBR partition table 210 print "gpart create -s mbr $1" 211 } 212 { 213 # Make partition 214 print "gpart add -t freebsd -b ", $1, " -s ", $2, " -i ", $3, " $1" 215 } 216 END { 217 # Force slice 1 to be marked active. This is necessary 218 # for booting the image from a USB device to work. 219 print "gpart set -a active -i 1 $1" 220 } 221 ' ${NANO_LOG}/_.partitioning > ${NANO_OBJ}/_.gpart 222 223 trap "echo 'Running exit trap code' ; df -i ${MNT} ; nano_umount ${MNT} || true ; mdconfig -d -u $MD" 1 2 15 EXIT 224 225 sh ${NANO_OBJ}/_.gpart ${MD} 226 gpart show ${MD} 227 # XXX: params 228 # XXX: pick up cached boot* files, they may not be in image anymore. 229 if [ -f ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ]; then 230 gpart bootcode -b ${NANO_WORLDDIR}/${NANO_BOOTLOADER} ${NANO_BOOTFLAGS} ${MD} 231 fi 232 233 echo "Writing code image..." 234 dd conv=sparse if=${NANO_DISKIMGDIR}/_.disk.image of=/dev/${MD}${NANO_SLICE_ROOT} bs=64k 235 236 if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then 237 # Duplicate to second image (if present) 238 echo "Duplicating to second image..." 239 dd conv=sparse if=/dev/${MD}${NANO_SLICE_ROOT} of=/dev/${MD}${NANO_SLICE_ALTROOT} bs=64k 240 mount /dev/${MD}${NANO_ALTROOT} ${MNT} 241 for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab 242 do 243 sed -i "" "s=${NANO_DRIVE}${NANO_SLICE_ROOT}=${NANO_DRIVE}${NANO_SLICE_ALTROOT}=g" $f 244 done 245 nano_umount ${MNT} 246 # Override the label from the first partition so we 247 # don't confuse glabel with duplicates. 248 if [ -n "${NANO_LABEL}" ]; then 249 tunefs -L ${NANO_LABEL}"${NANO_ALTROOT}" /dev/${MD}${NANO_ALTROOT} 250 fi 251 fi 252 253 # Create Config slice 254 populate_cfg_slice /dev/${MD}${NANO_SLICE_CFG} "${NANO_CFGDIR}" ${MNT} "${NANO_SLICE_CFG}" 255 256 # Create Data slice, if any. 257 if [ -n "$NANO_SLICE_DATA" -a "$NANO_SLICE_CFG" = "$NANO_SLICE_DATA" -a \ 258 "$NANO_DATASIZE" -ne 0 ]; then 259 pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix." 260 exit 2 261 fi 262 if [ $NANO_DATASIZE -ne 0 -a -n "$NANO_SLICE_DATA" ] ; then 263 populate_data_slice /dev/${MD}${NANO_SLICE_DATA} "${NANO_DATADIR}" ${MNT} "${NANO_SLICE_DATA}" 264 fi 265 266 if [ "${NANO_MD_BACKING}" = "swap" ] ; then 267 if [ ${NANO_IMAGE_MBRONLY} ]; then 268 echo "Writing out _.disk.mbr..." 269 dd if=/dev/${MD} of=${NANO_DISKIMGDIR}/_.disk.mbr bs=512 count=1 270 else 271 echo "Writing out ${NANO_IMGNAME}..." 272 dd if=/dev/${MD} of=${IMG} bs=64k 273 fi 274 275 echo "Writing out ${NANO_IMGNAME}..." 276 dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k 277 fi 278 279 mdconfig -d -u $MD 280 281 trap - 1 2 15 EXIT 282 283 ) > ${NANO_LOG}/_.di 2>&1 284} 285 286_create_diskimage() { 287 pprint 2 "build diskimage" 288 pprint 3 "log: ${NANO_OBJ}/_.di" 289 290 ( 291 local altroot bootloader cfgimage dataimage diskimage 292 293 CODE_SIZE=$(head -n 1 "${NANO_LOG}/_.partitioning" | awk '{ print $2 }') 294 CODE_SIZE=$(_xxx_adjust_code_size "$CODE_SIZE") 295 IMG=${NANO_DISKIMGDIR}/${NANO_IMGNAME} 296 297 if [ -f "${NANO_WORLDDIR}/${NANO_BOOTLOADER}" ]; then 298 bootloader="-b ${NANO_WORLDDIR}/${NANO_BOOTLOADER}" 299 else 300 echo "Image will not be bootable" 301 fi 302 303 diskimage="-p freebsd:=${NANO_DISKIMGDIR}/_.disk.image" 304 305 if [ "$NANO_IMAGES" -gt 1 ] && [ "$NANO_INIT_IMG2" -gt 0 ] ; then 306 echo "Duplicating to second image..." 307 tgt_switch_root_fstab "${NANO_SLICE_ROOT}" "${NANO_SLICE_ALTROOT}" 308 nano_makefs "-DxZ ${NANO_MAKEFS} -o minfree=0,optimization=space" \ 309 "${NANO_METALOG}" "${CODE_SIZE}" "${NANO_OBJ}/_.altroot.part" \ 310 "${NANO_WORLDDIR}" 311 tgt_switch_root_fstab "${NANO_SLICE_ALTROOT}" "${NANO_SLICE_ROOT}" 312 if [ -f "${NANO_WORLDDIR}/boot/boot" ]; then 313 bootcode="-b ${NANO_WORLDDIR}/boot/boot" 314 fi 315 mkimg -s bsd \ 316 ${bootcode} \ 317 -p freebsd-ufs:="${NANO_OBJ}/_.altroot.part" \ 318 -o "${NANO_OBJ}/_.altroot.image" 319 altroot="-p freebsd:=${NANO_OBJ}/_.altroot.image" 320 rm -f "${NANO_OBJ}/_.altroot.part" 321 else 322 altroot="-p-" 323 fi 324 if [ "${NANO_INIT_IMG2}" -eq 0 ]; then 325 altroot="-p freebsd::${CODE_SIZE}b" 326 fi 327 328 # Create Config slice 329 _populate_cfg_part "${NANO_OBJ}/_.cfg.part" "${NANO_CFGDIR}" \ 330 "${NANO_SLICE_CFG}" "${NANO_CONFSIZE}" "${NANO_METALOG_CFG}" 331 cfgimage="-p freebsd:=${NANO_OBJ}/_.cfg.part" 332 333 # Create Data slice, if any. 334 if [ -n "${NANO_SLICE_DATA}" ] && 335 [ "${NANO_SLICE_CFG}" = "${NANO_SLICE_DATA}" ] && 336 [ "${NANO_DATASIZE}" -ne 0 ]; then 337 pprint 2 "NANO_SLICE_DATA is the same as NANO_SLICE_CFG, fix." 338 exit 2 339 fi 340 if [ "${NANO_DATASIZE}" -ne 0 ] && [ -n "${NANO_SLICE_DATA}" ] ; then 341 _populate_data_part "${NANO_OBJ}/_.data.part" "${NANO_DATADIR}" \ 342 "${NANO_SLICE_DATA}" "${NANO_DATASIZE}" "${NANO_METALOG_DATA}" 343 dataimage="-p freebsd:=${NANO_OBJ}/_.data.part" 344 fi 345 346 echo "Writing out ${NANO_IMGNAME}..." 347 mkimg -s mbr \ 348 ${bootloader} \ 349 ${diskimage} \ 350 ${altroot} \ 351 ${cfgimage} \ 352 ${dataimage} \ 353 -o ${IMG} 354 exit 355 356 ) > ${NANO_LOG}/_.di 2>&1 357} 358