script/gentree: clean up custom config applicator to ignore missing cpios
[CDN/Mosi.git] / script / gencard
1 #!/bin/sh
2
3 _root="$(dirname "${0}")"; . "${_root}/lib/env.sh"
4 want root log
5
6 pebkac(){
7   [ "${*}" ] && echo "$(basename "${0}"): ${*}" && echo ""
8   echo "Generate a card image using the specified boot and root images,"
9   echo " and the optional conf directory to fill the free space."
10   echo ""
11   echo "Options:"
12   echo " -b <image>  Boot image filename (default boot.img)"
13   echo " -r <image>  Root image filename (default root.img)"
14   echo " -c <dir>    Config directory to embed into card image"
15   echo " -o <image>  Card image filename to write (default card.img)"
16   echo " -s <sects>  Intended card size, in 512-byte sectors"
17   echo " -a <image>  Bootcode file to use (default /boot/boot)"
18   echo " -h          Hi!"
19   exit 1
20 }
21
22 img_sects(){
23   [ ! -f "${1}" ] && return 0
24   (
25     eval $(stat -s "${1}")
26     echo "$(( ( ${st_size} + ( ${st_size} % 512 ) ) / 512 ))"
27   )
28 }
29
30 compute_label(){
31   # Params: 1: cardsects 2: boot.img 3: root.img
32   card_size="${1}"
33   boot_file="${2}"
34   root_file="${3}"
35   [ -z "${card_size}" -o -z "${boot_file}" -o -z "${root_file}" ] && pebkac "RTFS, bitch!"
36   
37   omfg_ofst=0
38   omfg_size=16
39   boot_ofst="$(( ${omfg_ofst} + ${omfg_size} ))"
40   boot_size="$(img_sects "${boot_file}")"
41   root_ofst="$(( ${boot_ofst} + ${boot_size} ))"
42   root_size="$(img_sects "${root_file}")"
43   conf_ofst="$(( ${root_ofst} + ${root_size} ))"
44   conf_size="$(( ${card_size} - ( ${omfg_size} + ${boot_size} + ${root_size} ) ))"
45   last_ofst="$(( ${conf_ofst} + ${conf_size} ))"
46   
47   echo "a: ${boot_size} ${boot_ofst} 4.2BSD"
48   echo "b: ${omfg_size} ${omfg_ofst} boot"
49   echo "c: ${card_size} 0 unused"
50   echo "d: ${root_size} ${root_ofst} ISO9660"
51   echo "e: ${conf_size} ${conf_ofst} 4.2BSD"
52 }
53
54 # Defaults
55 bootcode="/boot/boot"
56
57 # Since almost all of the boot process refers absolutely to /boot/... and
58 #  cannot work when /boot is on its own filesystem, the bootcode in /boot/boot
59 #  must be moved to make way for a 'boot -> .' symlink so that it works.
60 #  Unfortunately, this breaks bsdlabel, which expects the bootcode to be in
61 #  /boot/boot. bsdlabel will happily store whatever is in /boot/boot into the
62 #  track, including the directory itself. >o.O<
63 [ ! -f "${bootcode}" -a -f "/boot/boot.blk" ] && bootcode="/boot/boot.blk"
64
65 boot_img="boot.img"
66 root_img="root.img"
67 conf_dir="conf"
68 card_img="card.img"
69 card_size=1000944
70
71 # Parse command line options
72 while getopts "b:r:c:o:s:a:h" opt
73 do
74   case "${opt}" in
75     b) boot_img="${OPTARG}" ;;
76     r) root_img="${OPTARG}" ;;
77     c) conf_dir="${OPTARG}" ;;
78     o) card_img="${OPTARG}" ;;
79     s) card_size="${OPTARG}" ;;
80     a) bootcode="${OPTARG}" ;;
81     h) pebkac ;;
82     [?]) pebkac "Unrecognized option ${opt}" ;;
83   esac
84 done
85 shift $(( $OPTIND - 1 ))
86
87 [ -f "${boot_img}" ] || err "${boot_img}: no such file or directory"
88 [ -f "${root_img}" ] || err "${root_img}: no such file or directory"
89 [ -d "${conf_dir}" ] || err "${conf_dir}: not a directory"
90 [ "${card_size}" -gt 0 ] || err "${card_size}: not a number "
91 [ -f "${bootcode}" ] || err "${bootcode}: not a regular file"
92
93 log Card size: ${card_size} sectors
94 rm -f "${card_img}"
95 dd if=/dev/zero of="${card_img}" bs=512 count=0 seek="${card_size}" 2>/dev/null
96 md=$(mdconfig -a -t vnode -f "${card_img}")
97 mnt="$(mktemp -d /tmp/conf.XXXXXXXX)"
98 trap "umount '${mnt}'; rm -Rf '${mnt}'; mdconfig -d -u '${md}'" exit hup int term kill
99
100 compute_label "${card_size}" "${boot_img}" "${root_img}" | bsdlabel -R -B -b "${bootcode}" "${md}" /dev/stdin
101 log Applied label:
102 bsdlabel "${md}"
103
104 log Writing boot image from "${boot_img}"
105 dd if="${boot_img}" of="/dev/${md}a" bs=131072 2>/dev/null
106
107 log Writing root image from "${root_img}"
108 dd if="${root_img}" of="/dev/${md}d" bs=131072 2>/dev/null
109
110 log Writing conf image
111 newfs -U -L conf "/dev/${md}e"
112
113 log Populating conf from "${conf_dir}"
114 mount "/dev/${md}e" "${mnt}"
115 ( cd "${conf_dir}"; find . | cpio -p "${mnt}" )
116
117 sync