blob: e2a9ebcb62762588581397dcc35e97d4c5658f72 [file] [log] [blame]
Jorge Cisneros8a445a02020-09-03 21:09:03 +00001#!/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 read -t 5 -n 1 -s -r -p "Press any key to log in and try to manually fix, force recovery in 5 seconds"
132 if test $? -gt 0
133 then
134 mkdir -p /var/lock
135 envdev=$(findmtd u-boot-env)
136 echo -e "/dev/${envdev}\t0x00000\t0x10000" > /etc/fw_env.config
137 echo -e "/dev/${envdev}\t0x10000\t0x10000" >> /etc/fw_env.config
138 fw_setenv force_recovery 1
139 fw_setenv last_booterrmsg "$@"
140 devmem 0xc0000000 32 0x01
141 fi
142 cat << HERE
143After fixing run exit to continue this script, or reboot -f to retry, or
144touch /takeover and exit to become PID 1 allowing editing of this script.
145HERE
146
147 while ! sulogin && ! test -f /takeover
148 do
149 echo getty failed, retrying
150 done
151
152 # Touch /takeover in the above getty to become pid 1
153 if test -e /takeover
154 then
155 cat << HERE
156
157Takeover of init requested. Executing /bin/sh as PID 1.
158When finished exec new init or cleanup and run reboot -f.
159
160Warning: No job control! Shell exit will panic the system!
161HERE
162 export PS1=init#\
163 exec /bin/sh
164 fi
165}
166
167# Check System Maintenace Switch 7 and load factory default
168check_dip() {
169 devmem 0x800000b8 16 0xFF
170 dip=$(devmem 0x800000b8 16)
171
172 value1=$((( $dip & 0xFF00 ) >> 8 ))
173 value2=$((( $dip & 0x0040 ) >> 6 ))
174
175 if [ $value1 -eq 0 ] && [ $value2 -eq 1 ]
176 then
177 echo "Detect System Maintenace Switch 7 on. Will load factory default"
178 return 0
179 fi
180 return 1
181}
182
183rofs=$(findmtd rofs)
184rwfs=$(findmtd rwfs)
185
186rodev=/dev/mtdblock${rofs#mtd}
187rwdev=/dev/mtdblock${rwfs#mtd}
188
189# Set to y for yes, anything else for no.
190force_rwfst_jffs2=y
191flash_images_before_init=n
192consider_download_files=y
193consider_download_tftp=y
194consider_download_http=y
195consider_download_ftp=y
196
197rofst=squashfs
198rwfst=$(probe_fs_type $rwdev)
199roopts=ro
200rwopts=rw
201
202image=/run/initramfs/image-
203trigger=${image}rwfs
204
205init=/sbin/init
206fsckbase=/sbin/fsck.
207fsck=$fsckbase$rwfst
208fsckopts=-a
209optfile=/run/initramfs/init-options
210optbase=/run/initramfs/init-options-base
211urlfile=/run/initramfs/init-download-url
212update=/run/initramfs/update
213
214if test -e /${optfile##*/}
215then
216 cp /${optfile##*/} $optfile
217fi
218
219if test -e /${optbase##*/}
220then
221 cp /${optbase##*/} $optbase
222else
223 touch $optbase
224fi
225
226if test ! -f $optfile
227then
228 cat /proc/cmdline $optbase > $optfile
229 get_fw_env_var openbmcinit >> $optfile
230 get_fw_env_var openbmconce >> $optfile
231fi
232
233echo rofs = $rofs $rofst rwfs = $rwfs $rwfst
234
235if grep -w debug-init-sh $optfile
236then
237 debug_takeover "Debug initial shell requested by command line."
238fi
239
240if test "x$consider_download_files" = xy &&
241 grep -w openbmc-init-download-files $optfile
242then
243 if test -f ${urlfile##*/}
244 then
245 cp ${urlfile##*/} $urlfile
246 fi
247 if test ! -f $urlfile
248 then
249 get_fw_env_var openbmcinitdownloadurl > $urlfile
250 fi
251 url="$(cat $urlfile)"
252 rest="${url#*://}"
253 proto="${url%$rest}"
254
255 if test -z "$url"
256 then
257 echo "Download url empty. Ignoring download request."
258 elif test -z "$proto"
259 then
260 echo "Download failed."
261 elif test "$proto" = tftp://
262 then
263 if test "x$consider_download_tftp" = xy
264 then
265 try_tftp "$url"
266 else
267 echo "Download failed."
268 fi
269 elif test "$proto" = http://
270 then
271 if test "x$consider_download_http" = xy
272 then
273 try_wget "$url"
274 else
275 echo "Download failed."
276 fi
277 elif test "$proto" = ftp://
278 then
279 if test "x$consider_download_ftp" = xy
280 then
281 try_wget "$url"
282 else
283 echo "Download failed."
284 fi
285 else
286 echo "Download failed."
287 fi
288fi
289
290# If there are images in root move them to /run/initramfs/ or /run/ now.
291imagebasename=${image##*/}
292if test -n "${imagebasename}" && ls /${imagebasename}* > /dev/null 2>&1
293then
294 if test "x$flash_images_before_init" = xy
295 then
296 echo "Flash images found, will update before starting init."
297 mv /${imagebasename}* ${image%$imagebasename}
298 else
299 echo "Flash images found, will use but deferring flash update."
300 mv /${imagebasename}* /run/
301 fi
302fi
303
304if grep -w clean-rwfs-filesystem $optfile
305then
306 echo "Cleaning of read-write overlay filesystem requested."
307 touch $trigger
308fi
309
310if grep -w factory-reset $optfile || check_dip
311then
312 echo "Factory reset requested."
313 touch $trigger
314 do_save=--no-save-files
315else
316 do_save=--save-files
317fi
318
319if test "x$force_rwfst_jffs2" = xy -a $rwfst != jffs2 -a ! -f $trigger
320then
321 echo "Converting read-write overlay filesystem to jffs2 forced."
322 touch $trigger
323fi
324
325if ls $image* > /dev/null 2>&1
326then
327 if ! test -x $update
328 then
329 debug_takeover "Flash update requested but $update missing!"
330 elif test -f $trigger -a ! -s $trigger
331 then
332 if [ $do_save = "--save-files" ]
333 then
334 echo "Saving selected files from read-write overlay filesystem."
335 else
336 echo "No files will be selected for save."
337 fi
338 $update --no-restore-files $do_save
339 echo "Clearing read-write overlay filesystem."
340 flash_eraseall /dev/$rwfs
341 echo "Restoring saved files to read-write overlay filesystem."
342 touch $trigger
343 $update --no-save-files --clean-saved-files
344 else
345 $update --clean-saved-files $do_save
346 fi
347
348 rwfst=$(probe_fs_type $rwdev)
349 fsck=$fsckbase$rwfst
350fi
351
352if grep -w overlay-filesystem-in-ram $optfile
353then
354 rwfst=none
355fi
356
357copyfiles=
358if grep -w copy-files-to-ram $optfile
359then
360 rwfst=none
361 copyfiles=y
362fi
363
364# It would be nice to do this after fsck but that mean rofs is mounted
365# which triggers the mtd is mounted check
366if test "$rwfst$copyfiles" = noney
367then
368 touch $trigger
369 $update --copy-files --clean-saved-files --no-restore-files
370fi
371
372if grep -w copy-base-filesystem-to-ram $optfile &&
373 test ! -e /run/image-rofs && ! cp $rodev /run/image-rofs
374then
375 # Remove any partial copy to avoid attempted usage later
376 if test -e /run/image-rofs
377 then
378 ls -l /run/image-rofs
379 rm -f /run/image-rofs
380 fi
381 debug_takeover "Copying $rodev to /run/image-rofs failed."
382fi
383
384if test -s /run/image-rofs
385then
386 rodev=/run/image-rofs
387 roopts=$roopts,loop
388fi
389
390mount $rodev $rodir -t $rofst -o $roopts
391
392if test -x $rodir$fsck
393then
394 for fs in $fslist
395 do
396 mount --bind $fs $rodir/$fs
397 done
398 chroot $rodir $fsck $fsckopts $rwdev
399 rc=$?
400 for fs in $fslist
401 do
402 umount $rodir/$fs
403 done
404 if test $rc -gt 1
405 then
406 debug_takeover "fsck of read-write fs on $rwdev failed (rc=$rc)"
407 fi
408elif test "$rwfst" != jffs2 -a "$rwfst" != none
409then
410 echo "No '$fsck' in read only fs, skipping fsck."
411fi
412
413if test "$rwfst" = none
414then
415 echo "Running with read-write overlay in RAM for this boot."
416 echo "No state will be preserved unless flash update performed."
417elif ! mount $rwdev $rwdir -t $rwfst -o $rwopts
418then
419 msg="$(cat)" << HERE
420
421Mounting read-write $rwdev filesystem failed. Please fix and run
422 mount $rwdev $rwdir -t $rwfst -o $rwopts
423to to continue, or do change nothing to run from RAM for this boot.
424HERE
425 debug_takeover "$msg"
426fi
427
428rm -rf $work
429mkdir -p $upper $work
430
431mount -t overlay -o lowerdir=$rodir,upperdir=$upper,workdir=$work cow /root
432
433while ! chroot /root /bin/sh -c "test -x '$init' -a -s '$init'"
434do
435 msg="$(cat)" << HERE
436
437Unable to confirm /sbin/init is an executable non-empty file
438in merged file system mounted at /root.
439
440Change Root test failed! Invoking emergency shell.
441HERE
442 debug_takeover "$msg"
443done
444
445for f in $fslist
446do
447 mount --move $f root/$f
448done
449
450# switch_root /root $init
451exec chroot /root $init
452