Port to RAVPower RP-WD009

I'm writing this post in hopes that I could get some help and pointers in getting this device supported to an extent.

The RP-WD009 is a MediaTek MT7628AN-based portable travel router slash file hub slash backup solution. It's a lot of functions slapped into a single device. It's a quite handy solution for those on the move a lot, especially if they prefer a nice, portable backup solution.

However the stock firmware is utter garbage. Maybe due to the HooToo heritage (most RP-WD devices are rebranded HooToo units), or the utter incompetence at RAVPower HQ, but it simply just... Sucks.

The hardware on the other hand is quite capable. The main SoC is a MediaTek MT7628AN, paired with an MT7610E (for 5GHz WiFi), 16MB flash, and 64MB RAM. Sure, it won't be driving a full residential home, or a small office, but it does not have to. The main purpose is still to provide a WiFi network, and connect to an uplink via either Ethernet, WiFi, or USB tethering.

Luckily, I stumbled upon both the FCC approval photos (internal and external), and after a bit of fighting in email, RAVPower has also shared their GPL sources with me - including their whole build system, some precompiled binaries (mostly their own tools for managing e.g. LED status), and of course the web interface. I could spend some days or weeks coming up with a better solution based on the stock firmware, but in my opinion it's not worth the hassle. I'd rather use something that is more mainstream, like OpenWRT.

