11.31Sjmcneill#!/bin/sh 21.92Sgutterid# $NetBSD: mkimage,v 1.92 2025/04/01 00:04:00 gutteridge Exp $ 31.13Schristos# 41.45Schristos# Copyright (c) 2013, 2014 The NetBSD Foundation, Inc. 51.1Sagc# All rights reserved. 61.1Sagc# 71.17Schristos# This code is derived from software contributed to The NetBSD Foundation 81.17Schristos# by Christos Zoulas. 91.17Schristos# 101.1Sagc# Redistribution and use in source and binary forms, with or without 111.1Sagc# modification, are permitted provided that the following conditions 121.1Sagc# are met: 131.1Sagc# 1. Redistributions of source code must retain the above copyright 141.1Sagc# notice, this list of conditions and the following disclaimer. 151.1Sagc# 2. Redistributions in binary form must reproduce the above copyright 161.1Sagc# notice, this list of conditions and the following disclaimer in the 171.1Sagc# documentation and/or other materials provided with the distribution. 181.17Schristos# 3. Neither the name of The NetBSD Foundation nor the names of its 191.17Schristos# contributors may be used to endorse or promote products derived 201.17Schristos# from this software without specific prior written permission. 211.17Schristos# 221.17Schristos# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 231.17Schristos# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 241.17Schristos# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 251.17Schristos# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 261.17Schristos# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 271.17Schristos# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 281.17Schristos# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 291.17Schristos# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 301.17Schristos# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 311.17Schristos# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 321.17Schristos# POSSIBILITY OF SUCH DAMAGE. 331.1Sagc# 341.1Sagc 351.58Shubertf# 361.58Shubertf# Makes a bootable image for the host architecture given. 371.92Sgutterid# The host-specific functions are pulled in from a /bin/sh script in the 381.92Sgutterid# "conf" directory, which is expected to provide the following shell 391.58Shubertf# functions, which are called in the following order: 401.58Shubertf# 411.58Shubertf# - make_fstab: Creates the host's /etc/fstab with / on ${rootdev}. 421.58Shubertf# If -m is given, a number of directories are put on a tmpfs RAM disk 431.58Shubertf# - customize: After unpacking the sets, this gets the system to 441.92Sgutterid# a working state, e.g., by setting up /etc/rc.conf and /dev 451.58Shubertf# - populate: Add common goods like kernel and bootloader 461.58Shubertf# - make_label: Prints disklabel to stdout 471.58Shubertf# 481.58Shubertf 491.33Sjmcneillset -e 501.33Sjmcneill 511.17SchristosDIR="$(cd "$(dirname "$0")" && pwd)" 521.17SchristosPROG="$(basename "$0")" 531.17Schristos 541.66SjmcneillMAKE=${TOOL_MAKE:-make} 551.21SchristosDISKLABEL=${TOOL_DISKLABEL:-disklabel} 561.24SchristosFDISK=${TOOL_FDISK:-fdisk} 571.73SjmcneillGPT=${TOOL_GPT:-gpt} 581.21SchristosMAKEFS=${TOOL_MAKEFS:-makefs} 591.25SjmcneillMTREE=${TOOL_MTREE:-mtree} 601.45SchristosINSTALLBOOT=${TOOL_INSTALLBOOT:-installboot} 611.59SchristosMKUBOOTIMAGE=${TOOL_MKUBOOTIMAGE:-mkubootimage} 621.44SastGZIP_CMD=${TOOL_GZIP:-gzip} # ${GZIP} is special to gzip(1) 631.88SjmmvSED=${TOOL_SED:-sed} 641.88SjmmvPWD_MKDB=${TOOL_PWD_MKDB:-pwd_mkdb} 651.21Schristos 661.87Sjmmvpostfix=false 671.87Sjmmv[ "${MKPOSTFIX:-yes}" = no ] || postfix=true 681.87Sjmmv 691.17Schristossrc="/usr/src" 701.84Sskrllsets="base comp etc games gpufw man manhtml misc modules rescue tests text" 711.83Sskrllxsets="xbase xcomp xetc xfont xserver" 721.17Schristosminfree="10%" 731.17Schristosbar="===" 741.17Schristos 751.67Skretmp="$(mktemp -d "${TMPDIR:-/tmp}/$PROG.XXXXXX")" 761.17Schristosmnt="${tmp}/mnt" 771.46Schristosmkdir -p "${mnt}/etc" "${mnt}/dev" 781.23Schristos 791.17Schristostrap "cleanup" 0 1 2 3 15 801.17Schristos 811.17Schristoscleanup() { 821.17Schristos case "$tmp" in 831.68Skre "${TMPDIR:-/tmp}/$PROG."*) rm -fr "$tmp";; 841.17Schristos esac 851.17Schristos} 861.1Sagc 871.69Skrefail() { 881.69Skre IFS=' ' 891.69Skre echo >&2 "${PROG}: $*" 901.69Skre exit 1 911.69Skre} 921.69Skre 931.17Schristosgetsize() { 941.17Schristos set -- $(ls -l $1) 951.17Schristos echo $5 961.1Sagc} 971.1Sagc 981.63Sjmcneillgetsectors() { 991.63Sjmcneill case "$1" in 1001.63Sjmcneill *g) 1011.63Sjmcneill m=1073741824 1021.63Sjmcneill v=${1%g} 1031.63Sjmcneill ;; 1041.63Sjmcneill *m) 1051.63Sjmcneill m=1048576 1061.63Sjmcneill v=${1%m} 1071.63Sjmcneill ;; 1081.63Sjmcneill *k) 1091.63Sjmcneill m=1024 1101.63Sjmcneill v=${1%k} 1111.63Sjmcneill ;; 1121.63Sjmcneill *[0-9b]) 1131.63Sjmcneill m=1 1141.63Sjmcneill v=${1%b} 1151.63Sjmcneill ;; 1161.63Sjmcneill esac 1171.63Sjmcneill echo $((m * v / 512)) 1181.63Sjmcneill} 1191.63Sjmcneill 1201.85Schristosminwrites_fstab_entries() { 1211.85Schristos $minwrites || return 0 1221.85Schristos cat << EOF 1231.85Schristostmpfs /var/log tmpfs rw,union,-s32M 1241.85Schristostmpfs /var/run tmpfs rw,union,-s1M 1251.85Schristostmpfs /var/mail tmpfs rw,union,-s10M 1261.87Sjmmvtmpfs /var/chroot tmpfs rw,union,-s10M 1271.87SjmmvEOF 1281.87Sjmmv if $postfix; then 1291.87Sjmmv cat << EOF 1301.85Schristostmpfs /var/spool/postfix tmpfs rw,union,-s20M 1311.85Schristostmpfs /var/db/postfix tmpfs rw,union,-s1M 1321.85SchristosEOF 1331.87Sjmmv fi 1341.85Schristos} 1351.85Schristos 1361.85Schristosmake_fstab_gpt() { 1371.85Schristos local boot=$1 1381.85Schristos local rootopts= 1391.85Schristos if $minwrites; then 1401.85Schristos rootopts=,log,nodevmtime 1411.85Schristos fi 1421.85Schristos 1431.85Schristos cat > ${mnt}/etc/fstab << EOF 1441.85Schristos# NetBSD /etc/fstab 1451.85Schristos# See /usr/share/examples/fstab/ for more examples. 1461.85SchristosNAME=${gpt_label_ffs:-netbsd-root} / ffs rw,noatime${rootopts} 1 1 1471.85SchristosNAME=${gpt_label_boot:-$boot} /boot msdos rw 1 1 1481.85Schristosptyfs /dev/pts ptyfs rw 1491.85Schristosprocfs /proc procfs rw 1501.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1511.85SchristosEOF 1521.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1531.85Schristos} 1541.85Schristos 1551.85Schristos# From Richard Neswold's: 1561.85Schristos# http://rich-tbp.blogspot.com/2013/03/netbsd-on-rpi-minimizing-disk-writes.html 1571.85Schristos# Also for the postfix stuff below 1581.85Schristosmake_fstab_normal() { 1591.85Schristos local rootopts= 1601.85Schristos if $minwrites; then 1611.85Schristos rootopts=,nodevmtime 1621.85Schristos fi 1631.85Schristos cat > ${mnt}/etc/fstab << EOF 1641.85Schristos# NetBSD /etc/fstab 1651.85Schristos# See /usr/share/examples/fstab/ for more examples. 1661.90SjmcneillROOT.a / ffs rw,noatime${rootopts} 1 1 1671.85SchristosROOT.e /boot msdos rw 1 1 1681.85Schristosptyfs /dev/pts ptyfs rw 1691.85Schristosprocfs /proc procfs rw 1701.85Schristostmpfs /tmp tmpfs rw,-s32M 1711.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1721.85SchristosEOF 1731.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1741.85Schristos} 1751.85Schristos 1761.85Schristosmake_fstab_default() { 1771.85Schristos if $gpt; then 1781.85Schristos make_fstab_gpt "$@" 1791.85Schristos else 1801.85Schristos make_fstab_normal 1811.85Schristos fi 1821.85Schristos echo "./etc/fstab type=file uname=root gname=wheel mode=0644" \ 1831.85Schristos >> "$tmp/selected_sets" 1841.85Schristos 1851.85Schristos # Missing mount points from fstab 1861.85Schristos echo "./proc type=dir uname=root gname=wheel mode=0755" \ 1871.85Schristos >> "$tmp/selected_sets" 1881.85Schristos} 1891.85Schristos 1901.12Schristosusage() { 1911.12Schristos cat << EOF 1>&2 1921.60SmartinUsage: $PROG -h <host-arch> [-bdmx] [-B <byte-order>] [-K <kerneldir>] [-S <srcdir>] [-D <destdir>] [-c <custom-files-dir>] [-s <Mb size>] [<image>] 1931.39Schristos 1941.39Schristos-b Boot only, no sets loaded 1951.47Schristos-r root device kind (sd, wd, ld) 1961.39Schristos-d Add the debug sets 1971.43Schristos-m Optimize the OS installation to mimimize disk writes for SSDs 1981.57Shubertf-x Load the X sets too, not just the base ones 1991.12SchristosEOF 2001.13Schristos exit 1 2011.12Schristos} 2021.12Schristos 2031.32Sjmcneill# First pass for options to get the host and src directories 2041.60SmartinOPTS="B:D:K:S:bc:dh:mr:s:x" 2051.4Schristoswhile getopts "$OPTS" f 2061.4Schristosdo 2071.4Schristos case $f in 2081.4Schristos h) h="$OPTARG";; 2091.32Sjmcneill S) src="$OPTARG";; 2101.4Schristos *) ;; 2111.4Schristos esac 2121.4Schristosdone 2131.4Schristos 2141.4Schristosif [ -z "$h" ] 2151.4Schristosthen 2161.4Schristos usage 2171.4Schristosfi 2181.4Schristos 2191.5Schristosif [ ! -f "${DIR}/conf/${h}.conf" ] 2201.4Schristosthen 2211.5Schristos echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2 2221.4Schristos exit 1 2231.4Schristosfi 2241.4Schristos 2251.56Sjmcneillresize=false 2261.73Sjmcneillgpt=false 2271.74Sjmcneillgpt_hybrid=false 2281.89Sjmcneillfsize=8192 2291.89Sjmcneillbsize=65536 2301.89Sjmcneillffsversion=1 2311.56Sjmcneill 2321.5Schristos. "${DIR}/conf/${h}.conf" 2331.45Schristosrelease="/usr/obj/${MACHINE}/release" 2341.4Schristos 2351.17Schristosselected_sets="$sets" 2361.50Sskrlldsets_p=false 2371.50Sskrllxsets_p=false 2381.39Schristosminwrites=false 2391.47Schristosrootdev=ld 2401.60Smartinendian= 2411.17Schristos 2421.4SchristosOPTIND=1 2431.4Schristoswhile getopts "$OPTS" f 2441.4Schristosdo 2451.4Schristos case $f in 2461.60Smartin B) endian="-B $OPTARG";; 2471.18Schristos D) release="$OPTARG";; 2481.18Schristos K) kernel="$OPTARG";; 2491.32Sjmcneill S) ;; 2501.41Schristos b) bootonly=true;; 2511.50Sskrll d) dsets_p=true 2521.39Schristos selected_sets="$selected_sets debug" 2531.50Sskrll if $xsets_p; then 2541.39Schristos selected_sets="$selected_sets xdebug" 2551.39Schristos fi 2561.39Schristos ;; 2571.4Schristos c) custom="$OPTARG";; 2581.4Schristos h) ;; 2591.39Schristos m) minwrites=true;; 2601.47Schristos r) rootdev="$OPTARG";; 2611.4Schristos s) size="$OPTARG";; 2621.50Sskrll x) xsets_p=true 2631.39Schristos selected_sets="$selected_sets $xsets" 2641.50Sskrll if $dsets_p; then 2651.39Schristos selected_sets="$selected_sets xdebug" 2661.39Schristos fi 2671.39Schristos ;; 2681.6Schristos *) usage;; 2691.1Sagc esac 2701.1Sagcdone 2711.81Smlelstvif [ -n "${MKREPRO_TIMESTAMP}" ]; then 2721.80Schristos timestamp_opt="-T ${MKREPRO_TIMESTAMP}" 2731.80Schristos volume_opt=",volume_id=$((${MKREPRO_TIMESTAMP} & 0xffff))" 2741.80Schristosfi 2751.1Sagc 2761.20Sjmcneillshift $(( $OPTIND - 1 )) 2771.4Schristosif [ -n "$1" ]; then 2781.1Sagc # take the next argument as being the image name 2791.1Sagc image="$1" 2801.1Sagc shift 2811.1Sagcfi 2821.1Sagc 2831.22Schristoscase "$image" in 2841.22Schristos*.gz) compress=true; image="${image%.gz}";; 2851.22Schristos*) compress=false;; 2861.22Schristosesac 2871.22Schristos 2881.45Schristosif [ -z "${bootonly}" ]; then 2891.36Sgarbled echo ${bar} configuring sets ${bar} 2901.51Sskrll (cat "${release}/etc/mtree/NetBSD.dist" 2911.36Sgarbled for i in $selected_sets; do 2921.36Sgarbled s="${release}/etc/mtree/set.$i" 2931.36Sgarbled if [ -f "$s" ]; then 2941.36Sgarbled cat "$s" 2951.36Sgarbled fi 2961.36Sgarbled done) > "$tmp/selected_sets" 2971.36Sgarbledfi 2981.1Sagc 2991.4Schristosmake_fstab 3001.17Schristoscustomize 3011.17Schristospopulate 3021.1Sagc 3031.72Sjmcneillif [ ! "${MKDTB}" = "no" ]; then 3041.72Sjmcneill # 3051.72Sjmcneill # Part of the dtb set resides on the FAT partition (/boot/dtb/*), and 3061.72Sjmcneill # the rest on FFS. Split it up here. 3071.72Sjmcneill # 3081.72Sjmcneill echo ${bar} Installing devicetree blobs ${bar} 3091.72Sjmcneill mkdir -p "${mnt}/boot" 3101.72Sjmcneill cp -r "${release}/boot/dtb" "${mnt}/boot/dtb" 3111.72Sjmcneill 3121.72Sjmcneill mkdir -p "${mnt}/etc/mtree" 3131.72Sjmcneill cp "${release}/etc/mtree/set.dtb" "${mnt}/etc/mtree/set.dtb" 3141.72Sjmcneill echo "./etc/mtree/set.dtb type=file uname=root gname=wheel mode=0444" >> "$tmp/selected_sets" 3151.72Sjmcneill 3161.72Sjmcneill mkdir -p "${mnt}/var/db/obsolete" 3171.72Sjmcneill cp "${release}/var/db/obsolete/dtb" "${mnt}/var/db/obsolete/dtb" 3181.72Sjmcneill echo "./var/db/obsolete/dtb type=file uname=root gname=wheel mode=0644" >>"$tmp/selected_sets" 3191.72Sjmcneillfi 3201.72Sjmcneill 3211.45Schristosif [ -n "${msdosid}" ]; then 3221.17Schristos echo ${bar} Populating msdos filesystem ${bar} 3231.72Sjmcneill 3241.71Smartin case $(( ${msdosid} )) in 3251.71Smartin 1) fat_opt=",fat_type=12";; 3261.71Smartin 4|6|14) fat_opt=",fat_type=16";; 3271.71Smartin 11|12) fat_opt=",fat_type=32";; 3281.71Smartin *) fat_opt=;; 3291.71Smartin esac 3301.71Smartin ${MAKEFS} -N ${release}/etc -t msdos \ 3311.80Schristos -o "volume_label=NETBSD${fat_opt}${volume_opt}" ${timestamp_opt} \ 3321.63Sjmcneill -O $((${init} / 2))m -s $((${boot} / 2))m \ 3331.41Schristos ${image} ${mnt}/boot 3341.1Sagcfi 3351.1Sagc 3361.45Schristosif [ -z "${bootonly}" ]; then 3371.36Sgarbled echo ${bar} Populating ffs filesystem ${bar} 3381.60Smartin ${MAKEFS} -rx ${endian} -N ${release}/etc -t ffs \ 3391.80Schristos -O ${ffsoffset} ${timestamp_opt} \ 3401.89Sjmcneill -o d=4096,f=${fsize},b=${bsize},v=${ffsversion} -b $((${extra}))m \ 3411.36Sgarbled -F "$tmp/selected_sets" ${image} "${release}" "${mnt}" 3421.36Sgarbledfi 3431.1Sagc 3441.23Schristosif [ "${size}" = 0 ]; then 3451.77Srin size="$(getsize "${image}")" 3461.76Sriastrad # Round up to a multiple of 4m and add 1m of slop. 3471.76Sriastrad alignunit=$((4*1024*1024)) 3481.77Srin alignsize=$((alignunit*((size + alignunit - 1)/alignunit))) 3491.76Sriastrad alignsize=$((alignsize + 1024*1024)) 3501.77Srin if [ "${size}" -lt "${alignsize}" ]; then 3511.77Srin dd bs=1 count="$((alignsize - size))" if=/dev/zero \ 3521.77Srin >> "${image}" 2> /dev/null 3531.77Srin size="${alignsize}" 3541.76Sriastrad fi 3551.17Schristosfi 3561.1Sagc 3571.73Sjmcneillif $gpt; then 3581.74Sjmcneill if $gpt_hybrid; then 3591.74Sjmcneill gpt_flags="-H" 3601.74Sjmcneill fi 3611.80Schristos gpt_flags="${gpt_flags} ${timestamp_opt}" 3621.30Sjmcneill initsecs=$((${init} * 1024)) 3631.30Sjmcneill bootsecs=$((${boot} * 1024)) 3641.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3651.73Sjmcneill 3661.73Sjmcneill echo ${bar} Clearing existing partitions ${bar} 3671.74Sjmcneill ${GPT} ${gpt_flags} ${image} destroy || true 3681.73Sjmcneill 3691.73Sjmcneill echo ${bar} Creating partitions ${bar} 3701.74Sjmcneill ${GPT} ${gpt_flags} ${image} create ${gpt_create_flags} 3711.75Sjmcneill ${GPT} ${gpt_flags} ${image} add -b ${initsecs} -s ${bootsecs} -l ${gpt_label_boot:-EFI} -t ${gpt_boot_type:-efi} 3721.74Sjmcneill ${GPT} ${gpt_flags} ${image} set -a required -i 1 3731.74Sjmcneill ${GPT} ${gpt_flags} ${image} add -a 4m -b ${ffsstart} -l ${gpt_label_ffs:-netbsd-root} -t ffs 3741.74Sjmcneill ${GPT} ${gpt_flags} ${image} show 3751.74Sjmcneill if $gpt_hybrid; then 3761.74Sjmcneill echo ${bar} Creating hybrid MBR ${bar} 3771.74Sjmcneill ${FDISK} -f -g -u -0 -a -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3781.74Sjmcneill ${FDISK} -f -g -u -3 -s 238/1/$((${initsecs} - 1)) -F ${image} 3791.74Sjmcneill ${FDISK} -F ${image} 3801.74Sjmcneill fi 3811.73Sjmcneillelse 3821.73Sjmcneill if [ -n "${msdosid}" ]; then 3831.73Sjmcneill echo ${bar} Running fdisk ${bar} 3841.73Sjmcneill initsecs=$((${init} * 1024)) 3851.73Sjmcneill bootsecs=$((${boot} * 1024)) 3861.73Sjmcneill ${FDISK} -f -i ${image} 3871.73Sjmcneill ${FDISK} -f -a -u -0 -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3881.73Sjmcneill if [ -z "${bootonly}" ]; then 3891.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3901.73Sjmcneill imagesize="$(getsize "${image}")" 3911.73Sjmcneill imagesecs="$(getsectors ${imagesize})" 3921.73Sjmcneill ffssize="$(expr ${imagesecs} - ${ffsstart})" 3931.73Sjmcneill ${FDISK} -f -u -1 -s 169/${ffsstart}/${ffssize} -F ${image} 3941.73Sjmcneill fi 3951.73Sjmcneill 3961.73Sjmcneill echo ${bar} Adding label ${bar} 3971.73Sjmcneill make_label > ${tmp}/label 3981.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 3991.73Sjmcneill elif [ -n "${netbsdid}" ]; then 4001.73Sjmcneill echo ${bar} Adding label ${bar} 4011.73Sjmcneill make_label > ${tmp}/label 4021.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 4031.73Sjmcneill 4041.73Sjmcneill echo ${bar} Running fdisk ${bar} 4051.73Sjmcneill ${FDISK} -f -i ${image} 4061.73Sjmcneill ${FDISK} -f -a -u -0 -s 169/${init} ${image} 4071.73Sjmcneill ${INSTALLBOOT} -f -v ${image} ${release}/usr/mdec/bootxx_ffsv1 4081.63Sjmcneill fi 4091.2Sagcfi 4101.22Schristos 4111.22Schristosif $compress; then 4121.22Schristos echo ${bar} Compressing image ${bar} 4131.23Schristos rm -f "${image}.gz" 4141.80Schristos ${GZIP_CMD} -n -9 ${image} 4151.22Schristos image="${image}.gz" 4161.22Schristosfi 4171.22Schristos 4181.91Shgutchcd "${IMAGEDIR}" 4191.91Shgutch${CKSUM} -a MD5 "$(basename "${image}")" > MD5 4201.91Shgutch${CKSUM} -a SHA512 "$(basename "${image}")" > SHA512 4211.91Shgutch 4221.17Schristosecho ${bar} Image is ${image} ${bar} 423