summaryrefslogtreecommitdiffstats
path: root/init
blob: 6a206e935c0bea973ce6cc120f6dfe37c30100f2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
#!/bin/busybox ash
# Install busybox's applets as symlinks
/bin/busybox --install -s

. /init_functions

msg ":: Loading Initramfs"
/bin/mount -t proc proc /proc
/bin/mount -t sysfs sys /sys

read CMDLINE </proc/cmdline
export CMDLINE

export root=""
export init=""
echo "/sbin/modprobe" > /proc/sys/kernel/modprobe

# set default mount handler
mount_handler="default"

# if available, start udevd at this stage
if [ -x /sbin/udevd ]; then
    msg ":: Starting udevd..."
    echo > /proc/sys/kernel/hotplug
    /sbin/udevd --daemon --resolve-names=never
    msg "done."
fi

for cmd in ${CMDLINE}; do
    case "${cmd}" in
        \#*) break ;; # ignore everything after a # in the commandline
        # The kernel passes those to the kernel on its own
        [0123456Ss]) ;;
        [0-9]*) ;;
        single) ;;
        rw) readwrite="yes" ;;
        ro) readwrite="no" ;;
        # only export stuff that does work with ash :)
        *=*) rhs="$(echo "${cmd}" | cut -d= -f2-)"
             cmd="$(echo "${cmd}" | cut -d= -f1 | sed 's|\.|_|g')"
             cmd="$(echo "${cmd}" | sed 's|-|_|g')=${rhs}"
             (echo "${cmd}" | grep -qe '^[0-9]') || export "${cmd}"
             ;;
        *)   cmd="$(echo "${cmd}" | sed 's|\.|_|g')"
             cmd="$(echo "${cmd}" | sed 's|-|_|g')"
             (echo "${cmd}" | grep -qe '^[0-9]') || export "${cmd}=y"
             ;;
    esac
done

if [ -n "${disablehooks}" ]; then
    for d in $(echo "${disablehooks}" | sed 's|,| |g'); do
        export "hook_${d}=disabled"
    done
fi

if [ -n "${disablemodules}" ]; then
    for d in $(echo "${disablemodules}" | sed 's|,| |g'); do
        export "mod_${d}=disabled"
    done
fi

if [ -n "${earlymodules}" ]; then
    for m in $(echo "${earlymodules}" | sed 's|,| |g'); do
        /sbin/modprobe -q ${m} > /dev/null 2>&1
    done
fi

. /config

for m in ${MODULES}; do
    TST=""
    eval "TST=\$mod_${m}"
    if [ "${TST}" != "disabled" ]; then
        /sbin/modprobe -q ${m} > /dev/null 2>&1
    fi
done

# If rootdelay is empty or not a non-negative integer, set it to 10
if [ -z "${rootdelay}" ] || ! [ "${rootdelay}" -ge 0 ]; then
    export rootdelay=10
fi

if [ -e "/hooks" ]; then
    for h in ${HOOKS}; do
        TST=""
        eval "TST=\$hook_${h}"
        if [ "${TST}" != "disabled" ]; then
            run_hook () { msg "${h}: no run function defined"; }
            if [ -e "/hooks/${h}" ]; then
               . /hooks/${h}
               msg ":: Running Hook [${h}]"
               run_hook
            fi
        fi
    done
fi

if [ "${break}" = "y" ]; then
    echo ":: Break requested, type 'exit' to resume operation"
    launch_interactive_shell
fi

if [ -f "/message" ]; then
    msg "$(cat /message)"
fi

