| 1 | # The U-Boot loader of the some Allnet devices requires image sizes and |
| 2 | # checksums to be provided in the U-Boot environment. |
| 3 | # In case the check fails during boot, a failsafe-system is started to provide |
| 4 | # a minimal web-interface for flashing a new firmware. |
| 5 | |
| 6 | # make sure we got uboot-envtools and fw_env.config copied over to the ramfs |
| 7 | platform_add_ramfs_ubootenv() { |
| 8 | [ -e /usr/sbin/fw_printenv ] && install_bin /usr/sbin/fw_printenv /usr/sbin/fw_setenv |
| 9 | [ -e /etc/fw_env.config ] && install_file /etc/fw_env.config |
| 10 | } |
| 11 | append sysupgrade_pre_upgrade platform_add_ramfs_ubootenv |
| 12 | |
| 13 | # determine size of the main firmware partition |
| 14 | platform_get_firmware_size() { |
| 15 | local dev size erasesize name |
| 16 | while read dev size erasesize name; do |
| 17 | name=${name#'"'}; name=${name%'"'} |
| 18 | case "$name" in |
| 19 | firmware) |
| 20 | printf "%d" "0x$size" |
| 21 | break |
| 22 | ;; |
| 23 | esac |
| 24 | done < /proc/mtd |
| 25 | } |
| 26 | |
| 27 | # get the first 4 bytes (magic) of a given file starting at offset in hex format |
| 28 | get_magic_long_at() { |
| 29 | dd if="$1" skip=$(( $CI_BLKSZ / 4 * $2 )) bs=4 count=1 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' |
| 30 | } |
| 31 | |
| 32 | get_filesize() { |
| 33 | wc -c "$1" | while read image_size _n ; do echo $image_size ; break; done |
| 34 | } |
| 35 | |
| 36 | # scan through the update image pages until matching a magic |
| 37 | platform_get_offset() { |
| 38 | offsetcount=0 |
| 39 | magiclong="x" |
| 40 | if [ -n "$3" ]; then |
| 41 | offsetcount=$3 |
| 42 | fi |
| 43 | while magiclong=$( get_magic_long_at "$1" "$offsetcount" ) && [ -n "$magiclong" ]; do |
| 44 | case "$magiclong" in |
| 45 | "2705"*) |
| 46 | # U-Boot image magic |
| 47 | if [ "$2" = "uImage" ]; then |
| 48 | echo $offsetcount |
| 49 | return |
| 50 | fi |
| 51 | ;; |
| 52 | "68737173"|"73717368") |
| 53 | # SquashFS |
| 54 | if [ "$2" = "rootfs" ]; then |
| 55 | echo $offsetcount |
| 56 | return |
| 57 | fi |
| 58 | ;; |
| 59 | "deadc0de"|"19852003") |
| 60 | # JFFS2 empty page |
| 61 | if [ "$2" = "rootfs-data" ]; then |
| 62 | echo $offsetcount |
| 63 | return |
| 64 | fi |
| 65 | ;; |
| 66 | esac |
| 67 | offsetcount=$(( $offsetcount + 1 )) |
| 68 | done |
| 69 | } |
| 70 | |
| 71 | platform_check_image_allnet() { |
| 72 | local fw_printenv=/usr/sbin/fw_printenv |
| 73 | [ ! -n "$fw_printenv" -o ! -x "$fw_printenv" ] && { |
| 74 | echo "Please install uboot-envtools!" |
| 75 | return 1 |
| 76 | } |
| 77 | |
| 78 | [ ! -r "/etc/fw_env.config" ] && { |
| 79 | echo "/etc/fw_env.config is missing" |
| 80 | return 1 |
| 81 | } |
| 82 | |
| 83 | local image_size=$( get_filesize "$1" ) |
| 84 | local firmware_size=$( platform_get_firmware_size ) |
| 85 | [ $image_size -ge $firmware_size ] && |
| 86 | { |
| 87 | echo "upgrade image is too big (${image_size}b > ${firmware_size}b)" |
| 88 | } |
| 89 | |
| 90 | local vmlinux_blockoffset=$( platform_get_offset "$1" uImage ) |
| 91 | [ -z $vmlinux_blockoffset ] && { |
| 92 | echo "vmlinux-uImage not found" |
| 93 | return 1 |
| 94 | } |
| 95 | |
| 96 | local rootfs_blockoffset=$( platform_get_offset "$1" rootfs "$vmlinux_blockoffset" ) |
| 97 | [ -z $rootfs_blockoffset ] && { |
| 98 | echo "missing rootfs" |
| 99 | return 1 |
| 100 | } |
| 101 | |
| 102 | local data_blockoffset=$( platform_get_offset "$1" rootfs-data "$rootfs_blockoffset" ) |
| 103 | [ -z $data_blockoffset ] && { |
| 104 | echo "rootfs doesn't have JFFS2 end marker" |
| 105 | return 1 |
| 106 | } |
| 107 | |
| 108 | return 0 |
| 109 | } |
| 110 | |
| 111 | platform_do_upgrade_allnet() { |
| 112 | local firmware_base_addr=$( printf "%d" "$1" ) |
| 113 | local vmlinux_blockoffset=$( platform_get_offset "$2" uImage ) |
| 114 | if [ ! -n "$vmlinux_blockoffset" ]; then |
| 115 | echo "can't determine uImage offset" |
| 116 | return 1 |
| 117 | fi |
| 118 | local rootfs_blockoffset=$( platform_get_offset "$2" rootfs $(( $vmlinux_blockoffset + 1 )) ) |
| 119 | local vmlinux_offset=$(( $vmlinux_blockoffset * $CI_BLKSZ )) |
| 120 | local vmlinux_addr=$(( $firmware_base_addr + $vmlinux_offset )) |
| 121 | local vmlinux_hexaddr=0x$( printf "%08x" "$vmlinux_addr" ) |
| 122 | if [ ! -n "$rootfs_blockoffset" ]; then |
| 123 | echo "can't determine rootfs offset" |
| 124 | return 1 |
| 125 | fi |
| 126 | local rootfs_offset=$(( $rootfs_blockoffset * $CI_BLKSZ )) |
| 127 | local rootfs_addr=$(( $firmware_base_addr + $rootfs_offset )) |
| 128 | local rootfs_hexaddr=0x$( printf "%08x" "$rootfs_addr" ) |
| 129 | local vmlinux_blockcount=$(( $rootfs_blockoffset - $vmlinux_blockoffset )) |
| 130 | local vmlinux_size=$(( $rootfs_offset - $vmlinux_offset )) |
| 131 | local vmlinux_hexsize=0x$( printf "%08x" "$vmlinux_size" ) |
| 132 | local data_blockoffset=$( platform_get_offset "$2" rootfs-data $(( $rootfs_blockoffset + 1 )) ) |
| 133 | if [ ! -n "$data_blockoffset" ]; then |
| 134 | echo "can't determine rootfs size" |
| 135 | return 1 |
| 136 | fi |
| 137 | local data_offset=$(( $data_blockoffset * $CI_BLKSZ )) |
| 138 | local rootfs_blockcount=$(( $data_blockoffset - $rootfs_blockoffset )) |
| 139 | local rootfs_size=$(( $data_offset - $rootfs_offset )) |
| 140 | local rootfs_hexsize=0x$( printf "%08x" "$rootfs_size" ) |
| 141 | |
| 142 | local rootfs_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$rootfs_blockoffset count=$rootfs_blockcount 2>/dev/null | md5sum -); rootfs_md5="${rootfs_md5%% *}" |
| 143 | local vmlinux_md5=$( dd if="$2" bs=$CI_BLKSZ skip=$vmlinux_blockoffset count=$vmlinux_blockcount 2>/dev/null | md5sum -); vmlinux_md5="${vmlinux_md5%% *}" |
| 144 | # this needs a recent version of uboot-envtools! |
| 145 | cat >/tmp/fw_env_upgrade <<EOF |
| 146 | vmlinux_start_addr $vmlinux_hexaddr |
| 147 | vmlinux_size $vmlinux_hexsize |
| 148 | vmlinux_checksum $vmlinux_md5 |
| 149 | rootfs_start_addr $rootfs_hexaddr |
| 150 | rootfs_size $rootfs_hexsize |
| 151 | rootfs_checksum $rootfs_md5 |
| 152 | bootcmd bootm $vmlinux_hexaddr |
| 153 | EOF |
| 154 | fw_setenv -s /tmp/fw_env_upgrade || { |
| 155 | echo "failed to update U-Boot environment" |
| 156 | return 1 |
| 157 | } |
| 158 | shift |
| 159 | default_do_upgrade "$@" |
| 160 | } |
| 161 | |