OpenWrt support for Linksys MX4200

I think the problem is from the kernel command line passing from U-Boot.

partbootargs=init=/sbin/init rootfstype=squashfs ubi.mtd=22,2048 ubi.block=0,0 root=/dev/ubiblock0_0 rootwait ro
ubi.mtd=22,2048 

specifies the offset of EC and VID headers is 2048, which will force RO mode, since it is smaller than the minimum input/output unit of the NAND, 4096.

In the stock firmware, that UBI is only used for storing squashfs, so read-only mode is okay. In contrast, OpenWRT uses that UBI for storing squashfs and overlayfs, which requires RW mode.

UBI requires EC and VID headers reside on different minimum input/output unit to enable RW mode, and according to what the NAND driver reports, that is 4096.

To fix this issue, I think we need to let the kernel replace ubi.mtd=22,2048 in the kernel command line to ubi.mtd=22,4096, and create the UBI images without specifying SUBPAGESIZE and VID_HDR_OFFSET. (It will use 4096 as the offset of EC and VID, which will be on different minimum input/output units, and thus supports RW mode.)

2 Likes

Here is an image gallery for the Linksys LN1301 (MX4300) disassembly I did;

https://imgur.com/a/YJM1qfw

I didn't see anything interesting or unexpected. Opportunities for hacking are minimal. The serial port is already exposed and easy to get to. The antenna connections are easy to get to if someone wanted to do an antenna mod. NAND is on the back side, and there's plenty of storage on this thing anyway. Only one of the radio ICs had a thermal pad to connect to the heat sink. I might add pads there if I think it's an issue. My RAM is Kingston, or at least that's how it's etched. I laughed about that.

4 Likes

Thanks for pointing this out. I have prepared a new build for tests: https://github.com/testuser7/openwrt/releases/tag/qualcommax-6443be5

You need to modify this two u-boot env (change 2048 -> 4096):

partbootargs=init=/sbin/init rootfstype=squashfs ubi.mtd=22,4096 ubi.block=0,0 root=/dev/ubiblock0_0 rootwait ro
partbootargs2=init=/sbin/init rootfstype=squashfs ubi.mtd=24,4096 ubi.block=0,0 root=/dev/ubiblock0_0 rootwait ro
1 Like

That worked. After changing u-boot env, the error message disappeared and both WiFi and fw_printenv worked.

Log: https://gist.github.com/jzjsuper/4618019a51f3b798723740a17f70dac6

Perhaps we can patch ubi.mtd automatically by adding this to DT?

	chosen {
		/* look for root deviceblock nbr in this bootarg */
		find-rootblock = "ubi.mtd=";
		bootargs = "/sbin/init rootfstype=squashfs ubi.block=0,0 root=/dev/ubiblock0_0 rootwait ro root=/dev/ubiblock0_0";
		/* append to bootargs adding the root deviceblock nbr from bootloader */
		append-rootblock = "ubi.mtd=";
	};

I expect this will remove ",2048" from ubi.mtd, leaving only the mtd partition number, such as

/sbin/init rootfstype=squashfs ubi.block=0,0 root=/dev/ubiblock0_0 rootwait ro root=/dev/ubiblock0_0 ubi.mtd=22

This requires porting the following patch from ipq806x to qualcommax. I'm not sure whether it is doable.

Example usages of some devices:

Thanks, the last thing is the MAC addresses. Can you start wireless interfaces and show iwinfo output?

I think this could be considered as the next step after adding support.

phy0-ap0  ESSID: "OpenWrt"
          Access Point: D8:EC:5E:94:E5:64
          Mode: Master  Channel: 36 (5.180 GHz)  HT Mode: HE80
          Center Channel 1: 42 2: unknown
          Tx-Power: 24 dBm  Link Quality: unknown/70
          Signal: unknown  Noise: -113 dBm
          Bit Rate: unknown
          Encryption: none
          Type: nl80211  HW Mode(s): 802.11ac/ax/n
          Hardware: embedded [Qualcomm Atheros IPQ8074]
          TX power offset: none
          Frequency offset: none
          Supports VAPs: yes  PHY name: phy0

