xref: /dflybsd-src/initrd/mkinitrd.sh (revision 4b97670a1d6d8486ae3e94e8ece1082a9e435f2b)
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