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