Makefile{,.inc1}: Merge user-driven target descriptions and cleanups
[dragonfly.git] / sbin / mkinitrd / mkinitrd.sh
1 #!/bin/sh
2 #
3 # Copyright (c) 2010, 2018
4 #       The DragonFly Project.  All rights reserved.
5 #
6 # Redistribution and use in source and binary forms, with or without
7 # modification, are permitted provided that the following conditions
8 # are met:
9 #
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.
19 #
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.
32 #
33
34 . /etc/defaults/mkinitrd.conf
35
36 if [ -r /etc/mkinitrd.conf ]; then
37         . /etc/mkinitrd.conf
38         echo "Loaded configuration from /etc/mkinitrd.conf"
39 fi
40
41 VN_DEV=""
42
43 check_dirs()
44 {
45         for _dir; do
46                 [ -d "${_dir}" ] || {
47                         echo "Directory '${_dir}' does not exist"
48                         return 1
49                 }
50         done
51         return 0
52 }
53
54 # Calculate the total size of the given directory, taking care of the
55 # hard links.
56 calc_size()
57 {
58         find "$1" -ls | \
59             awk '{ print $7,$1 }' | \
60             sort -n -k 2 | \
61             uniq -f 1 | \
62             awk '{ sum+=$1 } END { print sum }'  # byte
63 }
64
65 calc_initrd_size()
66 {
67         echo "Contents directories:" >&2
68         isize=0
69         for dir in ${CONTENT_DIRS}; do
70                 csize=$(calc_size ${dir})
71                 echo "* ${dir}: ${csize} bytes" >&2
72                 isize=$((${isize} + ${csize}))
73         done
74         # Round initrd size up by MB
75         isize_mb=$(echo "${isize}" | awk '
76             function ceil(x) {
77                 y = int(x);
78                 return (x>y ? y+1 : y);
79             }
80             {
81                 mb = $1/1024/1024;
82                 print ceil(mb);
83             }')
84         # Add additional 1 MB
85         echo $((${isize_mb} + 1))
86 }
87
88 create_vn()
89 {
90         local _vndev
91         _vndev=${TMP_DIR}/vndev.$$
92
93         if [ ! -d "$BUILD_DIR" ]; then
94                 mkdir -p $BUILD_DIR
95                 echo "Created build directory $BUILD_DIR"
96         fi
97         vnconfig -c -S ${INITRD_SIZE}m -Z -T vn ${TMP_DIR}/initrd.img \
98             > ${_vndev} || {
99                 echo "Failed to configure vn device"
100                 exit 1
101         }
102
103         VN_DEV=`cat ${_vndev} | cut -f 2 -d ' '`
104         rm ${_vndev}
105
106         echo "Configured $VN_DEV"
107         newfs -i 131072 -m 0 /dev/${VN_DEV}s0
108         echo "Formatted initrd image with UFS"
109         mount -t ufs /dev/${VN_DEV}s0 $BUILD_DIR
110         echo "Mounted initrd image on ${BUILD_DIR}"
111 }
112
113 destroy_vn()
114 {
115         umount /dev/${VN_DEV}s0
116         echo "Unmounted initrd image"
117         vnconfig -u $VN_DEV
118         echo "Unconfigured $VN_DEV"
119         rmdir ${BUILD_DIR}
120 }
121
122 make_hier()
123 {
124         mkdir -p ${BUILD_DIR}/new_root
125         # symlink 'tmp' to 'var/tmp', as '/var' will be mounted with
126         # tmpfs, saving a second tmpfs been mounted on '/tmp'.
127         ln -sf var/tmp ${BUILD_DIR}/tmp
128         for _dir in ${INITRD_DIRS}; do
129             [ ! -d "${BUILD_DIR}/${_dir}" ] &&
130                 mkdir -p ${BUILD_DIR}/${_dir}
131         done
132         echo "Created directory structure"
133 }
134
135 copy_content()
136 {
137         for dir in ${CONTENT_DIRS}; do
138                 cpdup -o -u ${dir}/ ${BUILD_DIR}/ || {
139                         echo "Failed to copy ${dir} to ${BUILD_DIR}"
140                         exit 1
141                 }
142         done
143 }
144
145 print_info()
146 {
147         lt ${BUILD_DIR}
148         df -h ${BUILD_DIR}
149 }
150
151 usage()
152 {
153         echo "usage: ${0##*/} [-b bootdir] [-c contentsdir] [-t tmpdir]" \
154              "[-s size] [-S max_size]"
155         exit 2
156 }
157
158
159 #
160 # Main
161 #
162
163 while getopts :b:c:hs:S:t: opt; do
164         case ${opt} in
165         b)
166                 BOOT_DIR="${OPTARG}"
167                 ;;
168         c)
169                 CONTENT_DIRS="${OPTARG}"
170                 ;;
171         h)
172                 usage
173                 ;;
174         s)
175                 INITRD_SIZE="${OPTARG}"
176                 ;;
177         S)
178                 INITRD_SIZE_MAX="${OPTARG}"
179                 ;;
180         t)
181                 TMP_DIR="${OPTARG}"
182                 ;;
183         \?)
184                 log "Invalid option -${OPTARG}"
185                 usage
186                 ;;
187         :)
188                 log "Option -${OPTARG} requires an argument"
189                 usage
190                 ;;
191         esac
192 done
193
194 shift $((OPTIND - 1))
195 [ $# -ne 0 ] && usage
196 [ -z "${BOOT_DIR}" -o -z "${CONTENT_DIRS}"  -o -z "${TMP_DIR}" ] && usage
197 check_dirs ${BOOT_DIR} ${CONTENT_DIRS} ${TMP_DIR}
198
199 BUILD_DIR="${TMP_DIR}/initrd.$$"
200 INITRD_SIZE=${INITRD_SIZE%[mM]}  # MB
201 INITRD_SIZE_MAX=${INITRD_SIZE_MAX%[mM]}  # MB
202
203 CSIZE=$(calc_initrd_size)
204 echo "Required initrd image size: ${CSIZE} MB"
205 if [ -n "${INITRD_SIZE}" -a "${INITRD_SIZE}" != "0" ]; then
206         if [ ${CSIZE} -gt ${INITRD_SIZE} ]; then
207                 echo "Specified initrd size (${INITRD_SIZE} MB) too small"
208                 exit 1
209         fi
210 else
211         INITRD_SIZE=${CSIZE}
212 fi
213 echo "Initrd size: ${INITRD_SIZE} MB"
214
215 if [ -n "${INITRD_SIZE_MAX}" -a "${INITRD_SIZE_MAX}" != "0" ] && \
216    [ ${INITRD_SIZE} -gt ${INITRD_SIZE_MAX} ]; then
217         echo "Exceeded the specified maximum size (${INITRD_SIZE_MAX} MB)"
218         exit 1
219 fi
220
221 create_vn
222 copy_content
223 make_hier
224 print_info
225 destroy_vn
226
227 echo -n "Compressing ${TMP_DIR}/initrd.img ..."
228 gzip -9 ${TMP_DIR}/initrd.img
229 echo " OK"
230
231 DEST="${BOOT_DIR}/kernel/initrd.img.gz"
232 if [ -f "${DEST}" ]; then
233         echo -n "Backup ${DEST} ..."
234         mv ${DEST} ${DEST}.old
235         echo " OK (${DEST}.old)"
236 fi
237
238 echo -n "Copying ${TMP_DIR}/initrd.img.gz to ${DEST} ..."
239 mv ${TMP_DIR}/initrd.img.gz ${DEST}
240 echo " OK"