3 ###############################################################################
5 # IPFire.org - A linux based firewall #
6 # Copyright (C) 2009 Michael Tremer & Christian Schmidt #
8 # This program is free software: you can redistribute it and/or modify #
9 # it under the terms of the GNU General Public License as published by #
10 # the Free Software Foundation, either version 3 of the License, or #
11 # (at your option) any later version. #
13 # This program is distributed in the hope that it will be useful, #
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
16 # GNU General Public License for more details. #
18 # You should have received a copy of the GNU General Public License #
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
21 ###############################################################################
24 ## GLOBAL VARIABLES ARE UPPERCASE
25 ## LOCAL VARIABLES ARE LOWERCASE
35 # Check if we are root
36 if [ $UID != 0 ]; then
37 error
"$0 must be run as root."
43 echo "$0 [--help] [-f] [-v] <out-initrd-image> <kernel-version>"
44 echo " [--with=<module>]"
46 echo "example: $0 /boot/myinitramfs.img \`uname -r\`"
49 # Setting verbose mode
50 function set_verbose
() {
61 # Returns if verbose is on or not
62 function is_verbose
() {
63 [ -n "$VERBOSE" ] && return 0
67 # Like is_verbose but prints
68 # the content of $VERBOSE
69 function get_verbose
() {
74 # Prints text if verbose is on
76 is_verbose
&& echo "$@"
79 # Prints error if verbose is on
87 vecho
"[TASK] Compressing image $TARGET..."
88 (cd $TMPDIR && find . |
cpio -H newc
--quiet -o >|
$IMAGE) ||
exit 1
89 gzip -c9 $IMAGE > $TARGET
93 find "$@" |
awk '{ print $1; exit; }'
101 pushd "$1" >/dev
/null
2>&1
108 function read_link
() {
109 READLINK
=$
(readlink
$1)
110 if grep -q "^/" <<< $READLINK; then
113 echo "$(dirname $1)/$READLINK"
117 function get_dso_deps
() {
124 local LDSO
="/lib/ld-linux.so.2"
127 while read NAME I0 FILE ADDR I1
; do
128 [ "$FILE" == "not" ] && FILE
="$FILE $ADDR"
129 [ "$NAME" == "not" ] && NAME
="$NAME $I0"
134 $(LD_TRACE_PRELINKING=1 LD_WARN= LD_TRACE_LOADED_OBJECTS=1 \
135 $LDSO $bin 2>/dev/null)
138 [ ${#FILES[*]} -eq 0 ] && return 1
140 # we don't want the name of the binary in the list
141 if [ "${FILES[0]}" == "$bin" ]; then
144 [ ${#FILES[*]} -eq 1 ] && return 1
148 while [ $n -lt ${#FILES[*]} ]; do
149 local FILE
="${FILES[$n]}"
150 local NAME
="${NAMES[$n]}"
151 if [ "$FILE" == "not found" -o "$NAME" == "not found" ]; then
153 There are missing files on your system. The dynamic object $bin
154 requires ${NAMES[$n]} n order to properly function. mkinitramfs cannot continue.
160 TLIBDIR
=`echo "$FILE" | sed 's,\(/lib[^/]*\)/.*$,\1,'`
161 BASE
=`basename "$FILE"`
162 if [ -f "$TLIBDIR/$BASE" ]; then
163 FILE
="$TLIBDIR/$BASE"
178 ## Check if this is an absolute path
179 if [ "$(basename $file)" = "$file" ]; then
185 [ -e "$dest" ] && return 0
187 mkdir
-p "$(dirname $dest)" 2>/dev
/null
189 local old_indent
=$INDENT
192 [ "${file%%.ko}" != "${file}" ] && msg
="[KMOD]"
193 [ -L "$file" ] && msg
="[SYML]"
194 #vecho "$msg$INDENT$file -> $dest"
195 vecho
"$msg$INDENT$file"
197 # Check if $file is a symlink
198 if [ -L "$file" ]; then
199 install $
(read_link
$file)
202 if [ "${file%%.ko}" != "${file}" ]; then
203 for i
in $
(moduledep
$file); do
204 [ "$(locatemodule $i)" = "$file" ] && continue
211 # Check if file is a script file
212 if [ "$(dd if=$file bs=2 count=1 2>/dev/null)" = "#!" ]; then
213 install $
(head -n 1 $file | cut
-c3-)
214 # Check if file is a kernel module
215 elif [ "${file%%.ko}" != "${file}" ]; then
217 for firmware
in $
(modinfo
-F firmware
$file 2>/dev
/null
); do
218 firmware
="/lib/firmware/$firmware"
219 [ -e "$firmware" ] && install $firmware
222 for dep
in $
(get_dso_deps
"$file"); do
231 # find module dependencies
232 function moduledep
() {
234 if [ "$1" == "--ignore-install" ]; then
235 mpargs
="$mpargs --ignore-install"
238 local module
=$
(basename ${1%%.ko})
239 modprobe
$mpargs --set-version $KERNEL --show-depends $module 2>/dev
/null | \
240 awk '/^insmod / { print gensub(".*/","","g",$2) }' | \
242 [ "${foo%%.ko}" != "$1" ] && \
243 echo -n "${foo%%.ko} "; \
247 # XXX May be, we can drop this...
248 # This loops to make sure it resolves dependencies of dependencies of...
249 function resolvemoduledeps
() {
257 while [ $before != $after ]; do
259 before
=$
(wc -c <<< $modules)
260 for module
in $modules; do
261 deps
=$
(moduledep
$module)
262 is_verbose
&& echo "Module $module depends on: $deps"
263 newmodules
="$newmodules $module $deps"
265 modules
=$
(for i
in $newmodules; do echo $i; done |
sort -u)
266 after
=$
(wc -c <<< $modules)
271 function locatemodule
() {
273 if [ "$1" == "--ignore-install" ]; then
274 mpargs
="$mpargs --ignore-install"
277 local path
=$
(modprobe
$mpargs --set-version $KERNEL --show-depends $1 2>/dev
/null | \
278 awk '/^insmod / { print $2; }' |
tail -n 1)
279 [ -n "$path" -a -f "$path" ] && echo $path
282 function installmodule
() {
285 module
=$
(locatemodule
$module)
286 [ -z "$module" ] && continue
292 resolve_device_name
() {
293 if [[ "$1" =~ ^
/dev
]]; then
300 function finalize
() {
304 installmodule
$MODULES
306 # Build module deps file so we can use modprobe
307 vecho
"[TASK] Running depmod..."
308 depmod
-a -b "$TMPDIR" $KERNEL
311 install /etc
/ld.so.conf
312 [ -d "/etc/ld.so.conf.d" ] && \
313 for i
in $
(find /etc
/ld.so.conf.d
-type f
); do
316 vecho
"[TASK] Running ldconfig..."
321 rm -rf $TMPDIR 2>/dev
/null
324 # resolve a device node to its major:minor numbers in decimal or hex
325 function get_numeric_dev
() {
327 if [ "$1" == "hex" ]; then
330 ls -lH "$2" |
awk '{ sub(/,/, "", $5); printf("'"$fmt"'", $5, $6); }'
334 function resolve_device_name
() {
335 if [[ "$1" =~ ^
/dev
]]; then
342 function finddevnoinsys
() {
344 if [ -n "$majmin" ]; then
345 dev
=$
(for x
in /sys
/block
/* ; do find $x/ -name dev
; done |
while read device
; do \
346 echo "$majmin" |
cmp -s $device && echo $device ; done)
347 if [ -n "$dev" ]; then
357 findblockdevinsys
() {
358 devname
=$
(resolve_device_name
"$1")
359 if [[ "$devname" =~ ^
/sys
/block
/ ]]; then
362 majmin
=$
(get_numeric_dev dec
$devname)
363 finddevnoinsys
"$majmin"
366 findstoragedriverinsys
() {
367 while [ ! -L device
]; do
368 for slave
in $
(ls -d slaves
/* 2>/dev
/null
) ; do
369 slavename
=${slave##*/}
370 case " $slavestried " in
375 slavestried
="$slavestried $slavename"
377 findstoragedriverinsys
382 [ "$PWD" = "/sys" ] && return
385 cd $
(read_link .
/device
)
386 if echo $PWD |
grep -q /virtio-pci
/ ; then
387 installmodule virtio_pci
389 while [ "$PWD" != "/sys/devices" ]; do
391 if [ -f modalias
]; then
392 installmodule $
(cat modalias
)
395 [ -z "$deps" -a -L driver
/module
] && \
396 deps
=$
(basename $
(read_link driver
/module
))
402 function findstoragedriver
() {
404 case " $handleddevices " in
407 *) handleddevices
="$handleddevices $device" ;;
409 vecho
"[INFO] Looking for driver for device $device"
410 if [[ "$device" =~ ^
/sys
]]; then
414 device
=$
(echo "$device" |
sed 's,/,!,g')
415 if [ -d /sys
/block
/$device/ ]; then
416 sysfs
="/sys/block/$device"
418 sysfs
=$
(for x
in /sys
/block
/*; do findone
$x/ -type d
-name $device; done)
420 [ -z "$sysfs" ] && return
422 findstoragedriverinsys
428 while [ $# -gt 0 ] ; do
441 MODULES
="$MODULES ${1#--with=*}"
444 if [ -z "$target" ] ; then
446 elif [ -z "$kernel" ] ; then
449 echo "Unknown option or parameter \"$1\""
459 TARGET
=${target-$TARGET}
460 KERNEL
=${kernel-$KERNEL}
462 if [ -z "$TARGET" ]; then
467 [[ "$TARGET" =~
"^/" ]] && TARGET
="$PWD/$TARGET"
469 if [ -z "$FORCE" ] && [ -e "$TARGET" ]; then
470 echo "Image $TARGET already exists. Use -f to overwrite"
474 # Changing to our dir, where we do our actions in
475 qpushd
$TMPDIR ||
exit 1
477 # Make directory structure
478 mkdir
-p bin sbin dev sys proc sysroot \
479 etc
/udev
/rules.d lib
/udev
/rules.d
481 # Install some essential binaries
482 install bash
chmod cat cut
dd dmesg env
grep kbd_mode
kill killall5
ln ls lsmod mkdir \
483 mknod modprobe mount mountpoint openvt pidof
rm sed setfont sh
sleep switchroot \
484 udevadm udevd umount
/lib
/udev
/console_init
/lib
/udev
/vol_id
489 # Copy modprobe.conf and friends over
490 [ -e /etc
/modprobe.conf
] && install /etc
/modprobe.conf
491 for f
in $
(find /etc
/modprobe.d
-type f
); do
495 # terminfo bits make things work better if you fall into interactive mode
496 [ -d "/usr/lib/terminfo" ] && \
497 for f
in $
(find /usr
/lib
/terminfo
-type f
); do
502 install /etc
/sysconfig
/console
/etc
/inittab
503 .
/etc
/sysconfig
/console
504 [ -z "$FONT" ] && FONT
="latarcyrheb-sun16"
505 for i
in /lib
/kbd
/consolefonts
/$FONT.
*; do
506 mkdir
-p $TMPDIR/$
(dirname $i) 2>/dev
/null || true
521 # Mounting directories
522 mount -t proc proc /proc
523 mount -t sysfs /sys /sys
524 mount -t tmpfs -o mode=0755 udev /dev
527 echo > /proc/sys/kernel/printk "1 4 1 7"
529 # Adding important dev nodes
530 mknod /dev/console c 5 1
531 mknod /dev/null c 1 3
532 mknod /dev/kmsg c 1 11
533 mknod /dev/ptmx c 5 2
535 mknod /dev/systty c 4 0
537 # XXX really we need to openvt too, in case someting changes the
538 # color palette and then changes vts on fbcon before gettys start.
540 for i in 0 1 2 3 4 5 6 7 8 9 10 11 12 ; do
541 mknod /dev/tty$i c 4 $i
544 for i in 0 1 2 3 ; do
545 mknod /dev/ttyS$i c 4 $(($i + 64))
548 mkdir -m 1777 /dev/shm
549 ln -s /proc/self/fd /dev/fd
550 ln -s fd/0 /dev/stdin
551 ln -s fd/1 /dev/stdout
552 ln -s fd/2 /dev/stderr
555 mount -t devpts -o gid=5,mode=620 /dev/pts /dev/pts
561 # Write out real-init
562 touch sbin
/real-init
; chmod 755 sbin
/real-init
563 cat > sbin
/real-init
<<'EOF'
567 export PATH=/sbin:/bin:/usr/sbin:/usr/bin
577 function emergency_shell()
579 echo "Bug in initramfs /init detected. Dropping to a shell. Good luck!"
583 trap "emergency_shell" 0 2
585 # exit immediately if a command fails
588 # Setting verbose mode
589 function set_verbose() {
600 # Returns if verbose is on or not
601 function is_verbose() {
602 [ -n "$VERBOSE" ] && return 0
606 # Like is_verbose but prints
607 # the content of $VERBOSE
608 function get_verbose() {
613 # Prints text if verbose is on
615 if is_verbose; then echo "$@"; fi
618 # Prints error if verbose is on
623 /lib/udev/console_init tty0
625 # Disable hotplugging
626 echo "" > /proc/sys/kernel/hotplug
628 # Parse kernel commandline options
629 for o in $(cat /proc/cmdline) ; do
650 echo "blacklist ${o#blacklist=}" >> /etc/modprobe.conf
653 m=$(echo $o |cut -s -d . -f 1)
654 opt=$(echo $o |cut -s -d . -f 2-)
655 if [ -z "$m" -o -z "$opt" ]; then
658 p=$(echo $opt |cut -s -d = -f 1)
659 v=$(echo $opt |cut -s -d = -f 2-)
660 if [ -z "$p" -o -z "$v" ]; then
663 echo "options $m $p=$v" >> /etc/modprobe.conf
668 vecho "kernel commandline: $(cat /proc/cmdline)"