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