b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame^] | 1 | PART_NAME=firmware |
| 2 | |
| 3 | LXL_FLAGS_VENDOR_LUXUL=0x00000001 |
| 4 | |
| 5 | # $(1): file to read magic from |
| 6 | # $(2): offset in bytes |
| 7 | get_magic_long_at() { |
| 8 | dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' |
| 9 | } |
| 10 | |
| 11 | # $(1): file to read LE long number from |
| 12 | # $(2): offset in bytes |
| 13 | get_le_long_at() { |
| 14 | echo $((0x$(dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/4 "%02x"'))) |
| 15 | } |
| 16 | |
| 17 | platform_expected_image() { |
| 18 | local model="$(cat /tmp/sysinfo/model)" |
| 19 | |
| 20 | case "$model" in |
| 21 | "Netgear R6200 V1") echo "chk U12H192T00_NETGEAR"; return;; |
| 22 | "Netgear WGR614 V8") echo "chk U12H072T00_NETGEAR"; return;; |
| 23 | "Netgear WGR614 V9") echo "chk U12H094T00_NETGEAR"; return;; |
| 24 | "Netgear WGR614 V10") echo "chk U12H139T01_NETGEAR"; return;; |
| 25 | "Netgear WN2500RP V1") echo "chk U12H197T00_NETGEAR"; return;; |
| 26 | "Netgear WN2500RP V2") echo "chk U12H294T00_NETGEAR"; return;; |
| 27 | "Netgear WNDR3300") echo "chk U12H093T00_NETGEAR"; return;; |
| 28 | "Netgear WNDR3400 V1") echo "chk U12H155T00_NETGEAR"; return;; |
| 29 | "Netgear WNDR3400 V2") echo "chk U12H187T00_NETGEAR"; return;; |
| 30 | "Netgear WNDR3400 V3") echo "chk U12H208T00_NETGEAR"; return;; |
| 31 | "Netgear WNDR3400 Vcna") echo "chk U12H155T01_NETGEAR"; return;; |
| 32 | "Netgear WNDR3700 V3") echo "chk U12H194T00_NETGEAR"; return;; |
| 33 | "Netgear WNDR4000") echo "chk U12H181T00_NETGEAR"; return;; |
| 34 | "Netgear WNDR4500 V1") echo "chk U12H189T00_NETGEAR"; return;; |
| 35 | "Netgear WNDR4500 V2") echo "chk U12H224T00_NETGEAR"; return;; |
| 36 | "Netgear WNR2000 V2") echo "chk U12H114T00_NETGEAR"; return;; |
| 37 | "Netgear WNR3500L") echo "chk U12H136T99_NETGEAR"; return;; |
| 38 | "Netgear WNR3500U") echo "chk U12H136T00_NETGEAR"; return;; |
| 39 | "Netgear WNR3500 V2") echo "chk U12H127T00_NETGEAR"; return;; |
| 40 | "Netgear WNR3500 V2vc") echo "chk U12H127T70_NETGEAR"; return;; |
| 41 | "Netgear WNR834B V2") echo "chk U12H081T00_NETGEAR"; return;; |
| 42 | "Linksys E900 V1") echo "cybertan E900"; return;; |
| 43 | "Linksys E1000 V1") echo "cybertan E100"; return;; |
| 44 | "Linksys E1000 V2") echo "cybertan E100"; return;; |
| 45 | "Linksys E1000 V2.1") echo "cybertan E100"; return;; |
| 46 | "Linksys E1200 V2") echo "cybertan E122"; return;; |
| 47 | "Linksys E2000 V1") echo "cybertan 32XN"; return;; |
| 48 | "Linksys E3000 V1") echo "cybertan 61XN"; return;; |
| 49 | "Linksys E3200 V1") echo "cybertan 3200"; return;; |
| 50 | "Linksys E4200 V1") echo "cybertan 4200"; return;; |
| 51 | "Linksys WRT150N V1.1") echo "cybertan N150"; return;; |
| 52 | "Linksys WRT150N V1") echo "cybertan N150"; return;; |
| 53 | "Linksys WRT160N V1") echo "cybertan N150"; return;; |
| 54 | "Linksys WRT160N V3") echo "cybertan N150"; return;; |
| 55 | "Linksys WRT300N V1") echo "cybertan EWCB"; return;; |
| 56 | "Linksys WRT300N V1.1") echo "cybertan EWC2"; return;; |
| 57 | "Linksys WRT310N V1") echo "cybertan 310N"; return;; |
| 58 | "Linksys WRT310N V2") echo "cybertan 310N"; return;; |
| 59 | "Linksys WRT610N V1") echo "cybertan 610N"; return;; |
| 60 | "Linksys WRT610N V2") echo "cybertan 610N"; return;; |
| 61 | "Luxul XAP-310 V1") echo "lxl XAP-310"; return;; |
| 62 | "Luxul XAP-1210 V1") echo "lxl XAP-1210"; return;; |
| 63 | "Luxul XAP-1230 V1") echo "lxl XAP-1230"; return;; |
| 64 | "Luxul XAP-1240 V1") echo "lxl XAP-1240"; return;; |
| 65 | "Luxul XAP-1500 V1") echo "lxl XAP-1500"; return;; |
| 66 | "Luxul ABR-4400 V1") echo "lxl ABR-4400"; return;; |
| 67 | "Luxul XBR-4400 V1") echo "lxl XBR-4400"; return;; |
| 68 | "Luxul XVW-P30 V1") echo "lxl XVW-P30"; return;; |
| 69 | "Luxul XWR-600 V1") echo "lxl XWR-600"; return;; |
| 70 | "Luxul XWR-1750 V1") echo "lxl XWR-1750"; return;; |
| 71 | esac |
| 72 | } |
| 73 | |
| 74 | bcm47xx_identify() { |
| 75 | local magic |
| 76 | |
| 77 | magic=$(get_magic_long "$1") |
| 78 | case "$magic" in |
| 79 | "48445230") |
| 80 | echo "trx" |
| 81 | return |
| 82 | ;; |
| 83 | "2a23245e") |
| 84 | echo "chk" |
| 85 | return |
| 86 | ;; |
| 87 | "4c584c23") |
| 88 | echo "lxl" |
| 89 | return |
| 90 | ;; |
| 91 | esac |
| 92 | |
| 93 | magic=$(get_magic_long_at "$1" 14) |
| 94 | [ "$magic" = "55324e44" ] && { |
| 95 | echo "cybertan" |
| 96 | return |
| 97 | } |
| 98 | |
| 99 | magic=$(get_magic_long_at "$1" 60) |
| 100 | [ "$magic" = "4c584c23" ] && { |
| 101 | echo "lxlold" |
| 102 | return |
| 103 | } |
| 104 | |
| 105 | echo "unknown" |
| 106 | } |
| 107 | |
| 108 | platform_check_image() { |
| 109 | [ "$#" -gt 1 ] && return 1 |
| 110 | |
| 111 | local file_type=$(bcm47xx_identify "$1") |
| 112 | local magic |
| 113 | local error=0 |
| 114 | |
| 115 | case "$file_type" in |
| 116 | "chk") |
| 117 | local header_len=$((0x$(get_magic_long_at "$1" 4))) |
| 118 | local board_id_len=$(($header_len - 40)) |
| 119 | local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"') |
| 120 | local dev_board_id=$(platform_expected_image) |
| 121 | echo "Found CHK image with device board_id $board_id" |
| 122 | |
| 123 | [ -n "$dev_board_id" -a "chk $board_id" != "$dev_board_id" ] && { |
| 124 | echo "Firmware board_id doesn't match device board_id ($dev_board_id)" |
| 125 | error=1 |
| 126 | } |
| 127 | |
| 128 | if ! otrx check "$1" -o "$header_len"; then |
| 129 | echo "No valid TRX firmware in the CHK image" |
| 130 | notify_firmware_test_result "trx_valid" 0 |
| 131 | error=1 |
| 132 | else |
| 133 | notify_firmware_test_result "trx_valid" 1 |
| 134 | fi |
| 135 | ;; |
| 136 | "cybertan") |
| 137 | local pattern=$(dd if="$1" bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%c"') |
| 138 | local dev_pattern=$(platform_expected_image) |
| 139 | echo "Found CyberTAN image with device pattern: $pattern" |
| 140 | |
| 141 | [ -n "$dev_pattern" -a "cybertan $pattern" != "$dev_pattern" ] && { |
| 142 | echo "Firmware pattern doesn't match device pattern ($dev_pattern)" |
| 143 | error=1 |
| 144 | } |
| 145 | |
| 146 | if ! otrx check "$1" -o 32; then |
| 147 | echo "No valid TRX firmware in the CyberTAN image" |
| 148 | notify_firmware_test_result "trx_valid" 0 |
| 149 | error=1 |
| 150 | else |
| 151 | notify_firmware_test_result "trx_valid" 1 |
| 152 | fi |
| 153 | ;; |
| 154 | "lxl") |
| 155 | local hdr_len=$(get_le_long_at "$1" 8) |
| 156 | local flags=$(get_le_long_at "$1" 12) |
| 157 | local board=$(dd if="$1" skip=16 bs=1 count=16 2>/dev/null | hexdump -v -e '1/1 "%c"') |
| 158 | local dev_board=$(platform_expected_image) |
| 159 | echo "Found Luxul image for board $board" |
| 160 | |
| 161 | [ -n "$dev_board" -a "lxl $board" != "$dev_board" ] && { |
| 162 | echo "Firmware ($board) doesn't match device ($dev_board)" |
| 163 | error=1 |
| 164 | } |
| 165 | |
| 166 | [ $((flags & LXL_FLAGS_VENDOR_LUXUL)) -gt 0 ] && notify_firmware_no_backup |
| 167 | |
| 168 | if ! otrx check "$1" -o "$hdr_len"; then |
| 169 | echo "No valid TRX firmware in the Luxul image" |
| 170 | notify_firmware_test_result "trx_valid" 0 |
| 171 | error=1 |
| 172 | else |
| 173 | notify_firmware_test_result "trx_valid" 1 |
| 174 | fi |
| 175 | ;; |
| 176 | "lxlold") |
| 177 | local board_id=$(dd if="$1" skip=48 bs=1 count=12 2>/dev/null | hexdump -v -e '1/1 "%c"') |
| 178 | local dev_board_id=$(platform_expected_image) |
| 179 | echo "Found Luxul image with device board_id $board_id" |
| 180 | |
| 181 | [ -n "$dev_board_id" -a "lxl $board_id" != "$dev_board_id" ] && { |
| 182 | echo "Firmware board_id doesn't match device board_id ($dev_board_id)" |
| 183 | error=1 |
| 184 | } |
| 185 | |
| 186 | notify_firmware_no_backup |
| 187 | |
| 188 | if ! otrx check "$1" -o 64; then |
| 189 | echo "No valid TRX firmware in the Luxul image" |
| 190 | notify_firmware_test_result "trx_valid" 0 |
| 191 | error=1 |
| 192 | else |
| 193 | notify_firmware_test_result "trx_valid" 1 |
| 194 | fi |
| 195 | ;; |
| 196 | "trx") |
| 197 | if ! otrx check "$1"; then |
| 198 | echo "Invalid (corrupted?) TRX firmware" |
| 199 | notify_firmware_test_result "trx_valid" 0 |
| 200 | error=1 |
| 201 | else |
| 202 | notify_firmware_test_result "trx_valid" 1 |
| 203 | fi |
| 204 | ;; |
| 205 | *) |
| 206 | echo "Invalid image type. Please use firmware specific for this device." |
| 207 | notify_firmware_broken |
| 208 | error=1 |
| 209 | ;; |
| 210 | esac |
| 211 | |
| 212 | return $error |
| 213 | } |
| 214 | |
| 215 | platform_trx_from_chk_cmd() { |
| 216 | local header_len=$((0x$(get_magic_long_at "$1" 4))) |
| 217 | |
| 218 | echo -n dd bs=$header_len skip=1 |
| 219 | } |
| 220 | |
| 221 | platform_trx_from_cybertan_cmd() { |
| 222 | echo -n dd bs=32 skip=1 |
| 223 | } |
| 224 | |
| 225 | platform_trx_from_lxl_cmd() { |
| 226 | local hdr_len=$(get_le_long_at "$1" 8) |
| 227 | |
| 228 | echo -n dd skip=$hdr_len iflag=skip_bytes |
| 229 | } |
| 230 | |
| 231 | platform_trx_from_lxlold_cmd() { |
| 232 | echo -n dd bs=64 skip=1 |
| 233 | } |
| 234 | |
| 235 | platform_do_upgrade() { |
| 236 | local file_type=$(bcm47xx_identify "$1") |
| 237 | local trx="$1" |
| 238 | local cmd="" |
| 239 | |
| 240 | case "$file_type" in |
| 241 | "chk") cmd=$(platform_trx_from_chk_cmd "$trx");; |
| 242 | "cybertan") cmd=$(platform_trx_from_cybertan_cmd "$trx");; |
| 243 | "lxl") cmd=$(platform_trx_from_lxl_cmd "$trx");; |
| 244 | "lxlold") cmd=$(platform_trx_from_lxlold_cmd "$trx");; |
| 245 | esac |
| 246 | |
| 247 | default_do_upgrade "$trx" "$cmd" |
| 248 | } |