Edit (May 2020): The router is fully supported and can be flashed withouth opening the case.
Hi there,
A few days ago, a colleague from eXO pointed me to this new device by Xiaomi, which would be very nice to have it supported by OpenWrt to use it in our community network. I ordered it from a well-known on-line shop and I just received it, so I'll be posting here any updates on adding support for it.
Main specifications
- SoC: MediaTek MT7621
- RAM: 128 MB
- Flash: 16 MB SPI flash
- Ethernet: 3x10/100/1000 Mbps (2xLAN, 1xWAN)
- WiFi: dual band, 802.11bgn + 802.11ac
Pictures
IMPORTANT NOTICE
This post is not a tutorial on how to flash OpenWrt on the device; I am just showing what I've discovered so far regarding this device. If you try anything on your device and void its warranty, break it, or if you injure yourself or someone else, I take no responsibility. You've been warned.
TTL UART
First thing I do is soldering some cables to the UART pins on the board and connect them to a TTL to USB adapter. I can see the usual Linux output from a router but, unfortunately, I can't interact with it: I can't stop U-Boot from booting automatically and I can't enter the command line interface once the stock firmware has booted.
Stock firmware bootlog
Here you can see the full bootloader and stock firmware bootlogs:
- Stock U-Boot bootlog: https://pastebin.com/cnxq6TnZ
- Stock firmware bootlog: https://pastebin.com/ksSngTvF
No SSH/Telnet on the stock firmware
The router has, by default, the address 192.168.31.1/24. I try to SSH or telnet it, but the connection is refused.
First OpenWrt support attempt
Based on the information I collect from the stock firmware bootlog, I add basic support for the device. You can see my git branch here: https://github.com/rogerpueyo/openwrt/tree/xiaomi-mi-router-4a-1000m-gigabit-edition_wip
The stock firmware's web interface is a heavily modified LuCI, with a section for updating the firmware. It can search and download an image from the vendor's website, but it also allows manually uploading a firmware file. I try to upload my recently created openwrt-ramips-mt7621-xiaomi_mir4a-gigabit-squashfs-sysupgrade.bin, but the router refuses to flash it.
When the reset button is pressed during power-on, the stock bootloader starts a TFTP client to download and flash a firmware image. I set up a TFTP server on my computer and send an image file. Unfortunately, the bootloader does not like it:
Click here to see the stock U-Boot refusing the firmware image via TFTP log.
BOOTP broadcast 2
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 3
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 3
DHCP: state=SELECTING bp_file: "test.bin"
TRANSITIONING TO REQUESTING STATE
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: test.bin
DhcpSendRequestPkt: Sending DHCPREQUEST
Transmitting DHCPREQUEST packet: len = 343
DHCPHandler: got packet: (src=67, dst=68, len=300) state: 4
Filtering pkt = 0
DHCPHandler: got DHCP packet: (src=67, dst=68, len=300) state: 4
DHCP State: REQUESTING
*** Unhandled DHCP Option in OFFER/ACK: 28
Bootfile: test.bin
DHCP client bound to address 192.168.31.100
TFTP from server 192.168.31.2; our IP address is 192.168.31.100
Filename 'test.bin'.
TIMEOUT_COUNT=10,Load address: 0x82000000
Loading: Got ARP REPLY, set server/gtwy eth addr (00:1e:00:1e:1e:b1)
Got it
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################Got ARP REQUEST, return our IP
################################################
#################################################################
#################################################################
###########
done
Bytes transferred = 4380578 (42d7a2 hex)
LoadAddr=82000000 NetBootFileXferSize= 0042d7a2
TRX MAGIC error!
Header check error!
Image verify failed!
========Upgrade fail!========
Nevertheless, I've noticed that if during the TFTP file loading process I hit CTRL+C, the process stops:
TIMEOUT_COUNT=10,Load address: 0x82000000
Loading: Got ARP REPLY, set server/gtwy eth addr (00:1e:00:1e:1e:b1)
Got it
#################################################################
##################################
Abort
========Upgrade fail!========
This is good! It means the UART's RX port is active and U-Boot is receiving the command.
Dumping the SPI FLASH memory
Since I am unable to get access to the console or the bootloader, neither remotely (SSH/Telnet) nor using the UART, maybe it's time to see what's inside the FLASH memory.
With a CH341 USB SPI serial programmer and an SPI clamp, which you can both buy from a well-known on-line shop, I dump the whole content of the SPI FLASH memory to my computer. To do so, I use this very nice tool: ch341prog. Here is a picture of the whole thing in action:
A small detail: the SPI FLASH chip (or the whole router board, probably) draws too much power from the CH341, so I have to add some "extra" power by connecting the programmers' 3.3V pin to the USB to TTL's 3.3V pin to somehow "sum" the total amount of power on the 3.3V rail. It's a nasty trick from the formal point of view, but does the thing.
Extracting the SPI FLASH memory content using binwalk
I use binwalk to see what's inside the router's SPI FLASH now that I have it dumped on my computer:
binwalk -e spi_flash.dump
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
97696 0x17DA0 U-Boot version string, "U-Boot 1.1.3 (Jan 24 2019 - 07:46:43)"
98248 0x17FC8 CRC32 polynomial table, little endian
WARNING: Extractor.execute failed to run external extractor 'jefferson -d '%%jffs2-root%%' '%e'': [Errno 2] No such file or directory: 'jefferson'
524288 0x80000 JFFS2 filesystem, little endian
1572864 0x180000 uImage header, header size: 64 bytes, header CRC: 0xD8422C49, created: 2019-01-24 07:54:52, image size: 1855537 bytes, Data Address: 0x81001000, Entry Point: 0x813ECCE0, data CRC: 0xC26BDD0D, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "MIPS OpenWrt Linux-3.10.14"
1572928 0x180040 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 5458688 bytes
2705694 0x29491E COBALT boot rom data (Flat boot rom or file system)
3473408 0x350000 Squashfs filesystem, little endian, version 4.0, compression:xz, size: 11348484 bytes, 2236 inodes, blocksize: 262144 bytes, created: 2019-01-24 07:54:48
WARNING: Extractor.execute failed to run external extractor 'jefferson -d '%%jffs2-root%%' '%e'': [Errno 2] No such file or directory: 'jefferson'
15204352 0xE80000 JFFS2 filesystem, little endian
I see that the Squashfs partition contains the usual Ralink SDK based on OpenWrt 12.09.1. For instance:
$ cat _spi_flash.dump.extracted/squashfs-root/etc/openwrt_release
DISTRIB_ID="OpenWrt"
DISTRIB_RELEASE="Attitude Adjustment"
DISTRIB_REVISION="unknown"
DISTRIB_CODENAME="attitude_adjustment"
DISTRIB_TARGET="ramips/mt7621"
DISTRIB_DESCRIPTION="OpenWrt Attitude Adjustment 12.09.1"
Modifying the U-Boot bootloader timeout with Bless
As the U-Boot bootlog above shows, the bootloader shows the usual options (booting from TFTP, flashing an image, etc.) but it does not wait for the user's command with a countdown, it boots straight ahead:
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
n3: System Boot system code via Flash.
Using the Bless hex editor I open the SPI FLASH dump and find the "bootdelay" parameter at 0x19690 is set to "off":
I can change the value to something more convenient, say 5 seconds to, hopefully, be able to interact with the bootloader:
Using the ch341prog tool I erase the router's SPI FLASH chip and write the modified dump. Fortunately, the result is satisfactory and I can now stop the bootloader's countdown and interact with it:
Ralink UBoot Version: 5.0.0.0
--------------------------------------------
ASIC MT7621A DualCore (MAC to MT7530 Mode)
DRAM_CONF_FROM: Auto-Detection
DRAM_TYPE: DDR3
DRAM bus: 16 bit
Xtal Mode=3 OCP Ratio=1/3
Flash component: SPI Flash
Date:Jan 24 2019 Time:07:46:43
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:256, ways:4, linesz:32 ,total:32768
##### The CPU freq = 880 MHZ ####
estimate memory size =128 Mbytes
#Reset_MT7530
set LAN/WAN LLLLW
restore_defaults:1
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
2
You choosed 4
0
4: System Enter Boot Command Line Interface.
U-Boot 1.1.3 (Jan 24 2019 - 07:46:43)
MT7621 # ?
? - alias for 'help'
bootm - boot application image from memory
cp - memory copy
dhcp - invoke DHCP client to obtain IP/boot params
intena - intena
intena - intena
erase - erase SPI FLASH memory
go - start application at address 'addr'
help - print online help
loadb - load binary file over serial line (kermit mode)
md - memory display
mdio - Ralink PHY register R/W command !!
mm - memory modify (auto-incrementing)
mt - mt cnt start size
nm - memory modify (constant address)
printenv- print environment variables
readcnt - readcnt
reset - Perform RESET of the CPU
rf - read/write rf register
saveenv - save environment variables to persistent storage
setenv - set environment variables
spi - spi command
tftpboot- boot image via network using TFTP protocol
trap_init - trap_init
version - print monitor version
Amazing!
Booting an initramfs image via TFTP
Now that I can interact with U-Boot, I can send the initramfs image I generated to the device via TFTP:
Ralink UBoot Version: 5.0.0.0
--------------------------------------------
ASIC MT7621A DualCore (MAC to MT7530 Mode)
DRAM_CONF_FROM: Auto-Detection
DRAM_TYPE: DDR3
DRAM bus: 16 bit
Xtal Mode=3 OCP Ratio=1/3
Flash component: SPI Flash
Date:Jan 24 2019 Time:07:46:43
============================================
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:256, ways:4, linesz:32 ,total:32768
##### The CPU freq = 880 MHZ ####
estimate memory size =128 Mbytes
#Reset_MT7530
set LAN/WAN LLLLW
restore_defaults:1
Please choose the operation:
1: Load system code to SDRAM via TFTP.
2: Load system code then write to Flash via TFTP.
3: Boot system code via Flash (default).
4: Entr boot command line interface.
7: Load Boot Loader code then write to Flash via Serial.
9: Load Boot Loader code then write to Flash via TFTP.
You choosed 1
0
1: System Load Linux to SDRAM via TFTP.
Please Input new ones /or Ctrl-C to discard
Input device IP (192.168.31.1) ==:192.168.31.1
Input server IP (192.168.31.2) ==:192.168.31.2
Input Linux Kernel filename (test.bin) ==:test.bin
NetTxPacket = 0x87FE52C0
KSEG1ADDR(NetTxPacket) = 0xA7FE52C0
NetLoop,call eth_halt !
NetLoop,call eth_init !
Trying Eth0 (10/100-M)
Waitting for RX_DMA_BUSY status Start... done
ETH_STATE_ACTIVE!!
TFTP from server 192.168.31.2; our IP address is 192.168.31.1
Filename 'test.bin'.
TIMEOUT_COUNT=10,Load address: 0x80a00000
Loading: Got ARP REPLY, set server/gtwy eth addr (00:1e:00:1e:1e:b1)
Got it
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#######################################################Got ARP REQUEST, return our IP
##########
#################################################################
#################################################################
###########
done
Bytes transferred = 4380578 (42d7a2 hex)
LoadAddr=80a00000 NetBootFileXferSize= 0042d7a2
Automatic boot of image at addr 0x80A00000 ...
## Booting image at 80a00000 ...
Image Name: MIPS OpenWrt Linux-4.14.115
Image Type: MIPS Linux Kernel Image (lzma compressed)
Data Size: 4380514 Bytes = 4.2 MB
Load Address: 80001000
Entry Point: 80001000
Verifying Checksum ... OK
Uncompressing Kernel Image ... OK
Erasing SPI Flash...
raspi_erase: offs:30000 len:10000
.
Writing to SPI Flash...
.
done
commandline uart_en=0 factory_mode=0 mem=128m root=/dev/mtdblock9
No initrd
## Transferring control to Linux (at address 80001000) ...
## Giving linux memsize in MB, 128
Starting kernel ...
[ 0.000000] Linux version 4.14.115 (chumba@wamba) (gcc version 7.4.0 (OpenWrt GCC 7.4.0 r9945-bc85640cdc)) #0 SMP Wed May 8 19:40:47 2019
[ 0.000000] SoC Type: MediaTek MT7621 ver:1 eco:3
[ 0.000000] bootconsole [early0] enabled
[ 0.000000] CPU0 revision is: 0001992f (MIPS 1004Kc)
[ 0.000000] MIPS: machine is Xiaomi Mi Router 4A Gigabit Edition
[ 0.000000] Determined physical RAM map:
[ 0.000000] memory: 08000000 @ 00000000 (usable)
[ 0.000000] Initrd not found or empty - disabling initrd
[ 0.000000] VPE topology {2,2} total 4
[ 0.000000] Primary instruction cache 32kB, VIPT, 4-way, linesize 32 bytes.
[ 0.000000] Primary data cache 32kB, 4-way, PIPT, no aliases, linesize 32 bytes
[ 0.000000] MIPS secondary cache 256kB, 8-way, linesize 32 bytes.
[etc.]
Please press Enter to activate this console.
BusyBox v1.30.1 () built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| W I R E L E S S F R E E D O M
-----------------------------------------------------
OpenWrt SNAPSHOT, r9946-7c970cba98
-----------------------------------------------------
=== WARNING! =====================================
There is no root password defined on this device!
Use the "passwd" command to set up a new password
in order to prevent unauthorized SSH logins.
--------------------------------------------------
root@OpenWrt:/# cat /tmp/sysinfo/board_name
xiaomi,mir4a-gigabit
That's very good!
Summary: what's working, what's missing
-
Working
- SoC/RAM/FLASH detection
- Ethernet
- Wireless
- Reset button
- LEDS (1x blue, 1x orange)
-
Missing
- Sysupgrade
- Factory image