Back to Home

Flashing Upvel UR-313N4G router on OpenWRT

Upvel openwrt

Flashing Upvel UR-313N4G router on OpenWRT

  • Tutorial


Once, even before the dollar jumps, I needed a very cheap SOHO router. Requirements - 5 ports, NAT and Wi-Fi, USB would not hurt. The choice fell on the Upvel UR-313N4G, which in those days cost a ridiculous 860 rubles at Citilink. The router was purchased and performed its duties quite tolerably, stably hanging once a week. In addition, port forwarding did not work, so what, it didn’t need much pain. In addition, the Web interface had access to the command line, so in critical cases, you could just write iptables -A PREROUTING -j DNAT and enjoy working ports until the next hang. However, I did not expect more from the box for such a ridiculous price. Then something in my life changed and the router went to the far shelf, and it was replaced by TP-Link TR-ML3420. I must say that the TR-ML3420 works fine under OpenWRT and there are no problems with it, but Upvel routers are not officially supported by OpenWRT a little less than completely (of the entire model range - only two routers).
When it became clear that Upvel UR-313N4G was not a pity to me, I decided to try installing OpenWRT on it. The main task is to make Megafon M21-4 3G-modem work, it's also Huawei E3531. I must say that I had the experience of flashing routers on OpenWRT, both through the Web interface and through UART, but it boiled down to “select the file for the firmware and pray” or “type these three commands in the console and pray.” This time I wanted to figure out why such commands are being introduced, and in general to get a general idea of ​​the MIPS architecture, with which I had not worked before.

Here, of course, it should be noted that reading this material to fathers who are developing Gigabit Ethernet cards on FPGA and writing video drivers for the Mali-400 will probably be ridiculous - they all know this for so long.

First, ask Google what we will sew and where. The x86 architecture uses specially prepared media to boot the OS - a hard disk, SSD or flash memory marked according to the MBR or GPT standard, with the main boot record and a specially marked boot partition. The internal structure of the disk is hidden from the OS by its firmware, and the BIOS provides minimal functionality even when the OS is not installed. In a router with MIPS architecture, everything is arranged differently. The data is stored on an MTD device, which is an EEPROM chip without a controller, so when we write to this circuit, we need to try not to write to the same sectors too often. In addition, MTD has a fixed and rather large block size, which can be erased (in my case - 64Kb). There is no partition table on the MTD device, but when the Linux kernel is loaded, it simulates the presence of a partition table. The settings for this simulation are set either during the kernel assembly, or using the mtdparts parameter at boot time. At the beginning of MTD, there is a bootloader that can be erased if circumstances fail, and only the EEPROM firmware on the programmer will help. The bootloader unpacks the image stitched in MTD into memory and transfers control to the Linux kernel.

Now it's time to experiment. First, open the router and see the marking of the main chip - Ralink 5350F. Easy googling shows that this chip is supported by OpenWRT, and pretty good - there is a whole catalog of ramips with firmware for the 5350 series. You can also see a 32MB RAM chip and an 8MB EEPROM chip on the board. A search on the w3bsit3-dns.com site shows that the Upvel UR-322N4G, Hame MPR-A1 and Zyxel Keenetic 4G II are built on the Ralink 5350F chipset. Well, download OpenWRT for Hame MPR-A1 and try to flash through the router’s Web interface.
The firmware is not being sewn, apparently, some signatures are not being tested. To find out with the debugger at the ready which ones there is no desire. Well, okay, it didn’t hurt.

There are several ways to upgrade a router without using a web interface. You can, for example, use the recovery mode, which the bootloader switches to when the router starts. if the reset button is pressed. Looking ahead, I’ll say that Upvel UR-313N4G does not have this mode, it’s unlucky, what can you do.
You can also connect to the router via telnet, which is available in the original firmware, “clear” the router’s memory by killing unnecessary processes, load new firmware into the memory via tftp and flash it with the mtd_write command. This way is bad because we, in fact, have only one attempt - if the firmware turns out to be incompatible with the router and cannot boot, then at the output we get a “half brick” that can be restored, but only through UART. In addition, in this case you will have to rack your brains over which section of the MTD the firmware should be written to. I must say right away - in the MTD markup, which is used in the original firmware, there is no Firmware section.

