3 # Copyright (c) 2010, 2018
4 # The DragonFly Project. All rights reserved.
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
10 # 1. Redistributions of source code must retain the above copyright
11 # notice, this list of conditions and the following disclaimer.
12 # 2. Redistributions in binary form must reproduce the above copyright
13 # notice, this list of conditions and the following disclaimer in
14 # the documentation and/or other materials provided with the
16 # 3. Neither the name of The DragonFly Project nor the names of its
17 # contributors may be used to endorse or promote products derived
18 # from this software without specific, prior written permission.
20 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 # COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 # INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 # OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 # This tool packs the (statically linked) rescue tools (at /rescue by
38 # default) and contents specified by "-c <content_dirs>", such as the
39 # necessary etc files, into an UFS-formatted VN image. This image is
40 # installed at /boot/kernel/initrd.img.gz and used as the initial ramdisk
41 # to help mount the real root filesystem when it is encrypted or on LVM.
46 # Default configurations
49 # Directory hierarchy on the initrd
51 # * 'new_root' will always be created
52 # * 'sbin', 'usr.bin', and 'usr.sbin' will be symlinked to 'bin'
53 # * 'tmp' will be symlinked to 'var/tmp'
55 INITRD_DIRS
="bin dev etc mnt usr var"
57 # Directory of the statically linked rescue tools which will be copied
61 # Specify the location that the initrd will be installed to, i.e.,
62 # <BOOT_DIR>/kernel/initrd.img.gz
65 # Maximum size (number of MB) allowed for the initrd image
66 INITRD_SIZE_MAX
="15" # MB
68 # When run from the buildworld/installworld environment do not require that
69 # things like uniq, kldload, mount, newfs, etc be in the cross-tools.
70 # These must run natively for the current system version.
72 PATH
=${PATH}:/sbin
:/usr
/sbin
:/bin
:/usr
/bin
92 error
1 "Directory '${_dir}' does not exist"
103 log
"Calculating required initrd size ..."
106 csize
=$
(du
-kst ${_dir} |
awk '{ print $1 }') # KB
107 log
"* ${_dir}: ${csize} KB"
108 isize
=$
((${isize} + ${csize}))
110 # Round initrd size up by MB
111 isize_mb
=$
(echo ${isize} |
awk '
114 return (x>y ? y+1 : y);
117 print ceil($1 / 1024);
119 # Reserve another 1 MB for advanced user to add custom files to the
120 # initrd without creating it from scratch.
121 echo $
((${isize_mb} + 1))
125 kldstat
-qm vn || kldload
-n vn ||
126 error
1 "Failed to load vn kernel module"
128 VN_DEV
=$
(vnconfig
-c -S ${INITRD_SIZE}m
-Z -T vn
${INITRD_FILE}) &&
129 echo "Configured ${VN_DEV}" ||
130 error
1 "Failed to configure VN device"
132 newfs
-i 131072 -m 0 /dev
/${VN_DEV}s0
&&
133 echo "Formatted initrd image with UFS" ||
134 error
1 "Failed to format the initrd image"
135 mount_ufs
/dev
/${VN_DEV}s0
${BUILD_DIR} &&
136 echo "Mounted initrd image on ${BUILD_DIR}" ||
137 error
1 "Failed to mount initrd image on ${BUILD_DIR}"
141 umount
/dev
/${VN_DEV}s0
&&
142 echo "Unmounted initrd image" ||
143 error
1 "Failed to umount initrd image"
144 vnconfig
-u ${VN_DEV} &&
145 echo "Unconfigured ${VN_DEV}" ||
146 error
1 "Failed to unconfigure ${VN_DEV}"
150 mkdir
-p ${BUILD_DIR}/new_root ||
151 error
1 "Failed to mkdir ${BUILD_DIR}/new_root"
152 # Symlink 'sbin' to 'bin'
153 ln -sf bin
${BUILD_DIR}/sbin
154 # Symlink 'tmp' to 'var/tmp', as '/var' will be mounted with
155 # tmpfs, saving a second tmpfs been mounted on '/tmp'.
156 ln -sf var
/tmp
${BUILD_DIR}/tmp
157 for _dir
in ${INITRD_DIRS}; do
158 [ ! -d "${BUILD_DIR}/${_dir}" ] &&
159 mkdir
-p ${BUILD_DIR}/${_dir}
161 # Symlink 'usr/bin' and 'usr/sbin' to 'bin'
162 ln -sf ..
/bin
${BUILD_DIR}/usr
/bin
163 ln -sf ..
/bin
${BUILD_DIR}/usr
/sbin
164 echo "Created directory structure"
168 cpdup
-o -u ${RESCUE_DIR}/ ${BUILD_DIR}/bin
/ &&
169 echo "Copied ${RESCUE_DIR} to ${BUILD_DIR}/bin" ||
170 error
1 "Failed to copy ${RESCUE_DIR} to ${BUILD_DIR}/bin"
174 for _dir
in ${CONTENT_DIRS}; do
175 cpdup
-o -u ${_dir}/ ${BUILD_DIR}/ &&
176 echo "Copied ${_dir} to ${BUILD_DIR}" ||
177 error
1 "Failed to copy ${dir} to ${BUILD_DIR}"
186 # Check the validity of the created initrd image before moving over.
187 # This prevents creating an empty and broken initrd image by running
188 # this tool but without ${CONTENT_DIRS} prepared.
190 # NOTE: Need more improvements.
194 [ -x "${BUILD_DIR}/sbin/oinit" ] &&
195 [ -x "${BUILD_DIR}/bin/sh" ] &&
196 [ -x "${BUILD_DIR}/etc/rc" ] ||
{
198 error
1 "Ivalid initrd image!"
204 "usage: ${0##*/} [-b boot_dir] [-r rescue_dir]" \
205 "[-s size] [-S max_size] -c <content_dirs>"
213 while getopts :b
:c
:hr
:s
:S
: opt
; do
219 CONTENT_DIRS
="${OPTARG}"
225 RESCUE_DIR
="${OPTARG}"
228 INITRD_SIZE
="${OPTARG}"
231 INITRD_SIZE_MAX
="${OPTARG}"
234 log
"Invalid option -${OPTARG}"
238 log
"Option -${OPTARG} requires an argument"
244 shift $
((OPTIND
- 1))
245 [ $# -ne 0 ] && usage
246 [ -z "${BOOT_DIR}" -o -z "${RESCUE_DIR}" -o -z "${CONTENT_DIRS}" ] && usage
247 check_dirs
${BOOT_DIR} ${RESCUE_DIR} ${CONTENT_DIRS}
250 INITRD_SIZE
=${INITRD_SIZE%[mM]} # MB
251 INITRD_SIZE_MAX
=${INITRD_SIZE_MAX%[mM]} # MB
253 BUILD_DIR
=$
(mktemp
-d -t initrd
) || error $?
"Cannot create build directory"
254 echo "Initrd build directory: ${BUILD_DIR}"
255 INITRD_FILE
="${BUILD_DIR}.img"
256 INITRD_DEST
="${BOOT_DIR}/kernel/initrd.img.gz"
258 CSIZE
=$
(calc_initrd_size
${RESCUE_DIR} ${CONTENT_DIRS})
259 echo "Required initrd image size: ${CSIZE} MB"
260 if [ -n "${INITRD_SIZE}" -a "${INITRD_SIZE}" != "0" ]; then
261 if [ ${CSIZE} -gt ${INITRD_SIZE} ]; then
262 error
1 "Given initrd size (${INITRD_SIZE} MB) too small"
267 echo "Initrd size: ${INITRD_SIZE} MB"
269 if [ -n "${INITRD_SIZE_MAX}" -a "${INITRD_SIZE_MAX}" != "0" ] && \
270 [ ${INITRD_SIZE} -gt ${INITRD_SIZE_MAX} ]; then
271 error
1 "Exceeded the maximum size (${INITRD_SIZE_MAX} MB)"
282 echo -n "Compressing ${INITRD_FILE} ..."
283 gzip -9 ${INITRD_FILE}
286 if [ -f "${INITRD_DEST}" ]; then
287 echo -n "Backing up ${INITRD_DEST} ..."
288 mv ${INITRD_DEST} ${INITRD_DEST}.old
289 echo " OK (${INITRD_DEST}.old)"
292 echo -n "Installing ${INITRD_FILE}.gz to ${INITRD_DEST} ..."
293 install -o root
-g wheel
-m 444 ${INITRD_FILE}.gz
${INITRD_DEST}
295 rm -f ${INITRD_FILE}.gz