usr.sbin/makefs: Sync with sys/vfs/hammer2
[dragonfly.git] / initrd / mkinitrd.sh
blob0770dbaff06c48023394fe25a397c9a04b44e2de
1 #!/bin/sh
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
8 # are met:
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
15 # distribution.
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
31 # SUCH DAMAGE.
35 # Description
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 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
58 # onto the initrd.
59 RESCUE_DIR="/rescue"
61 # Specify the location that the initrd will be installed to, i.e.,
62 # <BOOT_DIR>/kernel/initrd.img.gz
63 BOOT_DIR="/boot"
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
75 # Helper functions
78 log() {
79 echo "$@" >&2
82 error() {
83 local rc=$1
84 shift
85 log "$@"
86 exit ${rc}
89 check_dirs() {
90 for _dir; do
91 [ -d "${_dir}" ] ||
92 error 1 "Directory '${_dir}' does not exist"
93 done
94 return 0
99 # Functions
102 calc_initrd_size() {
103 log "Calculating required initrd size ..."
104 isize=0
105 for _dir; do
106 csize=$(du -kst ${_dir} | awk '{ print $1 }') # KB
107 log "* ${_dir}: ${csize} KB"
108 isize=$((${isize} + ${csize}))
109 done
110 # Round initrd size up by MB
111 isize_mb=$(echo ${isize} | awk '
112 function ceil(x) {
113 y = int(x);
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))
124 make_img() {
125 makefs -m ${INITRD_SIZE}m -M ${INITRD_SIZE}m -t ffs -o density=131072 \
126 -o minfree=0 ${INITRD_FILE} ${BUILD_DIR}
129 make_hier() {
130 mkdir -p ${BUILD_DIR}/new_root ||
131 error 1 "Failed to mkdir ${BUILD_DIR}/new_root"
132 # Symlink 'sbin' to 'bin'
133 ln -sf bin ${BUILD_DIR}/sbin
134 # Symlink 'tmp' to 'var/tmp', as '/var' will be mounted with
135 # tmpfs, saving a second tmpfs been mounted on '/tmp'.
136 ln -sf var/tmp ${BUILD_DIR}/tmp
137 for _dir in ${INITRD_DIRS}; do
138 [ ! -d "${BUILD_DIR}/${_dir}" ] &&
139 mkdir -p ${BUILD_DIR}/${_dir}
140 done
141 # Symlink 'usr/bin' and 'usr/sbin' to 'bin'
142 ln -sf ../bin ${BUILD_DIR}/usr/bin
143 ln -sf ../bin ${BUILD_DIR}/usr/sbin
144 echo "Created directory structure"
147 copy_rescue() {
148 cpdup -o -u ${RESCUE_DIR}/ ${BUILD_DIR}/bin/ &&
149 echo "Copied ${RESCUE_DIR} to ${BUILD_DIR}/bin" ||
150 error 1 "Failed to copy ${RESCUE_DIR} to ${BUILD_DIR}/bin"
153 copy_content() {
154 for _dir in ${CONTENT_DIRS}; do
155 cpdup -o -u ${_dir}/ ${BUILD_DIR}/ &&
156 echo "Copied ${_dir} to ${BUILD_DIR}" ||
157 error 1 "Failed to copy ${dir} to ${BUILD_DIR}"
158 done
161 print_info() {
162 lt ${BUILD_DIR}
165 # Check the validity of the created initrd image before moving over.
166 # This prevents creating an empty and broken initrd image by running
167 # this tool but without ${CONTENT_DIRS} prepared.
169 # NOTE: Need more improvements.
171 check_initrd()
173 [ -x "${BUILD_DIR}/sbin/oinit" ] &&
174 [ -x "${BUILD_DIR}/bin/sh" ] &&
175 [ -x "${BUILD_DIR}/etc/rc" ] || {
176 error 1 "Invalid initrd image!"
180 usage() {
181 error 2 \
182 "usage: ${0##*/} [-b boot_dir] [-r rescue_dir]" \
183 "[-s size] [-S max_size] -c <content_dirs>"
188 # Main
191 while getopts :b:c:hr:s:S: opt; do
192 case ${opt} in
194 BOOT_DIR="${OPTARG}"
197 CONTENT_DIRS="${OPTARG}"
200 usage
203 RESCUE_DIR="${OPTARG}"
206 INITRD_SIZE="${OPTARG}"
209 INITRD_SIZE_MAX="${OPTARG}"
212 log "Invalid option -${OPTARG}"
213 usage
216 log "Option -${OPTARG} requires an argument"
217 usage
219 esac
220 done
222 shift $((OPTIND - 1))
223 [ $# -ne 0 ] && usage
224 [ -z "${BOOT_DIR}" -o -z "${RESCUE_DIR}" -o -z "${CONTENT_DIRS}" ] && usage
225 check_dirs ${BOOT_DIR} ${RESCUE_DIR} ${CONTENT_DIRS}
227 INITRD_SIZE=${INITRD_SIZE%[mM]} # MB
228 INITRD_SIZE_MAX=${INITRD_SIZE_MAX%[mM]} # MB
230 BUILD_DIR=$(mktemp -d -t initrd) || error $? "Cannot create build directory"
231 echo "Initrd build directory: ${BUILD_DIR}"
232 INITRD_FILE="${BUILD_DIR}.img"
233 INITRD_DEST="${BOOT_DIR}/kernel/initrd.img.gz"
235 CSIZE=$(calc_initrd_size ${RESCUE_DIR} ${CONTENT_DIRS})
236 echo "Required initrd image size: ${CSIZE} MB"
237 if [ -n "${INITRD_SIZE}" -a "${INITRD_SIZE}" != "0" ]; then
238 if [ ${CSIZE} -gt ${INITRD_SIZE} ]; then
239 error 1 "Given initrd size (${INITRD_SIZE} MB) too small"
241 else
242 INITRD_SIZE=${CSIZE}
244 echo "Initrd size: ${INITRD_SIZE} MB"
246 if [ -n "${INITRD_SIZE_MAX}" -a "${INITRD_SIZE_MAX}" != "0" ] && \
247 [ ${INITRD_SIZE} -gt ${INITRD_SIZE_MAX} ]; then
248 error 1 "Exceeded the maximum size (${INITRD_SIZE_MAX} MB)"
251 make_hier
252 copy_rescue
253 copy_content
254 print_info
255 make_img
256 rm -rf ${BUILD_DIR}
258 echo -n "Compressing ${INITRD_FILE} ..."
259 gzip -9 ${INITRD_FILE}
260 echo " OK"
262 if [ -f "${INITRD_DEST}" ]; then
263 echo -n "Backing up ${INITRD_DEST} ..."
264 mv ${INITRD_DEST} ${INITRD_DEST}.old
265 echo " OK (${INITRD_DEST}.old)"
268 echo -n "Installing ${INITRD_FILE}.gz to ${INITRD_DEST} ..."
269 install -o root -g wheel -m 444 ${INITRD_FILE}.gz ${INITRD_DEST}
270 echo " OK"
271 rm -f ${INITRD_FILE}.gz