Firmware via UART


From all this it follows that for experiments we need to connect to the router via UART, then we will have access to the console from the moment the router starts. Just in case, we will order a programmer from China for 160 rubles. If we do not kill the bootloader, we do not need a programmer, but, as they say, “there are different cases”. On the board, if you hold it with LEDs to yourself, in the upper right part there are 4 unconnected openings in a row, suspiciously similar to UART. We carefully look at the board - the first hole on the left is made in a wide layer of foil, it seems that this is circuit ground, the tracks from the next two holes through the resistors go somewhere deeper into the board - these are Rx and Tx, however, it is not yet clear. in what order. The far right hole is also located on the foil layer, but smaller, it is most likely +3.3 V. We pick up a tester and measure the voltage. On Tx there should be +3.3 V, on Rx - 0 V. We get (from left to right) - 0V; 3.3V, 0V, 3.3V. So, the second on the left is Tx, and the third is Rx. The pin on the right is 3.3V, we will not solder it - we will burn the adapter.
We take the Chinese clone of the Nokia CA-42 cord, cut it, find the pinout in Google and solder (from left to right) - orange, red, blue.

We put Putty (I have Linux on the workstation, there shouldn’t be any problems with Windows either) and select the port speed: we set the standard values ​​for the COM port, turn on the router and see that there are not crackers on the screen, but meaningful text. I connected at a speed of 57600 baud. Now we have access to the bootloader, which means that the chance to brick the router is reduced.

Ok, let's try to flash through the bootloader. At the start of the system, we see a greeting

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. 

What interests me most in this menu is point 1 - getting the firmware via TFTP and starting it from RAM. It turns out that you can check the firmware compatibility with the device without even flashing it in EEPROM. For me it was a pleasant surprise. We install the tftp server (I took atftpd), put the firmware from Hame MPR-A1 in the working directory and rename it more conveniently - to mpr-a1.bin.
We start the router, press the button 1 in the console, set the address 10.10.10.3 on the computer’s network interface, enter the necessary parameters in the bootloader and load the firmware.

The firmware has started, cheers! There is even access to the Web interface, which means that most of the firmware is functional. And we still didn’t sew anything! Only something strange is happening with the LEDs - only Wi-Fi is on (but it is turned off and should not be lit), but the LEDs on the Ethernet ports do not light. We understand further. OpenWRT uses the swconfig utility to configure switches. We find out what our switch can do

>swconfig dev rt2305x help
switch0: rt305x(rt305x-esw), ports: 7 (cpu @ 6), vlans: 4096
     --switch
    Attribute 1 (int): enable_vlan (VLAN mode (1:enabled))
    Attribute 2 (int): alternate_vlan_disable (Use en_vlan instead of doubletag to disable VLAN mode)
    Attribute 3 (int): bc_storm_protect (Global broadcast storm protection (0:Disable, 1:64 blocks, 2:96 blocks, 3:128 blocks))
    Attribute 4 (int): led_frequency (LED Flash frequency (0:30mS, 1:60mS, 2:240mS, 3:480mS))
    Attribute 5 (none): apply (Activate changes in the hardware)
    Attribute 6 (none): reset (Reset the switch)
     --vlan
    Attribute 1 (ports): ports (VLAN port mapping)
     --port
    Attribute 1 (int): disable (Port state (1:disabled))
    Attribute 2 (int): doubletag (Double tagging for incoming vlan packets (1:enabled))
    Attribute 3 (int): untag (Untag (1:strip outgoing vlan tag))
    Attribute 4 (int): led (LED mode (0:link, 1:100m, 2:duplex, 3:activity, 4:collision, 5:linkact, 6:duplcoll, 7:10mact, 8:100mact, 10:blink, 11:off, 12:on))
    Attribute 5 (int): lan (HW port group (0:wan, 1:lan))
    Attribute 6 (int): recv_bad (Receive bad packet counter)
    Attribute 7 (int): recv_good (Receive good packet counter)
    Attribute 8 (int): tr_bad (Transmit bad packet counter. rt5350 only)
    Attribute 9 (int): tr_good (Transmit good packet counter. rt5350 only)
    Attribute 10 (int): pvid (Primary VLAN ID)
    Attribute 11 (string): link (Get port link information)