Another OpenWRT user has made some progress in testing the waters out - according to the published request to add the sub-page, the MT7628 evaluation board image boots, and generally works on the WD007 (a practically identical model to the WD009, with some design changes on the PCB, mainly to reduce heating), with the exception of 5GHz WiFi (I suppose the MT7610 needs some extra initialisation), SD card reader (possibly a DTS change is required for proper pinouts), and LEDs (the official firmware uses a custom utility to control LED status, but based on the board, it is supposed to be nothing more than 7 LEDs (both the power and SD card icons have a secondary red LED to indicate malfunction or low battery) connected to 7 GPIO ports - at least hopefully.

I would be more than happy to start working on at least some minimal support on OpenWRT side. The original sources are based on Linux kernel 2.6.36, so unfortunately no DTS available for this board, however based on the experiments done before, the MT7628AN eval board's config should be a good starting point. The bootloader is U-Boot 1.1.3, which is also quite old, but not ancient like the kernel. It comes with the standard TFTP based recovery, so as long as the bootloader doesn't fail, the device should be reflashable with ease.

I'd gladly test out builds, or even make them, however my experience with OpenWRT is quite limited, and could definitely use some pointers on how to set certain things up, especially with a brand new device being added.

Hi,

Interested here as well, but it seems that they have their "stock" problem ... a 1.5 MB limit on the kernel size - so it breaks with "standard" OpenWrt builds (master). Do you still have contact with RavPower, see if they'll get you a new u-boot (bootloader) that supports up to a 2 MB kernel?

Thanks!

@arrmo If I'm not mistaken, kernel partition size is defined via the bootloader - meaning if we can get the OpenWRT U-Boot to work on it, we can easily repartition the device. Given that so far all the RAVPower (and HooToo, they seem to share their ODM) devices have been relatively straightforward to port to, I'd guess the WD007 and WD009 are not that different either.

Unfortunately they've ceased all communications, I think I might've pushed them too hard for the sources.

@fonix232 Yes, I did similar - and they quit responding to me too ... LOL. I have spent quite a bit of time trying to get my HooToo device working (even have a PR in process right now), and it unfortunately doesn't come back to partitioning. That would be too easy :laughing:. Rather, they have hard coded the load size in u-boot, so if the kernel is > 1.5 MB ... boom, it won't load, and the device "soft bricks" (can be recovered easily, TFTP re-load basically). I even checked the WD009 source code (they sent me the wrong one for my HooToo device, they say the can't find the right code :wink:) ... and yep, they hard-code the load size to 1.5 MB. Need to find a way around that, or build a small kernel to boot to, that then boots the full kernel. Make sense?

Thanks!

FYI - OpenWrt support for RP-WD009 has been added with https://git.openwrt.org/?p=openwrt/openwrt.git;a=commit;h=e959048c128e4350b78df653be7cd7277787518e

OpenWrt firmware images for RP-WD009 (Currently only snapshot support, therefore LuCI needs to be installed manually after flashing).

The dataentry currently shows as unsupported functions: "WiFi 5GHz, SD card, LEDs"

Can someone please verify if those are working or not and give feedback?

Thanks!

1 Like

Amazing news! David was faster than me :joy:And did a bit more. I didn't even hope to get a custom U-Boot working. Do you know if he frequents this forum, and if yes, under what name? It would be beneficial, I think, to involve him in the discussion for future support (e.g. I'd rather free up that little bit of extra space that was only required due to how the original firmware worked - I know it's only a handful of kilobytes, but on a 16M device, every bit counts. Plus a more simple partition layout is preferable).

Okay, a random question - I know there's a general sentiment against enabling (unprotected) WiFi networks on OpenWRT, however let's be honest, the project mainly deals with "set up and forget" devices, hooked up on a wall, in a utility closet, hidden from the world... On the other hand, travel routers like the WD009, it is kinda crucial to allow the user to reset the router, and set it up, even without a wired client. And with that note, I'd say that having at least baseline luci support is also something necessary.

For now, I'll be building my own image (need that sweet automatic WiFi on, on first boot, and of course luci), but will test the original image first. As far as I can see, based on the changeset, the features required for 5GHz WiFi (the addition of the PCI connected MT7610E), SD card (inclusion of kmod-sdhci-mt7620), and apparently the LEDs are indeed GPIO-based (the stock firmware had no GPIO access in sysfs). In theory, it should all work.

Nonetheless, I'm extremely happy this device got support. Finally, it's worth that £45 I paid for it... And at the same time, I'm still confused how a manufacturer, like RAVPower, who have done quite a good job on their other devices (though mainly power banks and chargers), could release such a cobbled together piece of software...

Oh, @tmomas one more thing. I've created, per the instructions, the appropriate wiki page of this device, though it never left the inbox area (specifically, two of them, out of accident). I do not have rights to delete it, and these pages are now obsolete (I will transfer the necessary information to the final page). Could you delete it, or advise the appropriate moderator to do so?

1 Like

That should be @davidc502

Do you still need the inbox pages?
If no, I can delete them right away.
If yes, just tell me when they can be deleted, and I will do so.

Not possible without fundamentally changing the installation procedure. The web recovery splits the image based on the uImage size and writes everything after this part is written to the vendors rootfs partition (firmware in OpenWrt).

Hi,

To the point about maximizing flash space - I could be wrong, but I believe the solution captured here works around the vendor (U-Boot) 1.5 MB limit by "skipping" (and throwing away?) the vendor kernel partition, and just using the "higher" portion of flash ... do I have that right?

FYI, with some great help from @xabolcs and @mpratt14 I was able to avoid the vendor 1.5 MB kernel limit, using the lzma loader (and okli) to get Openwrt working on the HooToo TM-05 (an 8 MB device, where it's even more critical to not throw away that 1.5 MB kernel partition). More on this in the thread, HooToo TM-05, Add LZMA Loader. I believe that same approach could be used here, right?

Thanks!

Reading your comment, it looks like that @981213's solution from [WiP][RFC] ath79: add support for PISEN WMB001N #2299 could do it's magic here, too!

See the Build/pisen_wmb001n-factory for the magic: the 3k sized loader-okli is going to be the vendor kernel, and the vendor rootfs comes from OpenWrt kernel + rootfs:

define Build/pisen_wmb001n-factory
  -[ -f "$@" ] && \
  mkdir -p "$@.tmp" && \
  cp "$(KDIR)/loader-$(word 1,$(1)).uImage" "$@.tmp/uImage" && \
  mv "$@" "$@.tmp/rootfs" && \
  cp "bin/pisen_wmb001n_factory-header.bin" "$@" && \
  $(TAR) -cp --numeric-owner --owner=0 --group=0 --mode=a-s --sort=name \
    $(if $(SOURCE_DATE_EPOCH),--mtime="@$(SOURCE_DATE_EPOCH)") \
    -C "$@.tmp" . | gzip -9n >> "$@" && \
  rm -rf "$@.tmp"
endef

From the commit message:

D. Firmware
 Factory u-boot is built without 'savenv' support so it's impossible
 to change kernel offset. A 2MB kernel partition won't be enough in
 the future. OKLI loader is used here to migrate this problem:
  1. add OKLI image magic support into uImage parser.
  2. build an OKLI loader, compress it with lzma and add a normal
     uImage header.
  3. flash the loader to where the original kernel supposed to be.
  4. create a uImage firmware using OKLI loader.
  5. flash the created firmware to where rootfs supposed to be.
 By doing so, u-boot will start OKLI loader, which will then load
 the actual kernel at 0x20000.

 The kernel partition is 2MB, which is too much for our loader.
 To save this space, "mtd-concat" is used here:
  1. create a 64K (1 erase block) partition for OKLI loader and
     create another partition with the left space.
  2. concatenate rootfs and this partition into a virtual flash.
  3. use the virtual flash for firmware partition.

The OpenWrt loader could certainly be patched to work on the MT76x8 SoC, however i prefer having the second stage U-Boot as the MT76x8 only maps the first 4M (?) of flash to it's address map. The OpenWrt loader would break with the currently used partition map here, the U-Boot can work around this by using SPI commands instead of relying on the mapped address space.

One could certainly argue to make the installation process two steps by first loading the bootloader and then let the loaded bootloader write the firmware (overwriting the three vendor partitions). However i prefer having the easier installation process here.

We still do not have OKLI support for the MT76x8. Also i would prefer not to use the mtd-concat hack where possible.

int up_grade_fw(const ulong size)
{
	image_header_t hdr;
	int kernel_size = 0, fw_size = 0;

	memcpy(&hdr, WEBFAILSAFE_UPLOAD_RAM_ADDRESS, sizeof(image_header_t));
	kernel_size = ntohl(hdr.ih_size)+sizeof(image_header_t);
	fw_size = size - kernel_size;
	if(fw_size <= 0)
		return -1;

	raspi_erase(SPI_USRBACK_ADDR, SPI_USRBACK_SIZE);
	raspi_erase(SPI_USR_ADDR, SPI_USR_SIZE);
	if(raspi_erase_write((char *)WEBFAILSAFE_UPLOAD_RAM_ADDRESS, SPI_KERN_ADDR, kernel_size) < 0)
		return -1;
	if(raspi_erase_write((char *)(WEBFAILSAFE_UPLOAD_RAM_ADDRESS+kernel_size), SPI_ROOTFS_ADDR, fw_size) < 0)
		return -1;

	return 0;
}

This is the upgrade code from vendor U-Boot. As you can see here it writes everything after the uImage to the firmware partition. We might be able to write continuous data to the kernel partition, overwriting the vendor partitions between kernel and rootfs.

However this would require us to have a large uImage (as the size is determined by the header), which in return would lead to the first stage bootloader crapping itself when it tries to load the image.

... exactly as PISEN WMB001N.

No need at all!

The only difference between RP-WD009 and WMB001N is that @981213 was able to avoid wasting the (kernel partition size - Loader size) sized flash space on the OEM kernel partition.

Sure, if you want to avoid mtd-concat then it's OK to keep this as is.

Okay, i think I've got your intention now.

Concatenating the space between loader and beginning of the squashfs to the rootfs partition is possible.

It's sad to see the vendor wasting this space (for apparently no good reason). However i still want to avoid using the mtd-concat hack. The remaining 14M flash should be plenty for most use cases.

1 Like

Agreed. Those extra KBytes will be a good place for improvement in community builds and a nice exercise for builders! :wink:

Offtopic here, but why do you want avoid it?
For example it will be used in Engenius ENS202EXT because of the 1.5M kernel size hard limit.
mtd-concat workarounds nicely those space wasting vendor partitions.

@blocktrron since you've also added custom compiled u-boot support, would it not be straightforward to build a "conversion" factory image, one that only contains u-boot (with the new partition parameters)? This would force the device back into the recovery mode (if I'm not mistaken, if u-boot can't execute the next stage, it falls back to either the TFTP or the web failsafe), after which the user would flash the full factory image.

There are a few instances of such approaches - or at least were, when I last played around with it a few years back, on lower end devices, I did read about the need of an extra step compared to "regular" OpenWrt conversions, which updated the bootloader.

In my opinion, establishing a clean, workable environment would have priority over preserving those various vendor partitions for the off chance someone wants to restore stock firmware.

If we do establish this tabula rasa on the flash, though, I'm fairly certain following what GL.inet did with the MT300N would be the pattern to follow.


On the other hand, spent the weekend testing the current snapshot builds. Everything works fine, with the exception of the SD card reader - but during my disassembly of my WD009 (to create a full flash dump using an EEPROM reader directly on the chip), I managed to pull the card reader slot off the board slightly, so I'm not sure if the card actually doesn't make contact, or if it's the system not recognising it. I've ordered another unit (these things are freaking cheap, £30 on discount right now) to play around with, which should arrive today.

I have to say, the battery life on OpenWrt is amazing. With the stock firmware, I've got about 3-4 hours of continuous use, connected to a WiFi uplink. Last night, after I finished a baseline configuration I was happy with (after numerous resets), I left it running with a handful of devices connected to it. To my surprise, I woke up to over 11 hours of uptime, and the battery was still at 11%! Amazing job.

There are a few things I'm not 100% happy with as of now. Mainly minuscule things, that can be easily changed, but it's still worth a discussion.

  1. The LEDs

    I understand that OpenWrt has some requirements for user feedback. However, since travel routers, unlike their shelf (or cabinet, or utility room) locked bigger brothers, will usually be sitting right next to you while in use, this behaviour could be changed. All my changes here are mostly in line with the original behaviour of stock firmware.
    My proposed changes are:

    1. Disconnect the WiFi LEDs from the phys, and instead use triggers tied to the virtual interfaces (AP type). This will stop their incessant blinking, which I'm sure many users would find annoying.
    2. Disconnect the globe LED from status feedback, and instead use triggers bound to the wan interface group
    3. (Possibly?) map the I2C-exposed power LED controls to sys-led instances (there should be in total two LEDs controllable through the PMIC - the standard white, and the red LED. I've noticed the stock OS would sometimes use the red LED of the power button to indicate certain core software issues, such as not being able to start a core OS service), and hook them up appropriately
  2. Networking

    Again, this device profile is slightly different than of your average router. Most of the time, you won't have an ethernet connection to it. In my opinion, it would be crucial to weer away slightly from the standard OpenWrt configuration (which, as it is right now, mainly considers stationary routers).

    Then, there's the thing with eth0 being capable of belonging to either wan or lan groups, depending on the configuration. In fact, I was wondering - does OpenWrt have any sort of tools that would allow a somewhat automatic discovery of the environment of eth0 upon link? The stock firmware did this somewhat automatically - if it was plugged into a router, it would set up eth0 to receive DHCP address, set up firewall rules for it as wan, etc., but if you plugged it into your laptop, it would behave as a lan group port, providing DHCP, and access to lan in general.

    My recommended default network setup would be then:

    1. Password-protected APs started on both radios by default.
    2. Create a default STA interface for wireless uplink, disabled on first boot.
    3. (Not sure about this?) Manage eth0 between wan and lan groups automatically.

    And with it, I have a question. Is there any sort of support for dynamic first boot

  3. Buttons

    The buttons on this device are mapped more or less right, with the exception of the WiFi picker. I'm not sure if that's the right call for a button so easily accessible. I've managed to accidentally press it a few times while handling the device. Rather,

  4. LuCI and other packages

    I feel this will be somewhat controversial, but I think the inclusion of must have packages that establish the base functionality of the device (above the "here are your interfaces, do whatever you want!" philosophy). Some of the packages, features, that are included in the base OpenWrt config that make no sense on this device, and vice versa, for full functionality on this unit, you'll have tools, utilities utterly unnecessary on a stationary, always powered device.

    I don't have a complete list, however for starters I'd definitely include luci and travelmate (with its LuCI addon!), and possibly a few others related to file sharing and disk management.


Oh, by the way @blocktrron - your addition of the ravpower-mcu package has caused the Image Builder to stop functioning. The package does not end up being in the imagebuilder tar, and pretty much all make commands fail because of this. I'm suspecting the two missing fields (PKG_VERSION and PKG_RELEASE) in the Makefile are the reason.

I haven't tested R/W but upon insertion a blockdevice was added. So your unit is most likely faulty.

Having them bound to the PHY is preferred, as otherwise it would only map to a single VAP / is dependent on the interface name.

The manual I've got was not specific on the function mapping (it described the LED as "Fadenstatus" in German) but mine came w/o retail packaging so there's that. However, the firmware it had installed had the Globe LED blinking as soon as a WiFi client was associated. So this seems to be ambiguous in the vendor firmware and I've found a dedicated status LED to be more useful in this case.

This would require writing a kernel driver which would (most likely) not be accepted upstream. As i don't like to maintain out-of-tree kernel code, I've specifically chosen to write a userspace application for that.

Keep in mind the LEDs seem to only be triggered by sending status information to the MCU, which in return might have other consequences. I've not found a clear documentation apart from the ugly vendor driver on that topic though.

This is something for a community build, as the OpenWrt network setup tries to be as generic as possible. There's a really long thread somewhere about having WiFi disabled by default. See the OpenWrt main page on this topic:

  • Security: OpenWrt's standard installation is secure by default, with Wi-Fi disabled, no poor passwords or backdoors. OpenWrt's software components are kept up-to-date, so vulnerabilities get closed shortly after they are discovered.

Also relevant for a community build as these packages can be reinstalled after installation (and LuCi is included by default in release builds anyway). Keep in mind, the purpose you are using the device for might differ greatly from someone else. I use the device as a battery-powered mesh node, so I (for example) do not have a benefit of these packages).

You can delete the rc.button script toggling the WiFi state to disable this behavior. The button itself also toggles the WiFi state in the vendor firmware (being it slightly different by allowing to select a single band).

I'll look into that.

Good to know. Once lockdown is over, I'll be able to head into the office and grab a soldering iron, fix this b**** up.

I see. You're completely right. I understand it's walking a tight line, balancing between OpenWrt and stock features - some people will want a pure, debloated OpenWrt experience from the start, some want OpenWrt, but with all the stock features, the device working mostly as it did OOTB...

I have the paper manual right in front of me, and the main description page of LED indicators states two states only - turned off means no internet connection, turned on means there's internet connection.

And I've just verified this - the globe simply comes on when the wan uplink (or whatever the equivalent of it is in the stock firmware) comes on.

I see. Aren't userland drivers a possibility, by running a service? I understand that the whole MCU communication is about as reliable as an eggshell dunked in liquid nitrogen - especially without the documentation - but I'm sure certain level of mapping could be achieved. Some further digging into what it exactly doing would be nice - maybe it's even possible to upgrade the firmware running on the MCU, thereby making it behave just as we want? Nonetheless I'm very interested what the other commands do (given that you've discovered commands running up to 0x61 - I bet there's a bunch of other things it can do, say, report charging/discharging speed, etc.).

I'm aware of the discussion, and can't say that I agree with most of it. OpenWrt has grown out of the original idea of running the same firmware on all routers, to a vast project supporting all sorts of embedded devices - from the original "wall router" it was developed for, through dumb wireless access points, mesh controllers, wireless/wired repeaters, powerline adapters, all the way to travel routers and file hubs such as this unit. These usage scenarios require different approaches - you won't need an SMB server for a dumb AP, but you'll need a music player for wireless media head units. It would be nice to see a sort of profile system added to OpenWrt - that way, the device config provides the truly device-specific bits, while the profile itself could provide the functionality, keyed together into a working package, platform-independently.

I understand that, though I suppose it shouldn't be too hard on the build system to add an extra config that includes a handful of packages for user convenience. But for now, community build it is.

On another note, how well does this unit function as a mesh node? What is your configuration (general network/mesh setup, and also the setup of the device)?

I've checked the original firmware. It detects a 3s press, and then proceeds to change mode (2.4/5/both) for client mode only. I think having it directly connected to rfkill is somewhat dangerous, though.

Thanks!

What about my idea for the repartitioning with u-boot, though? Would it not work?

@fonix232 Gentle reminder :slight_smile:

In theory, this would work. However we either need to patch the U-Boot quite a lot to enable a web-enabled conversion. Alternatively we can use TFTP. But again, we are talking about ~1.5M of flash space on a 16M device. I think (again) that this is a nice addition to a community build but for the stock OpenWrt i prefer the lighter patch and easier factory installation.

1 Like