blob: b61f9c23f6e362e3f40526efc28e57af5ff20390 [file] [log] [blame]
charkearee5dd4a2023-05-17 15:53:43 -05001#!/bin/sh
Jorge Cisneros8a445a02020-09-03 21:09:03 +00002
3fslist="proc sys dev run"
4rodir=run/initramfs/ro
5rwdir=run/initramfs/rw
6upper=$rwdir/cow
7work=$rwdir/work
8
9cd /
charkearee5dd4a2023-05-17 15:53:43 -050010for f in $fslist
11do
12 mkdir -p "$f"
13done
Jorge Cisneros8a445a02020-09-03 21:09:03 +000014mount 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##*/}
Patrick Williams8b86a412023-04-14 14:29:45 -050033 echo "$m"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000034}
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".
Patrick Williams8b86a412023-04-14 14:29:45 -050042 blkid "$1" | sed -e 's/^.*TYPE="//' -e 's/".*$//'
Jorge Cisneros8a445a02020-09-03 21:09:03 +000043}
44
45probe_fs_type() {
Patrick Williams8b86a412023-04-14 14:29:45 -050046 fst=$(blkid_fs_type "$1")
47 echo "${fst:=jffs2}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000048}
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)
Patrick Williams8b86a412023-04-14 14:29:45 -050071 if test -n "$envdev"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000072 then
Patrick Williams8b86a412023-04-14 14:29:45 -050073 tr '\n\000' '\r\n' < "/dev/$envdev" |
Jorge Cisneros8a445a02020-09-03 21:09:03 +000074 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#*/}
Patrick Williams8b86a412023-04-14 14:29:45 -0500103 host=${rest%"$path"}
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000104 host="${host%/}"
Patrick Williams8b86a412023-04-14 14:29:45 -0500105 port="${host#"${host%:*}"}"
106 host="${host%"$port"}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000107 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
charkearee5dd4a2023-05-17 15:53:43 -0500131getch() {
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
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000138debug_takeover() {
139 echo "$@"
charkearee5dd4a2023-05-17 15:53:43 -0500140 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" ] ;
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000143 then
144 mkdir -p /var/lock
145 envdev=$(findmtd u-boot-env)
charkearee5dd4a2023-05-17 15:53:43 -0500146 echo "/dev/${envdev} 0x00000 0x10000" > /etc/fw_env.config
147 echo "/dev/${envdev} 0x10000 0x10000" >> /etc/fw_env.config
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000148 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
Patrick Williams8b86a412023-04-14 14:29:45 -0500172 export PS1=init#\
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000173 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
Patrick Williams8b86a412023-04-14 14:29:45 -0500182 value1=$((( dip & 0xFF00 ) >> 8 ))
183 value2=$((( dip & 0x0040 ) >> 6 ))
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000184
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
Patrick Williams8b86a412023-04-14 14:29:45 -0500208rwfst=$(probe_fs_type "$rwdev")
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000209roopts=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
Patrick Williams8b86a412023-04-14 14:29:45 -0500243echo "rofs = $rofs $rofst rwfs = $rwfs $rwfst"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000244
245if grep -w debug-init-sh $optfile
246then
247 debug_takeover "Debug initial shell requested by command line."
248fi
249
Patrick Williams8b86a412023-04-14 14:29:45 -0500250if test "$consider_download_files" = "y" &&
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000251 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#*://}"
Patrick Williams8b86a412023-04-14 14:29:45 -0500263 proto="${url%"$rest"}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000264
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
Patrick Williams8b86a412023-04-14 14:29:45 -0500273 if test "$consider_download_tftp" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000274 then
275 try_tftp "$url"
276 else
277 echo "Download failed."
278 fi
279 elif test "$proto" = http://
280 then
Patrick Williams8b86a412023-04-14 14:29:45 -0500281 if test "$consider_download_http" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000282 then
283 try_wget "$url"
284 else
285 echo "Download failed."
286 fi
287 elif test "$proto" = ftp://
288 then
Patrick Williams8b86a412023-04-14 14:29:45 -0500289 if test "$consider_download_ftp" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000290 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##*/}
Patrick Williams8b86a412023-04-14 14:29:45 -0500302if test -n "${imagebasename}" && ls /"${imagebasename}"* > /dev/null 2>&1
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000303then
Patrick Williams8b86a412023-04-14 14:29:45 -0500304 if test "$flash_images_before_init" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000305 then
306 echo "Flash images found, will update before starting init."
Patrick Williams8b86a412023-04-14 14:29:45 -0500307 mv /"${imagebasename}"* ${image%"$imagebasename"}
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000308 else
309 echo "Flash images found, will use but deferring flash update."
Patrick Williams8b86a412023-04-14 14:29:45 -0500310 mv /"${imagebasename}"* /run/
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000311 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
Patrick Williams8b86a412023-04-14 14:29:45 -0500329if test "$force_rwfst_jffs2" = "y" -a "$rwfst" != jffs2 -a ! -f $trigger
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000330then
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."
Patrick Williams8b86a412023-04-14 14:29:45 -0500350 flash_eraseall "/dev/$rwfs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000351 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
Patrick Williams8b86a412023-04-14 14:29:45 -0500358 rwfst=$(probe_fs_type "$rwdev")
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000359 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 &&
Patrick Williams8b86a412023-04-14 14:29:45 -0500383 test ! -e /run/image-rofs && ! cp "$rodev" /run/image-rofs
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000384then
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
Patrick Williams8b86a412023-04-14 14:29:45 -0500400mount "$rodev" $rodir -t $rofst -o $roopts
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000401
Patrick Williams8b86a412023-04-14 14:29:45 -0500402if test -x "$rodir$fsck"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000403then
404 for fs in $fslist
405 do
Patrick Williams8b86a412023-04-14 14:29:45 -0500406 mount --bind "$fs" "$rodir/$fs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000407 done
Patrick Williams8b86a412023-04-14 14:29:45 -0500408 chroot $rodir "$fsck" $fsckopts "$rwdev"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000409 rc=$?
410 for fs in $fslist
411 do
Patrick Williams8b86a412023-04-14 14:29:45 -0500412 umount "$rodir/$fs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000413 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."
Patrick Williams8b86a412023-04-14 14:29:45 -0500427elif ! mount "$rwdev" $rwdir -t "$rwfst" -o $rwopts
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000428then
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
Patrick Williams8b86a412023-04-14 14:29:45 -0500457 mount --move "$f" "root/$f"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000458done
459
460# switch_root /root $init
461exec chroot /root $init
462