At first glance, it is encouraging, we can manage not only VLANs, which is vital for distinguishing between LAN and WAN subnet traffic, but also program LEDs.
Do

>swconfig dev rt305x port 4 set led 12
>swconfig dev rt305x set apply

and ... nothing happens. Apparently the problem is somewhere deeper in the drivers. Good thing OpenWRT has open source code. We go to the git repository , find the source of the driver there and see

446 static void esw_hw_init(struct rt305x_esw *esw)
447 {
448         int i;
449         u8 port_disable = 0;
450         u8 port_map = RT305X_ESW_PMAP_LLLLLL;
451
452         /* vodoo from original driver */
453         esw_w32(esw, 0xC8A07850, RT305X_ESW_REG_FCT0);
454         esw_w32(esw, 0x00000000, RT305X_ESW_REG_SGC2);

here, voodoo magic seems to be used. And yet - according to the driver code, it is immediately clear that without detailed documentation on the switch registers we can not figure it out. But it is clear that the driver parameters are set not through the arguments of the modprobe command, but, apparently, through the lines compiled into the kernel:

1431    reg_init = of_get_property(np, "ralink,led_polarity", NULL);

Okay, set aside the source and try to enter from the other side. All three routers - Upvel UR-322N4G, Hame MPR-A1 and Zyxel Keenetic 4G II - are dual-port. Surely among the clouds of supported models on the Ralink 5350 there are five-port models. We go to WikiDev and find, for example, D-Link 320 NRU B1. A five-port router, one USB port is what you need. We download the firmware, load it into the memory of the router, and launch it. LEDs work as expected. Very interesting. We will flash on it, for now we’ll try to find the difference between OpenWRT for the Hame MPR-A1 and D-Link 320 NRU B1. The difference must be sought in the assembly profiles - DTS. Here, for example, the led_polarity parameter for Hame is not specified, and for D-Link it is 0x17. And I thought that polarity is only direct and reverse! We climb into the driver source again, we find a constant there

#define RT5350_EWS_REG_LED_POLARITY     0x168

we find a way to set the polarity
565                 /* set the led polarity */
566                 esw_w32(esw, esw->reg_led_polarity & 0x1F, RT5350_EWS_REG_LED_POLARITY);

and again we are convinced that without a description of the registers of the switch, we have nothing to catch.

We found out that firmware from D-Link DIR-320 NRU B1 is best suited for our router. Now you need to flash. Perhaps you noticed that for testing the firmware I selected files with the word uImage in the name. Such a file contains only a kernel image and a file system loaded into RAM and read-only. Such an image can be run directly from memory, but it is not very suitable for firmware - there is simply nowhere to store settings in this image. Therefore, for firmware, we will choose an image with the sysupgrade extension - at the end of such an image, a JFFS2 section is attached, in which the changes made by us to the file system of the router will be stored. Therefore, the sysupgrade image cannot be started from memory without flash firmware.
It is very good that the Upvel UR-313N4G has a flash drive of 8 MB, after installation we will have a little more than 4 MB for additional packages. But in TP-Link TR-ML3420 a 4MB flash drive and free space there - the cat cried.
We reboot the router, press 2, indicate the name of the firmware and sew. So, everything seems to be fine: the interfaces are up, the LEDs are blinking, in general, life is bubbling. You still have not forgotten that our main goal was to make the router work with a Megafon M21-4 modem? We stick the modem into the USB port, look at dmesg and ... nothing. That is, nothing at all. There are two options here: either the kernel did not see any infernal bus on which a USB port hangs inside the chip (we can’t do anything here), or forgot to add drivers for this port to the firmware. The D-Link 320 NRU B1 has a USB port, so the second option is more likely. Google “OpenWRT usb support”, configure the WAN port on the router so that the firmware gets Internet access and install packages.

>opkg update
>opkg install kmod-usb2
>opkg install kmod-usb-ohci

It is in this order, because the kmod-usb2 module must be loaded earlier than kmod-usb-ohci

The lines immediately appear in the console:

[  121.570000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[  121.600000] ehci-platform: EHCI generic platform driver
[  121.810000] phy phy-usbphy.0: remote usb device wakeup disabled
[  121.830000] phy phy-usbphy.0: UTMI 16bit 30MHz
[  121.840000] ehci-platform 101c0000.ehci: EHCI Host Controller
[  121.850000] ehci-platform 101c0000.ehci: new USB bus registered, assigned bus number 1
[  121.860000] ehci-platform 101c0000.ehci: irq 26, io mem 0x101c0000
[  121.900000] ehci-platform 101c0000.ehci: USB 2.0 started, EHCI 1.00
[  121.910000] hub 1-0:1.0: USB hub found
[  121.920000] hub 1-0:1.0: 1 port detected
[  122.300000] usb 1-1: new high-speed USB device number 2 using ehci-platform
[  151.680000] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[  151.710000] ohci-platform: OHCI generic platform driver
[  151.720000] ohci-platform 101c1000.ohci: Generic Platform OHCI controller
[  151.730000] ohci-platform 101c1000.ohci: new USB bus registered, assigned bus number 2
[  151.750000] ohci-platform 101c1000.ohci: irq 26, io mem 0x101c1000
[  151.820000] hub 2-0:1.0: USB hub found
[  151.830000] hub 2-0:1.0: 1 port detected

Wow, the system saw the device on the USB bus, so we continue.

Now we put the package, which, when the modem is connected, sends a “magic sequence” to it, switching the modem from CD-ROM / TF Card mode to CD-ROM / TF Card mode + 3 COM ports.

>opkg install usb-modeswitch

In the console, we see the following:

[  278.230000] usb 1-1: USB disconnect, device number 2
[  278.990000] usb 1-1: new high-speed USB device number 3 using ehci-platform

So, usb-modeswitch worked - it sent a command to the modem, and after that the modem disappeared from the USB bus and appeared there as another device.

We will put two packages with drivers that will see COM ports and make them available to the system
>opkg install kmod-usb-serial kmod-usb-serial-options

[  326.530000] usbcore: registered new interface driver usbserial
[  326.540000] usbcore: registered new interface driver usbserial_generic
[  326.550000] usbserial: USB Serial support registered for generic
[  326.820000] usbcore: registered new interface driver option
[  326.830000] usbserial: USB Serial support registered for GSM modem (1-port)
[  326.850000] option 1-1:1.0: GSM modem (1-port) converter detected
[  326.860000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB0
[  326.870000] option 1-1:1.2: GSM modem (1-port) converter detected
[  326.890000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB1
[  326.900000] option 1-1:1.3: GSM modem (1-port) converter detected
[  326.910000] usb 1-1: GSM modem (1-port) converter now attached to ttyUSB2

It can be seen that the modem was detected correctly and 3 COM ports appeared in the system.

We put the package needed to create sending commands to 3G modems and an extension for the Web interface:
>opkg install comgt luci-proto-3g

We go into the Web interface, configure 3G, specify / dev / ttyUSB0 as the port, everything works.

Now take up the LEDs. First, install the kmod-ledtrig-usbdev package - it will allow us to control the LEDs depending on the availability of devices on the USB bus. We go into the Web interface on the System-> LED Configuration tab and define two LEDs there:

Name: usb
LED Name: d-link:green:usb
Trigger: usbdev
USB Device: 1-1 (HUAWEI - HUAWEI Mobile)
Name: wifi
LED Name: rt2800:phy0:radio
Trigger: netdev
Default state: on
Device: wlan0
Trigger Mode: Link On, Transmit, Receive

and click the Save / Apply button.
This completes the configuration of the router.
It’s worth adding that the “usb” LED refers to a specific device address on the USB bus (1-1), and therefore, if the address changes, the LED will not work.

Firmware via Telnet


And now it's time to find out whether it is possible to flash a router without access to UART. To begin, let's try the recovery mode - it usually turns on if the power is pressed while the reset button is pressed. Clamp, feed and look in the console: nothing. The mode is not available. We roll back through the bootloader to the original firmware and look at the boot log:

: System Boot system code via Flash.
## Booting image at bc050000 ...
raspi_read: from:50000 len:40 
.   Image Name:   Linux Kernel Image
   Created:      2014-06-11   7:38:15 UTC
   Image Type:   MIPS Linux Kernel Image (lzma compressed)
   Data Size:    3435300 Bytes =  3.3 MB
   Load Address: 80000000
   Entry Point:  80420000
raspi_read: from:50040 len:346b24 
.....................................................   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 80420000) ...
## Giving linux memsize in MB, 32

It can be seen that u-boot reads 64 bytes, starting with the address 0x00050000 ( fathers , explain why in the log bc050000?). Starting from 0x00050000, the uImage image is flashed on MTD and the header is in the first 64 bytes of it. The size of the image, its future address in RAM and the entry point are taken from the header, after which the image is unpacked into RAM and control is transferred to the entry point.
Let's wait until the original firmware boots up and look at the log:

mtd .name = raspi, .size = 0x00800000 (8M) .erasesize = 0x00010000 (64K) .numeraseregions = 0
Creating 6 MTD partitions on "raspi":
0x00000000-0x00800000 : "ALL"
0x00000000-0x00030000 : "Bootloader"
0x00030000-0x00040000 : "Config"
0x00040000-0x00050000 : "Factory"
0x00050000-0x007d0000 : "Kernel"
0x007d0000-0x00800000 : "RW_FS"

Starting from address 0x00050000, the Kernel section begins, and this address suspiciously matches the address from the u-boot log. So, this is where the firmware of the router is stored, here we will write OpenWRT. Let's see which devices displayed the sections:

cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00800000 00010000 "ALL"
mtd1: 00030000 00010000 "Bootloader"
mtd2: 00010000 00010000 "Config"
mtd3: 00010000 00010000 "Factory"
mtd4: 00780000 00010000 "Kernel"
mtd5: 00030000 00010000 "RW_FS"

The size of the Kernel partition is 7680 Kb, and the OpenWRT image takes about 3.5 Mb, therefore, you can flash without fear that the new firmware will not fit in the old partition.

Let's see how much free memory we have:

>free
              total         used         free       shared      buffers
  Mem:        28300        19952         8348            0            0
 Swap:            0            0            0
Total:        28300        19952         8348

We need about 3.5 MB and we have them.

Run atftpd on the workstation (address 192.168.10.100) and copy the firmware to the router RAM:

>tftp -l dir-320.bin -r dir-320.bin -g 192.168.10.100

First, delete the RW_FS partition. Maybe this does not need to be done, but just in case, be safe:

> mtd_write erase /dev/mtd5
Unlocking /dev/mtd5 ...
Erasing /dev/mtd5 ...
Erase char is 255


Now write the firmware:

>mtd_write -r write dir-320.bin /dev/mdt4
Unlocking /dev/mtd4 ...
Writing from dir-320.cc.sys.bin to /dev/mtd4 ...

The -r switch means that after the command is completed, the router will reboot. You do not need to adjust the partition table because it exists only inside the Linux kernel.

After rebooting, go to the Web interface, put the packages kmod-usb2, kmod-usb-ohci, kmod-usb-serial, kmod-usb-serial-option, kmod-ledtrig-usbdev, usb-modeswitch, comgt, luci-proto- 3G, configure interfaces and LEDs.

The router is stitched, you can open cookies and pour tea.

Read Next