Skip to content

Commit

Permalink
Updated recovery scripts for recovery 19.07.8
Browse files Browse the repository at this point in the history
The recovery scripts have been rewritten for the new recovery 19.07.8.
Besides the capability to mount/unmount the main firmware image, it is now
possible to reset the main to defaults.
To facilitate the unlocking of the MTD partitions a new script was also
included as the interface to the mtd-rw kernel module.

Signed-off-by: Bruno Pena <[email protected]>
  • Loading branch information
brunompena committed Sep 15, 2021
1 parent cad2f23 commit e58a309
Show file tree
Hide file tree
Showing 7 changed files with 210 additions and 195 deletions.
79 changes: 79 additions & 0 deletions mount-firmware
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/sh

# check if firmware is already mounted
if egrep -qs "^overlayfs:/firmware " /proc/mounts; then
echo "firmware is already mounted">&2
exit 1
fi

# find firmware mtd partition
firmware=$(grep '"firmware"' /proc/mtd | cut -d: -f1)
firmware_size=$(cat /sys/class/mtd/${firmware}/size)
firmware_blocksize=$(cat /sys/class/mtd/${firmware}/erasesize)

# setup filesystem markers (rootfs: squashfs, rootfs_data: jffs2)
rootfs_marker="6873"
rootfsdata_marker="(deadc0de|1985)"

# search for the rootfs filesystem offset within the firmware mtd partition
rootfs_offset=0
while [ ${rootfs_offset} -lt ${firmware_size} ]; do
# dump four bytes at offset (as hexadecimal string) and check if matches the marker pattern
if hexdump -e '"%x"' -n 4 -s ${rootfs_offset} /dev/${firmware} | egrep -qs "^${rootfs_marker}"; then
# marker found, break loop
break
fi
# continue searching, move to the next mtd block
rootfs_offset=$((rootfs_offset + firmware_blocksize))
done

# search for the rootfs_data filesystem offset within the firmware mtd partition
rootfsdata_offset=$((rootfs_offset + firmware_blocksize))
while [ ${rootfsdata_offset} -lt ${firmware_size} ]; do
# dump four bytes at offset (as hexadecimal string) and check if matches the marker pattern
if hexdump -e '"%x"' -n 4 -s ${rootfsdata_offset} /dev/${firmware} | egrep -qs "^${rootfsdata_marker}"; then
# marker found, break loop
break
fi
# continue searching, move to the next mtd block
rootfsdata_offset=$((rootfsdata_offset + firmware_blocksize))
done

# calculate filesystem sizes
rootfs_size=$((rootfsdata_offset - rootfs_offset))
rootfsdata_size=$((firmware_size - rootfsdata_offset))

# create loop device for each filesystem (virtual "partition" delimited by offset and size)
rootfs_loop=$(losetup --offset ${rootfs_offset} --sizelimit ${rootfs_size} -f --show /dev/mtdblock${firmware:3})
rootfsdata_loop=$(losetup --offset ${rootfsdata_offset} --sizelimit ${rootfsdata_size} -f --show /dev/mtdblock${firmware:3})

# create virtual mtd for the loop devices
modprobe -q block2mtd
echo "${rootfs_loop},${firmware_blocksize}" > /sys/module/block2mtd/parameters/block2mtd
echo "${rootfsdata_loop},${firmware_blocksize}" > /sys/module/block2mtd/parameters/block2mtd

# search for the newly created mtd names
rootfs=$(grep '"'${rootfs_loop}'"' /proc/mtd | cut -d: -f1)
rootfsdata=$(grep '"'${rootfsdata_loop}'"' /proc/mtd | cut -d: -f1)

# create mountpoint if needed
[ ! -d /firmware ] && mkdir /firmware

# mount filesystems (rootfs and rootfs_data)
mount -t squashfs /dev/mtdblock${rootfs:3} /firmware
mount -t jffs2 -o noatime /dev/mtdblock${rootfsdata:3} /firmware/overlay

# initialize rootfs_data
[ ! -d /firmware/overlay/upper ] && mkdir /firmware/overlay/upper
[ ! -d /firmware/overlay/work ] && mkdir /firmware/overlay/work
[ ! -h /firmware/overlay/.fs_state ] && ln -s 2 /firmware/overlay/.fs_state

# create rootfs_data overlay at /mnt
mount -t overlay -o noatime,lowerdir=/firmware,upperdir=/firmware/overlay/upper,workdir=/firmware/overlay/work overlayfs:/firmware /mnt

# combine all mountpoints on /mnt
mount --move /firmware/overlay /mnt/overlay
mount --move /firmware /mnt/rom

# finally, move the result to /firmware
mount --move /mnt /firmware
118 changes: 0 additions & 118 deletions mount_firmware

This file was deleted.

25 changes: 25 additions & 0 deletions mtd-rw
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/bin/sh

case "$1" in
lock) # lock all mtd partitions
"$0" unlocked && rmmod mtd-rw
;;

