blob: 53905fc82c7aa6bbcd3702ee44d24af21dcde162 [file] [log] [blame]
Patrick Williams8b86a412023-04-14 14:29:45 -05001#!/bin/bash
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 /
Patrick Williams8b86a412023-04-14 14:29:45 -050010mkdir -p "$fslist"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000011mount 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##*/}
Patrick Williams8b86a412023-04-14 14:29:45 -050030 echo "$m"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000031}
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".
Patrick Williams8b86a412023-04-14 14:29:45 -050039 blkid "$1" | sed -e 's/^.*TYPE="//' -e 's/".*$//'
Jorge Cisneros8a445a02020-09-03 21:09:03 +000040}
41
42probe_fs_type() {
Patrick Williams8b86a412023-04-14 14:29:45 -050043 fst=$(blkid_fs_type "$1")
44 echo "${fst:=jffs2}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000045}
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)
Patrick Williams8b86a412023-04-14 14:29:45 -050068 if test -n "$envdev"
Jorge Cisneros8a445a02020-09-03 21:09:03 +000069 then
Patrick Williams8b86a412023-04-14 14:29:45 -050070 tr '\n\000' '\r\n' < "/dev/$envdev" |
Jorge Cisneros8a445a02020-09-03 21:09:03 +000071 tail -c +5 | tail -c +${copies-1} |
72 sed -ne '/^$/,$d' -e "s/^$1=//p"
73 fi
74}
75
76setup_resolv() {
77 runresolv=/run/systemd/resolve/resolv.conf
78 etcresolv=/etc/resolv.conf
79
80 if test ! -e $etcresolv -a ! -L $etcresolv
81 then
82 mkdir -p ${runresolv%/*}
83 ln -s $runresolv $etcresolv
84 fi
85 if test ! -f $runresolv
86 then
87 cat /proc/net/pnp > $runresolv
88 fi
89
90 return 0
91}
92
93try_tftp() {
94 # split into tftp:// host:port/ path/on/remote
95 # then spilt off / and then :port from the end of host:port/
96 # and : from the beginning of port
97
98 rest="${1#tftp://}"
99 path=${rest#*/}
Patrick Williams8b86a412023-04-14 14:29:45 -0500100 host=${rest%"$path"}
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000101 host="${host%/}"
Patrick Williams8b86a412023-04-14 14:29:45 -0500102 port="${host#"${host%:*}"}"
103 host="${host%"$port"}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000104 port="${port#:}"
105
106 setup_resolv
107
108 if test -z "$host" -o -z "$path"
109 then
110 debug_takeover "Invalid tftp download url '$url'."
111 elif echo "Downloading '$url' from $host ..." &&
112 ! tftp -g -r "$path" -l /run/image-rofs "$host" ${port+"$port"}
113 then
114 debug_takeover "Download of '$url' failed."
115 fi
116}
117
118try_wget() {
119 setup_resolv
120
121 echo "Downloading '$1' ..."
122 if ! wget -O /run/image-rofs "$1"
123 then
124 debug_takeover "Download of '$url' failed."
125 fi
126}
127
128debug_takeover() {
129 echo "$@"
130 read -t 5 -n 1 -s -r -p "Press any key to log in and try to manually fix, force recovery in 5 seconds"
131 if test $? -gt 0
132 then
133 mkdir -p /var/lock
134 envdev=$(findmtd u-boot-env)
135 echo -e "/dev/${envdev}\t0x00000\t0x10000" > /etc/fw_env.config
136 echo -e "/dev/${envdev}\t0x10000\t0x10000" >> /etc/fw_env.config
137 fw_setenv force_recovery 1
138 fw_setenv last_booterrmsg "$@"
139 devmem 0xc0000000 32 0x01
140 fi
141 cat << HERE
142After fixing run exit to continue this script, or reboot -f to retry, or
143touch /takeover and exit to become PID 1 allowing editing of this script.
144HERE
145
146 while ! sulogin && ! test -f /takeover
147 do
148 echo getty failed, retrying
149 done
150
151 # Touch /takeover in the above getty to become pid 1
152 if test -e /takeover
153 then
154 cat << HERE
155
156Takeover of init requested. Executing /bin/sh as PID 1.
157When finished exec new init or cleanup and run reboot -f.
158
159Warning: No job control! Shell exit will panic the system!
160HERE
Patrick Williams8b86a412023-04-14 14:29:45 -0500161 export PS1=init#\
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000162 exec /bin/sh
163 fi
164}
165
166# Check System Maintenace Switch 7 and load factory default
167check_dip() {
168 devmem 0x800000b8 16 0xFF
169 dip=$(devmem 0x800000b8 16)
170
Patrick Williams8b86a412023-04-14 14:29:45 -0500171 value1=$((( dip & 0xFF00 ) >> 8 ))
172 value2=$((( dip & 0x0040 ) >> 6 ))
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000173
174 if [ $value1 -eq 0 ] && [ $value2 -eq 1 ]
175 then
176 echo "Detect System Maintenace Switch 7 on. Will load factory default"
177 return 0
178 fi
179 return 1
180}
181
182rofs=$(findmtd rofs)
183rwfs=$(findmtd rwfs)
184
185rodev=/dev/mtdblock${rofs#mtd}
186rwdev=/dev/mtdblock${rwfs#mtd}
187
188# Set to y for yes, anything else for no.
189force_rwfst_jffs2=y
190flash_images_before_init=n
191consider_download_files=y
192consider_download_tftp=y
193consider_download_http=y
194consider_download_ftp=y
195
196rofst=squashfs
Patrick Williams8b86a412023-04-14 14:29:45 -0500197rwfst=$(probe_fs_type "$rwdev")
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000198roopts=ro
199rwopts=rw
200
201image=/run/initramfs/image-
202trigger=${image}rwfs
203
204init=/sbin/init
205fsckbase=/sbin/fsck.
206fsck=$fsckbase$rwfst
207fsckopts=-a
208optfile=/run/initramfs/init-options
209optbase=/run/initramfs/init-options-base
210urlfile=/run/initramfs/init-download-url
211update=/run/initramfs/update
212
213if test -e /${optfile##*/}
214then
215 cp /${optfile##*/} $optfile
216fi
217
218if test -e /${optbase##*/}
219then
220 cp /${optbase##*/} $optbase
221else
222 touch $optbase
223fi
224
225if test ! -f $optfile
226then
227 cat /proc/cmdline $optbase > $optfile
228 get_fw_env_var openbmcinit >> $optfile
229 get_fw_env_var openbmconce >> $optfile
230fi
231
Patrick Williams8b86a412023-04-14 14:29:45 -0500232echo "rofs = $rofs $rofst rwfs = $rwfs $rwfst"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000233
234if grep -w debug-init-sh $optfile
235then
236 debug_takeover "Debug initial shell requested by command line."
237fi
238
Patrick Williams8b86a412023-04-14 14:29:45 -0500239if test "$consider_download_files" = "y" &&
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000240 grep -w openbmc-init-download-files $optfile
241then
242 if test -f ${urlfile##*/}
243 then
244 cp ${urlfile##*/} $urlfile
245 fi
246 if test ! -f $urlfile
247 then
248 get_fw_env_var openbmcinitdownloadurl > $urlfile
249 fi
250 url="$(cat $urlfile)"
251 rest="${url#*://}"
Patrick Williams8b86a412023-04-14 14:29:45 -0500252 proto="${url%"$rest"}"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000253
254 if test -z "$url"
255 then
256 echo "Download url empty. Ignoring download request."
257 elif test -z "$proto"
258 then
259 echo "Download failed."
260 elif test "$proto" = tftp://
261 then
Patrick Williams8b86a412023-04-14 14:29:45 -0500262 if test "$consider_download_tftp" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000263 then
264 try_tftp "$url"
265 else
266 echo "Download failed."
267 fi
268 elif test "$proto" = http://
269 then
Patrick Williams8b86a412023-04-14 14:29:45 -0500270 if test "$consider_download_http" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000271 then
272 try_wget "$url"
273 else
274 echo "Download failed."
275 fi
276 elif test "$proto" = ftp://
277 then
Patrick Williams8b86a412023-04-14 14:29:45 -0500278 if test "$consider_download_ftp" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000279 then
280 try_wget "$url"
281 else
282 echo "Download failed."
283 fi
284 else
285 echo "Download failed."
286 fi
287fi
288
289# If there are images in root move them to /run/initramfs/ or /run/ now.
290imagebasename=${image##*/}
Patrick Williams8b86a412023-04-14 14:29:45 -0500291if test -n "${imagebasename}" && ls /"${imagebasename}"* > /dev/null 2>&1
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000292then
Patrick Williams8b86a412023-04-14 14:29:45 -0500293 if test "$flash_images_before_init" = "y"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000294 then
295 echo "Flash images found, will update before starting init."
Patrick Williams8b86a412023-04-14 14:29:45 -0500296 mv /"${imagebasename}"* ${image%"$imagebasename"}
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000297 else
298 echo "Flash images found, will use but deferring flash update."
Patrick Williams8b86a412023-04-14 14:29:45 -0500299 mv /"${imagebasename}"* /run/
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000300 fi
301fi
302
303if grep -w clean-rwfs-filesystem $optfile
304then
305 echo "Cleaning of read-write overlay filesystem requested."
306 touch $trigger
307fi
308
309if grep -w factory-reset $optfile || check_dip
310then
311 echo "Factory reset requested."
312 touch $trigger
313 do_save=--no-save-files
314else
315 do_save=--save-files
316fi
317
Patrick Williams8b86a412023-04-14 14:29:45 -0500318if test "$force_rwfst_jffs2" = "y" -a "$rwfst" != jffs2 -a ! -f $trigger
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000319then
320 echo "Converting read-write overlay filesystem to jffs2 forced."
321 touch $trigger
322fi
323
324if ls $image* > /dev/null 2>&1
325then
326 if ! test -x $update
327 then
328 debug_takeover "Flash update requested but $update missing!"
329 elif test -f $trigger -a ! -s $trigger
330 then
331 if [ $do_save = "--save-files" ]
332 then
333 echo "Saving selected files from read-write overlay filesystem."
334 else
335 echo "No files will be selected for save."
336 fi
337 $update --no-restore-files $do_save
338 echo "Clearing read-write overlay filesystem."
Patrick Williams8b86a412023-04-14 14:29:45 -0500339 flash_eraseall "/dev/$rwfs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000340 echo "Restoring saved files to read-write overlay filesystem."
341 touch $trigger
342 $update --no-save-files --clean-saved-files
343 else
344 $update --clean-saved-files $do_save
345 fi
346
Patrick Williams8b86a412023-04-14 14:29:45 -0500347 rwfst=$(probe_fs_type "$rwdev")
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000348 fsck=$fsckbase$rwfst
349fi
350
351if grep -w overlay-filesystem-in-ram $optfile
352then
353 rwfst=none
354fi
355
356copyfiles=
357if grep -w copy-files-to-ram $optfile
358then
359 rwfst=none
360 copyfiles=y
361fi
362
363# It would be nice to do this after fsck but that mean rofs is mounted
364# which triggers the mtd is mounted check
365if test "$rwfst$copyfiles" = noney
366then
367 touch $trigger
368 $update --copy-files --clean-saved-files --no-restore-files
369fi
370
371if grep -w copy-base-filesystem-to-ram $optfile &&
Patrick Williams8b86a412023-04-14 14:29:45 -0500372 test ! -e /run/image-rofs && ! cp "$rodev" /run/image-rofs
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000373then
374 # Remove any partial copy to avoid attempted usage later
375 if test -e /run/image-rofs
376 then
377 ls -l /run/image-rofs
378 rm -f /run/image-rofs
379 fi
380 debug_takeover "Copying $rodev to /run/image-rofs failed."
381fi
382
383if test -s /run/image-rofs
384then
385 rodev=/run/image-rofs
386 roopts=$roopts,loop
387fi
388
Patrick Williams8b86a412023-04-14 14:29:45 -0500389mount "$rodev" $rodir -t $rofst -o $roopts
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000390
Patrick Williams8b86a412023-04-14 14:29:45 -0500391if test -x "$rodir$fsck"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000392then
393 for fs in $fslist
394 do
Patrick Williams8b86a412023-04-14 14:29:45 -0500395 mount --bind "$fs" "$rodir/$fs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000396 done
Patrick Williams8b86a412023-04-14 14:29:45 -0500397 chroot $rodir "$fsck" $fsckopts "$rwdev"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000398 rc=$?
399 for fs in $fslist
400 do
Patrick Williams8b86a412023-04-14 14:29:45 -0500401 umount "$rodir/$fs"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000402 done
403 if test $rc -gt 1
404 then
405 debug_takeover "fsck of read-write fs on $rwdev failed (rc=$rc)"
406 fi
407elif test "$rwfst" != jffs2 -a "$rwfst" != none
408then
409 echo "No '$fsck' in read only fs, skipping fsck."
410fi
411
412if test "$rwfst" = none
413then
414 echo "Running with read-write overlay in RAM for this boot."
415 echo "No state will be preserved unless flash update performed."
Patrick Williams8b86a412023-04-14 14:29:45 -0500416elif ! mount "$rwdev" $rwdir -t "$rwfst" -o $rwopts
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000417then
418 msg="$(cat)" << HERE
419
420Mounting read-write $rwdev filesystem failed. Please fix and run
421 mount $rwdev $rwdir -t $rwfst -o $rwopts
422to to continue, or do change nothing to run from RAM for this boot.
423HERE
424 debug_takeover "$msg"
425fi
426
427rm -rf $work
428mkdir -p $upper $work
429
430mount -t overlay -o lowerdir=$rodir,upperdir=$upper,workdir=$work cow /root
431
432while ! chroot /root /bin/sh -c "test -x '$init' -a -s '$init'"
433do
434 msg="$(cat)" << HERE
435
436Unable to confirm /sbin/init is an executable non-empty file
437in merged file system mounted at /root.
438
439Change Root test failed! Invoking emergency shell.
440HERE
441 debug_takeover "$msg"
442done
443
444for f in $fslist
445do
Patrick Williams8b86a412023-04-14 14:29:45 -0500446 mount --move "$f" "root/$f"
Jorge Cisneros8a445a02020-09-03 21:09:03 +0000447done
448
449# switch_root /root $init
450exec chroot /root $init
451