mkimage revision 1.87
11.31Sjmcneill#!/bin/sh 21.87Sjmmv# $NetBSD: mkimage,v 1.87 2024/12/29 09:46:44 jmmv 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.58Shubertf# The host specific functions are pulled in from a /bin/sh script in the 381.58Shubertf# "conf" directory, and 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.58Shubertf# 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.21Schristos 641.87Sjmmvpostfix=false 651.87Sjmmv[ "${MKPOSTFIX:-yes}" = no ] || postfix=true 661.87Sjmmv 671.17Schristossrc="/usr/src" 681.84Sskrllsets="base comp etc games gpufw man manhtml misc modules rescue tests text" 691.83Sskrllxsets="xbase xcomp xetc xfont xserver" 701.17Schristosminfree="10%" 711.17Schristosbar="===" 721.17Schristos 731.67Skretmp="$(mktemp -d "${TMPDIR:-/tmp}/$PROG.XXXXXX")" 741.17Schristosmnt="${tmp}/mnt" 751.46Schristosmkdir -p "${mnt}/etc" "${mnt}/dev" 761.23Schristos 771.17Schristostrap "cleanup" 0 1 2 3 15 781.17Schristos 791.17Schristoscleanup() { 801.17Schristos case "$tmp" in 811.68Skre "${TMPDIR:-/tmp}/$PROG."*) rm -fr "$tmp";; 821.17Schristos esac 831.17Schristos} 841.1Sagc 851.69Skrefail() { 861.69Skre IFS=' ' 871.69Skre echo >&2 "${PROG}: $*" 881.69Skre exit 1 891.69Skre} 901.69Skre 911.17Schristosgetsize() { 921.17Schristos set -- $(ls -l $1) 931.17Schristos echo $5 941.1Sagc} 951.1Sagc 961.63Sjmcneillgetsectors() { 971.63Sjmcneill case "$1" in 981.63Sjmcneill *g) 991.63Sjmcneill m=1073741824 1001.63Sjmcneill v=${1%g} 1011.63Sjmcneill ;; 1021.63Sjmcneill *m) 1031.63Sjmcneill m=1048576 1041.63Sjmcneill v=${1%m} 1051.63Sjmcneill ;; 1061.63Sjmcneill *k) 1071.63Sjmcneill m=1024 1081.63Sjmcneill v=${1%k} 1091.63Sjmcneill ;; 1101.63Sjmcneill *[0-9b]) 1111.63Sjmcneill m=1 1121.63Sjmcneill v=${1%b} 1131.63Sjmcneill ;; 1141.63Sjmcneill esac 1151.63Sjmcneill echo $((m * v / 512)) 1161.63Sjmcneill} 1171.63Sjmcneill 1181.85Schristosminwrites_fstab_entries() { 1191.85Schristos $minwrites || return 0 1201.85Schristos cat << EOF 1211.85Schristostmpfs /var/log tmpfs rw,union,-s32M 1221.85Schristostmpfs /var/run tmpfs rw,union,-s1M 1231.85Schristostmpfs /var/mail tmpfs rw,union,-s10M 1241.87Sjmmvtmpfs /var/chroot tmpfs rw,union,-s10M 1251.87SjmmvEOF 1261.87Sjmmv if $postfix; then 1271.87Sjmmv cat << EOF 1281.85Schristostmpfs /var/spool/postfix tmpfs rw,union,-s20M 1291.85Schristostmpfs /var/db/postfix tmpfs rw,union,-s1M 1301.85SchristosEOF 1311.87Sjmmv fi 1321.85Schristos} 1331.85Schristos 1341.85Schristosmake_fstab_gpt() { 1351.85Schristos local boot=$1 1361.85Schristos local rootopts= 1371.85Schristos if $minwrites; then 1381.85Schristos rootopts=,log,nodevmtime 1391.85Schristos fi 1401.85Schristos 1411.85Schristos cat > ${mnt}/etc/fstab << EOF 1421.85Schristos# NetBSD /etc/fstab 1431.85Schristos# See /usr/share/examples/fstab/ for more examples. 1441.85SchristosNAME=${gpt_label_ffs:-netbsd-root} / ffs rw,noatime${rootopts} 1 1 1451.85SchristosNAME=${gpt_label_boot:-$boot} /boot msdos rw 1 1 1461.85Schristosptyfs /dev/pts ptyfs rw 1471.85Schristosprocfs /proc procfs rw 1481.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1491.85SchristosEOF 1501.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1511.85Schristos} 1521.85Schristos 1531.85Schristos# From Richard Neswold's: 1541.85Schristos# http://rich-tbp.blogspot.com/2013/03/netbsd-on-rpi-minimizing-disk-writes.html 1551.85Schristos# Also for the postfix stuff below 1561.85Schristosmake_fstab_normal() { 1571.85Schristos local rootopts= 1581.85Schristos if $minwrites; then 1591.85Schristos rootopts=,nodevmtime 1601.85Schristos fi 1611.85Schristos cat > ${mnt}/etc/fstab << EOF 1621.85Schristos# NetBSD /etc/fstab 1631.85Schristos# See /usr/share/examples/fstab/ for more examples. 1641.86SchristosROOT.a / ffs rw,log,noatime${rootopts} 1 1 1651.85SchristosROOT.e /boot msdos rw 1 1 1661.85Schristosptyfs /dev/pts ptyfs rw 1671.85Schristosprocfs /proc procfs rw 1681.85Schristostmpfs /tmp tmpfs rw,-s32M 1691.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1701.85SchristosEOF 1711.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1721.85Schristos} 1731.85Schristos 1741.85Schristosmake_fstab_default() { 1751.85Schristos if $gpt; then 1761.85Schristos make_fstab_gpt "$@" 1771.85Schristos else 1781.85Schristos make_fstab_normal 1791.85Schristos fi 1801.85Schristos echo "./etc/fstab type=file uname=root gname=wheel mode=0644" \ 1811.85Schristos >> "$tmp/selected_sets" 1821.85Schristos 1831.85Schristos # Missing mount points from fstab 1841.85Schristos echo "./proc type=dir uname=root gname=wheel mode=0755" \ 1851.85Schristos >> "$tmp/selected_sets" 1861.85Schristos} 1871.85Schristos 1881.12Schristosusage() { 1891.12Schristos cat << EOF 1>&2 1901.60SmartinUsage: $PROG -h <host-arch> [-bdmx] [-B <byte-order>] [-K <kerneldir>] [-S <srcdir>] [-D <destdir>] [-c <custom-files-dir>] [-s <Mb size>] [<image>] 1911.39Schristos 1921.39Schristos-b Boot only, no sets loaded 1931.47Schristos-r root device kind (sd, wd, ld) 1941.39Schristos-d Add the debug sets 1951.43Schristos-m Optimize the OS installation to mimimize disk writes for SSDs 1961.57Shubertf-x Load the X sets too, not just the base ones 1971.12SchristosEOF 1981.13Schristos exit 1 1991.12Schristos} 2001.12Schristos 2011.32Sjmcneill# First pass for options to get the host and src directories 2021.60SmartinOPTS="B:D:K:S:bc:dh:mr:s:x" 2031.4Schristoswhile getopts "$OPTS" f 2041.4Schristosdo 2051.4Schristos case $f in 2061.4Schristos h) h="$OPTARG";; 2071.32Sjmcneill S) src="$OPTARG";; 2081.4Schristos *) ;; 2091.4Schristos esac 2101.4Schristosdone 2111.4Schristos 2121.4Schristosif [ -z "$h" ] 2131.4Schristosthen 2141.4Schristos usage 2151.4Schristosfi 2161.4Schristos 2171.5Schristosif [ ! -f "${DIR}/conf/${h}.conf" ] 2181.4Schristosthen 2191.5Schristos echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2 2201.4Schristos exit 1 2211.4Schristosfi 2221.4Schristos 2231.56Sjmcneillresize=false 2241.73Sjmcneillgpt=false 2251.74Sjmcneillgpt_hybrid=false 2261.56Sjmcneill 2271.5Schristos. "${DIR}/conf/${h}.conf" 2281.45Schristosrelease="/usr/obj/${MACHINE}/release" 2291.4Schristos 2301.17Schristosselected_sets="$sets" 2311.50Sskrlldsets_p=false 2321.50Sskrllxsets_p=false 2331.39Schristosminwrites=false 2341.47Schristosrootdev=ld 2351.60Smartinendian= 2361.17Schristos 2371.4SchristosOPTIND=1 2381.4Schristoswhile getopts "$OPTS" f 2391.4Schristosdo 2401.4Schristos case $f in 2411.60Smartin B) endian="-B $OPTARG";; 2421.18Schristos D) release="$OPTARG";; 2431.18Schristos K) kernel="$OPTARG";; 2441.32Sjmcneill S) ;; 2451.41Schristos b) bootonly=true;; 2461.50Sskrll d) dsets_p=true 2471.39Schristos selected_sets="$selected_sets debug" 2481.50Sskrll if $xsets_p; then 2491.39Schristos selected_sets="$selected_sets xdebug" 2501.39Schristos fi 2511.39Schristos ;; 2521.4Schristos c) custom="$OPTARG";; 2531.4Schristos h) ;; 2541.39Schristos m) minwrites=true;; 2551.47Schristos r) rootdev="$OPTARG";; 2561.4Schristos s) size="$OPTARG";; 2571.50Sskrll x) xsets_p=true 2581.39Schristos selected_sets="$selected_sets $xsets" 2591.50Sskrll if $dsets_p; then 2601.39Schristos selected_sets="$selected_sets xdebug" 2611.39Schristos fi 2621.39Schristos ;; 2631.6Schristos *) usage;; 2641.1Sagc esac 2651.1Sagcdone 2661.81Smlelstvif [ -n "${MKREPRO_TIMESTAMP}" ]; then 2671.80Schristos timestamp_opt="-T ${MKREPRO_TIMESTAMP}" 2681.80Schristos volume_opt=",volume_id=$((${MKREPRO_TIMESTAMP} & 0xffff))" 2691.80Schristosfi 2701.1Sagc 2711.20Sjmcneillshift $(( $OPTIND - 1 )) 2721.4Schristosif [ -n "$1" ]; then 2731.1Sagc # take the next argument as being the image name 2741.1Sagc image="$1" 2751.1Sagc shift 2761.1Sagcfi 2771.1Sagc 2781.22Schristoscase "$image" in 2791.22Schristos*.gz) compress=true; image="${image%.gz}";; 2801.22Schristos*) compress=false;; 2811.22Schristosesac 2821.22Schristos 2831.45Schristosif [ -z "${bootonly}" ]; then 2841.36Sgarbled echo ${bar} configuring sets ${bar} 2851.51Sskrll (cat "${release}/etc/mtree/NetBSD.dist" 2861.36Sgarbled for i in $selected_sets; do 2871.36Sgarbled s="${release}/etc/mtree/set.$i" 2881.36Sgarbled if [ -f "$s" ]; then 2891.36Sgarbled cat "$s" 2901.36Sgarbled fi 2911.36Sgarbled done) > "$tmp/selected_sets" 2921.36Sgarbledfi 2931.1Sagc 2941.4Schristosmake_fstab 2951.17Schristoscustomize 2961.17Schristospopulate 2971.1Sagc 2981.72Sjmcneillif [ ! "${MKDTB}" = "no" ]; then 2991.72Sjmcneill # 3001.72Sjmcneill # Part of the dtb set resides on the FAT partition (/boot/dtb/*), and 3011.72Sjmcneill # the rest on FFS. Split it up here. 3021.72Sjmcneill # 3031.72Sjmcneill echo ${bar} Installing devicetree blobs ${bar} 3041.72Sjmcneill mkdir -p "${mnt}/boot" 3051.72Sjmcneill cp -r "${release}/boot/dtb" "${mnt}/boot/dtb" 3061.72Sjmcneill 3071.72Sjmcneill mkdir -p "${mnt}/etc/mtree" 3081.72Sjmcneill cp "${release}/etc/mtree/set.dtb" "${mnt}/etc/mtree/set.dtb" 3091.72Sjmcneill echo "./etc/mtree/set.dtb type=file uname=root gname=wheel mode=0444" >> "$tmp/selected_sets" 3101.72Sjmcneill 3111.72Sjmcneill mkdir -p "${mnt}/var/db/obsolete" 3121.72Sjmcneill cp "${release}/var/db/obsolete/dtb" "${mnt}/var/db/obsolete/dtb" 3131.72Sjmcneill echo "./var/db/obsolete/dtb type=file uname=root gname=wheel mode=0644" >>"$tmp/selected_sets" 3141.72Sjmcneillfi 3151.72Sjmcneill 3161.45Schristosif [ -n "${msdosid}" ]; then 3171.17Schristos echo ${bar} Populating msdos filesystem ${bar} 3181.72Sjmcneill 3191.71Smartin case $(( ${msdosid} )) in 3201.71Smartin 1) fat_opt=",fat_type=12";; 3211.71Smartin 4|6|14) fat_opt=",fat_type=16";; 3221.71Smartin 11|12) fat_opt=",fat_type=32";; 3231.71Smartin *) fat_opt=;; 3241.71Smartin esac 3251.71Smartin ${MAKEFS} -N ${release}/etc -t msdos \ 3261.80Schristos -o "volume_label=NETBSD${fat_opt}${volume_opt}" ${timestamp_opt} \ 3271.63Sjmcneill -O $((${init} / 2))m -s $((${boot} / 2))m \ 3281.41Schristos ${image} ${mnt}/boot 3291.1Sagcfi 3301.1Sagc 3311.45Schristosif [ -z "${bootonly}" ]; then 3321.36Sgarbled echo ${bar} Populating ffs filesystem ${bar} 3331.60Smartin ${MAKEFS} -rx ${endian} -N ${release}/etc -t ffs \ 3341.80Schristos -O ${ffsoffset} ${timestamp_opt} \ 3351.61Sjmcneill -o d=4096,f=8192,b=65536 -b $((${extra}))m \ 3361.36Sgarbled -F "$tmp/selected_sets" ${image} "${release}" "${mnt}" 3371.36Sgarbledfi 3381.1Sagc 3391.23Schristosif [ "${size}" = 0 ]; then 3401.77Srin size="$(getsize "${image}")" 3411.76Sriastrad # Round up to a multiple of 4m and add 1m of slop. 3421.76Sriastrad alignunit=$((4*1024*1024)) 3431.77Srin alignsize=$((alignunit*((size + alignunit - 1)/alignunit))) 3441.76Sriastrad alignsize=$((alignsize + 1024*1024)) 3451.77Srin if [ "${size}" -lt "${alignsize}" ]; then 3461.77Srin dd bs=1 count="$((alignsize - size))" if=/dev/zero \ 3471.77Srin >> "${image}" 2> /dev/null 3481.77Srin size="${alignsize}" 3491.76Sriastrad fi 3501.17Schristosfi 3511.1Sagc 3521.73Sjmcneillif $gpt; then 3531.74Sjmcneill if $gpt_hybrid; then 3541.74Sjmcneill gpt_flags="-H" 3551.74Sjmcneill fi 3561.80Schristos gpt_flags="${gpt_flags} ${timestamp_opt}" 3571.30Sjmcneill initsecs=$((${init} * 1024)) 3581.30Sjmcneill bootsecs=$((${boot} * 1024)) 3591.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3601.73Sjmcneill 3611.73Sjmcneill echo ${bar} Clearing existing partitions ${bar} 3621.74Sjmcneill ${GPT} ${gpt_flags} ${image} destroy || true 3631.73Sjmcneill 3641.73Sjmcneill echo ${bar} Creating partitions ${bar} 3651.74Sjmcneill ${GPT} ${gpt_flags} ${image} create ${gpt_create_flags} 3661.75Sjmcneill ${GPT} ${gpt_flags} ${image} add -b ${initsecs} -s ${bootsecs} -l ${gpt_label_boot:-EFI} -t ${gpt_boot_type:-efi} 3671.74Sjmcneill ${GPT} ${gpt_flags} ${image} set -a required -i 1 3681.74Sjmcneill ${GPT} ${gpt_flags} ${image} add -a 4m -b ${ffsstart} -l ${gpt_label_ffs:-netbsd-root} -t ffs 3691.74Sjmcneill ${GPT} ${gpt_flags} ${image} show 3701.74Sjmcneill if $gpt_hybrid; then 3711.74Sjmcneill echo ${bar} Creating hybrid MBR ${bar} 3721.74Sjmcneill ${FDISK} -f -g -u -0 -a -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3731.74Sjmcneill ${FDISK} -f -g -u -3 -s 238/1/$((${initsecs} - 1)) -F ${image} 3741.74Sjmcneill ${FDISK} -F ${image} 3751.74Sjmcneill fi 3761.73Sjmcneillelse 3771.73Sjmcneill if [ -n "${msdosid}" ]; then 3781.73Sjmcneill echo ${bar} Running fdisk ${bar} 3791.73Sjmcneill initsecs=$((${init} * 1024)) 3801.73Sjmcneill bootsecs=$((${boot} * 1024)) 3811.73Sjmcneill ${FDISK} -f -i ${image} 3821.73Sjmcneill ${FDISK} -f -a -u -0 -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3831.73Sjmcneill if [ -z "${bootonly}" ]; then 3841.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3851.73Sjmcneill imagesize="$(getsize "${image}")" 3861.73Sjmcneill imagesecs="$(getsectors ${imagesize})" 3871.73Sjmcneill ffssize="$(expr ${imagesecs} - ${ffsstart})" 3881.73Sjmcneill ${FDISK} -f -u -1 -s 169/${ffsstart}/${ffssize} -F ${image} 3891.73Sjmcneill fi 3901.73Sjmcneill 3911.73Sjmcneill echo ${bar} Adding label ${bar} 3921.73Sjmcneill make_label > ${tmp}/label 3931.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 3941.73Sjmcneill elif [ -n "${netbsdid}" ]; then 3951.73Sjmcneill echo ${bar} Adding label ${bar} 3961.73Sjmcneill make_label > ${tmp}/label 3971.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 3981.73Sjmcneill 3991.73Sjmcneill echo ${bar} Running fdisk ${bar} 4001.73Sjmcneill ${FDISK} -f -i ${image} 4011.73Sjmcneill ${FDISK} -f -a -u -0 -s 169/${init} ${image} 4021.73Sjmcneill ${INSTALLBOOT} -f -v ${image} ${release}/usr/mdec/bootxx_ffsv1 4031.63Sjmcneill fi 4041.2Sagcfi 4051.22Schristos 4061.22Schristosif $compress; then 4071.22Schristos echo ${bar} Compressing image ${bar} 4081.23Schristos rm -f "${image}.gz" 4091.80Schristos ${GZIP_CMD} -n -9 ${image} 4101.22Schristos image="${image}.gz" 4111.22Schristosfi 4121.22Schristos 4131.17Schristosecho ${bar} Image is ${image} ${bar} 414