unlock) # unlock all mtd partitions
"$0" locked && insmod "$(find /lib/modules/ -name mtd-rw.ko)" i_want_a_brick=1
;;

locked) # check if mtd partitions are locked
! "$0" unlocked
;;

unlocked) # check if mtd partitions are unlocked
lsmod | egrep -qs "^mtd_rw "
;;

*) # usage help message
echo "Usage: $(basename $0) <lock|unlock|locked|unlocked>"
;;
esac

exit $?
37 changes: 37 additions & 0 deletions recovery-config
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/bin/sh

# check if script arguments are valid
if [ "$1" != "save" -a "$1" != "reset" ]; then
# display usage message in case of insufficient or invalid arguments
echo "Usage: $(basename $0) <save|reset>"
exit 1
fi

# check mtd state and unlock if needed
if mtd-rw locked; then
mtd-rw unlock
relock=1
fi

# check whether to save or reset the current configuration
if [ "$1" == "save" ]; then
# create archive of the current configuration
tar czf /tmp/config.tar.gz -C /volatile/upper $(ls /volatile/upper/)
else
# create an empty configuration archive
dd if=/dev/zero bs=10240 count=1 2>/dev/null | gzip > /tmp/config.tar.gz
fi

# store the configuration archive to mtd
snapshot_tool config_write &>/dev/null
if [ "$?" != "0" ]; then
echo "operation failed"
fi

# clean up configuration archive
rm -f /tmp/config.tar.gz

# lock mtd if it was unlocked by this script
if [ "${relock}" == "1" ]; then
mtd-rw lock
fi
42 changes: 42 additions & 0 deletions reset-firmware
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/sh

# display warn message, wait for user confirmation before continuing
echo -n "erase all settings and remove any installed packages? [N/y] ">&2 && read
[ "${REPLY}" != "y" ] && exit 1

# check firmware mount state to then delete data accordingly
if egrep -qs "^overlayfs:/firmware " /proc/mounts; then
# inform user about firmware mount state and action taken to reset rootfs_data
echo "firmware is mounted, only erasing files">&2

# erase all files (including "dot" and "dot-dot" files)
rm -rf /firmware/overlay/upper/*
rm -rf /firmware/overlay/upper/.[^.]*
rm -rf /firmware/overlay/upper/..?*
else
# inform user about firmware mount state and action taken to reset rootfs_data
echo "firmware not mounted, marking it to be erased on next mount">&2

# find firmware mtd partition
firmware=$(grep '"firmware"' /proc/mtd | cut -d: -f1)
firmware_size=$(cat /sys/class/mtd/${firmware}/size)
firmware_blocksize=$(cat /sys/class/mtd/${firmware}/erasesize)

# initialize rootfs_data search variables
rootfsdata_marker="(deadc0de|1985)"
rootfsdata_offset=0

# search for rootfs_data inside firmware mtd partition
while [ ${rootfsdata_offset} -lt ${firmware_size} ]; do
# dump four bytes at offset (as hexadecimal string) and check if matches the marker pattern
if hexdump -e '"%x"' -n 4 -s ${rootfsdata_offset} /dev/${firmware} | egrep -qs "^${rootfsdata_marker}"; then
# marker found, break loop
break
fi
# continue searching, move to the next mtd block
rootfsdata_offset=$((rootfsdata_offset + firmware_blocksize))
done

# write jffs2 marker (0xdeadc0de) to force initialization of rootfs_data on the next mount
echo -ne "\xde\xad\xc0\xde" | dd of=/dev/mtdblock${firmware:3} bs=${firmware_blocksize} seek=$((rootfsdata_offset / firmware_blocksize)) count=1 conv=sync &>/dev/null
fi
27 changes: 27 additions & 0 deletions umount-firmware
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh

# check if firmware is mounted
if ! egrep -qs "^overlayfs:/firmware " /proc/mounts; then
echo "firmware is not mounted">&2
exit 1
fi

# search /proc/mounts for firmware's virtual mtd devices
rootfs=$(grep " /firmware/rom " /proc/mounts | cut -d" " -f1 | cut -d/ -f3 | sed 's/block//')
rootfsdata=$(grep " /firmware/overlay " /proc/mounts | cut -d" " -f1 | cut -d/ -f3 | sed 's/block//')

# map the virtual mtd devices to the corresponding loop devices
rootfs_loop=$(egrep "^${rootfs}:" /proc/mtd | cut -d\" -f2)
rootfsdata_loop=$(egrep "^${rootfsdata}:" /proc/mtd | cut -d\" -f2)

# umount all mountpoints
umount /firmware/overlay
umount /firmware/rom
umount /firmware

# remove virtual mtd devices (only possible by unloading the block2mtd kernel module)
rmmod block2mtd

# remove the corresponding loop devices
losetup -d ${rootfs_loop}
losetup -d ${rootfsdata_loop}
Loading

0 comments on commit e58a309

Please sign in to comment.