mkimage revision 1.85
11.31Sjmcneill#!/bin/sh 21.85Schristos# $NetBSD: mkimage,v 1.85 2024/12/27 19:02:19 christos 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.17Schristossrc="/usr/src" 651.84Sskrllsets="base comp etc games gpufw man manhtml misc modules rescue tests text" 661.83Sskrllxsets="xbase xcomp xetc xfont xserver" 671.17Schristosminfree="10%" 681.17Schristosbar="===" 691.17Schristos 701.67Skretmp="$(mktemp -d "${TMPDIR:-/tmp}/$PROG.XXXXXX")" 711.17Schristosmnt="${tmp}/mnt" 721.46Schristosmkdir -p "${mnt}/etc" "${mnt}/dev" 731.23Schristos 741.17Schristostrap "cleanup" 0 1 2 3 15 751.17Schristos 761.17Schristoscleanup() { 771.17Schristos case "$tmp" in 781.68Skre "${TMPDIR:-/tmp}/$PROG."*) rm -fr "$tmp";; 791.17Schristos esac 801.17Schristos} 811.1Sagc 821.69Skrefail() { 831.69Skre IFS=' ' 841.69Skre echo >&2 "${PROG}: $*" 851.69Skre exit 1 861.69Skre} 871.69Skre 881.17Schristosgetsize() { 891.17Schristos set -- $(ls -l $1) 901.17Schristos echo $5 911.1Sagc} 921.1Sagc 931.63Sjmcneillgetsectors() { 941.63Sjmcneill case "$1" in 951.63Sjmcneill *g) 961.63Sjmcneill m=1073741824 971.63Sjmcneill v=${1%g} 981.63Sjmcneill ;; 991.63Sjmcneill *m) 1001.63Sjmcneill m=1048576 1011.63Sjmcneill v=${1%m} 1021.63Sjmcneill ;; 1031.63Sjmcneill *k) 1041.63Sjmcneill m=1024 1051.63Sjmcneill v=${1%k} 1061.63Sjmcneill ;; 1071.63Sjmcneill *[0-9b]) 1081.63Sjmcneill m=1 1091.63Sjmcneill v=${1%b} 1101.63Sjmcneill ;; 1111.63Sjmcneill esac 1121.63Sjmcneill echo $((m * v / 512)) 1131.63Sjmcneill} 1141.63Sjmcneill 1151.85Schristosminwrites_fstab_entries() { 1161.85Schristos $minwrites || return 0 1171.85Schristos cat << EOF 1181.85Schristostmpfs /var/log tmpfs rw,union,-s32M 1191.85Schristostmpfs /var/run tmpfs rw,union,-s1M 1201.85Schristostmpfs /var/mail tmpfs rw,union,-s10M 1211.85Schristostmpfs /var/spool/postfix tmpfs rw,union,-s20M 1221.85Schristostmpfs /var/db/postfix tmpfs rw,union,-s1M 1231.85Schristostmpfs /var/chroot tmpfs rw,union,-s10M 1241.85SchristosEOF 1251.85Schristos} 1261.85Schristos 1271.85Schristosmake_fstab_gpt() { 1281.85Schristos local boot=$1 1291.85Schristos local rootopts= 1301.85Schristos if $minwrites; then 1311.85Schristos rootopts=,log,nodevmtime 1321.85Schristos fi 1331.85Schristos 1341.85Schristos cat > ${mnt}/etc/fstab << EOF 1351.85Schristos# NetBSD /etc/fstab 1361.85Schristos# See /usr/share/examples/fstab/ for more examples. 1371.85SchristosNAME=${gpt_label_ffs:-netbsd-root} / ffs rw,noatime${rootopts} 1 1 1381.85SchristosNAME=${gpt_label_boot:-$boot} /boot msdos rw 1 1 1391.85Schristosptyfs /dev/pts ptyfs rw 1401.85Schristosprocfs /proc procfs rw 1411.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1421.85SchristosEOF 1431.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1441.85Schristos} 1451.85Schristos 1461.85Schristos# From Richard Neswold's: 1471.85Schristos# http://rich-tbp.blogspot.com/2013/03/netbsd-on-rpi-minimizing-disk-writes.html 1481.85Schristos# Also for the postfix stuff below 1491.85Schristosmake_fstab_normal() { 1501.85Schristos local rootopts= 1511.85Schristos if $minwrites; then 1521.85Schristos rootopts=,nodevmtime 1531.85Schristos fi 1541.85Schristos cat > ${mnt}/etc/fstab << EOF 1551.85Schristos# NetBSD /etc/fstab 1561.85Schristos# See /usr/share/examples/fstab/ for more examples. 1571.85SchristosROOT.a / ffs rw,log,noatime,$rootopts 1 1 1581.85SchristosROOT.e /boot msdos rw 1 1 1591.85Schristosptyfs /dev/pts ptyfs rw 1601.85Schristosprocfs /proc procfs rw 1611.85Schristostmpfs /tmp tmpfs rw,-s32M 1621.85Schristostmpfs /var/shm tmpfs rw,-m1777,-sram%25 1631.85SchristosEOF 1641.85Schristos minwrites_fstab_entries >> ${mnt}/etc/fstab 1651.85Schristos} 1661.85Schristos 1671.85Schristosmake_fstab_default() { 1681.85Schristos if $gpt; then 1691.85Schristos make_fstab_gpt "$@" 1701.85Schristos else 1711.85Schristos make_fstab_normal 1721.85Schristos fi 1731.85Schristos echo "./etc/fstab type=file uname=root gname=wheel mode=0644" \ 1741.85Schristos >> "$tmp/selected_sets" 1751.85Schristos 1761.85Schristos # Missing mount points from fstab 1771.85Schristos echo "./proc type=dir uname=root gname=wheel mode=0755" \ 1781.85Schristos >> "$tmp/selected_sets" 1791.85Schristos} 1801.85Schristos 1811.12Schristosusage() { 1821.12Schristos cat << EOF 1>&2 1831.60SmartinUsage: $PROG -h <host-arch> [-bdmx] [-B <byte-order>] [-K <kerneldir>] [-S <srcdir>] [-D <destdir>] [-c <custom-files-dir>] [-s <Mb size>] [<image>] 1841.39Schristos 1851.39Schristos-b Boot only, no sets loaded 1861.47Schristos-r root device kind (sd, wd, ld) 1871.39Schristos-d Add the debug sets 1881.43Schristos-m Optimize the OS installation to mimimize disk writes for SSDs 1891.57Shubertf-x Load the X sets too, not just the base ones 1901.12SchristosEOF 1911.13Schristos exit 1 1921.12Schristos} 1931.12Schristos 1941.32Sjmcneill# First pass for options to get the host and src directories 1951.60SmartinOPTS="B:D:K:S:bc:dh:mr:s:x" 1961.4Schristoswhile getopts "$OPTS" f 1971.4Schristosdo 1981.4Schristos case $f in 1991.4Schristos h) h="$OPTARG";; 2001.32Sjmcneill S) src="$OPTARG";; 2011.4Schristos *) ;; 2021.4Schristos esac 2031.4Schristosdone 2041.4Schristos 2051.4Schristosif [ -z "$h" ] 2061.4Schristosthen 2071.4Schristos usage 2081.4Schristosfi 2091.4Schristos 2101.5Schristosif [ ! -f "${DIR}/conf/${h}.conf" ] 2111.4Schristosthen 2121.5Schristos echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2 2131.4Schristos exit 1 2141.4Schristosfi 2151.4Schristos 2161.56Sjmcneillresize=false 2171.73Sjmcneillgpt=false 2181.74Sjmcneillgpt_hybrid=false 2191.56Sjmcneill 2201.5Schristos. "${DIR}/conf/${h}.conf" 2211.45Schristosrelease="/usr/obj/${MACHINE}/release" 2221.4Schristos 2231.17Schristosselected_sets="$sets" 2241.50Sskrlldsets_p=false 2251.50Sskrllxsets_p=false 2261.39Schristosminwrites=false 2271.47Schristosrootdev=ld 2281.60Smartinendian= 2291.17Schristos 2301.4SchristosOPTIND=1 2311.4Schristoswhile getopts "$OPTS" f 2321.4Schristosdo 2331.4Schristos case $f in 2341.60Smartin B) endian="-B $OPTARG";; 2351.18Schristos D) release="$OPTARG";; 2361.18Schristos K) kernel="$OPTARG";; 2371.32Sjmcneill S) ;; 2381.41Schristos b) bootonly=true;; 2391.50Sskrll d) dsets_p=true 2401.39Schristos selected_sets="$selected_sets debug" 2411.50Sskrll if $xsets_p; then 2421.39Schristos selected_sets="$selected_sets xdebug" 2431.39Schristos fi 2441.39Schristos ;; 2451.4Schristos c) custom="$OPTARG";; 2461.4Schristos h) ;; 2471.39Schristos m) minwrites=true;; 2481.47Schristos r) rootdev="$OPTARG";; 2491.4Schristos s) size="$OPTARG";; 2501.50Sskrll x) xsets_p=true 2511.39Schristos selected_sets="$selected_sets $xsets" 2521.50Sskrll if $dsets_p; then 2531.39Schristos selected_sets="$selected_sets xdebug" 2541.39Schristos fi 2551.39Schristos ;; 2561.6Schristos *) usage;; 2571.1Sagc esac 2581.1Sagcdone 2591.81Smlelstvif [ -n "${MKREPRO_TIMESTAMP}" ]; then 2601.80Schristos timestamp_opt="-T ${MKREPRO_TIMESTAMP}" 2611.80Schristos volume_opt=",volume_id=$((${MKREPRO_TIMESTAMP} & 0xffff))" 2621.80Schristosfi 2631.1Sagc 2641.20Sjmcneillshift $(( $OPTIND - 1 )) 2651.4Schristosif [ -n "$1" ]; then 2661.1Sagc # take the next argument as being the image name 2671.1Sagc image="$1" 2681.1Sagc shift 2691.1Sagcfi 2701.1Sagc 2711.22Schristoscase "$image" in 2721.22Schristos*.gz) compress=true; image="${image%.gz}";; 2731.22Schristos*) compress=false;; 2741.22Schristosesac 2751.22Schristos 2761.45Schristosif [ -z "${bootonly}" ]; then 2771.36Sgarbled echo ${bar} configuring sets ${bar} 2781.51Sskrll (cat "${release}/etc/mtree/NetBSD.dist" 2791.36Sgarbled for i in $selected_sets; do 2801.36Sgarbled s="${release}/etc/mtree/set.$i" 2811.36Sgarbled if [ -f "$s" ]; then 2821.36Sgarbled cat "$s" 2831.36Sgarbled fi 2841.36Sgarbled done) > "$tmp/selected_sets" 2851.36Sgarbledfi 2861.1Sagc 2871.4Schristosmake_fstab 2881.17Schristoscustomize 2891.17Schristospopulate 2901.1Sagc 2911.72Sjmcneillif [ ! "${MKDTB}" = "no" ]; then 2921.72Sjmcneill # 2931.72Sjmcneill # Part of the dtb set resides on the FAT partition (/boot/dtb/*), and 2941.72Sjmcneill # the rest on FFS. Split it up here. 2951.72Sjmcneill # 2961.72Sjmcneill echo ${bar} Installing devicetree blobs ${bar} 2971.72Sjmcneill mkdir -p "${mnt}/boot" 2981.72Sjmcneill cp -r "${release}/boot/dtb" "${mnt}/boot/dtb" 2991.72Sjmcneill 3001.72Sjmcneill mkdir -p "${mnt}/etc/mtree" 3011.72Sjmcneill cp "${release}/etc/mtree/set.dtb" "${mnt}/etc/mtree/set.dtb" 3021.72Sjmcneill echo "./etc/mtree/set.dtb type=file uname=root gname=wheel mode=0444" >> "$tmp/selected_sets" 3031.72Sjmcneill 3041.72Sjmcneill mkdir -p "${mnt}/var/db/obsolete" 3051.72Sjmcneill cp "${release}/var/db/obsolete/dtb" "${mnt}/var/db/obsolete/dtb" 3061.72Sjmcneill echo "./var/db/obsolete/dtb type=file uname=root gname=wheel mode=0644" >>"$tmp/selected_sets" 3071.72Sjmcneillfi 3081.72Sjmcneill 3091.45Schristosif [ -n "${msdosid}" ]; then 3101.17Schristos echo ${bar} Populating msdos filesystem ${bar} 3111.72Sjmcneill 3121.71Smartin case $(( ${msdosid} )) in 3131.71Smartin 1) fat_opt=",fat_type=12";; 3141.71Smartin 4|6|14) fat_opt=",fat_type=16";; 3151.71Smartin 11|12) fat_opt=",fat_type=32";; 3161.71Smartin *) fat_opt=;; 3171.71Smartin esac 3181.71Smartin ${MAKEFS} -N ${release}/etc -t msdos \ 3191.80Schristos -o "volume_label=NETBSD${fat_opt}${volume_opt}" ${timestamp_opt} \ 3201.63Sjmcneill -O $((${init} / 2))m -s $((${boot} / 2))m \ 3211.41Schristos ${image} ${mnt}/boot 3221.1Sagcfi 3231.1Sagc 3241.45Schristosif [ -z "${bootonly}" ]; then 3251.36Sgarbled echo ${bar} Populating ffs filesystem ${bar} 3261.60Smartin ${MAKEFS} -rx ${endian} -N ${release}/etc -t ffs \ 3271.80Schristos -O ${ffsoffset} ${timestamp_opt} \ 3281.61Sjmcneill -o d=4096,f=8192,b=65536 -b $((${extra}))m \ 3291.36Sgarbled -F "$tmp/selected_sets" ${image} "${release}" "${mnt}" 3301.36Sgarbledfi 3311.1Sagc 3321.23Schristosif [ "${size}" = 0 ]; then 3331.77Srin size="$(getsize "${image}")" 3341.76Sriastrad # Round up to a multiple of 4m and add 1m of slop. 3351.76Sriastrad alignunit=$((4*1024*1024)) 3361.77Srin alignsize=$((alignunit*((size + alignunit - 1)/alignunit))) 3371.76Sriastrad alignsize=$((alignsize + 1024*1024)) 3381.77Srin if [ "${size}" -lt "${alignsize}" ]; then 3391.77Srin dd bs=1 count="$((alignsize - size))" if=/dev/zero \ 3401.77Srin >> "${image}" 2> /dev/null 3411.77Srin size="${alignsize}" 3421.76Sriastrad fi 3431.17Schristosfi 3441.1Sagc 3451.73Sjmcneillif $gpt; then 3461.74Sjmcneill if $gpt_hybrid; then 3471.74Sjmcneill gpt_flags="-H" 3481.74Sjmcneill fi 3491.80Schristos gpt_flags="${gpt_flags} ${timestamp_opt}" 3501.30Sjmcneill initsecs=$((${init} * 1024)) 3511.30Sjmcneill bootsecs=$((${boot} * 1024)) 3521.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3531.73Sjmcneill 3541.73Sjmcneill echo ${bar} Clearing existing partitions ${bar} 3551.74Sjmcneill ${GPT} ${gpt_flags} ${image} destroy || true 3561.73Sjmcneill 3571.73Sjmcneill echo ${bar} Creating partitions ${bar} 3581.74Sjmcneill ${GPT} ${gpt_flags} ${image} create ${gpt_create_flags} 3591.75Sjmcneill ${GPT} ${gpt_flags} ${image} add -b ${initsecs} -s ${bootsecs} -l ${gpt_label_boot:-EFI} -t ${gpt_boot_type:-efi} 3601.74Sjmcneill ${GPT} ${gpt_flags} ${image} set -a required -i 1 3611.74Sjmcneill ${GPT} ${gpt_flags} ${image} add -a 4m -b ${ffsstart} -l ${gpt_label_ffs:-netbsd-root} -t ffs 3621.74Sjmcneill ${GPT} ${gpt_flags} ${image} show 3631.74Sjmcneill if $gpt_hybrid; then 3641.74Sjmcneill echo ${bar} Creating hybrid MBR ${bar} 3651.74Sjmcneill ${FDISK} -f -g -u -0 -a -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3661.74Sjmcneill ${FDISK} -f -g -u -3 -s 238/1/$((${initsecs} - 1)) -F ${image} 3671.74Sjmcneill ${FDISK} -F ${image} 3681.74Sjmcneill fi 3691.73Sjmcneillelse 3701.73Sjmcneill if [ -n "${msdosid}" ]; then 3711.73Sjmcneill echo ${bar} Running fdisk ${bar} 3721.73Sjmcneill initsecs=$((${init} * 1024)) 3731.73Sjmcneill bootsecs=$((${boot} * 1024)) 3741.73Sjmcneill ${FDISK} -f -i ${image} 3751.73Sjmcneill ${FDISK} -f -a -u -0 -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3761.73Sjmcneill if [ -z "${bootonly}" ]; then 3771.73Sjmcneill ffsstart="$(getsectors ${ffsoffset})" 3781.73Sjmcneill imagesize="$(getsize "${image}")" 3791.73Sjmcneill imagesecs="$(getsectors ${imagesize})" 3801.73Sjmcneill ffssize="$(expr ${imagesecs} - ${ffsstart})" 3811.73Sjmcneill ${FDISK} -f -u -1 -s 169/${ffsstart}/${ffssize} -F ${image} 3821.73Sjmcneill fi 3831.73Sjmcneill 3841.73Sjmcneill echo ${bar} Adding label ${bar} 3851.73Sjmcneill make_label > ${tmp}/label 3861.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 3871.73Sjmcneill elif [ -n "${netbsdid}" ]; then 3881.73Sjmcneill echo ${bar} Adding label ${bar} 3891.73Sjmcneill make_label > ${tmp}/label 3901.79Sjmcneill ${DISKLABEL} -m -R -F ${image} ${tmp}/label 3911.73Sjmcneill 3921.73Sjmcneill echo ${bar} Running fdisk ${bar} 3931.73Sjmcneill ${FDISK} -f -i ${image} 3941.73Sjmcneill ${FDISK} -f -a -u -0 -s 169/${init} ${image} 3951.73Sjmcneill ${INSTALLBOOT} -f -v ${image} ${release}/usr/mdec/bootxx_ffsv1 3961.63Sjmcneill fi 3971.2Sagcfi 3981.22Schristos 3991.22Schristosif $compress; then 4001.22Schristos echo ${bar} Compressing image ${bar} 4011.23Schristos rm -f "${image}.gz" 4021.80Schristos ${GZIP_CMD} -n -9 ${image} 4031.22Schristos image="${image}.gz" 4041.22Schristosfi 4051.22Schristos 4061.17Schristosecho ${bar} Image is ${image} ${bar} 407