1722fa22cSjmcneill#!/bin/sh 2*af4cbeb0Smaya# $NetBSD: mkimage,v 1.78 2021/09/25 08:54:30 maya Exp $ 343b25107Schristos# 4df5f4559Schristos# Copyright (c) 2013, 2014 The NetBSD Foundation, Inc. 5267b86c3Sagc# All rights reserved. 6267b86c3Sagc# 7bbaf0399Schristos# This code is derived from software contributed to The NetBSD Foundation 8bbaf0399Schristos# by Christos Zoulas. 9bbaf0399Schristos# 10267b86c3Sagc# Redistribution and use in source and binary forms, with or without 11267b86c3Sagc# modification, are permitted provided that the following conditions 12267b86c3Sagc# are met: 13267b86c3Sagc# 1. Redistributions of source code must retain the above copyright 14267b86c3Sagc# notice, this list of conditions and the following disclaimer. 15267b86c3Sagc# 2. Redistributions in binary form must reproduce the above copyright 16267b86c3Sagc# notice, this list of conditions and the following disclaimer in the 17267b86c3Sagc# documentation and/or other materials provided with the distribution. 18bbaf0399Schristos# 3. Neither the name of The NetBSD Foundation nor the names of its 19bbaf0399Schristos# contributors may be used to endorse or promote products derived 20bbaf0399Schristos# from this software without specific prior written permission. 21267b86c3Sagc# 22bbaf0399Schristos# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 23bbaf0399Schristos# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 24bbaf0399Schristos# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 25bbaf0399Schristos# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 26bbaf0399Schristos# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 27bbaf0399Schristos# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 28bbaf0399Schristos# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 29bbaf0399Schristos# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 30bbaf0399Schristos# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 31bbaf0399Schristos# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32bbaf0399Schristos# POSSIBILITY OF SUCH DAMAGE. 33267b86c3Sagc# 34267b86c3Sagc 354935107aShubertf# 364935107aShubertf# Makes a bootable image for the host architecture given. 374935107aShubertf# The host specific functions are pulled in from a /bin/sh script in the 384935107aShubertf# "conf" directory, and is expected to provide the following shell 394935107aShubertf# functions, which are called in the following order: 404935107aShubertf# 414935107aShubertf# - make_fstab: Creates the host's /etc/fstab with / on ${rootdev}. 424935107aShubertf# If -m is given, a number of directories are put on a tmpfs RAM disk 434935107aShubertf# - customize: After unpacking the sets, this gets the system to 444935107aShubertf# a working state, e. g. by setting up /etc/rc.conf and /dev 454935107aShubertf# - populate: Add common goods like kernel and bootloader 464935107aShubertf# - make_label: Prints disklabel to stdout 474935107aShubertf# 484935107aShubertf 49e140236eSjmcneillset -e 50e140236eSjmcneill 51bbaf0399SchristosDIR="$(cd "$(dirname "$0")" && pwd)" 52bbaf0399SchristosPROG="$(basename "$0")" 53267b86c3Sagc 5419b29e2cSjmcneillMAKE=${TOOL_MAKE:-make} 558ccc0b92SchristosDISKLABEL=${TOOL_DISKLABEL:-disklabel} 56bdbfe825SchristosFDISK=${TOOL_FDISK:-fdisk} 575b5842aeSjmcneillGPT=${TOOL_GPT:-gpt} 588ccc0b92SchristosMAKEFS=${TOOL_MAKEFS:-makefs} 59aa7339cdSjmcneillMTREE=${TOOL_MTREE:-mtree} 60df5f4559SchristosINSTALLBOOT=${TOOL_INSTALLBOOT:-installboot} 61141eb037SchristosMKUBOOTIMAGE=${TOOL_MKUBOOTIMAGE:-mkubootimage} 62ec8d7d73SastGZIP_CMD=${TOOL_GZIP:-gzip} # ${GZIP} is special to gzip(1) 638ccc0b92Schristos 64bbaf0399Schristossrc="/usr/src" 65*af4cbeb0Smayasets="base comp etc games gpufw man misc modules rescue tests text" 66bbaf0399Schristosxsets="xbase xcomp xetc xfont xserver" 67bbaf0399Schristosminfree="10%" 68bbaf0399Schristosbar="===" 69267b86c3Sagc 7088c7f048Skretmp="$(mktemp -d "${TMPDIR:-/tmp}/$PROG.XXXXXX")" 71bbaf0399Schristosmnt="${tmp}/mnt" 725b65fdecSchristosmkdir -p "${mnt}/etc" "${mnt}/dev" 73bf62f393Schristos 74bbaf0399Schristostrap "cleanup" 0 1 2 3 15 75bbaf0399Schristos 76bbaf0399Schristoscleanup() { 77bbaf0399Schristos case "$tmp" in 788c8fbbc3Skre "${TMPDIR:-/tmp}/$PROG."*) rm -fr "$tmp";; 79bbaf0399Schristos esac 80267b86c3Sagc} 81267b86c3Sagc 82d8532e20Skrefail() { 83d8532e20Skre IFS=' ' 84d8532e20Skre echo >&2 "${PROG}: $*" 85d8532e20Skre exit 1 86d8532e20Skre} 87d8532e20Skre 88bbaf0399Schristosgetsize() { 89bbaf0399Schristos set -- $(ls -l $1) 90bbaf0399Schristos echo $5 91267b86c3Sagc} 92267b86c3Sagc 938b34a10bSjmcneillgetsectors() { 948b34a10bSjmcneill case "$1" in 958b34a10bSjmcneill *g) 968b34a10bSjmcneill m=1073741824 978b34a10bSjmcneill v=${1%g} 988b34a10bSjmcneill ;; 998b34a10bSjmcneill *m) 1008b34a10bSjmcneill m=1048576 1018b34a10bSjmcneill v=${1%m} 1028b34a10bSjmcneill ;; 1038b34a10bSjmcneill *k) 1048b34a10bSjmcneill m=1024 1058b34a10bSjmcneill v=${1%k} 1068b34a10bSjmcneill ;; 1078b34a10bSjmcneill *[0-9b]) 1088b34a10bSjmcneill m=1 1098b34a10bSjmcneill v=${1%b} 1108b34a10bSjmcneill ;; 1118b34a10bSjmcneill esac 1128b34a10bSjmcneill echo $((m * v / 512)) 1138b34a10bSjmcneill} 1148b34a10bSjmcneill 115632e755aSchristosusage() { 116632e755aSchristos cat << EOF 1>&2 11790370017SmartinUsage: $PROG -h <host-arch> [-bdmx] [-B <byte-order>] [-K <kerneldir>] [-S <srcdir>] [-D <destdir>] [-c <custom-files-dir>] [-s <Mb size>] [<image>] 1187fc5abe8Schristos 1197fc5abe8Schristos-b Boot only, no sets loaded 1204b3e41fdSchristos-r root device kind (sd, wd, ld) 1217fc5abe8Schristos-d Add the debug sets 122c2c5d53cSchristos-m Optimize the OS installation to mimimize disk writes for SSDs 1231b551427Shubertf-x Load the X sets too, not just the base ones 124632e755aSchristosEOF 125632e755aSchristos exit 1 126632e755aSchristos} 127632e755aSchristos 12809e10ad8Sjmcneill# First pass for options to get the host and src directories 12990370017SmartinOPTS="B:D:K:S:bc:dh:mr:s:x" 130b6e2226dSchristoswhile getopts "$OPTS" f 131b6e2226dSchristosdo 132b6e2226dSchristos case $f in 133b6e2226dSchristos h) h="$OPTARG";; 13409e10ad8Sjmcneill S) src="$OPTARG";; 135b6e2226dSchristos *) ;; 136267b86c3Sagc esac 137267b86c3Sagcdone 138267b86c3Sagc 139b6e2226dSchristosif [ -z "$h" ] 140b6e2226dSchristosthen 141b6e2226dSchristos usage 142b6e2226dSchristosfi 143b6e2226dSchristos 1442e39be44Schristosif [ ! -f "${DIR}/conf/${h}.conf" ] 145b6e2226dSchristosthen 1462e39be44Schristos echo $PROG: ${DIR}/conf/${h}.conf is not present 1>&2 147b6e2226dSchristos exit 1 148b6e2226dSchristosfi 149b6e2226dSchristos 15052b91797Sjmcneillresize=false 1515b5842aeSjmcneillgpt=false 152cbc8e374Sjmcneillgpt_hybrid=false 15352b91797Sjmcneill 1542e39be44Schristos. "${DIR}/conf/${h}.conf" 155df5f4559Schristosrelease="/usr/obj/${MACHINE}/release" 156b6e2226dSchristos 157bbaf0399Schristosselected_sets="$sets" 158088203b8Sskrlldsets_p=false 159088203b8Sskrllxsets_p=false 1607fc5abe8Schristosminwrites=false 1614b3e41fdSchristosrootdev=ld 16290370017Smartinendian= 163bbaf0399Schristos 164b6e2226dSchristosOPTIND=1 165b6e2226dSchristoswhile getopts "$OPTS" f 166b6e2226dSchristosdo 167b6e2226dSchristos case $f in 16890370017Smartin B) endian="-B $OPTARG";; 169f1ca5eb5Schristos D) release="$OPTARG";; 170f1ca5eb5Schristos K) kernel="$OPTARG";; 17109e10ad8Sjmcneill S) ;; 172d2ca0586Schristos b) bootonly=true;; 173088203b8Sskrll d) dsets_p=true 1747fc5abe8Schristos selected_sets="$selected_sets debug" 175088203b8Sskrll if $xsets_p; then 1767fc5abe8Schristos selected_sets="$selected_sets xdebug" 1777fc5abe8Schristos fi 1787fc5abe8Schristos ;; 179b6e2226dSchristos c) custom="$OPTARG";; 180b6e2226dSchristos h) ;; 1817fc5abe8Schristos m) minwrites=true;; 1824b3e41fdSchristos r) rootdev="$OPTARG";; 183b6e2226dSchristos s) size="$OPTARG";; 184088203b8Sskrll x) xsets_p=true 1857fc5abe8Schristos selected_sets="$selected_sets $xsets" 186088203b8Sskrll if $dsets_p; then 1877fc5abe8Schristos selected_sets="$selected_sets xdebug" 1887fc5abe8Schristos fi 1897fc5abe8Schristos ;; 190a76783b5Schristos *) usage;; 191b6e2226dSchristos esac 192b6e2226dSchristosdone 193b6e2226dSchristos 194cd3b1ea3Sjmcneillshift $(( $OPTIND - 1 )) 195b6e2226dSchristosif [ -n "$1" ]; then 196267b86c3Sagc # take the next argument as being the image name 197267b86c3Sagc image="$1" 198267b86c3Sagc shift 199267b86c3Sagcfi 200267b86c3Sagc 201827b25efSchristoscase "$image" in 202827b25efSchristos*.gz) compress=true; image="${image%.gz}";; 203827b25efSchristos*) compress=false;; 204827b25efSchristosesac 205827b25efSchristos 206df5f4559Schristosif [ -z "${bootonly}" ]; then 207bbaf0399Schristos echo ${bar} configuring sets ${bar} 208ef34841fSskrll (cat "${release}/etc/mtree/NetBSD.dist" 209bbaf0399Schristos for i in $selected_sets; do 210bbaf0399Schristos s="${release}/etc/mtree/set.$i" 21153e719b6Schristos if [ -f "$s" ]; then 21253e719b6Schristos cat "$s" 21353e719b6Schristos fi 214bbaf0399Schristos done) > "$tmp/selected_sets" 215de7cb3aeSgarbledfi 216267b86c3Sagc 217b6e2226dSchristosmake_fstab 218b6e2226dSchristoscustomize 219bbaf0399Schristospopulate 220b6e2226dSchristos 221879faa2aSjmcneillif [ ! "${MKDTB}" = "no" ]; then 222879faa2aSjmcneill # 223879faa2aSjmcneill # Part of the dtb set resides on the FAT partition (/boot/dtb/*), and 224879faa2aSjmcneill # the rest on FFS. Split it up here. 225879faa2aSjmcneill # 226879faa2aSjmcneill echo ${bar} Installing devicetree blobs ${bar} 227879faa2aSjmcneill mkdir -p "${mnt}/boot" 228879faa2aSjmcneill cp -r "${release}/boot/dtb" "${mnt}/boot/dtb" 229879faa2aSjmcneill 230879faa2aSjmcneill mkdir -p "${mnt}/etc/mtree" 231879faa2aSjmcneill cp "${release}/etc/mtree/set.dtb" "${mnt}/etc/mtree/set.dtb" 232879faa2aSjmcneill echo "./etc/mtree/set.dtb type=file uname=root gname=wheel mode=0444" >> "$tmp/selected_sets" 233879faa2aSjmcneill 234879faa2aSjmcneill mkdir -p "${mnt}/var/db/obsolete" 235879faa2aSjmcneill cp "${release}/var/db/obsolete/dtb" "${mnt}/var/db/obsolete/dtb" 236879faa2aSjmcneill echo "./var/db/obsolete/dtb type=file uname=root gname=wheel mode=0644" >>"$tmp/selected_sets" 237879faa2aSjmcneillfi 238879faa2aSjmcneill 239df5f4559Schristosif [ -n "${msdosid}" ]; then 240bbaf0399Schristos echo ${bar} Populating msdos filesystem ${bar} 241879faa2aSjmcneill 2427e411275Smartin case $(( ${msdosid} )) in 2437e411275Smartin 1) fat_opt=",fat_type=12";; 2447e411275Smartin 4|6|14) fat_opt=",fat_type=16";; 2457e411275Smartin 11|12) fat_opt=",fat_type=32";; 2467e411275Smartin *) fat_opt=;; 2477e411275Smartin esac 2487e411275Smartin ${MAKEFS} -N ${release}/etc -t msdos \ 2497e411275Smartin -o "volume_label=NETBSD${fat_opt}" \ 2508b34a10bSjmcneill -O $((${init} / 2))m -s $((${boot} / 2))m \ 251d2ca0586Schristos ${image} ${mnt}/boot 252230874b2Sagcfi 253267b86c3Sagc 254df5f4559Schristosif [ -z "${bootonly}" ]; then 255bbaf0399Schristos echo ${bar} Populating ffs filesystem ${bar} 25690370017Smartin ${MAKEFS} -rx ${endian} -N ${release}/etc -t ffs \ 2575b65fdecSchristos -O ${ffsoffset} \ 2580cd0818eSjmcneill -o d=4096,f=8192,b=65536 -b $((${extra}))m \ 259bbaf0399Schristos -F "$tmp/selected_sets" ${image} "${release}" "${mnt}" 260de7cb3aeSgarbledfi 261bbaf0399Schristos 262bf62f393Schristosif [ "${size}" = 0 ]; then 263a2448456Srin size="$(getsize "${image}")" 264b5648ea5Sriastradh # Round up to a multiple of 4m and add 1m of slop. 265b5648ea5Sriastradh alignunit=$((4*1024*1024)) 266a2448456Srin alignsize=$((alignunit*((size + alignunit - 1)/alignunit))) 267b5648ea5Sriastradh alignsize=$((alignsize + 1024*1024)) 268a2448456Srin if [ "${size}" -lt "${alignsize}" ]; then 269a2448456Srin dd bs=1 count="$((alignsize - size))" if=/dev/zero \ 270a2448456Srin >> "${image}" 2> /dev/null 271a2448456Srin size="${alignsize}" 272bbaf0399Schristos fi 273b5648ea5Sriastradhfi 274bbaf0399Schristos 2755b5842aeSjmcneillif $gpt; then 276cbc8e374Sjmcneill if $gpt_hybrid; then 277cbc8e374Sjmcneill gpt_flags="-H" 278cbc8e374Sjmcneill fi 2795b5842aeSjmcneill initsecs=$((${init} * 1024)) 2805b5842aeSjmcneill bootsecs=$((${boot} * 1024)) 2815b5842aeSjmcneill ffsstart="$(getsectors ${ffsoffset})" 2825b5842aeSjmcneill 2835b5842aeSjmcneill echo ${bar} Clearing existing partitions ${bar} 284cbc8e374Sjmcneill ${GPT} ${gpt_flags} ${image} destroy || true 2855b5842aeSjmcneill 2865b5842aeSjmcneill echo ${bar} Creating partitions ${bar} 287cbc8e374Sjmcneill ${GPT} ${gpt_flags} ${image} create ${gpt_create_flags} 288f98b2f22Sjmcneill ${GPT} ${gpt_flags} ${image} add -b ${initsecs} -s ${bootsecs} -l ${gpt_label_boot:-EFI} -t ${gpt_boot_type:-efi} 289cbc8e374Sjmcneill ${GPT} ${gpt_flags} ${image} set -a required -i 1 290cbc8e374Sjmcneill ${GPT} ${gpt_flags} ${image} add -a 4m -b ${ffsstart} -l ${gpt_label_ffs:-netbsd-root} -t ffs 291cbc8e374Sjmcneill ${GPT} ${gpt_flags} ${image} show 292cbc8e374Sjmcneill if $gpt_hybrid; then 293cbc8e374Sjmcneill echo ${bar} Creating hybrid MBR ${bar} 294cbc8e374Sjmcneill ${FDISK} -f -g -u -0 -a -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 295cbc8e374Sjmcneill ${FDISK} -f -g -u -3 -s 238/1/$((${initsecs} - 1)) -F ${image} 296cbc8e374Sjmcneill ${FDISK} -F ${image} 297cbc8e374Sjmcneill fi 2985b5842aeSjmcneillelse 299df5f4559Schristos if [ -n "${msdosid}" ]; then 300bbaf0399Schristos echo ${bar} Running fdisk ${bar} 301e422fefcSjmcneill initsecs=$((${init} * 1024)) 302e422fefcSjmcneill bootsecs=$((${boot} * 1024)) 3038b34a10bSjmcneill ${FDISK} -f -i ${image} 3042ba6908cSskrll ${FDISK} -f -a -u -0 -s ${msdosid}/${initsecs}/${bootsecs} -F ${image} 3058b34a10bSjmcneill if [ -z "${bootonly}" ]; then 3068b34a10bSjmcneill ffsstart="$(getsectors ${ffsoffset})" 3078b34a10bSjmcneill imagesize="$(getsize "${image}")" 3088b34a10bSjmcneill imagesecs="$(getsectors ${imagesize})" 3098b34a10bSjmcneill ffssize="$(expr ${imagesecs} - ${ffsstart})" 3108b34a10bSjmcneill ${FDISK} -f -u -1 -s 169/${ffsstart}/${ffssize} -F ${image} 3118b34a10bSjmcneill fi 312e9957547Sjmcneill 313e9957547Sjmcneill echo ${bar} Adding label ${bar} 314e9957547Sjmcneill make_label > ${tmp}/label 315e9957547Sjmcneill ${DISKLABEL} -R -F ${image} ${tmp}/label 316df5f4559Schristos elif [ -n "${netbsdid}" ]; then 317e9957547Sjmcneill echo ${bar} Adding label ${bar} 318e9957547Sjmcneill make_label > ${tmp}/label 319e9957547Sjmcneill ${DISKLABEL} -R -F ${image} ${tmp}/label 320e9957547Sjmcneill 321df5f4559Schristos echo ${bar} Running fdisk ${bar} 322df5f4559Schristos ${FDISK} -f -i ${image} 32359b548e0Schristos ${FDISK} -f -a -u -0 -s 169/${init} ${image} 324df5f4559Schristos ${INSTALLBOOT} -f -v ${image} ${release}/usr/mdec/bootxx_ffsv1 325bbaf0399Schristos fi 3265b5842aeSjmcneillfi 327827b25efSchristos 328827b25efSchristosif $compress; then 329827b25efSchristos echo ${bar} Compressing image ${bar} 330bf62f393Schristos rm -f "${image}.gz" 331ec8d7d73Sast ${GZIP_CMD} -9 ${image} 332827b25efSchristos image="${image}.gz" 333827b25efSchristosfi 334827b25efSchristos 335bbaf0399Schristosecho ${bar} Image is ${image} ${bar} 336