| #!/bin/sh |
| |
| kgetopt () |
| { |
| _cmdline="$(cat /proc/cmdline)" |
| _optname="$1" |
| _optval="$2" |
| for _opt in $_cmdline |
| do |
| case "$_opt" in |
| "${_optname}"=*) |
| _optval="${_opt##"${_optname}"=}" |
| ;; |
| *) |
| ;; |
| esac |
| done |
| [ -n "$_optval" ] && echo "$_optval" |
| } |
| |
| fslist="proc sys dev run" |
| rodir=/mnt/rofs |
| mmcdev="/dev/mmcblk0" |
| rwfsdev="/dev/disk/by-partlabel/rwfs" |
| |
| cd / |
| |
| # We want to make all the directories in $fslist, not one directory named by |
| # concatonating the names with spaces |
| # |
| # shellcheck disable=SC2086 |
| mkdir -p $fslist |
| |
| mount dev dev -tdevtmpfs |
| mount sys sys -tsysfs |
| mount proc proc -tproc |
| mount tmpfs run -t tmpfs -o mode=755,nodev |
| |
| # Wait up to 5s for the mmc device to appear. Continue even if the count is |
| # exceeded. A failure will be caught later like in the mount command. |
| count=0 |
| while [ $count -lt 5 ]; do |
| if [ -e "${mmcdev}" ]; then |
| break |
| fi |
| sleep 1 |
| count=$((count + 1)) |
| done |
| |
| # Move the secondary GPT to the end of the device if needed. Look for the GPT |
| # header signature "EFI PART" located 512 bytes from the end of the device. |
| if ! tail -c 512 "${mmcdev}" | hexdump -C -n 8 | grep -q "EFI PART"; then |
| sgdisk -e "${mmcdev}" |
| partprobe |
| fi |
| |
| # There eMMC GPT labels for the rootfs are rofs-a and rofs-b, and the label for |
| # the read-write partition is rwfs. Run udev to make the partition labels show |
| # up. Mounting by label allows for partition numbers to change if needed. |
| udevd --daemon |
| udevadm trigger --type=devices --action=add |
| udevadm settle --timeout=10 |
| |
| mkdir -p $rodir |
| if ! mount /dev/disk/by-partlabel/"$(kgetopt root=PARTLABEL)" $rodir -t ext4 -o ro; then |
| /bin/sh |
| fi |
| |
| # Determine if a factory reset has been requested |
| mkdir -p /var/lock |
| resetval=$(fw_printenv -n rwreset 2>/dev/null) |
| if gpiopresent=$(gpiofind factory-reset-toggle) ; then |
| # gpiopresent contains both the gpiochip and line number as |
| # separate words, and gpioget needs to see them as such. |
| # shellcheck disable=SC2086 |
| gpioval=$(gpioget $gpiopresent) |
| else |
| gpioval="" |
| fi |
| # Prevent unnecessary resets on first boot |
| if [ -n "$gpioval" ] && [ -z "$resetval" ]; then |
| fw_setenv rwreset "$gpioval" |
| resetval=$gpioval |
| fi |
| if [ "$resetval" = "true" ] || [ -n "$gpioval" ] && [ "$resetval" != "$gpioval" ]; then |
| echo "Factory reset requested." |
| if ! mkfs.ext4 -F "${rwfsdev}"; then |
| echo "Reformat for factory reset failed." |
| /bin/sh |
| else |
| # gpioval will be an empty string if factory-reset-toggle was not found |
| fw_setenv rwreset "$gpioval" |
| echo "rwfs has been formatted." |
| fi |
| fi |
| |
| fsck.ext4 -p "${rwfsdev}" |
| if ! mount "${rwfsdev}" $rodir/var -t ext4 -o rw; then |
| /bin/sh |
| fi |
| |
| rm -rf $rodir/var/persist/etc-work/ |
| mkdir -p $rodir/var/persist/etc $rodir/var/persist/etc-work $rodir/var/persist/home/root |
| mount overlay $rodir/etc -t overlay -o lowerdir=$rodir/etc,upperdir=$rodir/var/persist/etc,workdir=$rodir/var/persist/etc-work |
| |
| init="$(kgetopt init /sbin/init)" |
| |
| for f in $fslist; do |
| mount --move "$f" "$rodir/$f" |
| done |
| |
| exec switch_root $rodir "$init" |