This adds checksum support to sysupgrade as needed for U-Boot on the ALL0258N. Probably this can be useful for other targets as well.
Signed-off-by: Daniel Golle <dgo...@allnet.de> Index: platform.sh =================================================================== --- platform.sh (revision 28191) +++ platform.sh (working copy) @@ -1,11 +1,14 @@ # # Copyright (C) 2009 OpenWrt.org # +# Added U-Boot MD5 checksums and failsafe stuff +# Copyright (C) 2011 Daniel Golle <dgo...@allnet.de> +# . /lib/ar71xx.sh PART_NAME=firmware -RAMFS_COPY_DATA=/lib/ar71xx.sh +RAMFS_COPY_DATA="/lib/ar71xx.sh /etc/fw_env.config" CI_BLKSZ=65536 CI_LDADR=0x80060000 @@ -39,6 +42,19 @@ done } +platform_get_firmware_size() { + local dev size erasesize name + while read dev size erasesize name; do + name=${name#'"'}; name=${name%'"'} + case "$name" in + firmware) + printf "%d" "0x$size" + break + ;; + esac + done < /proc/mtd +} + platform_do_upgrade_combined() { local partitions=$(platform_find_partitions) local kernelpart=$(platform_find_kernelpart "${partitions#*:}") @@ -61,6 +77,156 @@ fi } +platform_get_offset() { + # Scan through the update image pages until matching a magic + offsetcount=0 + magiclong="x" + if [ -n "$3" ]; then + offsetcount=$3 + fi + while magiclong=$( dd if="$1" skip=$(( $CI_BLKSZ / 4 * $offsetcount )) bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' ) && [ -n "$magiclong" ]; do + case "$magiclong" in + "2705"*) + # U-Boot image magic + if [ "$2" = "uImage" ]; then + echo $offsetcount + return + fi + ;; + "68737173"|"73717368") + # SquashFS + if [ "$2" = "rootfs" ]; then + echo $offsetcount + return + fi + ;; + "deadc0de"|"19852003") + # JFFS2 empty page + if [ "$2" = "rootfs-data" ]; then + echo $offsetcount + return + fi + ;; + esac + offsetcount=$(( $offsetcount + 1 )) + done +} + +platform_get_filesize() { + # busybox does not come with stat by default + # anyway, use it if we got it + local stat=$( which stat ) + if [ -n "$stat" -a -x "$stat" ]; then + $stat -c "%s" "$1" + else + ls -l "$1" | while read _p _x _u _g image_size _d _t _n ; do echo $image_size ; break; done + fi +} + +platform_do_upgrade_uboot() { + local firmware_base_addr=$( printf "%d" "$1" ) + local fw_setenv=$( which fw_setenv ) + local fw_printenv=$( which fw_printenv ) + local failsafe_hexaddr="" + shift + + if [ ! -n "$fw_setenv" -o ! -x "$fw_setenv" -o ! -n "$fw_printenv" -o ! -x "$fw_printenv" ]; then + echo "Please install uboot-envtools!" + return 1 + fi + if [ ! -r "/etc/fw_env.config" ]; then + echo "/etc/fw_env.config is missing" + return 1 + fi + local vmlinux_blockoffset=$( platform_get_offset "$1" uImage ) + local rootfs_blockoffset=$( platform_get_offset "$1" rootfs $(( $vmlinux_blockoffset + 1 )) ) + + local vmlinux_blockoffset=$( platform_get_offset "$1" uImage ) + if [ ! -n "$vmlinux_blockoffset" ]; then + echo "can't determine uImage offset" + return 1 + fi + local rootfs_blockoffset=$( platform_get_offset "$1" rootfs $(( $vmlinux_blockoffset + 1 )) ) + local vmlinux_offset=$(( $vmlinux_blockoffset * $CI_BLKSZ )) + local vmlinux_addr=$(( $firmware_base_addr + $vmlinux_offset )) + local vmlinux_hexaddr=0x$( printf "%08x" "$vmlinux_addr" ) + if [ -n "$rootfs_blockoffset" ]; then + local rootfs_offset=$(( $rootfs_blockoffset * $CI_BLKSZ )) + local rootfs_addr=$(( $firmware_base_addr + $rootfs_offset )) + local rootfs_hexaddr=0x$( printf "%08x" "$rootfs_addr" ) + local vmlinux_blockcount=$(( $rootfs_blockoffset - $vmlinux_blockoffset )) + local vmlinux_size=$(( $rootfs_offset - $vmlinux_offset )) + local vmlinux_hexsize=0x$( printf "%08x" "$vmlinux_size" ) + local data_blockoffset=$( platform_get_offset "$1" rootfs-data $(( $rootfs_blockoffset + 1 )) ) + if [ ! -n "$data_blockoffset" ]; then + echo "can't determine rootfs size" + return 1 + fi + local data_offset=$(( $data_blockoffset * $CI_BLKSZ )) + local rootfs_blockcount=$(( $data_blockoffset - $rootfs_blockoffset )) + local rootfs_size=$(( $data_offset - $rootfs_offset )) + local rootfs_hexsize=0x$( printf "%08x" "$rootfs_size" ) + + # scan for a 2nd uImage, if found, update failsafe + local failsafe_hexsize + local failsafe_blockoffset=$( platform_get_offset "$1" uImage $(( $data_blockoffset + 1 )) ) + if [ -n "$failsafe_blockoffset" ]; then + echo "Decteted a factory update package including the failsafe part" + local failsafe_offset=$(( $data_blockoffset * $CI_BLKSZ )) + local failsafe_addr=$(( $firmware_base_addr + $failsafe_offset )) + failsafe_hexaddr=0x$( printf "%08x" "$failsafe_addr" ) + failsafe_size=$(( $( platform_get_filesize "$1" ) - $failsafe_offset )) + failsafe_hexsize=0x$( printf "%08x" "$failsafe_size" ) + # the usual JFFS2-append method to keep the config files can't be used in case of a factory image + # if we really want it, we have to do it differently + SAVE_CONFIG=0 + fi + + echo -n "Partitions in upgrade image: " + for part in vmlinux rootfs failsafe ; do + eval b=\$${part}_blockoffset + eval a=\$${part}_hexaddr + eval s=\$${part}_hexsize + [ -n "$b" ] && echo -n "$part (b#$b@$a,$s) " + done + echo + echo "Updating checksums and sizes in U-Boot environment" + local rootfs_md5=$( dd if="$1" bs=$CI_BLKSZ skip=$rootfs_blockoffset count=$rootfs_blockcount 2>/dev/null | md5sum -); rootfs_md5="${rootfs_md5%% *}" + local vmlinux_md5=$( dd if="$1" bs=$CI_BLKSZ skip=$vmlinux_blockoffset count=$vmlinux_blockcount 2>/dev/null | md5sum -); vmlinux_md5="${vmlinux_md5%% *}" + # this needs a recent version of uboot-envtools! + $fw_setenv -s - <<EOF +vmlinux_start_addr $vmlinux_hexaddr +vmlinux_size $vmlinux_hexsize +vmlinux_checksum $vmlinux_md5 +rootfs_start_addr $rootfs_hexaddr +rootfs_size $rootfs_hexsize +rootfs_checksum $rootfs_md5 +bootcmd bootm $vmlinux_hexaddr +$( [ -n "$failsafe_hexaddr" ] && echo "failsafe_boot bootm $failsafe_hexaddr" ) +EOF + default_do_upgrade "$@" + else + # update failsafe if we get a single uImage without rootfs + echo "updating failsafe partition" + failsafe_offset=$vmlinux_offset + failsafe_blockoffset=$vmlinux_blockoffset + failsafe_hexaddr=$( $fw_printenv failsafe_boot | while read _dontcare failsafe_hexaddr _dontcare2 ; do echo $failsafe_hexaddr ; done ) + if [ -z "$failsafe_hexaddr" ]; then + echo "no failsafe bootcmd defined in current U-Boot environment" + return 1 + fi + failsafe_addr=$( printf "%d" "$failsafe_hexaddr" ) + failsafe_maxsize=$(( $( platform_get_firmware_size ) - ( $failsafe_addr - $firmware_base_addr ) )) + image_size=$(( $( platform_get_filesize "$1" ) - $failsafe_offset )) + if [ "$image_size" -gt "$failsafe_maxsize" ]; then + echo "image to large ($failsafe_maxsize bytes allowed for failsafe)" + return 1 + fi + echo "writing $image_size bytes to failsafe@$failsafe_hexaddr" + dd bs=$CI_BLKSZ if=$1 skip=$failsafe_blockoffset 2>/dev/null | mtd write - failsafe + fi +} + platform_check_image() { local board=$(ar71xx_board_name) local magic="$(get_magic_word "$1")" @@ -69,8 +235,64 @@ [ "$ARGC" -gt 1 ] && return 1 case "$board" in + all0258n ) + # accept both, OpenWrt uImage or factory-dump starting with 'custom' partition + [ "$magic" != "2705" -a "$magic_long" != "19852003" ] && { + echo "Invalid image type." + return 1 + } + case "$magic" in + 2705) + # OpenWrt uImage must have kernel and rootfs + local vmlinux_blockoffset=$( platform_get_offset "$1" uImage ) + [ -z $vmlinux_blockoffset ] && { + echo "vmlinux-uImage not found" + return 1 + } + local rootfs_blockoffset=$( platform_get_offset "$1" rootfs "$vmlinux_blockoffset" ) + [ -z $rootfs_blockoffset ] && { + echo "rootfs not found" + return 1 + } + local data_blockoffset=$( platform_get_offset "$1" rootfs-data "$rootfs_blockoffset" ) + [ -z $data_blockoffset ] && { + echo "rootfs doesn't have JFFS2 end marker" + return 1 + } + ;; + 1985) + # Factory dump got a custom filesystem first + local custom_blockoffset=$( platform_get_offset "$1" rootfs-data ) + [ -z $custom_blockoffset ] && { + echo "custom part not found" + return 1 + } + local vmlinux_blockoffset=$( platform_get_offset "$1" uImage "$custom_blockoffset" ) + [ -z $vmlinux_blockoffset ] && { + echo "vmlinux-uImage not found" + return 1 + } + local rootfs_blockoffset=$( platform_get_offset "$1" rootfs "$vmlinux_blockoffset" ) + [ -z $rootfs_blockoffset ] && { + echo "rootfs not found" + return 1 + } + local data_blockoffset=$( platform_get_offset "$1" rootfs-data "$rootfs_blockoffset" ) + [ -z $data_blockoffset ] && { + echo "rootfs doesn't have JFFS2 end marker" + return 1 + } + local failsafe_blockoffset=$( platform_get_offset "$1" uImage "$data_blockoffset" ) + [ -z $failsafe_blockoffset ] && { + echo "failsafe-uImage not found" + return 1 + } + ;; + esac + return 0 + ;; ap121 | ap121-mini | ap96 | db120 | zcn-1523h-2 | zcn-1523h-5) - [ "$magic" != "68737173" -a "$magic" != "19852003" ] && { + [ "$magic_long" != "68737173" -a "$magic_long" != "19852003" ] && { echo "Invalid image type." return 1 } @@ -141,6 +363,10 @@ routerstation | routerstation-pro | ls-sr71 | eap7660d | ja76pf ) platform_do_upgrade_combined "$ARGV" ;; + all0258n ) + local firmware_phys_addr=0x9f050000 + platform_do_upgrade_uboot $firmware_phys_addr "$ARGV" + ;; *) default_do_upgrade "$ARGV" ;; _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel