xiaomi_r3d.patch 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080
  1. From c433730d889d0dfb31bdcf4f102ca47939606c46 Mon Sep 17 00:00:00 2001
  2. From: remittor <[email protected]>
  3. Date: Fri, 11 Aug 2023 12:08:30 +0300
  4. Subject: [PATCH] ipq806x: Add support for Xiaomi Mi Router HD (R3D)
  5. Xiaomi R3D is a 2.4/5 GHz band 11ac router, based on IPQ8064.
  6. Specification:
  7. * SoC: Qualcomm IPQ8064
  8. * RAM: 512MB DDR3
  9. * Flash: 256MB NAND (Macronix MX30UF2G18AC-TI)
  10. * Ethernet: 4x 10/100/1000 Mbps (1x WAN, 3x LAN)
  11. * WiFi: Qualcomm QCA9984 (5GHz, 4T4R, n/ac)
  12. * WiFi: Qualcomm QCA9980 (2.4GHz, 4T4R, b/g/n)
  13. * USB: 1x 3.0
  14. * SATA: 1x SATA 3.1 (only for internal HDD 3.5")
  15. * BTN: Power, Reset
  16. * LEDS: Status(Green/Blue/Red)
  17. * UART: present as 4-pads on the PCB (3.3V, 115200-8-N-1)
  18. MAC addresses as verified by stock firmware:
  19. | Interface | MAC | ART | Format |
  20. |-------------+-------------------+---------+--------|
  21. | WAN (label) | xx:xx:xx:xx:xx:B2 | 0x0 | binary |
  22. | LAN | xx:xx:xx:xx:xx:B3 | 0x6 | binary |
  23. | WiFi 2g | xx:xx:xx:xx:xx:B4 | 0x1006 | binary |
  24. | WiFi 5g | xx:xx:xx:xx:xx:B5 | 0x5006 | binary |
  25. ---
  26. package/boot/uboot-envtools/files/ipq806x | 6 +-
  27. .../ipq806x/base-files/etc/board.d/02_network | 4 +
  28. .../etc/hotplug.d/firmware/11-ath10k-caldata | 6 +
  29. .../ipq806x/base-files/etc/init.d/bootcount | 8 +
  30. .../base-files/lib/upgrade/platform.sh | 3 +
  31. .../ipq806x/base-files/lib/upgrade/xiaomi.sh | 441 ++++++++++++++++
  32. .../arch/arm/boot/dts/qcom-ipq8064-r3d.dts | 479 ++++++++++++++++++
  33. target/linux/ipq806x/image/generic.mk | 17 +
  34. 8 files changed, 963 insertions(+), 1 deletion(-)
  35. create mode 100644 target/linux/ipq806x/base-files/lib/upgrade/xiaomi.sh
  36. create mode 100644 target/linux/ipq806x/files-6.6/arch/arm/boot/dts/qcom-ipq8064-r3d.dts
  37. diff --git a/package/boot/uboot-envtools/files/ipq806x b/package/boot/uboot-envtools/files/ipq806x
  38. index 01a86c7b19fca..c0a781c1e21b4 100644
  39. --- a/package/boot/uboot-envtools/files/ipq806x
  40. +++ b/package/boot/uboot-envtools/files/ipq806x
  41. @@ -52,6 +52,10 @@ qcom,ipq8064-ap148|\
  42. qcom,ipq8064-db149)
  43. ubootenv_add_uci_config $(ubootenv_mtdinfo)
  44. ;;
  45. +xiaomi,r3d)
  46. + ubootenv_add_uci_config "/dev/mtd9" "0x0" "0x10000" "0x10000"
  47. + ubootenv_add_uci_sys_config "/dev/mtd12" "0x0" "0x10000" "0x10000"
  48. + ;;
  49. ubnt,unifi-ac-hd|\
  50. zyxel,nbg6817)
  51. ubootenv_add_uci_config "/dev/mtdblock9" "0x0" "0x10000" "0x10000"
  52. @@ -59,6 +63,6 @@ zyxel,nbg6817)
  53. esac
  54. config_load ubootenv
  55. -config_foreach ubootenv_add_app_config ubootenv
  56. +config_foreach ubootenv_add_app_config
  57. exit 0
  58. diff --git a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
  59. index 4c5019cf5bd24..aa8ed06aae4b3 100644
  60. --- a/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
  61. +++ b/target/linux/ipq806x/base-files/etc/hotplug.d/firmware/11-ath10k-caldata
  62. @@ -56,6 +56,9 @@ case "$FIRMWARE" in
  63. caldata_extract "0:art" 0x1000 0x2f20
  64. ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:appsblenv ethaddr) +2)
  65. ;;
  66. + xiaomi,r3d)
  67. + caldata_extract "ART" 0x1000 0x2f20
  68. + ;;
  69. zyxel,nbg6817)
  70. caldata_extract "0:art" 0x1000 0x2f20
  71. ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:appsblenv ethaddr) 1)
  72. @@ -92,6 +95,9 @@ case "$FIRMWARE" in
  73. caldata_extract "0:art" 0x5000 0x2f20
  74. ath10k_patch_mac $(macaddr_add $(mtd_get_mac_ascii 0:appsblenv ethaddr) +3)
  75. ;;
  76. + xiaomi,r3d)
  77. + caldata_extract "ART" 0x5000 0x2f20
  78. + ;;
  79. zyxel,nbg6817)
  80. caldata_extract "0:art" 0x5000 0x2f20
  81. ath10k_patch_mac $(mtd_get_mac_ascii 0:appsblenv ethaddr)
  82. diff --git a/target/linux/ipq806x/base-files/etc/init.d/bootcount b/target/linux/ipq806x/base-files/etc/init.d/bootcount
  83. index cb32a4ed3568d..9d9ab3f100fe2 100755
  84. --- a/target/linux/ipq806x/base-files/etc/init.d/bootcount
  85. +++ b/target/linux/ipq806x/base-files/etc/init.d/bootcount
  86. @@ -16,5 +16,13 @@ boot() {
  87. linksys,ea8500)
  88. mtd resetbc s_env || true
  89. ;;
  90. + xiaomi,r3d)
  91. + local boot_wait=$( fw_printenv boot_wait | cut -d = -f 2 )
  92. + [ "$boot_wait" != "on" ] && fw_setenv boot_wait on
  93. + local bootdelay=$( fw_printenv bootdelay | cut -d = -f 2 )
  94. + [ "$bootdelay" != "3" ] && fw_setenv bootdelay 3
  95. + local uart_en=$( fw_printenv uart_en | cut -d = -f 2 )
  96. + [ "$uart_en" != "1" ] && fw_setenv uart_en 1
  97. + ;;
  98. esac
  99. }
  100. diff --git a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
  101. index 5ec4f513bd33d..b142fce86a082 100644
  102. --- a/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
  103. +++ b/target/linux/ipq806x/base-files/lib/upgrade/platform.sh
  104. @@ -71,6 +71,9 @@ platform_do_upgrade() {
  105. MTD_CONFIG_ARGS="-s 0x200000"
  106. default_do_upgrade "$1"
  107. ;;
  108. + xiaomi,r3d)
  109. + platform_do_upgrade_xiaomi "$1" 0x2800000
  110. + ;;
  111. zyxel,nbg6817)
  112. zyxel_do_upgrade "$1"
  113. ;;
  114. diff --git a/target/linux/ipq806x/base-files/lib/upgrade/xiaomi.sh b/target/linux/ipq806x/base-files/lib/upgrade/xiaomi.sh
  115. new file mode 100644
  116. index 0000000000000..9246e8f867e3f
  117. --- /dev/null
  118. +++ b/target/linux/ipq806x/base-files/lib/upgrade/xiaomi.sh
  119. @@ -0,0 +1,441 @@
  120. +# SPDX-License-Identifier: GPL-2.0-or-later OR MIT
  121. +
  122. +. /lib/functions.sh
  123. +
  124. +MAGIC_XIAOMI_HDR1="48445231" # "HDR1" - xiaomi image header
  125. +MAGIC_XIAOMI_BLK="beba0000"
  126. +MAGIC_UIMAGE="27051956" # uImage header
  127. +MAGIC_UBI="55424923" # "UBI#"
  128. +MAGIC_UBIFS="31181006"
  129. +MAGIC_HSQS="68737173" # "hsqs"
  130. +MAGIC_SYSUPG="7379737570677261" # TAR "sysupgrade"
  131. +
  132. +XIAOMI_PAGESIZE=2048
  133. +
  134. +XIAOMI_FW_FILE=""
  135. +XIAOMI_FW_SIZE=0
  136. +XIAOMI_KERNEL_PART=$CI_KERNPART
  137. +XIAOMI_KERNEL2_PART=""
  138. +XIAOMI_KERNEL2_NAMES="kernel_stock|kernel_dup"
  139. +XIAOMI_ROOTFS_PART=$CI_UBIPART
  140. +XIAOMI_ROOTFS_PARTSIZE=
  141. +
  142. +XIAOMI_RESTORE_ROOTFS2=
  143. +
  144. +log_msg() {
  145. + echo "$@"
  146. +}
  147. +
  148. +log_err() {
  149. + echo "ERROR: $@" >&2
  150. +}
  151. +
  152. +die() {
  153. + log_err "$@"
  154. + exit 1
  155. +}
  156. +
  157. +get_uint32_at() {
  158. + local offset=$1
  159. + local endianness=$2
  160. + local hex
  161. + if [ $(( $offset + 4 )) -gt $XIAOMI_FW_SIZE ]; then
  162. + echo ""
  163. + return
  164. + fi
  165. + local dd_args="if=$XIAOMI_FW_FILE skip=$offset bs=1 count=4"
  166. + if [ "$endianness" = "be" ]; then
  167. + hex=$( dd $dd_args 2>/dev/null | hexdump -v -n 4 -e '1/1 "%02x"' )
  168. + else
  169. + hex=$( dd $dd_args 2>/dev/null | hexdump -v -e '1/4 "%02x"' )
  170. + fi
  171. + echo $( printf "%d" 0x$hex )
  172. +}
  173. +
  174. +get_hexdump_at() {
  175. + local offset=$1
  176. + local size=$2
  177. + if [ $(( $offset + $size )) -gt $XIAOMI_FW_SIZE ]; then
  178. + echo ""
  179. + return
  180. + fi
  181. + local dd_args="if=$XIAOMI_FW_FILE skip=$offset bs=1 count=$size"
  182. + echo $( dd $dd_args 2>/dev/null | hexdump -v -n $size -e '1/1 "%02x"' )
  183. +}
  184. +
  185. +get_round_up() {
  186. + local value=$1
  187. + local base=$2
  188. + local pad=0
  189. + if [ -z "$base" ]; then
  190. + base=$XIAOMI_PAGESIZE
  191. + else
  192. + base=$( printf "%d" $base )
  193. + fi
  194. + if [ $(( $value % $base )) != 0 ]; then
  195. + pad=$(( $base - $value % $base ))
  196. + fi
  197. + echo $(( $value + $pad ))
  198. +}
  199. +
  200. +get_part_size() {
  201. + local part_name=$1
  202. + local part=$( cat /proc/mtd | grep \"$part_name\" )
  203. + if [ -z "$part" ]; then
  204. + echo 0
  205. + else
  206. + local mtd_size_hex=$( echo $part | awk '{print "0x"$2}' )
  207. + echo $( printf "%d" $mtd_size_hex )
  208. + fi
  209. +}
  210. +
  211. +xiaomi_check_sizes() {
  212. + local part_name=$1
  213. + local img_offset=$2
  214. + local img_size=$3
  215. +
  216. + local mtd_size=$( get_part_size $part_name )
  217. + if [ "$mtd_size" = "0" ]; then
  218. + echo "cannot find mtd partition with name '$part_name'"
  219. + return 1
  220. + fi
  221. + local img_end=$(( $img_offset + $img_size ))
  222. + if [ $img_end -gt $XIAOMI_FW_SIZE ]; then
  223. + echo "incorrect image size (part: '$part_name')"
  224. + return 1
  225. + fi
  226. + if [ $img_size -gt $mtd_size ]; then
  227. + echo "image is greater than partition '$part_name'"
  228. + return 1
  229. + fi
  230. + echo ""
  231. + return 0
  232. +}
  233. +
  234. +xiaomi_mtd_write() {
  235. + local part_name=$1
  236. + local img_offset=$2
  237. + local img_size=$3
  238. + local part_skip=$4
  239. +
  240. + img_size=$( get_round_up $img_size )
  241. + local err=$( xiaomi_check_sizes $part_name $img_offset $img_size )
  242. + if [ -n "$err" ]; then
  243. + log_err $err
  244. + return 1
  245. + fi
  246. + if [ -n "$part_skip" ]; then
  247. + part_skip="-p $part_skip"
  248. + fi
  249. + local count=$(( $img_size / $XIAOMI_PAGESIZE ))
  250. + local dd_args="if=$XIAOMI_FW_FILE iflag=skip_bytes skip=$img_offset bs=$XIAOMI_PAGESIZE count=$count"
  251. + dd $dd_args | mtd -f $part_skip write - "$part_name" || {
  252. + log_err "Failed to flash '$part_name'"
  253. + return 1
  254. + }
  255. + return 0
  256. +}
  257. +
  258. +xiaomi_flash_images() {
  259. + local kernel_offset=$1
  260. + local kernel_size=$2
  261. + local rootfs_offset=$3
  262. + local rootfs_size=$4
  263. + local err
  264. + local part_skip=0
  265. +
  266. + kernel_size=$( get_round_up $kernel_size )
  267. + rootfs_size=$( get_round_up $rootfs_size )
  268. +
  269. + err=$( xiaomi_check_sizes $XIAOMI_KERNEL_PART $kernel_offset $kernel_size )
  270. + [ -n "$err" ] && { log_err $err; return 1; }
  271. +
  272. + if [ -n "$XIAOMI_KERNEL2_PART" ]; then
  273. + err=$( xiaomi_check_sizes $XIAOMI_KERNEL2_PART $kernel_offset $kernel_size )
  274. + [ -n "$err" ] && { log_err $err; return 1; }
  275. + fi
  276. +
  277. + err=$( xiaomi_check_sizes $XIAOMI_ROOTFS_PART $rootfs_offset $rootfs_size )
  278. + [ -n "$err" ] && { log_err $err; return 1; }
  279. +
  280. + if [ "$XIAOMI_RESTORE_ROOTFS2" = "true" -a -n "$XIAOMI_ROOTFS_PARTSIZE" ]; then
  281. + part_skip=$( printf "%d" $XIAOMI_ROOTFS_PARTSIZE )
  282. + if [ $part_skip -lt 1000000 ]; then
  283. + part_skip=0
  284. + fi
  285. + fi
  286. +
  287. + if [ $part_skip -gt 0 ]; then
  288. + local ksize=$(( $part_skip + $rootfs_size ))
  289. + local mtd_size=$( get_part_size $XIAOMI_ROOTFS_PART )
  290. + if [ $ksize -gt $mtd_size ]; then
  291. + log_err "double rootfs is greater than partition '$XIAOMI_ROOTFS_PART'"
  292. + return 1
  293. + fi
  294. + fi
  295. +
  296. + mtd erase "$XIAOMI_ROOTFS_PART" || {
  297. + log_err "Failed to erase partition '$part_name'"
  298. + return 1
  299. + }
  300. +
  301. + xiaomi_mtd_write $XIAOMI_KERNEL_PART $kernel_offset $kernel_size || {
  302. + log_err "Failed flash data to '$XIAOMI_KERNEL_PART' partition"
  303. + return 1
  304. + }
  305. + log_msg "Kernel image flashed to '$XIAOMI_KERNEL_PART'"
  306. +
  307. + if [ -n "$XIAOMI_KERNEL2_PART" ]; then
  308. + xiaomi_mtd_write $XIAOMI_KERNEL2_PART $kernel_offset $kernel_size || {
  309. + log_err "Failed flash data to '$XIAOMI_KERNEL2_PART' partition"
  310. + return 1
  311. + }
  312. + log_msg "Kernel image flashed to '$XIAOMI_KERNEL2_PART'"
  313. + fi
  314. +
  315. + xiaomi_mtd_write $XIAOMI_ROOTFS_PART $rootfs_offset $rootfs_size || {
  316. + log_err "Failed flash data to '$XIAOMI_ROOTFS_PART' partition"
  317. + return 1
  318. + }
  319. + log_msg "Rootfs image flashed to '$XIAOMI_ROOTFS_PART'!"
  320. +
  321. + if [ $part_skip -gt 0 ]; then
  322. + xiaomi_mtd_write $XIAOMI_ROOTFS_PART $rootfs_offset $rootfs_size $part_skip || {
  323. + log_err "Failed flash data to '$XIAOMI_ROOTFS_PART' partition (2)"
  324. + return 1
  325. + }
  326. + log_msg "Rootfs image flashed to '$XIAOMI_ROOTFS_PART':$XIAOMI_ROOTFS_PARTSIZE"
  327. + fi
  328. +
  329. + log_msg "Firmware write successful! Reboot..."
  330. + sync
  331. + umount -a
  332. + reboot -f
  333. + exit 0
  334. +}
  335. +
  336. +check_ubi_header() {
  337. + local offset=$1
  338. +
  339. + local magic=$( get_hexdump_at $offset 4 )
  340. + [ "$magic" != $MAGIC_UBI ] && { echo ""; return 1; }
  341. +
  342. + local magic_ubi2="55424921" # "UBI!"
  343. + offset=$(( $offset + $XIAOMI_PAGESIZE ))
  344. + magic=$( get_hexdump_at $offset 4 )
  345. + [ "$magic" != $magic_ubi2 ] && { echo ""; return 1; }
  346. +
  347. + echo "true"
  348. + return 0
  349. +}
  350. +
  351. +get_rootfs_offset() {
  352. + local start=$1
  353. + local pos offset align end
  354. +
  355. + for offset in 0 1 2 3 4; do
  356. + pos=$(( $start + $offset ))
  357. + [ -n "$( check_ubi_header $pos )" ] && { echo $pos; return 0; }
  358. + done
  359. +
  360. + for align in 4 8 16 32 64 128 256 512 1024 2048 4096; do
  361. + pos=$( get_round_up $start $align )
  362. + [ -n "$( check_ubi_header $pos )" ] && { echo $pos; return 0; }
  363. + done
  364. +
  365. + align=65536
  366. + pos=$( get_round_up $start $align )
  367. + end=$(( $pos + 3000000 ))
  368. + while true; do
  369. + [ $(( $pos + 150000 )) -gt $XIAOMI_FW_SIZE ] && break
  370. + [ -n "$( check_ubi_header $pos )" ] && { echo $pos; return 0; }
  371. + pos=$(( $pos + $align ))
  372. + [ $pos -ge $end ] && break
  373. + done
  374. +
  375. + echo ""
  376. + return 1
  377. +}
  378. +
  379. +xiaomi_do_factory_upgrade() {
  380. + local err
  381. + local magic
  382. + local kernel_offset kernel_size
  383. + local rootfs_offset rootfs_size
  384. +
  385. + local kernel_mtd="$( find_mtd_index $XIAOMI_KERNEL_PART )"
  386. + if [ -z "$kernel_mtd" ]; then
  387. + log_err "partition '$XIAOMI_KERNEL_PART' not found"
  388. + return 1
  389. + fi
  390. + log_msg "Forced factory upgrade..."
  391. +
  392. + kernel_offset=0
  393. + kernel_size=$( get_uint32_at 12 "be" )
  394. + kernel_size=$(( $kernel_size + 64 ))
  395. +
  396. + rootfs_offset=$( get_rootfs_offset $kernel_size )
  397. + if [ -z "$rootfs_offset" ]; then
  398. + log_err "can't find ubinized rootfs in the firmware image"
  399. + return 1
  400. + fi
  401. + rootfs_size=$(( $XIAOMI_FW_SIZE - $rootfs_offset ))
  402. + local rootfs_end=$(( $rootfs_offset + $rootfs_size ))
  403. +
  404. + XIAOMI_RESTORE_ROOTFS2=false
  405. + xiaomi_flash_images $kernel_offset $kernel_size $rootfs_offset $rootfs_size || {
  406. + log_err "can't flash factory image"
  407. + return 1
  408. + }
  409. + exit 0
  410. +}
  411. +
  412. +xiaomi_do_revert_stock() {
  413. + local err
  414. + local magic
  415. + local blk blkpos blk_magic offset file_size
  416. + local kernel_offset
  417. + local kernel_size=0
  418. + local rootfs_offset
  419. + local rootfs_size=0
  420. +
  421. + local kernel_mtd=$( find_mtd_index $XIAOMI_KERNEL_PART )
  422. + if [ -z "$kernel_mtd" ]; then
  423. + log_err "partition '$XIAOMI_KERNEL_PART' not found"
  424. + return 1
  425. + fi
  426. + log_msg "Forced revert to stock firmware..."
  427. +
  428. + for blk in 16 20 24 28 32 36; do
  429. + blkpos=$( get_uint32_at $blk )
  430. + [ -z "$blkpos" ] && continue
  431. + [ $blkpos -lt 48 ] && continue
  432. + blk_magic=$( get_hexdump_at $blkpos 4 )
  433. + [ "$blk_magic" != $MAGIC_XIAOMI_BLK ] && continue
  434. + offset=$(( $blkpos + 8 ))
  435. + file_size=$( get_uint32_at $offset 4 )
  436. + [ -z "$file_size" ] && continue
  437. + [ $file_size -lt 1000000 ] && continue
  438. + offset=$(( $blkpos + 48 ))
  439. + magic=$( get_hexdump_at $offset 4 )
  440. + if [ "$magic" = $MAGIC_UIMAGE ]; then
  441. + kernel_size=$file_size
  442. + kernel_offset=$offset
  443. + fi
  444. + if [ "$magic" = $MAGIC_UBI -o "$magic" = $MAGIC_HSQS ]; then
  445. + rootfs_size=$file_size
  446. + rootfs_offset=$offset
  447. + fi
  448. + done
  449. + if [ $kernel_size -eq 0 ]; then
  450. + log_err "incorrect stock firmware image (kernel not found)"
  451. + return 1
  452. + fi
  453. + if [ $rootfs_size -eq 0 ]; then
  454. + log_err "incorrect stock firmware image (rootfs not found)"
  455. + return 1
  456. + fi
  457. +
  458. + XIAOMI_RESTORE_ROOTFS2=true
  459. + xiaomi_flash_images $kernel_offset $kernel_size $rootfs_offset $rootfs_size || {
  460. + log_err "ERROR: can't revert to stock firmware"
  461. + return 1
  462. + }
  463. + exit 0
  464. +}
  465. +
  466. +platform_do_upgrade_xiaomi() {
  467. + XIAOMI_FW_FILE=$1
  468. + local stock_rootfs_size=$2
  469. + local magic
  470. + local kernel_mtd kernel2_mtd rootfs_mtd
  471. + local kernel2_part_list part_name
  472. +
  473. + XIAOMI_FW_SIZE=$( wc -c "$XIAOMI_FW_FILE" 2> /dev/null | awk '{print $1}' )
  474. + if [ -z "$XIAOMI_FW_SIZE" ]; then
  475. + log_err "File '$XIAOMI_FW_FILE' not found!"
  476. + exit 1
  477. + fi
  478. + if [ $XIAOMI_FW_SIZE -lt 1000000 ]; then
  479. + log_err "file '$XIAOMI_FW_FILE' is incorrect"
  480. + exit 1
  481. + fi
  482. +
  483. + kernel_mtd=$( find_mtd_index $XIAOMI_KERNEL_PART )
  484. + if [ -z "$kernel_mtd" ]; then
  485. + log_err "cannot find mtd partition for '$XIAOMI_KERNEL_PART'"
  486. + exit 1
  487. + fi
  488. + kernel2_part_list=$( echo "$XIAOMI_KERNEL2_NAMES" | sed 's/|/\n/g' )
  489. + for part_name in $kernel2_part_list; do
  490. + kernel2_mtd=$( find_mtd_index $part_name )
  491. + if [ -n "$kernel2_mtd" ]; then
  492. + XIAOMI_KERNEL2_PART="$part_name"
  493. + log_msg "Found alt kernel partition '$XIAOMI_KERNEL2_PART'"
  494. + break
  495. + fi
  496. + done
  497. + rootfs_mtd=$( find_mtd_index $XIAOMI_ROOTFS_PART )
  498. + if [ -z "$rootfs_mtd" ]; then
  499. + log_err "cannot find mtd partition for '$XIAOMI_ROOTFS_PART'"
  500. + exit 1
  501. + fi
  502. +
  503. + magic=$( get_hexdump_at 0 4 )
  504. +
  505. + # Flash factory image (uImage header)
  506. + if [ "$magic" = $MAGIC_UIMAGE ]; then
  507. + xiaomi_do_factory_upgrade
  508. + exit $?
  509. + fi
  510. +
  511. + # Revert to stock firmware ("HDR1" header)
  512. + if [ "$magic" = $MAGIC_XIAOMI_HDR1 ]; then
  513. + if [ -n "$stock_rootfs_size" ]; then
  514. + XIAOMI_ROOTFS_PARTSIZE=$stock_rootfs_size
  515. + fi
  516. + xiaomi_do_revert_stock
  517. + exit $?
  518. + fi
  519. +
  520. + magic=$( get_hexdump_at 0 8 )
  521. + if [ "$magic" != $MAGIC_SYSUPG ]; then
  522. + log_err "incorrect image for system upgrading!"
  523. + exit 1
  524. + fi
  525. + log_msg "SysUpgrade start..."
  526. + local tar_file=$XIAOMI_FW_FILE
  527. + local board_dir=$( tar tf $tar_file | grep -m 1 '^sysupgrade-.*/$' )
  528. + [ -z "$board_dir" ] && {
  529. + log_err "board dir not found"
  530. + exit 1
  531. + }
  532. + board_dir=${board_dir%/}
  533. +
  534. + local control_len=$( (tar xf $tar_file $board_dir/CONTROL -O | wc -c) 2> /dev/null)
  535. + if [ $control_len -lt 3 ]; then
  536. + log_err "incorrect stock firmware image (CONTROL not found)"
  537. + exit 1
  538. + fi
  539. + local kernel_len=$( (tar xf $tar_file $board_dir/kernel -O | wc -c) 2> /dev/null)
  540. + if [ $kernel_len -lt 1000000 ]; then
  541. + log_err "incorrect stock firmware image (kernel not found)"
  542. + exit 1
  543. + fi
  544. + local rootfs_len=$( (tar xf $tar_file $board_dir/root -O | wc -c) 2> /dev/null)
  545. + if [ $rootfs_len -lt 1000000 ]; then
  546. + log_err "incorrect stock firmware image (rootfs not found)"
  547. + exit 1
  548. + fi
  549. +
  550. + if [ -n "$XIAOMI_KERNEL2_PART" ]; then
  551. + tar Oxf $tar_file $board_dir/kernel | mtd -f write - $XIAOMI_KERNEL2_PART && {
  552. + log_msg "Kernel image flashed to '$XIAOMI_KERNEL2_PART'"
  553. + } || {
  554. + log_err "cannot flash partition '$XIAOMI_KERNEL2_PART'"
  555. + exit 1
  556. + }
  557. + fi
  558. +
  559. + nand_do_upgrade "$XIAOMI_FW_FILE"
  560. +}
  561. diff --git a/target/linux/ipq806x/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq8064-r3d.dts b/target/linux/ipq806x/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq8064-r3d.dts
  562. new file mode 100644
  563. index 0000000000000..fd952d230c5da
  564. --- /dev/null
  565. +++ b/target/linux/ipq806x/files-6.6/arch/arm/boot/dts/qcom/qcom-ipq8064-r3d.dts
  566. @@ -0,0 +1,479 @@
  567. +// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
  568. +
  569. +#include "qcom-ipq8064-v2.0-smb208.dtsi"
  570. +
  571. +#include <dt-bindings/input/input.h>
  572. +
  573. +/ {
  574. + model = "Xiaomi Mi Router HD (R3D)";
  575. + compatible = "xiaomi,r3d", "qcom,ipq8064";
  576. +
  577. + memory@0 {
  578. + device_type = "memory";
  579. + reg = <0x42000000 0x1e000000>;
  580. + };
  581. +
  582. + reserved-memory {
  583. + rsvd@44600000 {
  584. + reg = <0x44600000 0x200000>; /* IPQ_TZ_APPS_ADDR */
  585. + no-map;
  586. + };
  587. + };
  588. +
  589. + aliases {
  590. + label-mac-device = &gmac1;
  591. +
  592. + mdio-gpio0 = &mdio0;
  593. +
  594. + led-boot = &led_status_yellow;
  595. + led-failsafe = &led_status_red;
  596. + led-running = &led_status_blue;
  597. + led-upgrade = &led_status_yellow;
  598. + };
  599. +
  600. + chosen {
  601. + bootargs = "rootfstype=squashfs noinitrd";
  602. + };
  603. +
  604. + keys {
  605. + compatible = "gpio-keys";
  606. + pinctrl-0 = <&button_pins>;
  607. + pinctrl-names = "default";
  608. +
  609. + reset {
  610. + label = "reset";
  611. + gpios = <&qcom_pinmux 16 GPIO_ACTIVE_LOW>;
  612. + linux,code = <KEY_RESTART>;
  613. + debounce-interval = <60>;
  614. + wakeup-source;
  615. + };
  616. +
  617. + power {
  618. + label = "power"; /* Labeled POWER on the device, but using for sleep mode */
  619. + gpios = <&qcom_pinmux 68 GPIO_ACTIVE_LOW>;
  620. + linux,code = <KEY_POWER>;
  621. + debounce-interval = <60>;
  622. + wakeup-source;
  623. + };
  624. + };
  625. +
  626. + leds {
  627. + compatible = "gpio-leds";
  628. + pinctrl-0 = <&led_pins>;
  629. + pinctrl-names = "default";
  630. +
  631. + led_status_red: led_status_red {
  632. + label = "red:status";
  633. + gpios = <&qcom_pinmux 7 GPIO_ACTIVE_HIGH>;
  634. + default-state = "keep";
  635. + };
  636. +
  637. + led_status_blue: led_status_blue {
  638. + label = "blue:status";
  639. + gpios = <&qcom_pinmux 8 GPIO_ACTIVE_HIGH>;
  640. + default-state = "keep";
  641. + };
  642. +
  643. + led_status_yellow: led_status_yellow {
  644. + label = "yellow:status";
  645. + gpios = <&qcom_pinmux 9 GPIO_ACTIVE_HIGH>;
  646. + default-state = "keep";
  647. + };
  648. + };
  649. +
  650. + i2c_gpio_0 { // GSBI1
  651. + compatible = "i2c-gpio";
  652. + #address-cells = <1>;
  653. + #size-cells = <0>;
  654. + pinctrl-0 = <&i2c1_pins>;
  655. + pinctrl-names = "default";
  656. + sda-gpios = <&qcom_pinmux 53 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
  657. + scl-gpios = <&qcom_pinmux 54 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
  658. + i2c-gpio,delay-us = <5>;
  659. +
  660. + emc2301@2f {
  661. + compatible = "smsc,emc2301";
  662. + reg = <0x2f>;
  663. + #address-cells = <1>;
  664. + #size-cells = <0>;
  665. +
  666. + fan@0 {
  667. + reg = <0>;
  668. + pwm-output-mode = <1>;
  669. + };
  670. + };
  671. + };
  672. +
  673. + i2c_gpio_1 { // GSBI2
  674. + compatible = "i2c-gpio";
  675. + #address-cells = <1>;
  676. + #size-cells = <0>;
  677. + pinctrl-0 = <&i2c2_pins>;
  678. + pinctrl-names = "default";
  679. + sda-gpios = <&qcom_pinmux 24 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
  680. + scl-gpios = <&qcom_pinmux 25 (GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN)>;
  681. + i2c-gpio,delay-us = <5>;
  682. +
  683. + tmp75@48 {
  684. + compatible = "ti,tmp75";
  685. + reg = <0x48>;
  686. + #address-cells = <1>;
  687. + #size-cells = <0>;
  688. + #thermal-sensor-cells = <0>;
  689. + status = "okay";
  690. + };
  691. + };
  692. +};
  693. +
  694. +// https://github.com/openwrt/openwrt/commit/622ce713ca246aa465bf28d2a743f96999085ea2
  695. +// https://github.com/openwrt/openwrt/commit/2336c2dbb1929837f7e42d4315c8073342a5b46b
  696. +// https://forum.openwrt.org/t/failed-to-startup-an-ipq806x-router-on-kernel-5-4/60775/41
  697. +&CPU_SPC {
  698. + status = "disabled";
  699. +};
  700. +
  701. +&adm_dma {
  702. + status = "okay";
  703. +};
  704. +
  705. +&qcom_pinmux {
  706. + i2c1_pins: i2c1_pins { // GSBI1 - EMC2301
  707. + mux {
  708. + pins = "gpio53", "gpio54";
  709. + function = "gsbi1";
  710. + drive-strength = <12>;
  711. + bias-none;
  712. + input;
  713. + };
  714. + };
  715. +
  716. + i2c2_pins: i2c2_pins { // GSBI2 - TMP75
  717. + mux {
  718. + pins = "gpio24", "gpio25";
  719. + function = "gsbi2";
  720. + drive-strength = <12>;
  721. + bias-none;
  722. + input;
  723. + };
  724. + };
  725. +
  726. + button_pins: button_pins {
  727. + mux {
  728. + pins = "gpio16", "gpio68";
  729. + function = "gpio";
  730. + drive-strength = <2>;
  731. + bias-pull-up;
  732. + };
  733. + };
  734. +
  735. + led_pins: led_pins {
  736. + mux {
  737. + pins = "gpio7", "gpio8", "gpio9";
  738. + function = "gpio";
  739. + drive-strength = <2>;
  740. + bias-pull-up;
  741. + };
  742. + };
  743. +
  744. + usb_pwr_en_pins: usb_pwr_en_pins {
  745. + mux {
  746. + pins = "gpio56";
  747. + function = "gpio";
  748. + drive-strength = <12>;
  749. + bias-pull-up;
  750. + output-high;
  751. + };
  752. + };
  753. +};
  754. +
  755. +&sata_phy {
  756. + status = "okay";
  757. +};
  758. +
  759. +&sata {
  760. + status = "okay";
  761. +};
  762. +
  763. +&hs_phy_0 {
  764. + status = "okay";
  765. +};
  766. +
  767. +&ss_phy_0 {
  768. + status = "okay";
  769. +};
  770. +
  771. +&usb3_0 {
  772. + status = "okay";
  773. +};
  774. +
  775. +&hs_phy_1 {
  776. + status = "okay";
  777. +};
  778. +
  779. +&ss_phy_1 {
  780. + status = "okay";
  781. +};
  782. +
  783. +&usb3_1 {
  784. + status = "okay";
  785. + pinctrl-0 = <&usb_pwr_en_pins>;
  786. + pinctrl-names = "default";
  787. +};
  788. +
  789. +&pcie0 {
  790. + status = "okay";
  791. + reset-gpio = <&qcom_pinmux 3 GPIO_ACTIVE_LOW>;
  792. + pinctrl-0 = <&pcie0_pins>;
  793. + pinctrl-names = "default";
  794. +
  795. + bridge@0,0 {
  796. + reg = <0x00000000 0 0 0 0>;
  797. + #address-cells = <3>;
  798. + #size-cells = <2>;
  799. + ranges;
  800. +
  801. + wifi@1,0 {
  802. + compatible = "pci168c,0040";
  803. + reg = <0x00010000 0 0 0 0>;
  804. +
  805. + nvmem-cells = <&macaddr_art_1006>, <&precal_art_1000>;
  806. + nvmem-cell-names = "mac-address", "pre-calibration";
  807. + };
  808. + };
  809. +};
  810. +
  811. +&pcie1 {
  812. + status = "okay";
  813. + reset-gpio = <&qcom_pinmux 48 GPIO_ACTIVE_LOW>;
  814. + pinctrl-0 = <&pcie1_pins>;
  815. + pinctrl-names = "default";
  816. + max-link-speed = <1>;
  817. +
  818. + bridge@0,0 {
  819. + reg = <0x00000000 0 0 0 0>;
  820. + #address-cells = <3>;
  821. + #size-cells = <2>;
  822. + ranges;
  823. +
  824. + wifi@1,0 {
  825. + compatible = "pci168c,0040";
  826. + reg = <0x00010000 0 0 0 0>;
  827. +
  828. + nvmem-cells = <&macaddr_art_5006>, <&precal_art_5000>;
  829. + nvmem-cell-names = "mac-address", "pre-calibration";
  830. + };
  831. + };
  832. +};
  833. +
  834. +&nand {
  835. + status = "okay";
  836. +
  837. + pinctrl-0 = <&nand_pins>;
  838. + pinctrl-names = "default";
  839. +
  840. + nand@0 {
  841. + reg = <0>;
  842. + compatible = "qcom,nandcs";
  843. +
  844. + nand-bus-width = <8>;
  845. + nand-ecc-strength = <4>;
  846. + nand-ecc-step-size = <512>;
  847. +
  848. + nand-is-boot-medium;
  849. + qcom,boot-partitions = <0 0xf0000000>;
  850. +
  851. + partitions {
  852. + compatible = "fixed-partitions";
  853. + #address-cells = <1>;
  854. + #size-cells = <1>;
  855. +
  856. + partition@0 {
  857. + label = "SBL1";
  858. + reg = <0x0 0x40000>;
  859. + read-only;
  860. + };
  861. +
  862. + partition@40000 {
  863. + label = "MIBIB";
  864. + reg = <0x40000 0x80000>;
  865. + read-only;
  866. + };
  867. +
  868. + partition@c0000 {
  869. + label = "SBL2";
  870. + reg = <0xc0000 0x80000>;
  871. + read-only;
  872. + };
  873. +
  874. + partition@140000 {
  875. + label = "SBL3";
  876. + reg = <0x140000 0x80000>;
  877. + read-only;
  878. + };
  879. +
  880. + partition@1c0000 {
  881. + label = "DDRCONFIG";
  882. + reg = <0x1c0000 0x80000>;
  883. + read-only;
  884. + };
  885. +
  886. + partition@240000 {
  887. + label = "SSD";
  888. + reg = <0x240000 0x80000>;
  889. + read-only;
  890. + };
  891. +
  892. + partition@2c0000 {
  893. + label = "TZ";
  894. + reg = <0x2c0000 0x80000>;
  895. + read-only;
  896. + };
  897. +
  898. + partition@340000 {
  899. + label = "RPM";
  900. + reg = <0x340000 0x80000>;
  901. + read-only;
  902. + };
  903. +
  904. + partition@3c0000 {
  905. + label = "APPSBL";
  906. + reg = <0x3c0000 0x100000>;
  907. + read-only;
  908. + };
  909. +
  910. + partition@4c0000 {
  911. + label = "APPSBLENV";
  912. + reg = <0x4c0000 0x80000>;
  913. + };
  914. +
  915. + art: partition@540000 {
  916. + label = "ART";
  917. + reg = <0x540000 0x80000>;
  918. + read-only;
  919. +
  920. + compatible = "nvmem-cells";
  921. + #address-cells = <1>;
  922. + #size-cells = <1>;
  923. +
  924. + macaddr_art_0: macaddr@0 { // WAN (label)
  925. + reg = <0x0 0x6>;
  926. + };
  927. + macaddr_art_6: macaddr@6 { // LAN
  928. + reg = <0x6 0x6>;
  929. + };
  930. + macaddr_art_1006: macaddr@1006 { // WiFi 2g
  931. + reg = <0x1006 0x6>;
  932. + };
  933. + macaddr_art_5006: macaddr@5006 { // WiFi 5g
  934. + reg = <0x5006 0x6>;
  935. + };
  936. + precal_art_1000: precal@1000 {
  937. + reg = <0x1000 0x2f20>;
  938. + };
  939. + precal_art_5000: precal@5000 {
  940. + reg = <0x5000 0x2f20>;
  941. + };
  942. + };
  943. +
  944. + partition@5c0000 {
  945. + label = "BOOTCONFIG";
  946. + reg = <0x5c0000 0x40000>;
  947. + read-only;
  948. + };
  949. +
  950. + partition@600000 {
  951. + label = "bdata";
  952. + reg = <0x600000 0x80000>;
  953. + };
  954. +
  955. + partition@680000 {
  956. + label = "crash";
  957. + reg = <0x680000 0x80000>;
  958. + read-only;
  959. + };
  960. +
  961. + partition@700000 {
  962. + label = "crash_syslog";
  963. + reg = <0x700000 0x80000>;
  964. + read-only;
  965. + };
  966. +
  967. + partition@780000 {
  968. + label = "rsvd";
  969. + reg = <0x780000 0x80000>;
  970. + read-only;
  971. + };
  972. +
  973. + /* Stock U-Boot support Dual Boot */
  974. + partition@800000 {
  975. + label = "kernel_dup";
  976. + reg = <0x800000 0x400000>;
  977. + };
  978. +
  979. + partition@c00000 {
  980. + label = "kernel";
  981. + reg = <0xc00000 0x400000>;
  982. + };
  983. +
  984. + partition@1000000 {
  985. + label = "ubi";
  986. + reg = <0x1000000 0xf000000>;
  987. + };
  988. + };
  989. + };
  990. +};
  991. +
  992. +&mdio0 {
  993. + status = "okay";
  994. +
  995. + pinctrl-0 = <&mdio0_pins>;
  996. + pinctrl-names = "default";
  997. +
  998. + phy0: ethernet-phy@0 {
  999. + reg = <0>;
  1000. + qca,ar8327-initvals = <
  1001. + 0x04 0x07600000 /* PAD0_MODE */
  1002. + 0x08 0x01000000 /* PAD5_MODE */
  1003. + 0x0c 0x00000080 /* PAD6_MODE */
  1004. + 0x7c 0x0000004e /* PORT0_STATUS */
  1005. + 0x94 0x0000004e /* PORT6_STATUS */
  1006. + 0xe0 0xc74164de /* SGMII_CTRL */
  1007. + 0xe4 0x0006a545 /* MAC_POWER_SEL */
  1008. + >;
  1009. + };
  1010. +
  1011. + phy4: ethernet-phy@4 {
  1012. + reg = <4>;
  1013. + };
  1014. +};
  1015. +
  1016. +&gmac1 {
  1017. + status = "okay";
  1018. + phy-mode = "rgmii";
  1019. + qcom,id = <1>;
  1020. +
  1021. + pinctrl-0 = <&rgmii2_pins>;
  1022. + pinctrl-names = "default";
  1023. +
  1024. + nvmem-cells = <&macaddr_art_0>;
  1025. + nvmem-cell-names = "mac-address";
  1026. +
  1027. + fixed-link {
  1028. + speed = <1000>;
  1029. + full-duplex;
  1030. + };
  1031. +};
  1032. +
  1033. +&gmac2 {
  1034. + status = "okay";
  1035. + phy-mode = "sgmii";
  1036. + qcom,id = <2>;
  1037. +
  1038. + nvmem-cells = <&macaddr_art_6>;
  1039. + nvmem-cell-names = "mac-address";
  1040. +
  1041. + fixed-link {
  1042. + speed = <1000>;
  1043. + full-duplex;
  1044. + };
  1045. +};
  1046. diff --git a/target/linux/ipq806x/image/generic.mk b/target/linux/ipq806x/image/generic.mk
  1047. index aac0a2c8fadfd..b437706cd445e 100644
  1048. --- a/target/linux/ipq806x/image/generic.mk
  1049. +++ b/target/linux/ipq806x/image/generic.mk
  1050. @@ -471,6 +471,23 @@ define Device/ubnt_unifi-ac-hd
  1051. endef
  1052. TARGET_DEVICES += ubnt_unifi-ac-hd
  1053. +define Device/xiaomi_r3d
  1054. + $(call Device/LegacyImage)
  1055. + DEVICE_VENDOR := Xiaomi
  1056. + DEVICE_MODEL := R3D
  1057. + SOC := qcom-ipq8064
  1058. + BLOCKSIZE := 128k
  1059. + PAGESIZE := 2048
  1060. + KERNEL_SIZE := 4096k
  1061. + IMAGE_SIZE := 86016k
  1062. + UBINIZE_OPTS := -E 5
  1063. + IMAGES := factory.bin sysupgrade.bin
  1064. + IMAGE/factory.bin := append-kernel | pad-to $$$$(KERNEL_SIZE) | append-ubi | pad-to $$$$(BLOCKSIZE) | check-size
  1065. + DEVICE_PACKAGES := kmod-i2c-gpio kmod-hwmon-lm75 kmod-hwmon-emc2305 hwmon-drivetemp \
  1066. + kmod-usb-storage-uas ath10k-firmware-qca9984-ct ath10k-firmware-qca99x0-ct
  1067. +endef
  1068. +TARGET_DEVICES += xiaomi_r3d
  1069. +
  1070. define Device/zyxel_nbg6817
  1071. DEVICE_VENDOR := ZyXEL
  1072. DEVICE_MODEL := NBG6817