phy1-ap0  ESSID: "OpenWrt"
          Access Point: D8:EC:5E:94:E5:63
          Mode: Master  Channel: 1 (2.412 GHz)  HT Mode: HE20
          Center Channel 1: 1 2: unknown
          Tx-Power: 26 dBm  Link Quality: unknown/70
          Signal: unknown  Noise: -102 dBm
          Bit Rate: unknown
          Encryption: none
          Type: nl80211  HW Mode(s): 802.11ax/b/g/n
          Hardware: embedded [Qualcomm Atheros IPQ8074]
          TX power offset: none
          Frequency offset: none
          Supports VAPs: yes  PHY name: phy1

phy2-ap0  ESSID: "OpenWrt"
          Access Point: D8:EC:5E:94:E5:65
          Mode: Master  Channel: 100 (6.450 GHz)  HT Mode: NOHT
          Center Channel 1: unknown 2: unknown
          Tx-Power: 0 dBm  Link Quality: unknown/70
          Signal: unknown  Noise: unknown
          Bit Rate: unknown
          Encryption: none
          Type: nl80211  HW Mode(s): 802.11ac/ax/n
          Hardware: embedded [Qualcomm Atheros IPQ8074]
          TX power offset: none
          Frequency offset: none
          Supports VAPs: yes  PHY name: phy2

By the way, /etc/fw_env.config is incorrect. It should be

/dev/mtd18 0x0 0x000040000 0x00040000 1
1 Like

Thanks, corrected.

The storage configuration on this device (MX4300) is a tragedy of wastefulness. The kernel is on raw NAND, outside of any UBI. Uboot supports UBI but isn't using it. The squashfs and writable config filesystems are seperate UBIs, so that's a pile of wasted space (160MB x2) and constrains the theoretical size of the squashfs at the same time. It's the worst of all possible options. The writable storage area is non-redundant, which reduces the usefulness of redundant system partitions to near-zero.

As for the app2_data and app2 partitions that take up half the damn NAND, I don't even know what that is yet.

It appears that the MAC addresses for the wireless interfaces are configured correctly in the art partition.

I have prepared another build with MAC address assignment for LAN interfaces: https://github.com/testuser7/openwrt/releases/tag/qualcommax-83f0bf7

1 Like

I'm working on basic support. You can submit changes in the future.

3 Likes

Using this build and modifying the uboot partbootargs, this booted on my device successfully. WAN port works correctly and automatically received a DHCP lease and I got internet connectivity. Wifi also works following the steps to set disabled=0 in the config then running wifi.

Was able to easily install LuCI via opkg as well.

LAN/WAN MAC addresses:

3 Likes

I used nanddump to dump both partitions.
My app2 is empty (only 0xFF from the start to the end).
app2_data is quite interesting.

ubireader_display_info ~/app2_data 
UBI File
---------------------
	Min I/O: 4096
	LEB Size: 253952
	PEB Size: 262144
	Total Block Count: 343
	Data Block Count: 241
	Layout Block Count: 2
	Internal Volume Block Count: 0
	Unknown Block Count: 100
	First UBI PEB Number: 1071

	Image: 1047401851
	---------------------
		Image Sequence Num: 1047401851
		Volume Name:kernel
		Volume Name:ubi_rootfs
		PEB Range: 0 - 342

		Volume: kernel
		---------------------
			Vol ID: 0
			Name: kernel
			Block Count: 16

			Volume Record
			---------------------
				alignment: 1
				crc: '0x69f200d5'
				data_pad: 0
				errors: ''
				flags: 0
				name: 'kernel'
				name_len: 6
				padding: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
				rec_index: 0
				reserved_pebs: 42
				upd_marker: 0
				vol_type: 'dynamic'


		Volume: ubi_rootfs
		---------------------
			Vol ID: 1
			Name: ubi_rootfs
			Block Count: 225

			Volume Record
			---------------------
				alignment: 1
				crc: '0x387a730f'
				data_pad: 0
				errors: ''
				flags: 'autoresize'
				name: 'ubi_rootfs'
				name_len: 10
				padding: '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
				rec_index: 1
				reserved_pebs: 225
				upd_marker: 0
				vol_type: 'dynamic'

