2017-07-29 01:44:22 +10:00

376 lines
9.7 KiB
Bash
Executable File

#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
ROOT_MOUNT="/rootfs/"
# Copied from initramfs-framework. The core of this script probably should be
# turned into initramfs-framework modules to reduce duplication.
udev_daemon() {
OPTIONS="/sbin/udev/udevd /sbin/udevd /lib/udev/udevd /lib/systemd/systemd-udevd"
for o in $OPTIONS; do
if [ -x "$o" ]; then
echo $o
return 0
fi
done
return 1
}
_UDEV_DAEMON=`udev_daemon`
early_setup() {
mkdir -p /proc
mkdir -p /sys
mount -t proc proc /proc
mount -t sysfs sysfs /sys
mount -t devtmpfs none /dev
# mknod -m 600 /dev/initctl p
# support modular kernel
modprobe isofs 2> /dev/null
mkdir -p /run
mkdir -p /var/run
#$_UDEV_DAEMON --daemon
#udevadm trigger --action=add
}
read_args() {
[ -z "$CMDLINE" ] && CMDLINE=`cat /proc/cmdline`
for arg in $CMDLINE; do
optarg=`expr "x$arg" : 'x[^=]*=\(.*\)'`
case $arg in
root=*)
ROOT_DEVICE=$optarg ;;
factoryreset=*)
FORCE_FACTORY_RESET=$optarg;;
esac
done
}
boot_live_root() {
# Watches the udev event queue, and exits if all current events are handled
#udevadm settle --timeout=3 --quiet
#killall "${_UDEV_DAEMON##*/}" 2>/dev/null
mount -n --move /proc ${ROOT_MOUNT}/proc
mount -n --move /sys ${ROOT_MOUNT}/sys
mount -n --move /dev ${ROOT_MOUNT}/dev
echo "Switching root"
cd $ROOT_MOUNT
exec switch_root -c /dev/console $ROOT_MOUNT /sbin/init
}
fatal() {
echo $1 >$CONSOLE
echo >$CONSOLE
exec sh
}
create_partitions()
{
echo "Creating partitions"
parted -s -- /dev/mmcblk0 unit MB mkpart primary fat32 100 200
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 200 300
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 300 -1
echo "Formatting LATEST"
mkfs.vfat /dev/mmcblk0p2 -n LATEST
echo "Formatting RWFS"
mkfs.ext3 /dev/mmcblk0p3 -L RWFS -q
echo "Formatting LOG"
mkfs.ext3 /dev/mmcblk0p4 -L LOG -q
}
remove_partitions()
{
parted -s -- /dev/mmcblk0 rm 2
parted -s -- /dev/mmcblk0 rm 3
parted -s -- /dev/mmcblk0 rm 4
}
setScreenUpdating() {
#Set up the Artoo serial port, send a slip-encoded message
#indicating that we've started the update.
stty -F /dev/ttymxc1 115200 cs8 -cstopb -parity -crtscts
echo -en "\xC0\x12\x00\xC0" > /dev/ttymxc1
}
setLedUpdating() {
#Blink the LED crazy fast
echo timer >> /sys/class/leds/user2/trigger
echo 50 >> /sys/class/leds/user2/delay_on
echo 50 >> /sys/class/leds/user2/delay_off
}
setLedDone() {
echo none >> /sys/class/leds/user2/trigger
}
checkRwfs() {
fsck.ext3 -y /dev/mmcblk0p3
if [ $? -ge 4 ]; then
echo "Error detected on RWFS partition"
setLedUpdating
umount /dev/mmcblk0p3
mkfs.ext3 /dev/mmcblk0p3 -L RWFS -q
setLedDone
fi
}
checkLog() {
fsck.ext3 -y /dev/mmcblk0p4
if [ $? -ge 4 ]; then
echo "Error detected on LOG partition, repartitioning"
setLedUpdating
umount /dev/mmcblk0p4
parted -s -- /dev/mmcblk0 rm 4
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 300 -1
mkfs.ext3 /dev/mmcblk0p4 -L LOG -q
setLedDone
# this should not trigger an "update done" screen
mkdir -f /mnt/log/updates
mount /dev/mmcblk0p4 /mnt/log
mkdir /mnt/log/updates
touch /mnt/log/updates/READY
umount /mnt/log
fi
}
mount_and_boot() {
mkdir $ROOT_MOUNT
mknod /dev/loop0 b 7 0 2>/dev/null
mkdir -p /mnt/ro_rootfs
mkdir -p /mnt/rw_rootfs
mkdir -p /mnt/boot
#Check the boot partitions
fsck.vfat -y /dev/mmcblk0p1
if [ $? -ge 4 ]; then
echo "Error detected on GOLDEN partition"
fi
fsck.vfat -y /dev/mmcblk0p2
if [ $? -ge 4 ]; then
echo "Error detected on LATEST partition"
fi
#Mount the boot partition
echo "Using $ROOT_DEVICE as the boot partition"
mount -o ro $ROOT_DEVICE /mnt/boot
#Mount the read-only squashfs partition
mount -o ro /mnt/boot/*.squashfs /mnt/ro_rootfs
#Check the rw partition
checkRwfs
#mount the read-write partition
mount /dev/mmcblk0p3 /mnt/rw_rootfs
#Mount the aufs union partition
mount -t aufs -o br=/mnt/rw_rootfs:/mnt/ro_rootfs none $ROOT_MOUNT
#Move all those mount points
mkdir -p $ROOT_MOUNT/mnt/rootfs.ro $ROOT_MOUNT/mnt/rootfs.rw $ROOT_MOUNT/mnt/boot
mount --move /mnt/boot $ROOT_MOUNT/mnt/boot
mount --move /mnt/ro_rootfs $ROOT_MOUNT/mnt/rootfs.ro
mount --move /mnt/rw_rootfs $ROOT_MOUNT/mnt/rootfs.rw
# boot the image
boot_live_root
}
factory_reset() {
setScreenUpdating
setLedUpdating
#delete partions 2-4,
#Recreate new partitions
remove_partitions
create_partitions
#Reflash u-boot if its file exists
mkdir -p /mnt/golden
mount /dev/mmcblk0p1 /mnt/golden
if [ -e /mnt/golden/u-boot.imx ]; then
dd if=/mnt/golden/u-boot.imx of=/dev/mmcblk0 bs=512 seek=2
fi
setLedDone
umount /mnt/golden
sync
/sbin/shutdown -r -n now
}
echo "******************** INITRD ********************"
early_setup
read_args
[ -z "$CONSOLE" ] && CONSOLE="/dev/console"
#if there is no LATEST partition, assume that we need to create
#the RWFS and LOG partitions as well
if [ ! -e /dev/mmcblk0p2 ]; then
echo "No LATEST partition, creating partition scheme"
#Set the LED to let the user know its formatting
setScreenUpdating
setLedUpdating
create_partitions
setLedDone
else
#If there was a factory reset request from u-boot, handle it here
echo "Factory reset: " $FORCE_FACTORY_RESET
if [ $FORCE_FACTORY_RESET == 1 ]; then
echo "Factory reset from GPIO request"
factory_reset
fi
checkLog
echo "Checking for an update..."
#See if there is an update file we should be using
mkdir /mnt/log
mount /dev/mmcblk0p4 /mnt/log
if [ -e /mnt/log/updates/UPDATE ]; then
echo "Update requested checking for update file"
rm -f /mnt/log/updates/READY
sync
setScreenUpdating
setLedUpdating
for file in $(find /mnt/log/updates/ -type f -name "*.tar.gz" | sort); do
echo "Found file $file".
latestFile=$file
done
#Is there an update file?
if [ -z $latestFile ]; then
echo "No update tarball, restarting"
rm /mnt/log/updates/UPDATE
echo "No update tarball" >> /mnt/log/updates/UPDATEFAILED
setLedDone
sync
/sbin/shutdown -r -n now
fi
#Check the MD5sum of the update tarball
if [ ! -e ${latestFile}.md5 ]; then
echo "No MD5 file for update tarball, removing and restarting"
rm $latestFile
rm /mnt/log/updates/UPDATE
echo "MD5 Missing" >> /mnt/log/updates/UPDATEFAILED
setLedDone
sync
/sbin/shutdown -r -n now
fi
cd /mnt/log/updates
md5res=`md5sum -c ${latestFile}.md5 | awk '{print $2}'`
if [ $md5res == 'OK' ]; then
echo "MD5 OK, proceeding"
else
echo "MD5 failure, removing file and rebooting"
rm $latestFile
rm ${latestFile}.md5
rm /mnt/log/updates/UPDATE
echo "MD5 Failed" >> /mnt/log/updates/UPDATEFAILED
setLedDone
sync
/sbin/shutdown -r -n now
fi
cd ~/
#Mount the LATEST partition and overwrite everything in it
echo "Formatting LATEST"
mkfs.vfat /dev/mmcblk0p2 -n LATEST
echo "Updating LATEST with $latestFile"
mkdir /mnt/latest
mount /dev/mmcblk0p2 /mnt/latest
tar -xf $latestFile -C /mnt/latest/
#if there is a u-boot.imx, flash it to the SD card
if [ -e /mnt/latest/u-boot.imx ]; then
dd if=/mnt/latest/u-boot.imx of=/dev/mmcblk0 bs=512 seek=2
fi
#We're all done here
rm /mnt/log/updates/UPDATE
# Check and see if theres a settings reset also requested
if [ -e /mnt/log/updates/RESETSETTINGS ]; then
echo "Settings reset also requested."
#Unmount active partitions, delete partions 3-4,
#Recreate new partitions 3 and 4
umount /mnt/log /mnt/latest
parted -s -- /dev/mmcblk0 rm 3
parted -s -- /dev/mmcblk0 rm 4
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 200 300
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 300 -1
mkfs.ext3 /dev/mmcblk0p3 -L RWFS -q
mkfs.ext3 /dev/mmcblk0p4 -L LOG -q
fi
echo "Done updating, restarting"
setLedDone
sync
/sbin/shutdown -r -n now
elif [ -e /mnt/log/updates/FACTORYRESET ]; then
echo "Factory reset requested."
umount /mnt/log
factory_reset
elif [ -e /mnt/log/updates/RESETSETTINGS ]; then
echo "Settings reset requested."
#Set the LED to let the user know its formatting
setScreenUpdating
setLedUpdating
#Unmount active partitions, delete partions 3-4,
#Recreate new partitions 3 and 4
umount /mnt/log
parted -s -- /dev/mmcblk0 rm 3
parted -s -- /dev/mmcblk0 rm 4
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 200 300
parted -s -- /dev/mmcblk0 unit MB mkpart primary ext2 300 -1
mkfs.ext3 /dev/mmcblk0p3 -L RWFS -q
mkfs.ext3 /dev/mmcblk0p4 -L LOG -q
setLedDone
sync
/sbin/shutdown -r -n now
else
echo "No update available, booting."
fi
umount /mnt/log
fi
#Boot the squashfs
mount_and_boot