1e79a303fSAaron LI#!/bin/sh 2e79a303fSAaron LI# 3e79a303fSAaron LI# Copyright (c) 2010, 2018 4e79a303fSAaron LI# The DragonFly Project. All rights reserved. 5e79a303fSAaron LI# 6e79a303fSAaron LI# Redistribution and use in source and binary forms, with or without 7e79a303fSAaron LI# modification, are permitted provided that the following conditions 8e79a303fSAaron LI# are met: 9e79a303fSAaron LI# 10e79a303fSAaron LI# 1. Redistributions of source code must retain the above copyright 11e79a303fSAaron LI# notice, this list of conditions and the following disclaimer. 12e79a303fSAaron LI# 2. Redistributions in binary form must reproduce the above copyright 13e79a303fSAaron LI# notice, this list of conditions and the following disclaimer in 14e79a303fSAaron LI# the documentation and/or other materials provided with the 15e79a303fSAaron LI# distribution. 16e79a303fSAaron LI# 3. Neither the name of The DragonFly Project nor the names of its 17e79a303fSAaron LI# contributors may be used to endorse or promote products derived 18e79a303fSAaron LI# from this software without specific, prior written permission. 19e79a303fSAaron LI# 20e79a303fSAaron LI# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21e79a303fSAaron LI# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22e79a303fSAaron LI# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23e79a303fSAaron LI# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24e79a303fSAaron LI# COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25e79a303fSAaron LI# INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 26e79a303fSAaron LI# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 27e79a303fSAaron LI# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28e79a303fSAaron LI# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29e79a303fSAaron LI# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 30e79a303fSAaron LI# OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31e79a303fSAaron LI# SUCH DAMAGE. 32e79a303fSAaron LI# 33e79a303fSAaron LI 34e79a303fSAaron LI# 35e79a303fSAaron LI# Description 36e79a303fSAaron LI# 37e79a303fSAaron LI# This tool packs the (statically linked) rescue tools (at /rescue by 38e79a303fSAaron LI# default) and contents specified by "-c <content_dirs>", such as the 39*4b97670aSSascha Wildner# necessary etc files, into an UFS-formatted image. This image is 40e79a303fSAaron LI# installed at /boot/kernel/initrd.img.gz and used as the initial ramdisk 41e79a303fSAaron LI# to help mount the real root filesystem when it is encrypted or on LVM. 42e79a303fSAaron LI# 43e79a303fSAaron LI 44e79a303fSAaron LI 45e79a303fSAaron LI# 46e79a303fSAaron LI# Default configurations 47e79a303fSAaron LI# 48e79a303fSAaron LI 49cf7cecf5SSascha Wildner# Directory hierarchy on the initrd 50e79a303fSAaron LI# 51e79a303fSAaron LI# * 'new_root' will always be created 528506a14bSSascha Wildner# * 'sbin', 'usr.bin', and 'usr.sbin' will be symlinked to 'bin' 53e79a303fSAaron LI# * 'tmp' will be symlinked to 'var/tmp' 54e79a303fSAaron LI# 558506a14bSSascha WildnerINITRD_DIRS="bin dev etc mnt usr var" 56e79a303fSAaron LI 57e79a303fSAaron LI# Directory of the statically linked rescue tools which will be copied 58e79a303fSAaron LI# onto the initrd. 59e79a303fSAaron LIRESCUE_DIR="/rescue" 60e79a303fSAaron LI 61e79a303fSAaron LI# Specify the location that the initrd will be installed to, i.e., 62e79a303fSAaron LI# <BOOT_DIR>/kernel/initrd.img.gz 63e79a303fSAaron LIBOOT_DIR="/boot" 64e79a303fSAaron LI 65e79a303fSAaron LI# Maximum size (number of MB) allowed for the initrd image 66e79a303fSAaron LIINITRD_SIZE_MAX="15" # MB 67e79a303fSAaron LI 68bc897c50SAaron LI# When run from the buildworld/installworld environment do not require that 699b724c0dSMatthew Dillon# things like uniq, kldload, mount, newfs, etc be in the cross-tools. 709b724c0dSMatthew Dillon# These must run natively for the current system version. 719b724c0dSMatthew Dillon# 729b724c0dSMatthew DillonPATH=${PATH}:/sbin:/usr/sbin:/bin:/usr/bin 73e79a303fSAaron LI 74e79a303fSAaron LI# 75e79a303fSAaron LI# Helper functions 76e79a303fSAaron LI# 77e79a303fSAaron LI 78e79a303fSAaron LIlog() { 79e79a303fSAaron LI echo "$@" >&2 80e79a303fSAaron LI} 81e79a303fSAaron LI 82e79a303fSAaron LIerror() { 83e79a303fSAaron LI local rc=$1 84e79a303fSAaron LI shift 85e79a303fSAaron LI log "$@" 86e79a303fSAaron LI exit ${rc} 87e79a303fSAaron LI} 88e79a303fSAaron LI 89e79a303fSAaron LIcheck_dirs() { 90e79a303fSAaron LI for _dir; do 91e79a303fSAaron LI [ -d "${_dir}" ] || 92e79a303fSAaron LI error 1 "Directory '${_dir}' does not exist" 93e79a303fSAaron LI done 94e79a303fSAaron LI return 0 95e79a303fSAaron LI} 96e79a303fSAaron LI 97e79a303fSAaron LI 98e79a303fSAaron LI# 99e79a303fSAaron LI# Functions 100e79a303fSAaron LI# 101e79a303fSAaron LI 102e79a303fSAaron LIcalc_initrd_size() { 103e79a303fSAaron LI log "Calculating required initrd size ..." 104e79a303fSAaron LI isize=0 105e79a303fSAaron LI for _dir; do 106567f41d0SAaron LI csize=$(du -kst ${_dir} | awk '{ print $1 }') # KB 107567f41d0SAaron LI log "* ${_dir}: ${csize} KB" 108e79a303fSAaron LI isize=$((${isize} + ${csize})) 109e79a303fSAaron LI done 110e79a303fSAaron LI # Round initrd size up by MB 111e79a303fSAaron LI isize_mb=$(echo ${isize} | awk ' 112e79a303fSAaron LI function ceil(x) { 113e79a303fSAaron LI y = int(x); 114e79a303fSAaron LI return (x>y ? y+1 : y); 115e79a303fSAaron LI } 116e79a303fSAaron LI { 117567f41d0SAaron LI print ceil($1 / 1024); 118e79a303fSAaron LI }') 119bc897c50SAaron LI # Reserve another 1 MB for advanced user to add custom files to the 120bc897c50SAaron LI # initrd without creating it from scratch. 121e79a303fSAaron LI echo $((${isize_mb} + 1)) 122e79a303fSAaron LI} 123e79a303fSAaron LI 124*4b97670aSSascha Wildnermake_img() { 125*4b97670aSSascha Wildner makefs -m ${INITRD_SIZE}m -M ${INITRD_SIZE}m -t ffs -o density=131072 \ 126*4b97670aSSascha Wildner -o minfree=0 ${INITRD_FILE} ${BUILD_DIR} 127e79a303fSAaron LI} 128e79a303fSAaron LI 129e79a303fSAaron LImake_hier() { 130f170ef59SAaron LI mkdir -p ${BUILD_DIR}/new_root || 131f170ef59SAaron LI error 1 "Failed to mkdir ${BUILD_DIR}/new_root" 132e79a303fSAaron LI # Symlink 'sbin' to 'bin' 133e79a303fSAaron LI ln -sf bin ${BUILD_DIR}/sbin 134e79a303fSAaron LI # Symlink 'tmp' to 'var/tmp', as '/var' will be mounted with 135e79a303fSAaron LI # tmpfs, saving a second tmpfs been mounted on '/tmp'. 136e79a303fSAaron LI ln -sf var/tmp ${BUILD_DIR}/tmp 137e79a303fSAaron LI for _dir in ${INITRD_DIRS}; do 138e79a303fSAaron LI [ ! -d "${BUILD_DIR}/${_dir}" ] && 139e79a303fSAaron LI mkdir -p ${BUILD_DIR}/${_dir} 140e79a303fSAaron LI done 1418506a14bSSascha Wildner # Symlink 'usr/bin' and 'usr/sbin' to 'bin' 1428506a14bSSascha Wildner ln -sf ../bin ${BUILD_DIR}/usr/bin 1438506a14bSSascha Wildner ln -sf ../bin ${BUILD_DIR}/usr/sbin 144e79a303fSAaron LI echo "Created directory structure" 145e79a303fSAaron LI} 146e79a303fSAaron LI 147e79a303fSAaron LIcopy_rescue() { 148e79a303fSAaron LI cpdup -o -u ${RESCUE_DIR}/ ${BUILD_DIR}/bin/ && 149e79a303fSAaron LI echo "Copied ${RESCUE_DIR} to ${BUILD_DIR}/bin" || 150e79a303fSAaron LI error 1 "Failed to copy ${RESCUE_DIR} to ${BUILD_DIR}/bin" 151e79a303fSAaron LI} 152e79a303fSAaron LI 153e79a303fSAaron LIcopy_content() { 154e79a303fSAaron LI for _dir in ${CONTENT_DIRS}; do 155e79a303fSAaron LI cpdup -o -u ${_dir}/ ${BUILD_DIR}/ && 156e79a303fSAaron LI echo "Copied ${_dir} to ${BUILD_DIR}" || 157e79a303fSAaron LI error 1 "Failed to copy ${dir} to ${BUILD_DIR}" 158e79a303fSAaron LI done 159e79a303fSAaron LI} 160e79a303fSAaron LI 161e79a303fSAaron LIprint_info() { 162e79a303fSAaron LI lt ${BUILD_DIR} 163e79a303fSAaron LI} 164e79a303fSAaron LI 165e79a303fSAaron LI# Check the validity of the created initrd image before moving over. 166e79a303fSAaron LI# This prevents creating an empty and broken initrd image by running 167e79a303fSAaron LI# this tool but without ${CONTENT_DIRS} prepared. 168e79a303fSAaron LI# 169e79a303fSAaron LI# NOTE: Need more improvements. 170e79a303fSAaron LI# 171e79a303fSAaron LIcheck_initrd() 172e79a303fSAaron LI{ 173f170ef59SAaron LI [ -x "${BUILD_DIR}/sbin/oinit" ] && 174f170ef59SAaron LI [ -x "${BUILD_DIR}/bin/sh" ] && 175f170ef59SAaron LI [ -x "${BUILD_DIR}/etc/rc" ] || { 17690442087SSascha Wildner error 1 "Invalid initrd image!" 177e79a303fSAaron LI } 178e79a303fSAaron LI} 179e79a303fSAaron LI 180e79a303fSAaron LIusage() { 181e79a303fSAaron LI error 2 \ 182e79a303fSAaron LI "usage: ${0##*/} [-b boot_dir] [-r rescue_dir]" \ 183e79a303fSAaron LI "[-s size] [-S max_size] -c <content_dirs>" 184e79a303fSAaron LI} 185e79a303fSAaron LI 186e79a303fSAaron LI 187e79a303fSAaron LI# 188e79a303fSAaron LI# Main 189e79a303fSAaron LI# 190e79a303fSAaron LI 191e79a303fSAaron LIwhile getopts :b:c:hr:s:S: opt; do 192e79a303fSAaron LI case ${opt} in 193e79a303fSAaron LI b) 194e79a303fSAaron LI BOOT_DIR="${OPTARG}" 195e79a303fSAaron LI ;; 196e79a303fSAaron LI c) 197e79a303fSAaron LI CONTENT_DIRS="${OPTARG}" 198e79a303fSAaron LI ;; 199e79a303fSAaron LI h) 200e79a303fSAaron LI usage 201e79a303fSAaron LI ;; 202e79a303fSAaron LI r) 203e79a303fSAaron LI RESCUE_DIR="${OPTARG}" 204e79a303fSAaron LI ;; 205e79a303fSAaron LI s) 206e79a303fSAaron LI INITRD_SIZE="${OPTARG}" 207e79a303fSAaron LI ;; 208e79a303fSAaron LI S) 209e79a303fSAaron LI INITRD_SIZE_MAX="${OPTARG}" 210e79a303fSAaron LI ;; 211e79a303fSAaron LI \?) 212e79a303fSAaron LI log "Invalid option -${OPTARG}" 213e79a303fSAaron LI usage 214e79a303fSAaron LI ;; 215e79a303fSAaron LI :) 216e79a303fSAaron LI log "Option -${OPTARG} requires an argument" 217e79a303fSAaron LI usage 218e79a303fSAaron LI ;; 219e79a303fSAaron LI esac 220e79a303fSAaron LIdone 221e79a303fSAaron LI 222e79a303fSAaron LIshift $((OPTIND - 1)) 223e79a303fSAaron LI[ $# -ne 0 ] && usage 224e79a303fSAaron LI[ -z "${BOOT_DIR}" -o -z "${RESCUE_DIR}" -o -z "${CONTENT_DIRS}" ] && usage 225e79a303fSAaron LIcheck_dirs ${BOOT_DIR} ${RESCUE_DIR} ${CONTENT_DIRS} 226e79a303fSAaron LI 227e79a303fSAaron LIINITRD_SIZE=${INITRD_SIZE%[mM]} # MB 228e79a303fSAaron LIINITRD_SIZE_MAX=${INITRD_SIZE_MAX%[mM]} # MB 229e79a303fSAaron LI 230e79a303fSAaron LIBUILD_DIR=$(mktemp -d -t initrd) || error $? "Cannot create build directory" 231e79a303fSAaron LIecho "Initrd build directory: ${BUILD_DIR}" 232e79a303fSAaron LIINITRD_FILE="${BUILD_DIR}.img" 233e79a303fSAaron LIINITRD_DEST="${BOOT_DIR}/kernel/initrd.img.gz" 234e79a303fSAaron LI 235e79a303fSAaron LICSIZE=$(calc_initrd_size ${RESCUE_DIR} ${CONTENT_DIRS}) 236e79a303fSAaron LIecho "Required initrd image size: ${CSIZE} MB" 237e79a303fSAaron LIif [ -n "${INITRD_SIZE}" -a "${INITRD_SIZE}" != "0" ]; then 238e79a303fSAaron LI if [ ${CSIZE} -gt ${INITRD_SIZE} ]; then 239e79a303fSAaron LI error 1 "Given initrd size (${INITRD_SIZE} MB) too small" 240e79a303fSAaron LI fi 241e79a303fSAaron LIelse 242e79a303fSAaron LI INITRD_SIZE=${CSIZE} 243e79a303fSAaron LIfi 244e79a303fSAaron LIecho "Initrd size: ${INITRD_SIZE} MB" 245e79a303fSAaron LI 246e79a303fSAaron LIif [ -n "${INITRD_SIZE_MAX}" -a "${INITRD_SIZE_MAX}" != "0" ] && \ 247e79a303fSAaron LI [ ${INITRD_SIZE} -gt ${INITRD_SIZE_MAX} ]; then 248e79a303fSAaron LI error 1 "Exceeded the maximum size (${INITRD_SIZE_MAX} MB)" 249e79a303fSAaron LIfi 250e79a303fSAaron LI 251e79a303fSAaron LImake_hier 252e79a303fSAaron LIcopy_rescue 253e79a303fSAaron LIcopy_content 254e79a303fSAaron LIprint_info 255*4b97670aSSascha Wildnermake_img 256e79a303fSAaron LIrm -rf ${BUILD_DIR} 257e79a303fSAaron LI 258e79a303fSAaron LIecho -n "Compressing ${INITRD_FILE} ..." 259e79a303fSAaron LIgzip -9 ${INITRD_FILE} 260e79a303fSAaron LIecho " OK" 261e79a303fSAaron LI 262e79a303fSAaron LIif [ -f "${INITRD_DEST}" ]; then 263e79a303fSAaron LI echo -n "Backing up ${INITRD_DEST} ..." 264e79a303fSAaron LI mv ${INITRD_DEST} ${INITRD_DEST}.old 265e79a303fSAaron LI echo " OK (${INITRD_DEST}.old)" 266e79a303fSAaron LIfi 267e79a303fSAaron LI 268bc897c50SAaron LIecho -n "Installing ${INITRD_FILE}.gz to ${INITRD_DEST} ..." 269f170ef59SAaron LIinstall -o root -g wheel -m 444 ${INITRD_FILE}.gz ${INITRD_DEST} 270e79a303fSAaron LIecho " OK" 27157179abeSAaron LIrm -f ${INITRD_FILE}.gz 272