mkdir -p /new_root
if [ -z "${mount_handler}" -o "${mount_handler}" = "default" ]; then
  if [ ${root:0:5} != "/dev/" ] || ! poll_device "${root}" ${rootdelay}; then
    msg "\nRoot device '${root}' doesn't exist. Attempting to create it."
    rootdev=""
    if [ ${root:0:5} = "/dev/" ]; then
      # It might be a block device (/dev/sda)
      if [ -f /sys/block/${root:5}/dev ]; then
        rootdev="$(cat /sys/block/${root:5}/dev | sed 's|:| |')"
      # It might be a partition on any block device (/dev/sda1)
      else
        for dir in /sys/block/*; do
          if [ -f ${dir}/${root:5}/dev ]; then
            rootdev="$(cat ${dir}/${root:5}/dev | sed 's|:| |')"
            break
          fi
        done
      fi
    # It might be a major/minor pair (8:1)
    elif echo ${root} | grep -q :; then
      rootdev="$(echo ${root} | sed 's|:| |')"
      root="/dev/root"
    # It might be major/minor encoded as a single hex-number (lilo-style) (801)
    elif [ ${#root} -le 4 -a ${#root} -gt 2 ] && echo "${root}" | grep -qe '^[A-Fa-f0-9]*$'; then
      str_offset=$((${#root}-2))
      major=$(printf "%d" 0x${root:0:${str_offset}})
      minor=$(printf "%d" 0x${root:${str_offset}})
      rootdev="${major} ${minor}"
      root="/dev/root"
    fi
    if [ -n "${rootdev}" ]; then
      msg "Creating root device ${root} with major $(echo "${rootdev}" | cut -d\   -f1) and minor $(echo "${rootdev}" | cut -d\   -f2)."
      mknod ${root} b ${rootdev}
    else
      err "Unable to determine major/minor number of root device '${root}'."
      echo "You are being dropped to a recovery shell"
      echo "    Type 'exit' to try and continue booting"
      launch_interactive_shell
      msg "Trying to continue (this will most likely fail) ..."
    fi
  fi
  # We didn't build filesystem support into busybox,
  # instead we use util-linux-ng's blkid for best compatibility
  if [ -n "${rootfstype}" ]; then
    fstype="${rootfstype}"
  else
    fstype=$(eval $(/sbin/blkid -o udev -p "${root}"); echo $ID_FS_TYPE)
    if [ -z "${fstype}" ]; then
      err "Unable to determine the file system type of ${root}:"
      echo "Either it contains no filesystem, an unknown filesystem,"
      echo "or more than one valid file system signature was found."
      echo
      echo "Try adding"
      echo "    rootfstype=your_filesystem_type"
      echo "to the kernel command line."
      echo
      echo "You are now being dropped into an emergency shell."
      launch_interactive_shell
      msg "Trying to continue (this will most likely fail) ..."
    fi
  fi
  if [ "${readwrite}" = "yes" ]; then
    rwopt="rw"
  else
    rwopt="ro"
  fi
  mount ${fstype:+-t ${fstype}} -o ${rwopt}${rootflags:+,${rootflags}} "${root}" /new_root
else
  ${mount_handler} /new_root
fi

[ -z "${init}" ] && init="/sbin/init"
if [ "$(stat -f -c %i /)" = "$(stat -f -c %i /new_root)" ]; then
  # Nothing got mounted on /new_root. This is the end, we don't know what to do anymore
  # We fall back into a shell, but the shell has now PID 1
  # This way, manual recovery is still possible.
  err "Failed to mount the real root device."
  echo "Bailing out, you are on your own. Good luck."
  echo
  launch_interactive_shell --exec
elif [ ! -f "/new_root${init}" ]; then
  # Successfully mounted /new_root, but ${init} is missing
  # The same logic as above applies
  err "Root device mounted successfully, but ${init} does not exist."
  echo "Bailing out, you are on your own. Good luck."
  echo
  launch_interactive_shell --exec
fi

#Special handling if udev is running
udevpid=$(/bin/pidof udevd)
if [ -n "${udevpid}" ]; then
    # Settle pending uevents, then kill udev
    /sbin/udevadm settle
    /bin/kill ${udevpid} > /dev/null 2>&1
    while /bin/pidof udevd >/dev/null; do
        sleep 0.1
    done
fi

umount /proc
umount /sys
exec /sbin/switch_root -c /dev/console /new_root ${init} "$@"