platform.sh 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. RAMFS_COPY_BIN='osafeloader oseama'
  2. PART_NAME=firmware
  3. # $(1): file to read magic from
  4. # $(2): offset in bytes
  5. get_magic_long_at() {
  6. dd if="$1" skip=$2 bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%02x"'
  7. }
  8. platform_flash_type() {
  9. # On NAND devices "rootfs" is UBI volume, so won't be find in /proc/mtd
  10. grep -q "\"rootfs\"" /proc/mtd && {
  11. echo "serial"
  12. return
  13. }
  14. echo "nand"
  15. }
  16. platform_expected_image() {
  17. local machine=$(board_name)
  18. case "$machine" in
  19. "dlink,dir-885l") echo "seama wrgac42_dlink.2015_dir885l"; return;;
  20. "netgear,r6250v1") echo "chk U12H245T00_NETGEAR"; return;;
  21. "netgear,r6300v2") echo "chk U12H240T00_NETGEAR"; return;;
  22. "netgear,r7000") echo "chk U12H270T00_NETGEAR"; return;;
  23. "netgear,r7900") echo "chk U12H315T30_NETGEAR"; return;;
  24. "netgear,r8000") echo "chk U12H315T00_NETGEAR"; return;;
  25. "netgear,r8500") echo "chk U12H334T00_NETGEAR"; return;;
  26. "tplink,archer-c9-v1") echo "safeloader"; return;;
  27. esac
  28. }
  29. platform_identify() {
  30. local magic
  31. magic=$(get_magic_long "$1")
  32. case "$magic" in
  33. "48445230")
  34. echo "trx"
  35. return
  36. ;;
  37. "2a23245e")
  38. echo "chk"
  39. return
  40. ;;
  41. "5ea3a417")
  42. echo "seama"
  43. return
  44. ;;
  45. esac
  46. magic=$(get_magic_long_at "$1" 14)
  47. [ "$magic" = "55324e44" ] && {
  48. echo "cybertan"
  49. return
  50. }
  51. if osafeloader info "$1" > /dev/null 2>&1; then
  52. echo "safeloader"
  53. return
  54. fi
  55. echo "unknown"
  56. }
  57. platform_check_image() {
  58. [ "$#" -gt 1 ] && return 1
  59. local file_type=$(platform_identify "$1")
  60. local magic
  61. local error=0
  62. case "$file_type" in
  63. "chk")
  64. local header_len=$((0x$(get_magic_long_at "$1" 4)))
  65. local board_id_len=$(($header_len - 40))
  66. local board_id=$(dd if="$1" skip=40 bs=1 count=$board_id_len 2>/dev/null | hexdump -v -e '1/1 "%c"')
  67. local dev_board_id=$(platform_expected_image)
  68. echo "Found CHK image with device board_id $board_id"
  69. [ -n "$dev_board_id" -a "chk $board_id" != "$dev_board_id" ] && {
  70. echo "Firmware board_id doesn't match device board_id ($dev_board_id)"
  71. error=1
  72. }
  73. if ! otrx check "$1" -o "$header_len"; then
  74. echo "No valid TRX firmware in the CHK image"
  75. error=1
  76. fi
  77. ;;
  78. "cybertan")
  79. local pattern=$(dd if="$1" bs=1 count=4 2>/dev/null | hexdump -v -e '1/1 "%c"')
  80. local dev_pattern=$(platform_expected_image)
  81. echo "Found CyberTAN image with device pattern: $pattern"
  82. [ -n "$dev_pattern" -a "cybertan $pattern" != "$dev_pattern" ] && {
  83. echo "Firmware pattern doesn't match device pattern ($dev_pattern)"
  84. error=1
  85. }
  86. if ! otrx check "$1" -o 32; then
  87. echo "No valid TRX firmware in the CyberTAN image"
  88. error=1
  89. fi
  90. ;;
  91. "safeloader")
  92. ;;
  93. "seama")
  94. local img_signature=$(oseama info "$1" | grep "Meta entry:.*signature=" | sed "s/.*=//")
  95. local dev_signature=$(platform_expected_image)
  96. echo "Found Seama image with device signature: $img_signature"
  97. [ -n "$dev_signature" -a "seama $img_signature" != "$dev_signature" ] && {
  98. echo "Firmware signature doesn't match device signature ($dev_signature)"
  99. error=1
  100. }
  101. $(oseama info "$1" -e 0 | grep -q "Meta entry:.*type=firmware") || {
  102. echo "Seama container doesn't have firmware entity"
  103. error=1
  104. }
  105. ;;
  106. "trx")
  107. local expected=$(platform_expected_image)
  108. [ "$expected" == "safeloader" ] && {
  109. echo "This device expects SafeLoader format and may not work with TRX"
  110. error=1
  111. }
  112. if ! otrx check "$1"; then
  113. echo "Invalid (corrupted?) TRX firmware"
  114. error=1
  115. fi
  116. ;;
  117. *)
  118. echo "Invalid image type. Please use only .trx files"
  119. error=1
  120. ;;
  121. esac
  122. return $error
  123. }
  124. # $(1): image for upgrade (with possible extra header)
  125. # $(2): offset of trx in image
  126. platform_pre_upgrade_trx() {
  127. local dir="/tmp/sysupgrade-bcm53xx"
  128. local trx="$1"
  129. local offset="$2"
  130. # Extract partitions from trx
  131. rm -fR $dir
  132. mkdir -p $dir
  133. otrx extract "$trx" \
  134. ${offset:+-o $offset} \
  135. -1 $dir/kernel \
  136. -2 $dir/root
  137. [ $? -ne 0 ] && {
  138. echo "Failed to extract TRX partitions."
  139. return
  140. }
  141. # Firmwares without UBI image should be flashed "normally"
  142. local root_type=$(identify $dir/root)
  143. [ "$root_type" != "ubi" ] && {
  144. echo "Provided firmware doesn't use UBI for rootfs."
  145. return
  146. }
  147. # Prepare TRX file with just a kernel that will replace current one
  148. local linux_length=$(grep "\"linux\"" /proc/mtd | sed "s/mtd[0-9]*:[ \t]*\([^ \t]*\).*/\1/")
  149. [ -z "$linux_length" ] && {
  150. echo "Unable to find \"linux\" partition size"
  151. exit 1
  152. }
  153. linux_length=$((0x$linux_length))
  154. local kernel_length=$(wc -c $dir/kernel | cut -d ' ' -f 1)
  155. [ $kernel_length -gt $linux_length ] && {
  156. echo "New kernel doesn't fit \"linux\" partition."
  157. return
  158. }
  159. rm -f /tmp/null.bin
  160. rm -f /tmp/kernel.trx
  161. touch /tmp/null.bin
  162. otrx create /tmp/kernel.trx \
  163. -f $dir/kernel -b $(($linux_length + 28)) \
  164. -f /tmp/null.bin
  165. [ $? -ne 0 ] && {
  166. echo "Failed to create simple TRX with new kernel."
  167. return
  168. }
  169. # Prepare UBI image (drop unwanted extra blocks)
  170. local ubi_length=0
  171. while [ "$(dd if=$dir/root skip=$ubi_length bs=1 count=4 2>/dev/null)" = "UBI#" ]; do
  172. ubi_length=$(($ubi_length + 131072))
  173. done
  174. dd if=$dir/root of=/tmp/root.ubi bs=131072 count=$((ubi_length / 131072)) 2>/dev/null
  175. [ $? -ne 0 ] && {
  176. echo "Failed to prepare new UBI image."
  177. return
  178. }
  179. # Flash
  180. mtd write /tmp/kernel.trx firmware
  181. nand_do_upgrade /tmp/root.ubi
  182. }
  183. platform_pre_upgrade_seama() {
  184. local dir="/tmp/sysupgrade-bcm53xx"
  185. local seama="$1"
  186. local tmp
  187. # Extract Seama entity from Seama seal
  188. rm -fR $dir
  189. mkdir -p $dir
  190. oseama extract "$seama" \
  191. -e 0 \
  192. -o $dir/seama.entity
  193. [ $? -ne 0 ] && {
  194. echo "Failed to extract Seama entity."
  195. return
  196. }
  197. local entity_size=$(wc -c $dir/seama.entity | cut -d ' ' -f 1)
  198. local ubi_offset=0
  199. tmp=0
  200. while [ 1 ]; do
  201. [ $tmp -ge $entity_size ] && break
  202. [ "$(dd if=$dir/seama.entity skip=$tmp bs=1 count=4 2>/dev/null)" = "UBI#" ] && {
  203. ubi_offset=$tmp
  204. break
  205. }
  206. tmp=$(($tmp + 131072))
  207. done
  208. [ $ubi_offset -eq 0 ] && {
  209. echo "Failed to find UBI in Seama entity."
  210. return
  211. }
  212. local ubi_length=0
  213. while [ "$(dd if=$dir/seama.entity skip=$(($ubi_offset + $ubi_length)) bs=1 count=4 2>/dev/null)" = "UBI#" ]; do
  214. ubi_length=$(($ubi_length + 131072))
  215. done
  216. dd if=$dir/seama.entity of=$dir/kernel.seama bs=131072 count=$(($ubi_offset / 131072)) 2>/dev/null
  217. dd if=$dir/seama.entity of=$dir/root.ubi bs=131072 skip=$(($ubi_offset / 131072)) count=$(($ubi_length / 131072)) 2>/dev/null
  218. # Flash
  219. local kernel_size=$(sed -n 's/mtd[0-9]*: \([0-9a-f]*\).*"\(kernel\|linux\)".*/\1/p' /proc/mtd)
  220. mtd write $dir/kernel.seama firmware
  221. mtd ${kernel_size:+-c 0x$kernel_size} fixseama firmware
  222. nand_do_upgrade $dir/root.ubi
  223. }
  224. platform_pre_upgrade() {
  225. local file_type=$(platform_identify "$1")
  226. [ "$(platform_flash_type)" != "nand" ] && return
  227. # Find trx offset
  228. case "$file_type" in
  229. "chk") platform_pre_upgrade_trx "$1" $((0x$(get_magic_long_at "$1" 4)));;
  230. "cybertan") platform_pre_upgrade_trx "$1" 32;;
  231. "seama") platform_pre_upgrade_seama "$1";;
  232. "trx") platform_pre_upgrade_trx "$1";;
  233. esac
  234. }
  235. platform_trx_from_chk_cmd() {
  236. local header_len=$((0x$(get_magic_long_at "$1" 4)))
  237. echo -n dd bs=$header_len skip=1
  238. }
  239. platform_trx_from_cybertan_cmd() {
  240. echo -n dd bs=32 skip=1
  241. }
  242. platform_img_from_safeloader() {
  243. local dir="/tmp/sysupgrade-bcm53xx"
  244. # Extract partitions from SafeLoader
  245. rm -fR $dir
  246. mkdir -p $dir
  247. osafeloader extract "$1" \
  248. -p "os-image" \
  249. -o $dir/os-image
  250. osafeloader extract "$1" \
  251. -p "file-system" \
  252. -o $dir/file-system
  253. mtd write $dir/file-system rootfs
  254. echo -n $dir/os-image
  255. }
  256. platform_img_from_seama() {
  257. local dir="/tmp/sysupgrade-bcm53xx"
  258. local offset=$(oseama info "$1" -e 0 | grep "Entity offset:" | sed "s/.*:\s*//")
  259. local size=$(oseama info "$1" -e 0 | grep "Entity size:" | sed "s/.*:\s*//")
  260. # Busybox doesn't support required iflag-s
  261. # echo -n dd iflag=skip_bytes,count_bytes skip=$offset count=$size
  262. rm -fR $dir
  263. mkdir -p $dir
  264. dd if="$1" of=$dir/image-noheader.bin bs=$offset skip=1
  265. dd if=$dir/image-noheader.bin of=$dir/image-entity.bin bs=$size count=1
  266. echo -n $dir/image-entity.bin
  267. }
  268. platform_do_upgrade() {
  269. local file_type=$(platform_identify "$1")
  270. local trx="$1"
  271. local cmd=
  272. [ "$(platform_flash_type)" == "nand" ] && {
  273. echo "Writing whole image to NAND flash. All erase counters will be lost."
  274. }
  275. case "$file_type" in
  276. "chk") cmd=$(platform_trx_from_chk_cmd "$trx");;
  277. "cybertan") cmd=$(platform_trx_from_cybertan_cmd "$trx");;
  278. "safeloader") trx=$(platform_img_from_safeloader "$trx");;
  279. "seama") trx=$(platform_img_from_seama "$trx");;
  280. esac
  281. default_do_upgrade "$trx" "$cmd"
  282. }