2 Likes

All four ports (3 lan and 1 wan) worked.

Log: https://gist.github.com/jzjsuper/69773a8944710af89163f3b59d805d2c

3 Likes

interesting, ln1301 seems to be given away with stuff in USA as dirt cheap, not much in the UK!
Interesting it has fortinet branding. i'm guessing the default firmware still "looks" linksys and from details above it certainly has the same linksys layout

Does anybody have a compiled version of the NSS branch for MX4200v1 (or instructions how to compile it)? I'm interested in testing it out as I experience random disconnects and notice this error:

ath11k c000000.wifi: failed to flush transmit queue, data pkts pending

It is very noticeable in Teams calls where the meeting freezes for 2-3 seconds.

MAC addresses for lan2 and lan3 are still incorrect.

Can you try this new build: https://github.com/testuser7/openwrt/releases/tag/qualcommax-c61cb0f ?

Please also check if it works:

  • led
  • reset button
  • wps button

What MAC addresses do the wired interfaces have on OEM software?

Interestingly the stock firmware reports all ethernet MACs as the same value (80:69:1A:22:FE:8B is also the MAC printed on the bottom of the device)

~ # ifconfig | grep "HWaddr"
ath0      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8C  
ath0.4    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8C  
ath1      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8D  
ath1.4    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8D  
ath10     Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8E  
ath10.4   Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8E  
ath5      Link encap:Ethernet  HWaddr 86:69:1A:22:FE:8C  
br0       Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
br2       Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8C  
eth0      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth1      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth1.4    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth2      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth2.4    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth3      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
eth3.4    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B  
wifi0     Link encap:UNSPEC  HWaddr 80-69-1A-22-FE-8D-00-00-00-00-00-00-00-00-00-00  
wifi1     Link encap:UNSPEC  HWaddr 80-69-1A-22-FE-8C-00-00-00-00-00-00-00-00-00-00  
wifi2     Link encap:UNSPEC  HWaddr 80-69-1A-22-FE-8E-00-00-00-00-00-00-00-00-00-00

Using your latest release https://github.com/testuser7/openwrt/releases/tag/qualcommax-c61cb0f

root@OpenWrt:/# ifconfig | grep "HWaddr"
br-lan    Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8C  
lan1      Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8C  
lan2      Link encap:Ethernet  HWaddr BA:5E:06:8A:BF:72  
lan3      Link encap:Ethernet  HWaddr 76:BD:4B:57:03:B3  
phy0-ap0  Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8E  
phy1-ap0  Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8D  
wan       Link encap:Ethernet  HWaddr 80:69:1A:22:FE:8B

Reset button works - short press for reboot, long press for factory reset both work.

WPS button doesn't seem to work even when configured correctly on the wifi ifaces. Seems like the GPIO pin might be incorrect. I tried to find which one it was without much success, but here's a dump of /sys/kernel/debug/gpio that might be helpful.

