]>
Commit | Line | Data |
---|---|---|
3b403b32 | 1 | #!/bin/bash |
cc02093d HH |
2 | # |
3 | # Copyright 2005-2010 Harald Hoyer <harald@redhat.com> | |
4 | # Copyright 2005-2010 Red Hat, Inc. All rights reserved. | |
5 | # | |
6 | # This program is free software; you can redistribute it and/or modify | |
7 | # it under the terms of the GNU General Public License as published by | |
8 | # the Free Software Foundation; either version 2 of the License, or | |
9 | # (at your option) any later version. | |
10 | # | |
11 | # This program is distributed in the hope that it will be useful, | |
12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | # GNU General Public License for more details. | |
15 | # | |
16 | # You should have received a copy of the GNU General Public License | |
17 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | # | |
074d12c1 | 19 | |
9a52c3fd | 20 | usage() { |
dde2db3d | 21 | { |
7d9bb76a HH |
22 | echo "Usage: ${0##*/} [options] [<initramfs file> [<filename> [<filename> [...] ]]]" |
23 | echo "Usage: ${0##*/} [options] -k <kernel version>" | |
dde2db3d | 24 | echo |
7d9bb76a HH |
25 | echo "-h, --help print a help message and exit." |
26 | echo "-s, --size sort the contents of the initramfs by size." | |
05d2a145 | 27 | echo "-m, --mod list modules." |
7d9bb76a | 28 | echo "-f, --file <filename> print the contents of <filename>." |
97bbba69 | 29 | echo "--unpack unpack the initramfs, instead of displaying the contents." |
143420bc KS |
30 | echo " If optional filenames are given, will only unpack specified files," |
31 | echo " else the whole image will be unpacked. Won't unpack anything from early cpio part." | |
97bbba69 | 32 | echo "--unpackearly unpack the early microcode part of the initramfs." |
143420bc | 33 | echo " Same as --unpack, but only unpack files from early cpio part." |
97bbba69 | 34 | echo "-v, --verbose unpack verbosely." |
7d9bb76a | 35 | echo "-k, --kver <kernel version> inspect the initramfs of <kernel version>." |
dde2db3d HH |
36 | echo |
37 | } >&2 | |
f7bccf37 HH |
38 | } |
39 | ||
b208aad5 HH |
40 | [[ $dracutbasedir ]] || dracutbasedir=/usr/lib/dracut |
41 | ||
3ea5d2e2 | 42 | sorted=0 |
05d2a145 | 43 | modules=0 |
97bbba69 | 44 | unset verbose |
7d9bb76a HH |
45 | declare -A filenames |
46 | ||
47 | unset POSIXLY_CORRECT | |
48 | TEMP=$(getopt \ | |
97bbba69 | 49 | -o "vshmf:k:" \ |
7d9bb76a HH |
50 | --long kver: \ |
51 | --long file: \ | |
05d2a145 | 52 | --long mod \ |
7d9bb76a HH |
53 | --long help \ |
54 | --long size \ | |
97bbba69 HH |
55 | --long unpack \ |
56 | --long unpackearly \ | |
57 | --long verbose \ | |
7d9bb76a HH |
58 | -- "$@") |
59 | ||
0ce54e80 | 60 | # shellcheck disable=SC2181 |
9a52c3fd | 61 | if (($? != 0)); then |
7d9bb76a HH |
62 | usage |
63 | exit 1 | |
64 | fi | |
65 | ||
66 | eval set -- "$TEMP" | |
67 | ||
68 | while (($# > 0)); do | |
69 | case $1 in | |
9a52c3fd HH |
70 | -k | --kver) |
71 | KERNEL_VERSION="$2" | |
72 | shift | |
73 | ;; | |
74 | -f | --file) | |
75 | filenames[${2#/}]=1 | |
76 | shift | |
77 | ;; | |
78 | -s | --size) sorted=1 ;; | |
79 | -h | --help) | |
80 | usage | |
81 | exit 0 | |
82 | ;; | |
83 | -m | --mod) modules=1 ;; | |
84 | -v | --verbose) verbose="--verbose" ;; | |
85 | --unpack) unpack=1 ;; | |
86 | --unpackearly) unpackearly=1 ;; | |
87 | --) | |
88 | shift | |
89 | break | |
90 | ;; | |
91 | *) | |
92 | usage | |
93 | exit 1 | |
94 | ;; | |
3ea5d2e2 | 95 | esac |
7d9bb76a | 96 | shift |
3ea5d2e2 | 97 | done |
3ea5d2e2 | 98 | |
7d9bb76a | 99 | [[ $KERNEL_VERSION ]] || KERNEL_VERSION="$(uname -r)" |
dde2db3d | 100 | |
7d9bb76a | 101 | if [[ $1 ]]; then |
dde2db3d | 102 | image="$1" |
75d758e8 | 103 | if ! [[ -f $image ]]; then |
dde2db3d HH |
104 | { |
105 | echo "$image does not exist" | |
106 | echo | |
107 | } >&2 | |
108 | usage | |
109 | exit 1 | |
110 | fi | |
dde2db3d | 111 | else |
49ea6c42 AAF |
112 | if [[ -d /efi/Default ]] || [[ -d /boot/Default ]] || [[ -d /boot/efi/Default ]]; then |
113 | MACHINE_ID="Default" | |
971b302d | 114 | elif [[ -s /etc/machine-id ]]; then |
49ea6c42 | 115 | read -r MACHINE_ID < /etc/machine-id |
971b302d | 116 | [[ $MACHINE_ID == "uninitialized" ]] && MACHINE_ID="Default" |
49ea6c42 AAF |
117 | else |
118 | MACHINE_ID="Default" | |
119 | fi | |
727e68d0 | 120 | |
093bc9b5 JG |
121 | if [[ -d /efi/loader/entries || -L /efi/loader/entries ]] \ |
122 | && [[ $MACHINE_ID ]] \ | |
9a52c3fd | 123 | && [[ -d /efi/${MACHINE_ID} || -L /efi/${MACHINE_ID} ]]; then |
093bc9b5 JG |
124 | image="/efi/${MACHINE_ID}/${KERNEL_VERSION}/initrd" |
125 | elif [[ -d /boot/loader/entries || -L /boot/loader/entries ]] \ | |
7d9bb76a | 126 | && [[ $MACHINE_ID ]] \ |
9a52c3fd | 127 | && [[ -d /boot/${MACHINE_ID} || -L /boot/${MACHINE_ID} ]]; then |
727e68d0 | 128 | image="/boot/${MACHINE_ID}/${KERNEL_VERSION}/initrd" |
49ea6c42 AAF |
129 | elif [[ -d /boot/efi/loader/entries || -L /boot/efi/loader/entries ]] \ |
130 | && [[ $MACHINE_ID ]] \ | |
131 | && [[ -d /boot/efi/${MACHINE_ID} || -L /boot/efi/${MACHINE_ID} ]]; then | |
132 | image="/boot/efi/${MACHINE_ID}/${KERNEL_VERSION}/initrd" | |
133 | elif [[ -f /lib/modules/${KERNEL_VERSION}/initrd ]]; then | |
134 | image="/lib/modules/${KERNEL_VERSION}/initrd" | |
e877be69 K |
135 | elif [[ -f /lib/modules/${KERNEL_VERSION}/initramfs.img ]]; then |
136 | image="/lib/modules/${KERNEL_VERSION}/initramfs.img" | |
49ea6c42 | 137 | elif [[ -f /boot/initramfs-${KERNEL_VERSION}.img ]]; then |
d928724c | 138 | image="/boot/initramfs-${KERNEL_VERSION}.img" |
d6343146 AAF |
139 | elif [[ $MACHINE_ID ]] \ |
140 | && mountpoint -q /efi; then | |
49ea6c42 | 141 | image="/efi/${MACHINE_ID}/${KERNEL_VERSION}/initrd" |
d6343146 AAF |
142 | elif [[ $MACHINE_ID ]] \ |
143 | && mountpoint -q /boot/efi; then | |
49ea6c42 AAF |
144 | image="/boot/efi/${MACHINE_ID}/${KERNEL_VERSION}/initrd" |
145 | else | |
146 | image="" | |
727e68d0 | 147 | fi |
dde2db3d HH |
148 | fi |
149 | ||
7d9bb76a HH |
150 | shift |
151 | while (($# > 0)); do | |
9a52c3fd | 152 | filenames[${1#/}]=1 |
7d9bb76a HH |
153 | shift |
154 | done | |
727e68d0 | 155 | |
75d758e8 | 156 | if ! [[ -f $image ]]; then |
dde2db3d HH |
157 | { |
158 | echo "No <initramfs file> specified and the default image '$image' cannot be accessed!" | |
159 | echo | |
160 | } >&2 | |
161 | usage | |
162 | exit 1 | |
163 | fi | |
074d12c1 | 164 | |
cbf32008 | 165 | TMPDIR="$(mktemp -d -t lsinitrd.XXXXXX)" |
0ce54e80 | 166 | # shellcheck disable=SC2064 |
cbf32008 MR |
167 | trap "rm -rf '$TMPDIR'" EXIT |
168 | ||
d3be9275 AŻ |
169 | dracutlibdirs() { |
170 | for d in lib64/dracut lib/dracut usr/lib64/dracut usr/lib/dracut; do | |
171 | echo "$d/$1" | |
172 | done | |
173 | } | |
174 | ||
9a52c3fd HH |
175 | extract_files() { |
176 | ((${#filenames[@]} == 1)) && nofileinfo=1 | |
3721635b | 177 | for f in "${!filenames[@]}"; do |
b208aad5 HH |
178 | [[ $nofileinfo ]] || echo "initramfs:/$f" |
179 | [[ $nofileinfo ]] || echo "========================================================================" | |
1f84ff88 AAF |
180 | # shellcheck disable=SC2001 |
181 | [[ $f == *"\\x"* ]] && f=$(echo "$f" | sed 's/\\x.\{2\}/????/g') | |
9a52c3fd HH |
182 | $CAT "$image" 2> /dev/null | cpio --extract --verbose --quiet --to-stdout "$f" 2> /dev/null |
183 | ((ret += $?)) | |
b208aad5 HH |
184 | [[ $nofileinfo ]] || echo "========================================================================" |
185 | [[ $nofileinfo ]] || echo | |
186 | done | |
187 | } | |
188 | ||
9a52c3fd | 189 | list_modules() { |
05d2a145 | 190 | echo "dracut modules:" |
0ce54e80 | 191 | # shellcheck disable=SC2046 |
d3be9275 | 192 | $CAT "$image" | cpio --extract --verbose --quiet --to-stdout -- \ |
9a52c3fd HH |
193 | $(dracutlibdirs modules.txt) 2> /dev/null |
194 | ((ret += $?)) | |
05d2a145 HB |
195 | } |
196 | ||
9a52c3fd | 197 | list_files() { |
b208aad5 HH |
198 | echo "========================================================================" |
199 | if [ "$sorted" -eq 1 ]; then | |
9a52c3fd | 200 | $CAT "$image" 2> /dev/null | cpio --extract --verbose --quiet --list | sort -n -k5 |
b208aad5 | 201 | else |
9a52c3fd | 202 | $CAT "$image" 2> /dev/null | cpio --extract --verbose --quiet --list | sort -k9 |
b208aad5 | 203 | fi |
9a52c3fd | 204 | ((ret += $?)) |
b208aad5 HH |
205 | echo "========================================================================" |
206 | } | |
207 | ||
9a52c3fd | 208 | list_squash_content() { |
8f7c332e | 209 | SQUASH_IMG="squash-root.img" |
cbf32008 MR |
210 | SQUASH_TMPFILE="$TMPDIR/initrd.root.sqsh" |
211 | ||
9a52c3fd HH |
212 | $CAT "$image" 2> /dev/null | cpio --extract --verbose --quiet --to-stdout -- \ |
213 | $SQUASH_IMG > "$SQUASH_TMPFILE" 2> /dev/null | |
1ff306a3 KS |
214 | if [[ -s $SQUASH_TMPFILE ]]; then |
215 | echo "Squashed content ($SQUASH_IMG):" | |
216 | echo "========================================================================" | |
217 | unsquashfs -ll "$SQUASH_TMPFILE" | tail -n +4 | |
218 | echo "========================================================================" | |
219 | fi | |
220 | } | |
221 | ||
9a52c3fd HH |
222 | unpack_files() { |
223 | if ((${#filenames[@]} > 0)); then | |
f81c864e | 224 | for f in "${!filenames[@]}"; do |
1f84ff88 AAF |
225 | # shellcheck disable=SC2001 |
226 | [[ $f == *"\\x"* ]] && f=$(echo "$f" | sed 's/\\x.\{2\}/????/g') | |
227 | $CAT "$image" 2> /dev/null | cpio -id --quiet $verbose "$f" | |
9a52c3fd | 228 | ((ret += $?)) |
f81c864e KS |
229 | done |
230 | else | |
9a52c3fd HH |
231 | $CAT "$image" 2> /dev/null | cpio -id --quiet $verbose |
232 | ((ret += $?)) | |
f81c864e | 233 | fi |
97bbba69 HH |
234 | } |
235 | ||
0ce54e80 | 236 | read -r -N 2 bin < "$image" |
cbf32008 | 237 | if [ "$bin" = "MZ" ]; then |
9a52c3fd HH |
238 | command -v objcopy > /dev/null || { |
239 | echo "Need 'objcopy' to unpack an UEFI executable." | |
240 | exit 1 | |
241 | } | |
cbf32008 MR |
242 | objcopy \ |
243 | --dump-section .linux="$TMPDIR/vmlinuz" \ | |
244 | --dump-section .initrd="$TMPDIR/initrd.img" \ | |
245 | --dump-section .cmdline="$TMPDIR/cmdline.txt" \ | |
246 | --dump-section .osrel="$TMPDIR/osrel.txt" \ | |
247 | "$image" /dev/null | |
248 | uefi="$image" | |
249 | image="$TMPDIR/initrd.img" | |
250 | [ -f "$image" ] || exit 1 | |
251 | fi | |
b208aad5 | 252 | |
75d758e8 | 253 | if ((${#filenames[@]} <= 0)) && [[ -z $unpack ]] && [[ -z $unpackearly ]]; then |
32dfd416 | 254 | if [ -n "$uefi" ]; then |
cbf32008 | 255 | echo -n "initrd in UEFI: $uefi: " |
0ce54e80 | 256 | du -h "$image" | while read -r a _ || [ -n "$a" ]; do echo "$a"; done |
cbf32008 MR |
257 | if [ -f "$TMPDIR/osrel.txt" ]; then |
258 | name=$(sed -En '/^PRETTY_NAME/ s/^\w+=["'"'"']?([^"'"'"'$]*)["'"'"']?/\1/p' "$TMPDIR/osrel.txt") | |
259 | id=$(sed -En '/^ID/ s/^\w+=["'"'"']?([^"'"'"'$]*)["'"'"']?/\1/p' "$TMPDIR/osrel.txt") | |
260 | build=$(sed -En '/^BUILD_ID/ s/^\w+=["'"'"']?([^"'"'"'$]*)["'"'"']?/\1/p' "$TMPDIR/osrel.txt") | |
261 | echo "OS Release: $name (${id}-${build})" | |
262 | fi | |
263 | if [ -f "$TMPDIR/vmlinuz" ]; then | |
264 | version=$(strings -n 20 "$TMPDIR/vmlinuz" | sed -En '/[0-9]+\.[0-9]+\.[0-9]+/ { p; q 0 }') | |
265 | echo "Kernel Version: $version" | |
266 | fi | |
267 | if [ -f "$TMPDIR/cmdline.txt" ]; then | |
268 | echo "Command line:" | |
269 | sed -En 's/\s+/\n/g; s/\x00/\n/; p' "$TMPDIR/cmdline.txt" | |
270 | fi | |
271 | else | |
272 | echo -n "Image: $image: " | |
0ce54e80 | 273 | du -h "$image" | while read -r a _ || [ -n "$a" ]; do echo "$a"; done |
cbf32008 MR |
274 | fi |
275 | ||
b208aad5 HH |
276 | echo "========================================================================" |
277 | fi | |
278 | ||
0ce54e80 | 279 | read -r -N 6 bin < "$image" |
b208aad5 | 280 | case $bin in |
9a52c3fd | 281 | $'\x71\xc7'* | 070701) |
18a5011f | 282 | CAT="cat --" |
9a52c3fd | 283 | is_early=$(cpio --extract --verbose --quiet --to-stdout -- 'early_cpio' < "$image" 2> /dev/null) |
ce62465c | 284 | # Debian mkinitramfs does not create the file 'early_cpio', so let's check if firmware files exist |
9a52c3fd | 285 | [[ "$is_early" ]] || is_early=$(cpio --list --verbose --quiet --to-stdout -- 'kernel/*/microcode/*.bin' < "$image" 2> /dev/null) |
b208aad5 | 286 | if [[ "$is_early" ]]; then |
75d758e8 | 287 | if [[ -n $unpack ]]; then |
f81c864e KS |
288 | # should use --unpackearly for early CPIO |
289 | : | |
75d758e8 | 290 | elif [[ -n $unpackearly ]]; then |
97bbba69 | 291 | unpack_files |
9a52c3fd | 292 | elif ((${#filenames[@]} > 0)); then |
b208aad5 HH |
293 | extract_files |
294 | else | |
295 | echo "Early CPIO image" | |
296 | list_files | |
297 | fi | |
5eb996a9 AAF |
298 | if [[ -d "$dracutbasedir/src/skipcpio" ]]; then |
299 | SKIP="$dracutbasedir/src/skipcpio/skipcpio" | |
98fd0693 HH |
300 | else |
301 | SKIP="$dracutbasedir/skipcpio" | |
302 | fi | |
b208aad5 HH |
303 | if ! [[ -x $SKIP ]]; then |
304 | echo | |
305 | echo "'$SKIP' not found, cannot display remaining contents!" >&2 | |
306 | echo | |
307 | exit 0 | |
308 | fi | |
309 | fi | |
310 | ;; | |
311 | esac | |
312 | ||
9a52c3fd | 313 | if [[ $SKIP ]]; then |
0ce54e80 | 314 | bin="$($SKIP "$image" | { read -r -N 6 bin && echo "$bin"; })" |
3ce14286 | 315 | else |
0ce54e80 | 316 | read -r -N 6 bin < "$image" |
3ce14286 HD |
317 | fi |
318 | case $bin in | |
319 | $'\x1f\x8b'*) | |
320 | CAT="zcat --" | |
321 | ;; | |
322 | BZh*) | |
323 | CAT="bzcat --" | |
324 | ;; | |
9a52c3fd | 325 | $'\x71\xc7'* | 070701) |
18a5011f | 326 | CAT="cat --" |
3ce14286 HD |
327 | ;; |
328 | $'\x02\x21'*) | |
329 | CAT="lz4 -d -c" | |
330 | ;; | |
331 | $'\x89'LZO$'\0'*) | |
332 | CAT="lzop -d -c" | |
333 | ;; | |
ebfd53e1 | 334 | $'\x28\xB5\x2F\xFD'*) |
7dbadcc7 TPG |
335 | CAT="zstd -d -c" |
336 | ;; | |
3ce14286 | 337 | *) |
9a52c3fd | 338 | if echo "test" | xz | xzcat --single-stream > /dev/null 2>&1; then |
3ce14286 | 339 | CAT="xzcat --single-stream --" |
fd9f9024 | 340 | else |
3ce14286 HD |
341 | CAT="xzcat --" |
342 | fi | |
343 | ;; | |
344 | esac | |
66fe35eb | 345 | |
1300a930 FG |
346 | type "${CAT%% *}" > /dev/null 2>&1 || { |
347 | echo "Need '${CAT%% *}' to unpack the initramfs." | |
348 | exit 1 | |
349 | } | |
350 | ||
9a52c3fd | 351 | skipcpio() { |
b208aad5 HH |
352 | $SKIP "$@" | $ORIG_CAT |
353 | } | |
354 | ||
355 | if [[ $SKIP ]]; then | |
356 | ORIG_CAT="$CAT" | |
357 | CAT=skipcpio | |
358 | fi | |
359 | ||
9a52c3fd | 360 | if ((${#filenames[@]} > 1)); then |
cbf32008 | 361 | TMPFILE="$TMPDIR/initrd.cpio" |
0ce54e80 | 362 | $CAT "$image" 2> /dev/null > "$TMPFILE" |
9a52c3fd | 363 | pre_decompress() { |
0ce54e80 | 364 | cat "$TMPFILE" |
986b12d3 KS |
365 | } |
366 | CAT=pre_decompress | |
367 | fi | |
368 | ||
884e1cda HH |
369 | ret=0 |
370 | ||
75d758e8 | 371 | if [[ -n $unpack ]]; then |
97bbba69 | 372 | unpack_files |
9a52c3fd | 373 | elif ((${#filenames[@]} > 0)); then |
b208aad5 | 374 | extract_files |
3ea5d2e2 | 375 | else |
0ce54e80 | 376 | # shellcheck disable=SC2046 |
d3be9275 | 377 | version=$($CAT "$image" | cpio --extract --verbose --quiet --to-stdout -- \ |
9a52c3fd HH |
378 | $(dracutlibdirs 'dracut-*') 2> /dev/null) |
379 | ((ret += $?)) | |
ae01bd18 | 380 | echo "Version: $version" |
b208aad5 | 381 | echo |
05d2a145 HB |
382 | if [ "$modules" -eq 1 ]; then |
383 | list_modules | |
384 | echo "========================================================================" | |
385 | else | |
386 | echo -n "Arguments: " | |
0ce54e80 | 387 | # shellcheck disable=SC2046 |
d3be9275 | 388 | $CAT "$image" | cpio --extract --verbose --quiet --to-stdout -- \ |
9a52c3fd | 389 | $(dracutlibdirs build-parameter.txt) 2> /dev/null |
05d2a145 HB |
390 | echo |
391 | list_modules | |
392 | list_files | |
1ff306a3 | 393 | list_squash_content |
05d2a145 | 394 | fi |
3ea5d2e2 | 395 | fi |
4460416a | 396 | |
0ce54e80 | 397 | exit "$ret" |