aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/brcm47xx/base-files/lib/upgrade/platform.sh
blob: d4017b4980ae4d71aff9214911df7672f9d69819 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
PART_NAME=firmware

# $(1): file to read magic from
# $(2): offset in bytes
get_magic_long_at() {
	dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"'
}

platform_machine() {
	grep "machine" /proc/cpuinfo | sed "s/.*:[ \t]*//"
}

platform_expected_chk_board_id() {
	local machine=$(platform_machine)

	case "$machine" in
		"Netgear WGR614 V8")	echo "U12H072T00_NETGEAR"; return;;
		"Netgear WGR614 V9")	echo "U12H094T00_NETGEAR"; return;;
		"Netgear WGR614 V10")	echo "U12H139T01_NETGEAR"; return;;
		"Netgear WNDR3300")	echo "U12H093T00_NETGEAR"; return;;
		"Netgear WNDR3400 V1")	echo "U12H155T00_NETGEAR"; return;;
		"Netgear WNDR3400 V2")	echo "U12H187T00_NETGEAR"; return;;
		"Netgear WNDR3400 V3")	echo "U12H208T00_NETGEAR"; return;;
		"Netgear WNDR3400 Vcna")	echo "U12H155T01_NETGEAR"; return;;
		"Netgear WNDR3700 V3")	echo "U12H194T00_NETGEAR"; return;;
		"Netgear WNDR4000")	echo "U12H181T00_NETGEAR"; return;;
		"Netgear WNDR4500 V1")	echo "U12H189T00_NETGEAR"; return;;
		"Netgear WNDR4500 V2")	echo "U12H224T00_NETGEAR"; return;;
		"Netgear WNR2000 V2")	echo "U12H114T00_NETGEAR"; return;;
		"Netgear WNR3500L")	echo "U12H136T99_NETGEAR"; return;;
		"Netgear WNR3500U")	echo "U12H136T00_NETGEAR"; return;;
		"Netgear WNR3500 V2")	echo "U12H127T00_NETGEAR"; return;;
		"Netgear WNR3500 V2vc")	echo "U12H127T70_NETGEAR"; return;;
		"Netgear WNR834B V2")	echo "U12H081T00_NETGEAR"; return;;
	esac
}

platform_expected_cybertan_pattern() {
	local machine=$(platform_machine)

	case "$machine" in
		"Linksys E900 V1")	echo "E900"; return;;
		"Linksys E1000 V1")	echo "E100"; return;;
		"Linksys E1000 V2")	echo "E100"; return;;
		"Linksys E1000 V2.1")	echo "E100"; return;;
		"Linksys E1200 V2")	echo "E122"; return;;
		"Linksys E2000 V1")	echo "32XN"; return;;
		"Linksys E3000 V1")	echo "61XN"; return;;
		"Linksys E3200 V1")	echo "3200"; return;;
		"Linksys E4200 V1")	echo "4200"; return;;
		"Linksys WRT150N V1.1")	echo "N150"; return;;
		"Linksys WRT150N V1")	echo "N150"; return;;
		"Linksys WRT160N V1")	echo "N150"; return;;
		"Linksys WRT160N V3")	echo "N150"; return;;
		"Linksys WRT300N V1.1")	echo "EWCB"; return;;
		"Linksys WRT310N V1")	echo "310N"; return;;
		"Linksys WRT310N V2")	echo "310N"; return;;
		"Linksys WRT610N V1")	echo "610N"; return;;
		"Linksys WRT610N V2")	echo "610N"; return;;
	esac
}

brcm47xx_identify() {
	local magic

	magic=$(get_magic_long "$1")
	case "$magic" in
		"48445230")
			echo "trx"
			return
			;;
		"2a23245e")
			echo "chk"
			return
			;;
	esac

	magic=$(get_magic_long_at "$1" 14)
	[ "$magic" = "55324e44" ] && {
		echo "cybertan"
		return
	}

	echo "unknown"
}

platform_check_image() {
	[ "$#" -gt 1 ] && return 1

	local file_type=$(brcm47xx_identify "$1")
	local magic

	case "$file_type" in
		"chk")
			local header_len=$((0x$(get_magic_long_at "$1" 4)))
			local board_id_len=$(($header_len - 40))
			local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
			local dev_board_id=$(platform_expected_chk_board_id)
			echo "Found CHK image with device board_id $board_id"

			[ -n "$dev_board_id" -a "$board_id" != "$dev_board_id" ] && {
				echo "Firmware board_id doesn't match device board_id ($dev_board_id)"
				return 1
			}

			magic=$(get_magic_long_at "$1" "$header_len")
			[ "$magic" != "48445230" ] && {
				echo "No valid TRX firmware in the CHK image"
				return 1
			}

			return 0
		;;
		"cybertan")
			local pattern=$(dd if="$1" bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%c"')
			local dev_pattern=$(platform_expected_cybertan_pattern)
			echo "Found CyberTAN image with device pattern: $pattern"

			[ -n "$dev_pattern" -a "$pattern" != "$dev_pattern" ] && {
				echo "Firmware pattern doesn't match device pattern ($dev_pattern)"
				return 1
			}

			magic=$(get_magic_long_at "$1" 32)
			[ "$magic" != "48445230" ] && {
				echo "No valid TRX firmware in the CyberTAN image"
				return 1
			}

			return 0
		;;
		"trx")
			return 0
		;;
		*)
			echo "Invalid image type. Please use only .trx files"
			return 1
		;;
	esac
}

platform_do_upgrade_chk() {
	local header_len=$((0x$(get_magic_long_at "$1" 4)))
	local trx="/tmp/$1.trx"

	dd if="$1" of="$trx" bs=$header_len skip=1
	shift
	default_do_upgrade "$trx" "$@"
}

platform_do_upgrade_cybertan() {
	local trx="/tmp/$1.trx"

	dd if="$1" of="$trx" bs=32 skip=1
	shift
	default_do_upgrade "$trx" "$@"
}

platform_do_upgrade() {
	local file_type=$(brcm47xx_identify "$1")

	case "$file_type" in
		"chk")		platform_do_upgrade_chk "$ARGV";;
		"cybertan")	platform_do_upgrade_cybertan "$ARGV";;
		*)		default_do_upgrade "$ARGV";;
	esac
}