1#!/bin/sh 2 3fslist="proc sys dev run" 4rodir=run/initramfs/ro 5rwdir=run/initramfs/rw 6upper=$rwdir/cow 7work=$rwdir/work 8 9cd / 10mkdir -p $fslist 11mount dev dev -tdevtmpfs 12mount sys sys -tsysfs 13mount proc proc -tproc 14if ! grep run proc/mounts 15then 16 mount tmpfs run -t tmpfs -o mode=755,nodev 17fi 18 19mkdir -p $rodir $rwdir 20 21cp -rp init shutdown update whitelist bin sbin usr lib etc var run/initramfs 22 23# To start a interactive shell with job control at this point, run 24# getty 38400 ttyS4 25 26findmtd() { 27 m=$(grep -xl "$1" /sys/class/mtd/*/name) 28 m=${m%/name} 29 m=${m##*/} 30 echo $m 31} 32 33blkid_fs_type() { 34 # Emulate util-linux's `blkid -s TYPE -o value $1` 35 # Example busybox blkid output: 36 # # blkid /dev/mtdblock5 37 # /dev/mtdblock5: TYPE="squashfs" 38 # Process output to extract TYPE value "squashfs". 39 blkid $1 | sed -e 's/^.*TYPE="//' -e 's/".*$//' 40} 41 42probe_fs_type() { 43 fst=$(blkid_fs_type $1) 44 echo ${fst:=jffs2} 45} 46 47# This fw_get_env_var is a possibly broken version of fw_printenv that 48# does not check the crc or flag byte. 49# The u-boot environment starts with a crc32, followed by a flag byte 50# when a redundannt environment is configured, followed by var=value\0 sets. 51# The flag byte for nand is a 1 byte counter; for nor it is a 1 or 0 byte. 52 53get_fw_env_var() { 54 # do we have 1 or 2 copies of the environment? 55 # count non-blank non-comment lines 56 # copies=$(grep -v ^# /etc/fw_env.config | grep -c [::alnum::]) 57 # ... we could if we had the fw_env.config in the initramfs 58 copies=2 59 60 # * Change \n to \r and \0 to \n 61 # * Skip to the 5th byte to skip over crc 62 # * then skip to the first or 2nd byte to skip over flag if it exists 63 # * stop parsing at first empty line corresponding to the 64 # double \0 at the end of the environment. 65 # * print the value of the variable name passed as argument 66 67 envdev=$(findmtd u-boot-env) 68 if test -n $envdev 69 then 70 cat /dev/$envdev | 71 tr '\n\000' '\r\n' | 72 tail -c +5 | tail -c +${copies-1} | 73 sed -ne '/^$/,$d' -e "s/^$1=//p" 74 fi 75} 76 77setup_resolv() { 78 runresolv=/run/systemd/resolve/resolv.conf 79 etcresolv=/etc/resolv.conf 80 81 if test ! -e $etcresolv -a ! -L $etcresolv 82 then 83 mkdir -p ${runresolv%/*} 84 ln -s $runresolv $etcresolv 85 fi 86 if test ! -f $runresolv 87 then 88 cat /proc/net/pnp > $runresolv 89 fi 90 91 return 0 92} 93 94try_tftp() { 95 # split into tftp:// host:port/ path/on/remote 96 # then spilt off / and then :port from the end of host:port/ 97 # and : from the beginning of port 98 99 rest="${1#tftp://}" 100 path=${rest#*/} 101 host=${rest%$path} 102 host="${host%/}" 103 port="${host#${host%:*}}" 104 host="${host%$port}" 105 port="${port#:}" 106 107 setup_resolv 108 109 if test -z "$host" -o -z "$path" 110 then 111 debug_takeover "Invalid tftp download url '$url'." 112 elif echo "Downloading '$url' from $host ..." && 113 ! tftp -g -r "$path" -l /run/image-rofs "$host" ${port+"$port"} 114 then 115 debug_takeover "Download of '$url' failed." 116 fi 117} 118 119try_wget() { 120 setup_resolv 121 122 echo "Downloading '$1' ..." 123 if ! wget -O /run/image-rofs "$1" 124 then 125 debug_takeover "Download of '$url' failed." 126 fi 127} 128 129debug_takeover() { 130 echo "$@" 131 132 if ! grep -w enable-initrd-debug-sh "$optfile" 133 then 134 echo "Fatal error, triggering kernel panic!" 135 exit 1 136 fi 137 138 test -n "$@" && echo Try to manually fix. 139 cat << HERE 140After fixing run exit to continue this script, or reboot -f to retry, or 141touch /takeover and exit to become PID 1 allowing editing of this script. 142HERE 143 144 while ! /bin/sh && ! test -f /takeover 145 do 146 echo /bin/sh failed, retrying 147 done 148 149 # Touch /takeover in the above shell to become pid 1 150 if test -e /takeover 151 then 152 cat << HERE 153 154Takeover of init requested. Executing /bin/sh as PID 1. 155When finished exec new init or cleanup and run reboot -f. 156 157Warning: No job control! Shell exit will panic the system! 158HERE 159 export PS1=init#\ 160 exec /bin/sh 161 fi 162} 163 164rofs=$(findmtd rofs) 165rwfs=$(findmtd rwfs) 166 167rodev=/dev/mtdblock${rofs#mtd} 168rwdev=/dev/mtdblock${rwfs#mtd} 169 170# Set to y for yes, anything else for no. 171force_rwfst_jffs2=y 172flash_images_before_init=n 173consider_download_files=y 174consider_download_tftp=y 175consider_download_http=y 176consider_download_ftp=y 177 178rofst=squashfs 179rwfst=$(probe_fs_type $rwdev) 180roopts=ro 181rwopts=rw 182 183image=/run/initramfs/image- 184trigger=${image}rwfs 185 186init=/sbin/init 187fsckbase=/sbin/fsck. 188fsck=$fsckbase$rwfst 189fsckopts=-a 190optfile=/run/initramfs/init-options 191optbase=/run/initramfs/init-options-base 192urlfile=/run/initramfs/init-download-url 193update=/run/initramfs/update 194 195if test -e /${optfile##*/} 196then 197 cp /${optfile##*/} $optfile 198fi 199 200if test -e /${optbase##*/} 201then 202 cp /${optbase##*/} $optbase 203else 204 touch $optbase 205fi 206 207if test ! -f $optfile 208then 209 cat /proc/cmdline $optbase > $optfile 210 get_fw_env_var openbmcinit >> $optfile 211 get_fw_env_var openbmconce >> $optfile 212fi 213 214echo rofs = $rofs $rofst rwfs = $rwfs $rwfst 215 216if grep -w debug-init-sh $optfile 217then 218 if grep -w enable-initrd-debug-sh "$optfile" 219 then 220 debug_takeover "Debug initial shell requested by command line." 221 else 222 echo "Need to also add enable-initrd-debug-sh for debug shell." 223 fi 224fi 225 226if test "x$consider_download_files" = xy && 227 grep -w openbmc-init-download-files $optfile 228then 229 if test -f ${urlfile##*/} 230 then 231 cp ${urlfile##*/} $urlfile 232 fi 233 if test ! -f $urlfile 234 then 235 get_fw_env_var openbmcinitdownloadurl > $urlfile 236 fi 237 url="$(cat $urlfile)" 238 rest="${url#*://}" 239 proto="${url%$rest}" 240 241 if test -z "$url" 242 then 243 echo "Download url empty. Ignoring download request." 244 elif test -z "$proto" 245 then 246 echo "Download failed." 247 elif test "$proto" = tftp:// 248 then 249 if test "x$consider_download_tftp" = xy 250 then 251 try_tftp "$url" 252 else 253 echo "Download failed." 254 fi 255 elif test "$proto" = http:// 256 then 257 if test "x$consider_download_http" = xy 258 then 259 try_wget "$url" 260 else 261 echo "Download failed." 262 fi 263 elif test "$proto" = ftp:// 264 then 265 if test "x$consider_download_ftp" = xy 266 then 267 try_wget "$url" 268 else 269 echo "Download failed." 270 fi 271 else 272 echo "Download failed." 273 fi 274fi 275 276# If there are images in root move them to /run/initramfs/ or /run/ now. 277imagebasename=${image##*/} 278if test -n "${imagebasename}" && ls /${imagebasename}* > /dev/null 2>&1 279then 280 if test "x$flash_images_before_init" = xy 281 then 282 echo "Flash images found, will update before starting init." 283 mv /${imagebasename}* ${image%$imagebasename} 284 else 285 echo "Flash images found, will use but deferring flash update." 286 mv /${imagebasename}* /run/ 287 fi 288fi 289 290if grep -w clean-rwfs-filesystem $optfile 291then 292 echo "Cleaning of read-write overlay filesystem requested." 293 touch $trigger 294fi 295 296if grep -w factory-reset $optfile 297then 298 echo "Factory reset requested." 299 touch $trigger 300 do_save=--no-save-files 301else 302 do_save=--save-files 303fi 304 305if test "x$force_rwfst_jffs2" = xy -a $rwfst != jffs2 -a ! -f $trigger 306then 307 echo "Converting read-write overlay filesystem to jffs2 forced." 308 touch $trigger 309fi 310 311if ls $image* > /dev/null 2>&1 312then 313 if ! test -x $update 314 then 315 debug_takeover "Flash update requested but $update missing!" 316 elif test -f $trigger -a ! -s $trigger 317 then 318 if [ $do_save = "--save-files" ] 319 then 320 echo "Saving selected files from read-write overlay filesystem." 321 else 322 echo "No files will be selected for save." 323 fi 324 $update --no-restore-files $do_save 325 echo "Clearing read-write overlay filesystem." 326 flash_eraseall /dev/$rwfs 327 echo "Restoring saved files to read-write overlay filesystem." 328 touch $trigger 329 $update --no-save-files --clean-saved-files 330 else 331 $update --clean-saved-files $do_save 332 fi 333 334 rwfst=$(probe_fs_type $rwdev) 335 fsck=$fsckbase$rwfst 336fi 337 338if grep -w overlay-filesystem-in-ram $optfile 339then 340 rwfst=none 341fi 342 343copyfiles= 344if grep -w copy-files-to-ram $optfile 345then 346 rwfst=none 347 copyfiles=y 348fi 349 350# It would be nice to do this after fsck but that mean rofs is mounted 351# which triggers the mtd is mounted check 352if test "$rwfst$copyfiles" = noney 353then 354 touch $trigger 355 $update --copy-files --clean-saved-files --no-restore-files 356fi 357 358if grep -w copy-base-filesystem-to-ram $optfile && 359 test ! -e /run/image-rofs && ! cp $rodev /run/image-rofs 360then 361 # Remove any partial copy to avoid attempted usage later 362 if test -e /run/image-rofs 363 then 364 ls -l /run/image-rofs 365 rm -f /run/image-rofs 366 fi 367 debug_takeover "Copying $rodev to /run/image-rofs failed." 368fi 369 370if test -s /run/image-rofs 371then 372 rodev=/run/image-rofs 373 roopts=$roopts,loop 374fi 375 376mount $rodev $rodir -t $rofst -o $roopts 377 378if test -x $rodir$fsck 379then 380 for fs in $fslist 381 do 382 mount --bind $fs $rodir/$fs 383 done 384 chroot $rodir $fsck $fsckopts $rwdev 385 rc=$? 386 for fs in $fslist 387 do 388 umount $rodir/$fs 389 done 390 if test $rc -gt 1 391 then 392 debug_takeover "fsck of read-write fs on $rwdev failed (rc=$rc)" 393 fi 394elif test "$rwfst" != jffs2 -a "$rwfst" != none 395then 396 echo "No '$fsck' in read only fs, skipping fsck." 397fi 398 399if test "$rwfst" = none 400then 401 echo "Running with read-write overlay in RAM for this boot." 402 echo "No state will be preserved unless flash update performed." 403elif ! mount $rwdev $rwdir -t $rwfst -o $rwopts 404then 405 msg="$(cat)" << HERE 406 407Mounting read-write $rwdev filesystem failed. Please fix and run 408 mount $rwdev $rwdir -t $rwfst -o $rwopts 409or perform a factory reset with the clean-rwfs-filesystem option. 410HERE 411 debug_takeover "$msg" 412fi 413 414rm -rf $work 415mkdir -p $upper $work 416 417mount -t overlay -o lowerdir=$rodir,upperdir=$upper,workdir=$work cow /root 418 419while ! chroot /root /bin/sh -c "test -x '$init' -a -s '$init'" 420do 421 msg="$(cat)" << HERE 422 423Unable to confirm /sbin/init is an executable non-empty file 424in merged file system mounted at /root. 425 426Change Root test failed! 427HERE 428 debug_takeover "$msg" 429done 430 431for f in $fslist 432do 433 mount --move $f root/$f 434done 435 436# switch_root /root $init 437exec chroot /root $init 438 439