#!/bin/sh _root="$(dirname "${0}")"; . "${_root}/lib/env.sh" want root log pebkac(){ [ "${*}" ] && echo "$(basename "${0}"): ${*}" && echo "" echo "Generate a card image using the specified boot and root images," echo " and the optional conf directory to fill the free space." echo "" echo "Options:" echo " -b Boot image filename (default boot.img)" echo " -r Root image filename (default root.img)" echo " -c Config directory to embed into card image" echo " -o Card image filename to write (default card.img)" echo " -s Intended card size, in 512-byte sectors" echo " -a Bootcode file to use (default /boot/boot)" echo " -h Hi!" exit 1 } img_sects(){ [ ! -f "${1}" ] && return 0 ( eval $(stat -s "${1}") echo "$(( ( ${st_size} + ( ${st_size} % 512 ) ) / 512 ))" ) } compute_label(){ # Params: 1: cardsects 2: boot.img 3: root.img card_size="${1}" boot_file="${2}" root_file="${3}" [ -z "${card_size}" -o -z "${boot_file}" -o -z "${root_file}" ] && pebkac "RTFS, bitch!" omfg_ofst=0 omfg_size=16 boot_ofst="$(( ${omfg_ofst} + ${omfg_size} ))" boot_size="$(img_sects "${boot_file}")" root_ofst="$(( ${boot_ofst} + ${boot_size} ))" root_size="$(img_sects "${root_file}")" conf_ofst="$(( ${root_ofst} + ${root_size} ))" conf_size="$(( ${card_size} - ( ${omfg_size} + ${boot_size} + ${root_size} ) ))" last_ofst="$(( ${conf_ofst} + ${conf_size} ))" echo "a: ${boot_size} ${boot_ofst} 4.2BSD" echo "b: ${omfg_size} ${omfg_ofst} boot" echo "c: ${card_size} 0 unused" echo "d: ${root_size} ${root_ofst} ISO9660" echo "e: ${conf_size} ${conf_ofst} 4.2BSD" } # Defaults bootcode="/boot/boot" # Since almost all of the boot process refers absolutely to /boot/... and # cannot work when /boot is on its own filesystem, the bootcode in /boot/boot # must be moved to make way for a 'boot -> .' symlink so that it works. # Unfortunately, this breaks bsdlabel, which expects the bootcode to be in # /boot/boot. bsdlabel will happily store whatever is in /boot/boot into the # track, including the directory itself. >o.O< [ ! -f "${bootcode}" -a -f "/boot/boot.blk" ] && bootcode="/boot/boot.blk" boot_img="boot.img" root_img="root.img" conf_dir="conf" card_img="card.img" card_size=1000944 # Parse command line options while getopts "b:r:c:o:s:a:h" opt do case "${opt}" in b) boot_img="${OPTARG}" ;; r) root_img="${OPTARG}" ;; c) conf_dir="${OPTARG}" ;; o) card_img="${OPTARG}" ;; s) card_size="${OPTARG}" ;; a) bootcode="${OPTARG}" ;; h) pebkac ;; [?]) pebkac "Unrecognized option ${opt}" ;; esac done shift $(( $OPTIND - 1 )) [ -f "${boot_img}" ] || err "${boot_img}: no such file or directory" [ -f "${root_img}" ] || err "${root_img}: no such file or directory" [ -d "${conf_dir}" ] || err "${conf_dir}: not a directory" [ "${card_size}" -gt 0 ] || err "${card_size}: not a number " [ -f "${bootcode}" ] || err "${bootcode}: not a regular file" log Card size: ${card_size} sectors rm -f "${card_img}" dd if=/dev/zero of="${card_img}" bs=512 count=0 seek="${card_size}" 2>/dev/null md=$(mdconfig -a -t vnode -f "${card_img}") mnt="$(mktemp -d /tmp/conf.XXXXXXXX)" trap "umount '${mnt}'; rm -Rf '${mnt}'; mdconfig -d -u '${md}'" exit hup int term kill compute_label "${card_size}" "${boot_img}" "${root_img}" | bsdlabel -R -B -b "${bootcode}" "${md}" /dev/stdin log Applied label: bsdlabel "${md}" log Writing boot image from "${boot_img}" dd if="${boot_img}" of="/dev/${md}a" bs=131072 2>/dev/null log Writing root image from "${root_img}" dd if="${root_img}" of="/dev/${md}d" bs=131072 2>/dev/null log Writing conf image newfs -U -L conf "/dev/${md}e" log Populating conf from "${conf_dir}" mount "/dev/${md}e" "${mnt}" ( cd "${conf_dir}"; find . | cpio -p "${mnt}" ) sync