root@OpenWrt:~# cat /sys/kernel/debug/gpio
gpiochip0: GPIOs 512-581, parent: platform/1000000.pinctrl, 1000000.pinctrl:
 gpio0   : in  low  func1 2mA pull down
 gpio1   : in  high func1 8mA no pull
 gpio2   : in  high func1 2mA pull down
 gpio3   : in  high func1 8mA no pull
 gpio4   : in  high func1 8mA no pull
 gpio5   : in  low  func1 8mA no pull
 gpio6   : in  low  func1 8mA no pull
 gpio7   : in  low  func1 8mA no pull
 gpio8   : in  low  func1 8mA no pull
 gpio9   : in  high func1 2mA pull down
 gpio10  : in  high func1 8mA no pull
 gpio11  : in  high func1 8mA no pull
 gpio12  : in  low  func1 8mA no pull
 gpio13  : in  low  func1 8mA no pull
 gpio14  : in  low  func1 8mA no pull
 gpio15  : in  low  func1 8mA no pull
 gpio16  : in  low  func1 2mA pull down
 gpio17  : in  high func1 8mA no pull
 gpio18  : in  low  func0 2mA pull down
 gpio19  : in  low  func0 2mA pull down
 gpio20  : in  low  func0 2mA pull down
 gpio21  : in  high func0 2mA pull up
 gpio22  : in  low  func0 2mA pull down
 gpio23  : in  high func2 8mA no pull
 gpio24  : out low  func2 8mA no pull
 gpio25  : in  low  func0 2mA pull down
 gpio26  : in  low  func0 2mA pull down
 gpio27  : in  low  func0 2mA pull down
 gpio28  : in  high func0 2mA pull down
 gpio29  : in  low  func0 2mA pull down
 gpio30  : in  high func0 2mA pull down
 gpio31  : in  low  func0 2mA pull down
 gpio32  : in  high func0 2mA pull down
 gpio33  : in  low  func0 2mA pull down
 gpio34  : in  low  func0 2mA pull down
 gpio35  : in  low  func0 2mA pull down
 gpio36  : in  high func0 2mA pull down
 gpio37  : out high func0 2mA pull down
 gpio38  : in  high func0 2mA pull up
 gpio39  : in  high func0 2mA pull up
 gpio40  : in  high func0 2mA pull up
 gpio41  : in  high func0 2mA pull up
 gpio42  : in  high func0 8mA no pull
 gpio43  : in  high func0 8mA no pull
 gpio44  : in  low  func0 2mA pull down
 gpio45  : in  high func0 2mA pull down
 gpio46  : in  high func0 8mA no pull
 gpio47  : in  high func0 8mA no pull
 gpio48  : in  high func0 8mA no pull
 gpio49  : in  high func0 8mA no pull
 gpio50  : in  low  func0 2mA pull down
 gpio51  : in  low  func0 2mA pull down
 gpio52  : in  high func0 8mA pull up
 gpio53  : in  low  func0 2mA pull down
 gpio54  : in  low  func0 2mA pull down
 gpio55  : in  low  func0 2mA pull down
 gpio56  : in  low  func0 2mA pull down
 gpio57  : in  low  func0 2mA pull down
 gpio58  : in  low  func0 2mA pull down
 gpio59  : in  low  func0 2mA pull down
 gpio60  : in  low  func0 2mA pull down
 gpio61  : in  low  func0 2mA pull down
 gpio62  : in  low  func0 2mA pull down
 gpio63  : in  low  func0 2mA pull down
 gpio64  : in  low  func0 2mA pull down
 gpio65  : in  low  func0 2mA pull down
 gpio66  : in  low  func0 2mA pull down
 gpio67  : in  high func0 8mA pull up
 gpio68  : in  high func0 8mA pull up
 gpio69  : in  high func0 8mA pull up

gpiochip1: GPIOs 582-593, parent: platform/200f000.spmi:pmic@0:gpio@c000, 200f000.spmi:pmic@0:gpio@c000:
 gpio1 : ---
 gpio2 : in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio3 : out  high normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio4 : in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio5 : in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio6 : in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio7 : out  high normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio8 : in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio9 : out  high normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio10: in   low  normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio11: out  high normal  vin-0 pull-down 10uA              push-pull  high    atest-1 dtest-0
 gpio12: ---
1 Like