Friday, March 25, 2016

Recovery from failed fastboot flash (return to 'DROIDBOOT PROVISION OS' from 'white USB symbol' problem)

I have made the dangerous attempt of trying to flash a 'fastboot droidboot.img' from a similar specs ZenFone 2, for which people already figured out how to unlock the bootloader without waiting for Asus.

That work was reported here.

and I've seen that the official firmware for the ZenFone 2 ZE551ML (downloaded from here ) contains indeed a 'droidboot.img' file which the ZenPad S8.0 CA allows to flash, without complaints about signatures.

However, upon rebooting via 'reboot bootloader', the 'Droidboot provision PS' no longer shows up. The screen shows a white USB symbol, no more, and is no longer visible from a PC through 'adb devices' or 'fastboot devices'. The rest still works; but have we lost fastboot forever?

NO: if the device was rooted before (strongly advised...), a trick allows to flash without passing from 'fastboot' at all.

1) Get the official full firmware archive from Asus ( file ), and copy it on the device.
2) run:
$ adb shell
3) became root:
$ su
4) move that archive on a 'safe' place, i.e. /data
# mv /storage/emulated/0/ /data

5) magic trick: create a recovery command via:
# cat > /cache/recovery/command <PRESS ENTER, CONTINUE WRITING UNDERNEATH>
--update_package=/data/ <ENTER>

6) restart and go through that script:
# reboot recovery

The device will reboot, and start a reinstallation which will, in particular, restore the Droidboot system and get rid of the white USB symbol.

Fastboot is back with us! ;-)
$ adb reboot bootloader

Saturday, February 13, 2016

De-bloating / customized stock ROM HOWTO

De-bloating / customized ZenPad Z580CA stock ROM HOWTO

Get the reference full firmware (not just the over-the-air (OTA) patch) from Asus (will be mirrored here)

Unzip it; start modifications:

1) Debloating: remove from system/app and system/priv-app the unwanted subdirectories. Compare the original lists:

AffiliateLauncher             AWS                   DMClient                   IBook                 Music2                    PicoTts                           Stk                      WeatherTime
AsusAs                        BasicDreams           DocumentsUI                InstantPage           MyASUS                    PlayTo                            Street                   WebViewGoogle
ASUSBrowser                   BbblerActors          DownloadProviderUi         IntelCamera           MyFrame                   PlusOne                           StylusDataService        WhatsNext
AsusConfigUpdater             Bluetooth             DrBooster                  IrisService           MyWater                   PowerHistory                      Syndor                   Yahoo
AsusDrawRes                   BookLiveDownloader    Drive                      Keyboard              NoiseField                PowerSaving2                      SystemUpdate             YouTube
AsusMirror                    BrowserProviderProxy  DriveActivator             KeyChain              Omlet-stub                PrintSpooler                      talkback                 ZenUIHelp
AsusSensorService             CaptivePortalLogin    Flipfont                   Kindle                PackageInstaller          PuffinBrowser                     TaskManager              ZinioReader
AsusSetupWizard               CertInstaller         Galaxy4                    LatinImeGoogle        PacProcessor              QuickMemo                         Transformer              ZinioSettingsProvider
AsusSplendidCommandAgent      Chrome                Gmail2                     LiveWallpapers        PAIStub                   QuickMemoService                  Tripadvisor
AsusVisualMasterCommandAgent  CleanMaster           GoogleCalendarSyncAdapter  LiveWallpapersPicker  PartnerBookmarksProvider  QuickPanel                        UpdateLauncher
ASUSWebView                   ConfigUpdater         GoogleContactsSyncAdapter  LocationPicker        PCLinkBinary              QuickSearch                       UserDictionaryProvider
ATOKIME                       CWSClientService      Hangouts                   Lockscreen            PCLinkManager             RemoteLink                        Videos
AudioWizard                   DataTransfor          HdmiSettings               Maps                  PhaseBeam                 SensorCal                         VisualizationWallpapers
AudioWizardView               DeskClock             HoloSpiralWallpaper        MobileManager         PhotoFrameWidget          sl_installer                      VppSettings
AwareResource                 DLNAService           HTMLViewer                 MobileManagerService  PhotoTable                SMMI_TEST_V5.1.13_CSC_L1L2_Z580C  WAPPushManager

AppLocker                   AsusEasyLauncher     AsusLiveDemoUI    AsusSystemUI               ContactsProvider         GoogleBackupTransport     ituxd                ProxyHandler         SuperNote          ZenCircle
ASUSAppInstallationService  AsusEmail            AsusMusic         AsusTask                   DefaultContainerService  GoogleFeedback            ManagedProvisioning  SettingsProvider     Telecom
AsusBackup                  ASUSGallery          AsusPhotoCollage  AsusVisualMaster           DownloadProvider         GoogleLoginService        MediaProvider        SetupWizard          TelephonyProvider
AsusCalculator              ASUSGalleryBurst     AsusQuickSearch   AsusZenUIServices          ExternalStorageProvider  GoogleOneTimeInitializer  MicroFilm            SharedStorageBackup  TeleService
AsusCalendar                AsusKidsLauncher     AsusSettings      BackupRestoreConfirmation  FileManager2             GooglePartnerSetup        MmsService           ShareRimBinary       Velvet
AsusCamera                  AsusLauncher         AsusSmartCrop     CalendarProvider           FusedLocation            GoogleServicesFramework   MusicFX              Shell                VpnDialogs
AsusContacts                AsusLiveDemoService  AsusSplendid      CMSKeyV3                   GmsCore                  InputDevices              Phonesky             SoundRecorder        WallpaperCropper

and a debloated, but still pretty fat one:

AffiliateLauncher             ATOKIME               CaptivePortalLogin  DocumentsUI                IBook           Maps                      PlusOne           RemoteLink         TaskManager              WebViewGoogle
AsusAs                        AudioWizard           CertInstaller       DownloadProviderUi         InstantPage     MobileManager             PowerHistory      SensorCal          Transformer              WhatsNext
AsusConfigUpdater             AudioWizardView       Chrome              Drive                      IntelCamera     MobileManagerService      PowerSaving2      sl_installer       Tripadvisor              YouTube
AsusDrawRes                   AwareResource         CleanMaster         Flipfont                   IrisService     PackageInstaller          PrintSpooler      Stk                UpdateLauncher           ZenUIHelp
AsusMirror                    AWS                   ConfigUpdater       Gmail2                     Keyboard        PacProcessor              PuffinBrowser     Street             UserDictionaryProvider
AsusSensorService             BasicDreams           CWSClientService    GoogleCalendarSyncAdapter  KeyChain        PAIStub                   QuickMemo         StylusDataService  Videos
AsusSetupWizard               Bluetooth             DataTransfor        GoogleContactsSyncAdapter  LatinImeGoogle  PartnerBookmarksProvider  QuickMemoService  Syndor             VisualizationWallpapers
AsusSplendidCommandAgent      BookLiveDownloader    DLNAService         HdmiSettings               LocationPicker  PicoTts                   QuickPanel        SystemUpdate       VppSettings
AsusVisualMasterCommandAgent  BrowserProviderProxy  DMClient            HTMLViewer                 Lockscreen      PlayTo                    QuickSearch       talkback           WAPPushManager

AppLocker            AsusSettings   AsusVisualMaster           ContactsProvider         GmsCore                   GooglePartnerSetup       MediaProvider  ProxyHandler         Shell              TeleService
AsusLauncher         AsusSmartCrop  AsusZenUIServices          DefaultContainerService  GoogleBackupTransport     GoogleServicesFramework  MicroFilm      SettingsProvider     SoundRecorder      Velvet
AsusLiveDemoService  AsusSplendid   BackupRestoreConfirmation  DownloadProvider         GoogleFeedback            InputDevices             MmsService     SetupWizard          SuperNote          VpnDialogs
AsusLiveDemoUI       AsusSystemUI   CalendarProvider           ExternalStorageProvider  GoogleLoginService        ituxd                    MusicFX        SharedStorageBackup  Telecom            WallpaperCropper
AsusQuickSearch      AsusTask       CMSKeyV3                   FusedLocation            GoogleOneTimeInitializer  ManagedProvisioning      Phonesky       ShareRimBinary       TelephonyProvider

2) Manually change the build restrictions/details as desired (allow tethering; remove fake shutter sound upon taking photos etc.):
edit the file system/build.prop

3) Recompress the image: from within its root directory containing:
$ ls
boot.img  droidboot.img  file_contexts  l_recovery.fstab  META-INF  partition.tbl  recovery  splash.img  system

$ zip ../ -r *
For the above selection of utilties, a debloated 4.6.1 stock ROM is made available here.

4) Prepare a fat32 (i.e. not an 'extended FAT': better compatibility) microSD card:
# cfdisk /dev/mmcblk0
then 'New', 'Change type' to: b (W95 fat32), 'Write' and 'Quit'

# mkfs.vfat /dev/mmcblk0p1 -n SD16GB_fat

5) Copy there the zipped image. Add any additional extras desired, like SuperSU to root the device:

6) Umount the microSD card and place it back into the device. Reboot it into Droidboot: either connect via USB (after enabling 'USB debugging' under 'Settings'->'Developer mode') and issue:
$ adb reboot bootloader

or reboot it, keeping Volume UP and Power pressed together, until the android logo with service hat shows up.

7) Download the Intel Fastboot Tethered Temporary Recovery Session Launcher (FBRL; mirror of the relevant files here) and unpack i.e. under /tmp/FBRL the files:

-rw-r--r-- 1 root root  410105 May 16  2015 recovery.launcher
(MD5SUM: 572cc4351881656cf4df7d538f60dd7f)
-rw-r--r-- 1 root root  183198 May 16  2015
(MD5SUM: d3c12ee127f87437a8e94470f193dc57)
-rw-r--r-- 1 root root  174902 May 16  2015 recovery.trigger.original
(MD5SUM: a1047156addd80ae14284816e0de94df)
-rw-r--r-- 1 root root 3560544 Dec 27  2014
(MD5SUM: 49e8bb46834dccb1ef95a2bb9b55a9db)

8) Connect the USB cable, and from such directory issue:

# fastboot devices (verify connectivity. If nothing shows up, an obsolete version of the utility may be installed. Get a new one, for instance a recent Debian package for your desktop architecture).

Then, if things seem fine:
# fastboot flash /tmp/
# fastboot flash /tmp/recovery.launcher recovery.launcher
# fastboot flash /system/bin/cp recovery.trigger.original
# fastboot oem backup_factory

Device will reboot into a custom CWM recovery, and show (slowly, line after line):
Tethered Recovery Launcher Concept
social-design-concepts. 05/16/2015
After some more information listing, it will refresh and show a new menu in blue.

9) Select:
9a) Wipe data/factory reset;
9b) Advanced->wipe Dalvik cache->Yes - Wipe Dalvik Cache
9c) Mounts and Storage -> Format /system -> Yes - Format
9d) Format /data and /data/media (/sdcard) -> Yes - Format
go back;
9e) install zip -> choose zip from external card -> Select -> Yes - Install
(it will take some minutes - BE PATIENT!)
9f) Repeat with any desired additional zip file placed into the microSD (i.e. the last stable (mirror here) for root access), and go back;

10) Reboot system now -> Yes - fix root
The device will restart; the message 'Android is upgrading' will show up shortly. All done! ;-)


1) I've tried to make initially even Gmail optional; this seems to work at first, however it will soon require the user to upgrade 'Google Play Services' from the Play Store. Which works... except that then the service will keep crashing and restarting, with the error message 'Unfortunately Google Play services has stopped'.

2) Minor annoyance: many removed package will be still automatically downloaded at the first boot; but they can be now cleanly removed.

3) After debloating, the /system partition does not need to be so large. As shipped, 'df' at 'adb shell' gives (as root) it to be around 2.8GiB, but it could be now wiser to reduce its size.

I haven't touched the partiton table yet, just to keep on the safe side. The file 'partition.tbl' would allow to simply reduce its default size (just changing the number of blocks (in units of 512 bytes?) where /system should end, and hence /data begins). It is called by the script: 'META-INF/com/google/android/updater-script', but only if the is_osip function returns 'true' (see i.e. this presentation)

However, a following OTA update will expect to find enough space, and thus break if these parameters are modified.

Enjoy a cleaner device! Mirror copy of the above debloated & /system/etc/hosts -filtered stock ROM is here.

Sunday, February 7, 2016

Rooting the Asus ZenPad S 8.0 Z580CA tablet

Rooting the ZenPad S 8.0 Z580CA tablet

Asus ZenPad S 8.0 Z580CA product shot


The tablet in subject is a very slim and portable high resolution 8' 4:3 device by Asus. Different variants are available; here the model with an Intel Atom Z3560 and 2GB RAM / 16 GB SSD will be considered (full specifications: here).

Instructions are provided for a standard Linux desktop, in particular a Debian stable 8.3 distribution "Jessie". For Windows, see i.e. here. Japanese notes: here.

Enable "Developer mode" on the tablet: "Settings" -> "About device" -> tap "Build number" many times. Confirm and look for the new "Developer options" entry appearing among the "Settings". Tap the "USB Debugging" box to enable it.
Download or copy into the device (mirror here).

Connect the provided USB cable to an available desktop port, and verify that root can see the device: issue (as root) on a desktop terminal the command:
# adb devices 

Reboot into the bootloader:

# adb reboot bootloader

Verify that fastboot can still see the device:
# fastboot devices

If lsusb shows it but fastboot returns nothing, it can be a known issue with the utility version provided by the desktop Linux distribution is too old. Try a more recent one from Debian 'testing' for instance, or a recompiled i686 binary is provided here (mirror) from the XDA forum by senior developer Vampirefo (but beware of the security risks - safe hex is better! ;-).

Download on the desktop the last Intel Fastboot Tethered Temporary Recovery Session Launcher (FBRL; mirror here) and unpack it under /tmp/FBRL/.

Move to such directory and issue (as root) on a desktop terminal the following 4 commands:

# fastboot flash /tmp/
# fastboot flash /tmp/recovery.launcher recovery.launcher
# fastboot flash /system/bin/cp recovery.trigger.original
# fastboot oem backup_factory

... and check on the device screen that each one completes without problems. Select 'Reboot' to continue.

Insert a microSD card (important: make sure it is formatted as 'FAT32', not 'exFAT', for compatibility reasons: under Linux, the filesystem must be created with mkfs.vfat, not mkfs.exfat) in which the binary 

Select: Install zip, read it in from 'External SD', proceed with installation and then reboot into the new, rooted state.
Enjoy things like i.e. Linux Deploy for availability of a really open source, complete system!

Tuesday, June 17, 2014

Accessing the serial interface on the Intenso Memory 2 Move

Accessing the serial interface on the Intenso Memory 2 Move

Similar to many other comparable devices, the Ralink RT5350 SoC has an almost ready-to-use serial port, which is always powered on and is supposed to be used for debugging purposes, even if not directly accessible from the outside. This could be inferred from the stock firmware too: a look at running services (see a previous post) shows in fact that after booting the device in standalone mode, a Linux "getty" terminal is always running and ready to offer serial console access.

Lacking an external socket to connect to, access to this feature of the device requires opening the case. The plastic shell is tightly held together only by 6 plastic clips, three on each elongated side, and the two halves can be separated after carefully applying force along the seams, possibly with a flat screwdriver, not-too-sharp blade or similar piece of equipment. One needs attention not to break the relatively tiny clips.

A review of the device, and additional pictures of its components.

Once inside, the first thing to stand out is the hard-disk. It is a Seagate .... "advanced format" model, as speculated from looking at the firmware; and it can be indeed replaced with other 2.5'' ones, to increase for instance capacity.

Underneath it lies the Li -based rechargable battery, and the circuit board. The latter is fully covered by an adhesive, insulating plastic sheet, easy to peel away. Aluminium foil on the plastic case provides instead a measure of Faraday cage insulation against electrical noise, while allowing the WiFi signal out.

The power plug to the battery pack can then be removed (note the polarity in order to reconnect it correctly later), and the circuit board detached from the lower part of the case, to which it clings via 3 standard screws.

Underneath the plastic sheet one finds the serial port pads, close to the battery side of the board.
Top of the SoC circuit board, after peeling off the black, insulating adhesive.
On the left, from the bottom: RJ45 Ethernet socket; reset button, USB 3.0 socket, power button.
On the board, under a barcode sticker: SATA socket for the hard-disk.
On the right side, close to the battery pack: notice the 4 aligned pads for the serial port. The top, square corners one is +Vcc, then Txc, then Rxc, then Gnd.
Access to the port requires soldering some pins, as no header has been left in the final assembly. I've done this on the bottom side:
Bottom of the SoC circuit board, with insulating adhesive sticker still attached. On the right, notice the 4 pins manually soldered to the UART port, for serial access through an external TTL-to-serial voltage level adaptor.

The device in operation, powered by its battery pack, and connected to the USB port of a laptop through a CP2102 serial adaptor that furthermore converts TTL levels to the serial standard. Hard disk not connected for clarity.

Notice that simple connection to the GND and Vcc of the adaptor is sufficient to power up the SoC circuit board, which would then start the boot process, but would produce half-gibberish on the serial port due to insufficient power. Strangely enough, it is the lowercase half of the ASCII spectrum which gets corrupted, while uppercase letters seem to come out fine ;p

To overcome this, simply connect the battery pack first, and switch on the board by pressing its power button, before completing the serial connection to the laptop.

SoC circuit board in function, powered by the battery pack and connected to a USB-to-TTL-serial CP2102 adaptor, itself plugged to a laptop USB port running Minicom.
Communication parameters are: /dev/ttyUSB0, software flow control, 57600 8N1.

Captured serial port log upon booting.

After boot is complete, it is possible to simply log on through the default root account.

Friday, May 30, 2014

Debian on the Intenso Memory 2 Move

Debian on the Intenso Memory 2 Move

Intenso Gmbh distributes a line of cheap, battery -powered portable 2.5'' external USB hard-drives which furthermore include WiFi and Ethernet capability. Such devices are very interesting for a variety of applications beyond those envisioned by the manufacturer, and would make for an ideal "PirateBox" among other things.

These notes refer in particular to the 1TB "Black" model:

Basic operating modes:

As described in the manual (mirrored here for convenience), the device has at least two operating modes. When connected via USB to a computer in the initial "power off" state, it behaves as a simple USB-to-SATA bridge, making the whole hard-disk externally accessible.

When indipendently switchted on, the internal embedded SoC Linux system takes over, and after a relatively fast booting sequence it will make a series of services available through the WiFi / Ethernet ports, while using any later USB connection only as a power source for topping up the internal battery of about 3000 mAh.

The SoC is rated for a typical power load of about 3W, to which the hard-disk consumption must be added - see below. If the chemistry would be a standard 3.7 V one, we would have 3.7*3=11.1 Wh of energy, or little more than 2 hours of continuous, standalone use once the top disk load of about 2 W is also accounted for.

Notice that while the hard-disk is properly spinned down after 3 minutes of uninterrupted idle, the default kernel appears to be compiled without any power management support, see below. Longer running time than the advertised 5 hours may be achievable.

Hardware description and default working modes:

The internal hard-disk seems to be a Seagate / Samsung part:
# hdparm -I /dev/sdb:
Model Number:           ST1000LM024 HN-M101MBB

... which should have the following specifications:
  • Form factor: 2.5", 9.5mm
  • Rotation speed: 5400rpm
  • Cache: 8MB
  • Power consumption: 2.20W (load), 0.70W (idle)
  • Loudness: 26dB(load), 24dB (idle)
  • SMART feature set: supported.
There have been reports of possible replacement with other disks, but even larger capacities than 1 TiB, despite possibly working, are normally thicker and don't fully fit within the case. Some rough ideas about performances:

  • When driven in standalone mode, from the embedded SoC Linux system:
    # hdparm -tT /dev/sda
     Timing cached reads:   114 MB in  2.03 seconds =  56.21 MB/sec
     Timing buffered disk reads:   28 MB in  3.10 seconds =   9.04 MB/sec
  • When driven from the USB bridge mode, from an external PC:

The internal SoC is very flexible, if somehow resources -limited. 
The devices uses a Ralink RT5350 MIPS24 KEc (cat /proc/cpuinfo: MIPS 24 Kc V4.12, corresponding to gcc -march=24kec switch, see below) with 32MiB of RAM, in a little-endian layout. As remarked here, this particular CPU variant lacks a hardware floating point unit (FPU), which has to be emulated in software. This is fine for the current deployment as portable NAS unit, or for the other common usage in routers etc. More demanding mathematical tasks, such as video compression in IP cameras etc., are based on variant with FPU included.

Some device -specific details are also tabulated on

Default services in the stock firmware ver. 1.1 are based on ulibc (the system will also re-create, if needed, and use an extra 64MiB of swap as a rather inefficient ".vst/swapfile" on the first VFAT/NTFS partition /dev/sda1 of the internal hard-disk) and include:

  • minidlna: DLNA (via UPnP) multimedia files serving, for instance to clients such as Android WonderShare player or Apple IOS analogus;
  • smbd: SMB protocol support for filesystem access from Microsoft Windows / Apple OSX / Linux;
  • lighttpd: HTTP protocol support for configuration and/or filesystem access from standard browsers
  • ...
Source code for all the GPL components is available as an archive from the manufacturer, and is mirrored here (MD5SUM: 296fce876c589c181aeabd1dcdcdb127) for convenience.

These notes report on the installation of a complete, if slightly out-of-date, Debian MIPSEL distribution "Lenny". This makes readily available for installation and use all packages listed i.e. here.

Compiling and running standalone code:

It is possible to develop and cross-compile standalone programs for the default embedded Linux system, working i.e. on a standard x86 Debian PC and just copying the resulting MIPS executables on the device as generic files.

This requires availability of a cross-compilation toolchain. A suitable one for Jessie/Sid may be installed by adding to /etc/apt/sources.list the lines:

deb squeeze main

Then simply:
apt-get install gcc-4.3-mipsel-linux-gnu

...will pull in all required dependencies.

A nice example of what can be compiled and run this way is the CLI "Tetris" game by Victor Nilsson.

Installing a full, ready-to-use Debian release:

Better capabilities can be made accessible through installation of a complete Debian environment.

"Lenny" i.e. Debian release 5.0 is the latest release that can run with the stock kernel 2.6.21. This allows in particular easiest and safest deployment on top of the existing firmware, as the whole system can work in a "chroot" jail with no risk of bricking the device.

Gaining root:

The stock firmware ver. 1.1 (mirrored here for convenience, MD5sum: 8acc9d9bbb8d18d5da2ad6b6a20a043d ) contains a backdoor. To my eyes this is by the way very useful, but an extremely dangerous data securety issue too.

In practice the system will boot in standalone mode with a telnetd daemon running on default port 23, and offering root login with:

username: root
password: 20080826

The instructions below mitigate the problem by switching off such daemon, and offering instead SSH access with a chosen password instead. This must however be repeated at every reboot, as by default the system starts in insecure mode.

Further notes below document a different attempt to address the issue by rebuilding the embedded Linux firmware. One should consider the security implication of the classic "Trusting trust", and more recent discussions such as this post by Bruce Schneier.

Choosing a suitable Debian version:

After logging in as root through the stock firmware telnet backdoor, the system reveals itself as:

  • Processor brand and featurs:
    # cat /proc/cpuinfo
    system type             : Ralink SoC
    processor               : 0
    cpu model               : MIPS 24K V4.12
    BogoMIPS                : 239.61
    wait instruction        : yes
    microsecond timers      : yes
    tlb_entries             : 32
    extra interrupt vector  : yes
    hardware watchpoint     : yes
    ASEs implemented        : mips16 dsp
    VCED exceptions         : not available
    VCEI exceptions         : not available
  • The physical RAM is:
    # free
                 total       used       free     shared    buffers     cached
    Mem:         28008      26028       1980          0       2016      13384
  • The kernel version in use is:
    # uname -a
    Linux M2M 2.6.21 #256 Thu Apr 25 09:35:37 CST 2013 mips GNU/Linux
  • The default booting arguments were:
    # cat /proc/cmdline
    console=ttyS1,57600n8 root=/dev/mtdblock8 rootfstype=squashfs quiet

    (a serial console should in other words be available for debugging, if interfacing with the appropriate pins on the mainboard);
  • The default flash memory layout reads:
    # cat /proc/mtd
    dev:    size   erasesize  name
    mtd0: 00800000 00010000 "ALL"
    mtd1: 00030000 00010000 "Bootloader"
    mtd2: 00010000 00010000 "Config"
    mtd3: 00010000 00010000 "Factory"
    mtd4: 00180000 00010000 "Kernel_RootFS"
    mtd5: 00010000 00010000 "params"
    mtd6: 00010000 00010000 "user_backup"
    mtd7: 00010000 00010000 "user"
    mtd8: 00600000 00010000 "Rootfs
All the above points to the conclusion that a viable option for full Linux environment installation will be Debian 5.0.10 "Lenny", in the little endian "MIPSEL" architecture.

A later, more up-to-date distribution release will not be compatible with the stock firmware kernel.

Debian root filesystem option 1: As a loopback image within the default hard-disk partion scheme:

  • Simplest deployment;
  • Safer against unmounting;
  • Fairly inefficient I/O, which makes many operations painful to use on the rather resources -starved SoC;
In view of the above considerations, a different installation scheme based on proper hard-disk re-partitioning and ext2 formatting (outlined  below) is preferred. In either cases, the first steps of passing through a loopback image are shared, and detailed in the instructions below:

  1. Prepare and mount an image filesystem to work on:
    # dd if=/dev/zero of=/tmp/debianfs bs=1M count=2000

    (something smaller than 2GiB may also be sufficient);

    # mkfs.ext2 /tmp/debianfs

    mount /tmp/debianfs /tmp/db -o loop

    (modprobe loop may be required);
  2. Fill the image filesystem with a basic Debian "Lenny" installation:
    # apt-get install debootstrap

    # debootstrap --foreign --verbose --arch=mipsel lenny /tmp/db/

    (apt-get install debootstrap may be required);
  3. Transfer the image filesystem to the device:
    # umount /tmp/db ; mount -t cifs // /mnt -o username=admin

    (or just switch the disk off and connect & mount it as USB mass storage, to perform a faster copy);
  4. Log on the stock firmware Linux system through the backdoor:
    # telnet

    (default IP assignment for WiFi connection),
    username: root
    password: 20080826
  5. Mount the empty filesystem image to complete the Debian base installation, automatically downloading all the needed "base" packages from the network:
    # mount data/UsbDisk1/Volume1/debianfs /mnt/ -o loop

    (on a single line:)
    # DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt /debootstrap/debootstrap --second-stage

    (on a single line:)
    # DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt dpkg --configure -a
  6. Set up the Debian system network and virtual filesystems: verify that its /etc/resolv.conf points to a proper nameserver, i.e. contains something like:
    # cat /mnt/etc/resolv.conf

    ...and that these mountpoints are present and properly populated:
    # mount none /mnt/proc -t proc
    # mount -t sysfs sysfs /mnt/sys/
    # mkdir /mnt/dev/pts
    # mount -t devpts devpts /mnt/dev/pts/
    # mount -t usbfs usbfs /mnt/proc/bus/usb/

    Further useful devices may be creted with:
    # mknod /dev/sda b 8 0
    # mknod /dev/sda1 b 8 1
    # mknod /dev/sda2 b 8 2

    ... and the default VFAT partition may be made visible to the Debian system too with:
    # mount /dev/sda1 /mnt/mnt
  7. Set up the correct time zone:
    # dpkg-reconfigure tzdata

    The command:
    # ntpdate-debian
    ... may later be used for precise NTP clock syncronization.
  8. Install any other needed Debian package as usual. At the very least, a SSH server is advised, such as dropbear:
    # apt-get install dropbear
  9. Verify SSH is working:
    # netstat -tan
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address           Foreign Address         State     
    tcp        0      0 *:8200                  *:*                     LISTEN    
    tcp        0      0 *:netbios-ssn           *:*                     LISTEN    
    tcp        0      0 *:www                   *:*                     LISTEN    
    tcp        0      0 *:81                    *:*                     LISTEN    
    tcp        0      0       *:*                     LISTEN    
    tcp        0      0     *:*                     LISTEN    
    tcp        0      0 localhost:6010          *:*                     LISTEN    
    tcp        0      0 *:microsoft-ds          *:*                     LISTEN    
    tcp        0      0        ESTABLISHED
    tcp        0      0 localhost:81            localhost:3122          TIME_WAIT 
    tcp6       0      0 [::]:ssh                [::]:*                  LISTEN    
    tcp6       0      0        ESTABLISHED
  10. close the stock firmware backdoor:
    # killall telnetd

    (the backdoor will be automatically re-opened upon rebooting, until the "rootfs" default initrd squashfs flashed on the NAND memory is customized as per instructions below)

Debian root filesystem option 2: as a standalone ext2 partition within  a re-partitioned hard-disk

The stock kernel has been compiled with no more modern filesystem capabilities than "ext2".

  • faster;
  • slightly safer from accidental erasure when using the system as a dumb USB external disk;
This latter method is preferred, and better described below.

  • The stock firmware Linux system is set up to assume that a (ex)VFAT or NTFS partition should be present as /dev/sda1, and be used for all the default standalone device services.
  • Create a swap partition. Suggested size is just 64MiB, i.e. twice as big as the physical RAM; for better performances it is best to set it up as close as possible to hard disk cylinder 0, i.e. as /dev/sda2 just after the resized /dev/sda1;
  • Create a ext2 partition for the new Debian MIPSEL installation. Suggested size is about 3GBi, as /dev/sda3;
  • Create a ext2 partition with the rest of the unallocated space, i.e. as /dev/sda4.
This step can be carried out via i.e. the Gnome Partition Editor "", available as standard Linux application or a standalone, bootable USB image.
Install the base system:
Same as for the method above. At the end of it, simply copy everything to the desired ext2 partition, such as /dev/sda3 in the scheme above (make sure not to unnecessarily copy bare devices themselves from /dev !).
Prepare an automatic Debian launcher script
The following "~/bin/" may be used to semi-automatically boot the Debian system after each device reboot. It assumes the "telnet" client and "expect" interpreter being available, and works through the default firmware ver. 1.1 backdoor:

# Script to deploy the Debian chroot and close the default telnet backdoor.

# Access the backdoor:
spawn "telnet" ""

expect "M2M login:"
send "root\r"
expect "Password:"
send "20080826\r"
# expect "BusyBox"
expect "#"

# We are in. Switch from the VFAT -hosted swapfile to a swap partition (faster):
send "swapon /dev/sda2\r"
expect "#"
send "swapoff /data/UsbDisk1/Volume1/.vst/swapfile\r"
expect "#"

# Mount the Debian and leftover storage partition. Sync mode is used, even if slower (the SoC offers limited performances anyway, we are limited by it rather than the I/O subsystem) to afford a margin of safety against sudden switching off.

send "mount /dev/sda3 /mnt/ -o sync\r"
send "mount none /mnt/proc -t proc\r"
expect "#"

# Populate the virtual filesystem:
send "mount -t sysfs sysfs /mnt/sys/\r"
expect "#"
# send "mkdir /mnt/dev/pts\r"
send "mount -t devpts devpts /mnt/dev/pts/\r"
expect "#"
send "mount -t usbfs usbfs /mnt/proc/bus/usb/\r"
expect "#"

# Start the chroot. WARNING: no standard services are initialized, this saves resources but breaks some Debian available services assumptions.
send "chroot /mnt /bin/bash\r"
expect "#"

# Before mounting the leftover partition, the Debian fsck.ext2 tool is used to check it for errors in case it has not been properly unmounted before:
send "fsck.ext2 -p -v -C0 /dev/sda4\r"
expect "#"
send "mount /dev/sda4 /home/ -o sync\r"
expect "#"

# Mount everything else may have been configured:
send "mount -a\r"
expect "#"

# Launch the SSH server: either Dropbear (fewer resources) or OpenSSH:
send "/etc/init.d/dropbear start\r"
expect "Starting Dropbear SSH server: dropbear."
# send "/etc/init.d/ssh start\r"
# expect "Starting OpenBSD Secure Shell server: sshd."

# Close this telnet backdoor, leaving only SSH (and other stock firmware services such as UPnP i.e. minidlna, SAMBA i.e. smbd etc.) access:
send "killall telnetd\r"

# interact

Prepare a custom firmware:

Temporary notes, high risk of bricking the device. Proceed with caution! No kernel upgrade has been tried yet, only userspace modifications.

Analysis of a stock firmware image and the flashing process:

The following notes apply to the stock firmware ver. 1.1:
$ unzip gives a license, and the actual firmware image fw-M2M-1.100.000

fw-M2M-1.100.000 is a peculiar UNIX self-extracting archive.
$ file fw-M2M-1.100.000 returns:
fw-M2M-1.100.000: POSIX shell script executable (binary data)

$ binwalk fw-M2M-1.100.000 returns:

DECIMAL         HEX             DESCRIPTION
4326            0x10E6          gzip compressed data, was "initrdup", from Unix, last modified: Mon Jul  1 09:44:07 2013, max compression
1539822         0x177EEE        LZMA compressed data, properties: 0x5D, dictionary size: 8388608 bytes, uncompressed size: 65536 bytes

In practice, the first 170 ASCII text lines are a shell script that instruct on how to unpack (and flash) the rest. Following these, we begin with:

tail -n +171 fw-M2M-1.100.000 > upfs.gz

which gives:
$ file upfs.gz
upfs.gz: gzip compressed data, was "initrdup", last modified: Mon Jul  1 09:44:07 2013, max compression, from Unix

$ gunzip upfs.gz
gives a upfs file, which is a standard ext2 filesystem image:

$ file upfs
upfs: Linux rev 1.0 ext2 filesystem data, UUID=48ee846c-1fa2-4ad2-a3d0-692446b63b1f

This can be mounted as loopback device for further analysis:
# mount upfs initdup/ -o loop

initdup# ls -l
total 15
drwxr-xr-x 2 root root 2048 Mar 21  2013 bin
drwxr-xr-x 3 root root 1024 Jul 15  2012 boot
drwxr-xr-x 3 root root 1024 Jul 15  2012 config
drwxr-xr-x 5 root root 1024 Jul 15  2012 dev
drwxr-xr-x 2 root root 1024 Jun  9  2013 etc
drwxr-xr-x 2 root root 1024 Jul  1  2013 firmware
drwxr-xr-x 5 root root 2048 Jul 15  2012 lib
drwxr-xr-x 3 root root 1024 Jul 15  2012 mnt
drwxr-xr-x 2 root root 1024 Jul 15  2012 proc
drwxr-xr-x 2 root root 1024 Jul 15  2012 sys
-rwxr-xr-x 1 root root 1151 Nov 21  2012
drwxr-xr-x 5 root root 1024 Jul 15  2012 var

The "" script does the flashing of the MTD NAND, as directed by its numerical argument. In particular, it takes versioning informations, the kernel binary, its rootfs and the U-Boot bootloader from the "firmware" subdirectory:
# cat firmware/firmware.conf

# file firmware/kernel
firmware/kernel: u-boot legacy uImage, Linux Kernel Image, Linux/MIPS, OS Kernel Image (lzma), 1439867 bytes, Thu Apr 25 03:35:52 2013, Load Address: 0x80000000, Entry Point: 0x8043F000, Header CRC: 0x6A7044ED, Data CRC: 0x652C3C28

The first difficulty appears in interpreting the firmware/rootfs file. At first its magic is not recognized:
# file firmware/rootfs
firmware/rootfs: data
but binwalk reveals:
# binwalk firmware/rootfs

DECIMAL         HEX             DESCRIPTION
0               0x0             Squashfs filesystem, little endian, non-standard signature,  version 3.0, size: 5167458 bytes,  926 inodes, blocksize: 65536 bytes, created: Mon Jul  1 09:44:02 2013

As shown by hexedit, the file begins with "shsq" rather than the usual "hsqs", thus the "non-standard signature" statement. This denotes a LZMA compression scheme with SWAPPED fields, which is not yet supported by Debian "unstable" unsquashfs-tools ver. 1:4.0-8 :

# unsquashfs -h
Decompressors available:

To unpack this, a later version of the squashfs tools may be downloaded from SourceForge via GIT (apt-get install git may be needed):
$ git clone git:// squashfs-code

It must be compiled with the new compression scheme enabled, but also a patch to support this particular deployment.
  1. Download a patch from:, and apply it:
    $ git apply --stat ~/Downloads/0001-unsquashfs-add-support-for-LZMA-magics.patch

    ...will show:

    $ cd .. ; git apply --check ~/Downloads/0001-unsquashfs-add-support-for-LZMA-magics.patch

    squashfs-tools/squashfs_fs.h |    6 ++++++
    squashfs-tools/unsquashfs.c  |   24 ++++++++++++++++++------
     2 files changed, 24 insertions(+), 6 deletions(-)

    ... should show no output (i.e. no errors or conflicts, the patch may be applied cleanly);
  2. Actually apply the patch; either via git, or by hand (removing all lines before:
    --- a/squashfs-tools/squashfs_fs.h
    +++ b/squashfs-tools/squashfs_fs.h , and issuing a simple:
    patch -p1 < 0001-unsquashfs-add-support-for-LZMA-magics.patch )
  3. Edit the squashfs-tools/Makefile and make sure that it reads (apt-get install liblzma-dev may be needed):
    ########### Building XZ support #############
    # LZMA2 compression.
    # XZ Utils liblzma ( is supported
    # To build using XZ Utils liblzma - install the library and uncomment
    # the XZ_SUPPORT line below.
    XZ_SUPPORT = 1
    and further below:
    ########### Building LZMA support #############
    # LZMA1 compression.
    # LZMA1 compression is deprecated, and the newer and better XZ (LZMA2)
    # compression should be used in preference.
    # Both XZ Utils liblzma ( and LZMA SDK
    # ( are supported
    # To build using XZ Utils liblzma - install the library and uncomment
    # the LZMA_XZ_SUPPORT line below.
    # To build using the LZMA SDK (4.65 used in development, other versions may
    # work) - download and unpack it, uncomment and set LZMA_DIR to unpacked source,
    # and uncomment the LZMA_SUPPORT line below.
  4. Alternatively, an archive of the patched & configured snapshot of the tools is made available here. Simply unpack and issue a:
Now the root filesystem may be unpacked and studied in full detail:
# unsquashfs -li /tmp/initdup/firmware/rootfs

For instance, the default passwords for the "admin" user, and the "root" backdoor may be brute-forced via John the Ripper (apt-get install john may be needed):
# john etc/passwd
Created directory: /root/.john
Loaded 2 password hashes with 2 different salts (md5crypt [MD5 32/64 X2])
Press 'q' or Ctrl-C to abort, almost any other key for status
00000            (admin)

This will be the default configuration password for the stock firmware HTTP interface.

Some additional information for this firmware release can be found in the etc/versioninfo file:

... which would point to a Ralink 5350 part running at 360MHz, and confirming availability of 32MiB RAM.

Customizing a stock firmware image:

When rootfs modifications are satisfactory, the new filesystem can be re-squashed via:
mksquashfs . ../new_rootfs -comp lzma

The mksquashfs compiled above, or the default Debian "Jessie" ver. 4.0, will however not be suitable for re-compressing the image before flashing. Besides compressor support for other algorithms such as LZMA, the squashfs binary format has been changed before vanilla kernel inclusion, and is not backwards compatible with the patched support of stock firmware kernel ver. 2.6.21, which will not mount our new new_rootfs file with error message:
SQUASHFS error: Major/Minor mismatch, trying to mount newer 4.0 filesystem
SQUASHFS error: Please update your kernel

Upgrading kernel at the same time as the root filesystem on an embedded system is risky, we may lose all access to the device if something goes wrong.

We can however simply produce a vintage format of our modified rootfs, using obsolete versions of the mksquashfs as available from i.e. the Debian archive. After unpacking the original firmware rootfs through the patched, latest unsquashfs v4.0, it doesn't really matter if the new, modified rootfs will be compressed via gzip rather than the more space efficient LZMA method.

The mksquashfs utility compiled from squashfs_3.1r2.orig.tar.gz works:
# mksquashfs squashfs-root/ new_rootfs_v3.1_format a file in the older ver.3.0 format:
$ binwalk new_rootfs_v3.0_format

DECIMAL         HEX             DESCRIPTION
0               0x0             Squashfs filesystem, little endian, version 3.0, size: 6043973 bytes,  920 inodes, blocksize: 65536 bytes, created: Fri May 30 17:14:40 2014

...which the stock firmware kernel ver. 2.6.21 can mount without problems, for instance as loopback filesystem just for testing before flashing:
# mount /mnt/new_rootfs_v3.0_format /opt/ -o loop
M2M:/# ls /opt/
bin  boot  data  dev  etc  etc_ro  home  lib  media  mnt  opt  proc  sbin  sys  tmp  usr  var  www

The standard magic "hsqs" header will now denote in particular reliance on the older, less efficient compression algorithm.

When all customizations are satisfactory, the "new_rootfs" can replace the original "firmware/rootfs":
$ mv new_rootfs_v3.0_format firmware/rootfs

The whole pre-flashing filesystem can then be unmounted:
# umount initdup

...and re-compressed via gzip:
# gzip initdup

As a last step a self-extracting firmware file has to be created. In particular, the modified ext2 initdup.gz payload will have a different CRCSUM, as computed by the standard 'cksum' utility after some file massaging by sed.

Following the original firmware file scripted lines, the checksum is computed as:

$ sed '1,3d' fw-M2M-1.100.000 |cksum|sed -e 's/ /Z/' -e 's/   /Z/'|cut -dZ -f1

... which matches the expected value as listed within the self-extracting archive:

$ head fw-M2M-1.100.000
# constant

The new self-extracting firmware can be assembled as follows:
  1. Extract the unpacking and flashing script lines:
    $ head -n 170 fw-M2M-1.100.000 >
  2. Prepare a temporary firmware (complete payload, but still invalid CRCSUM) with:
    $ cp
    $ cat upfs.gz >>
  3. Compute the valid CRCSUM via:
    $ sed '1,3d' |cksum|sed -e 's/ /Z/' -e 's/   /Z/'|cut -dZ -f1

    ...and replace the resulting value inside the new file.

    Normally, more than a single iteration can be required: the CRCSUM field is also part of the file content, for which the CRC is calculated, hence it changes as the field is updated. Such CRC calculation procedure is however a sort of lossy compression scheme. As such, modification of a few bytes, like the CRCSUM=... constant, will not change the outcome dramatically. Recalculation a second time is typically sufficient; just repeat this step 3) until the check value is stable and matches the file content.
The customized firmware is now ready for flashing, simply using the default HTTP interface and internal tools. Be aware that this will also reset the WiFi network configuration options.

Building a complete alternative:

A custom embedded Linux image may be assembled ("backed", in Android jargon...) via the BuildRoot system. This allows a great amount of customization, as it provides a set of rules and Makefiles to download, configure and cross-compile only the needed package and specifically supporting the device hardware, for a more efficient usage of the available SoC resources.

Apparently, Ralink also provides a customized BuildRoot SDK. A mirror copy of ver. (including a more recent, but patched for a later board, Linux kernel 2.6.36 besides an older, patched ver. 2.6.21) is available for download for instance here.

The SDK above still needs an external cross-compilation toolchain. The oldish kernel version provided looks in particular not compatible with later GCC developments, such as ver. 4.4 included in the above MIPS(el) toolchain.

It would fail with error:
  CHK     include/linux/version.h
  CHK     include/linux/utsrelease.h
  CC      arch/mips/kernel/asm-offsets.s
arch/mips/kernel/asm-offsets.c: In function 'output_mm_defines':
arch/mips/kernel/asm-offsets.c:233: error: invalid 'asm': invalid use of '%X'
arch/mips/kernel/asm-offsets.c:234: error: invalid 'asm': invalid use of '%X'
arch/mips/kernel/asm-offsets.c:235: error: invalid 'asm': invalid use of '%X'
/tmp/rt5350_GPL_source/kernel/linux-2.6.21.x/./Kbuild:42: recipe for target 'arch/mips/kernel/asm-offsets.s' failed
make[1]: *** [arch/mips/kernel/asm-offsets.s] Error 1
Makefile:863: recipe for target 'prepare0' failed
make: *** [prepare0] Error 2

It seems the SDK refers to a specific GCC version, gcc-3.4.2. This is available from a study of another Ralink -based product, the Coolcam NIP-09 NIP-02, also based on the RT5350 (in the F = FPU variant). And also, by the way, including a telnet backdoor! (username: root, password: 123456) and is mirrored here for convenience.

Instructions on how to use the SDK and toolchain are available from here, and have been also mirrored here for convenience. In practice, the content of buildroot-gcc342.tar.bz2 should be placed within /opt, and one may issue:
$ export MANPATH=$MANPATH:/opt/buildroot-gcc342/man

... to furthermore have access to the included manpages.

Another, slightly more up-to-date version of the SDK (ver. has been also made available online, and is mirrored for convenience here (including compiler toolchain etc.).

Further packages which may require installation are, for instance:
# apt-get install flex bison

... and so on, as per list of dependencies.

LZMA compression:
  • Beside that toolchain, a (patched up) standalone LZMA compressor is also needed, if one wants to follow the default SDK build process. It seems slightly different from this version, and should be provided as part of the RT288X_SDK for instance. The utility "lzma_alone" must be compiled and placed in /opt/buildroot-gcc342/bin/
  • Alternatively, it seems possible to switch to the older, less space efficient but far more established gzip compression scheme. The crucial stage where the rootfs is compressed, as part of the kernel building process, is controlled by the scrip linux-2.6.21.x/scripts/, which can be modified not to use the (vendor -patched) lzma_alone compressor by changing interpretation of option use_lzma to "n":
To use the SDK, unpack it and enter the "source" subdirectory. Issue a:
$ make menuconfig

... command (apt-get install libncurses5-dev may be needed) and press Enter on the "Select the Product you wish to target", then select "Ralink Products", and "RT5350". Then select "Default configuration file" and choose "4M/32M(AP+NAS), and exit repeteadly.

The item "Kernel/Library/Defaults Selection" allows to change what cross-compiler chain to use, which parts of the BuildRoot distribution will be included in the firmware, which libc will these linked with, and which Linux kernel should drive the whole.

Even if no parameters will at first be changed, it is crucial to let BuildRoot scripted process take care of setting up the right cross-compiler toolchain in all subdirectory. This can be achieved by selecting for customization all the fields:
  • Customize Kernel Settings
  • Customize Vendor/User Settings
  • Customize Busybox Settings
  • Customize uClibc Settings
  • Customize uClibc++ Settings
... so that each one sub-menu will be brought up at least once, and updated with the right parameters from the main menu upon saving.

Once happy with all selection, save and exit the main menuconfig interface, and issue a simple:

# make

The build will take a few minutes but succeed without errors. The (safer) default BuildRoot behaviour has been modified in the SDK version, so as to try and create device files too under /dev in the rootfs. This will fail if the user is not root.
The outcome is stored in the images/ subdirectory, and attempts are made to also copy it as a /tftboot file in the host root filesystem (!). In particular, even after swiching off usage of the lzma_alone utility, a images/zImage.lzma file gets created and may be decompressed via:
$ unlzma ralink_sdk-master/source/images/zImage.lzma

Again binwalk provides better insight on its content:
$ binwalk zImage
$ binwalk zImage

DECIMAL         HEX             DESCRIPTION
752777          0xB7C89         LZMA compressed data, properties: 0x88, dictionary size: 1048576 bytes, uncompressed size: 4608 bytes
940089          0xE5839         LZMA compressed data, properties: 0x38, dictionary size: 1048576 bytes, uncompressed size: 4160 bytes
950753          0xE81E1         LZMA compressed data, properties: 0x30, dictionary size: 524288 bytes, uncompressed size: 992 bytes
2261044         0x228034        Linux kernel version "2.6.21 (root@t420) (gcc version 3.4.2) #2 Sat May 31 21:56:45 C 3.4.2) #2 Sat May 31 21:56:45 CEST 2014CEST 2014"
2267836         0x229ABC        LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 50331648 bytes
2424580         0x24FF04        ASCII cpio archive (SVR4 with no CRC), file name: "sh entry"
2875460         0x2BE044        LZMA compressed data, properties: 0x02, dictionary size: 16777216 bytes, uncompressed size: 512 bytes
2875541         0x2BE095        LZMA compressed data, properties: 0x02, dictionary size: 131072 bytes, uncompressed size: 33620481 bytes
2887043         0x2C0D83        LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887067         0x2C0D9B        LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887259         0x2C0E5B        LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887283         0x2C0E73        LZMA compressed data, properties: 0x02, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887307         0x2C0E8B        LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 32 bytes
2887331         0x2C0EA3        LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887355         0x2C0EBB        LZMA compressed data, properties: 0x31, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887379         0x2C0ED3        LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887427         0x2C0F03        LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887451         0x2C0F1B        LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887475         0x2C0F33        LZMA compressed data, properties: 0x30, dictionary size: 65536 bytes, uncompressed size: 64 bytes
2887499         0x2C0F4B        LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 128 bytes
2887523         0x2C0F63        LZMA compressed data, properties: 0x40, dictionary size: 65536 bytes, uncompressed size: 256 bytes
2892036         0x2C2104        LZMA compressed data, properties: 0x01, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892136         0x2C2168        LZMA compressed data, properties: 0x09, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2892156         0x2C217C        LZMA compressed data, properties: 0x0A, dictionary size: 131072 bytes, uncompressed size: 2 bytes
2894087         0x2C2907        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894107         0x2C291B        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894127         0x2C292F        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894147         0x2C2943        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894167         0x2C2957        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2894187         0x2C296B        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 896 bytes
2905944         0x2C5758        LZMA compressed data, properties: 0x01, dictionary size: 16777216 bytes, uncompressed size: 16777473 bytes
3084288         0x2F1000        gzip compressed data, from Unix, last modified: Sat May 31 21:56:39 2014, max compression

The crucial information is at the end. As a result of the script modification, the rootfs archive has been appended at the end of the file in gzip format. It can be extracted for verification by skipping all preceeding parts of the file:
$ dd if=zImage of=rootfs_recomp.gz seek=3084288 bs=1
and simply:
$ gunzip rootfs_recomp.gz
... to reveal a standard CPIO archive:
$ file rootfs_recomp
rootfs_recomp: ASCII cpio archive (SVR4 with no CRC)

As per standard Linux kernel documentation, this can be opened via:
$ cpio -i -d -H newc -F rootfs_recomp --no-absolute-filenames

(again, attempts at creating special /dev files will fail, without root permission)

In other words, we should be able to check that this SDK -recompiled CPIO archive of a rootfs matches the stock firmware "firmware/rootfs" ext2 image, which is itself normally shipped within the initrdup.gz payload of a ready-to-flash self-extracting firmware file.
This allows to upgrade the userspace parts of the embedded Linux environment, without changing yet the default kernel. It is possible in particular to close the default telnet backdoor; add other packages such as i.e. like the Snort NIDS to better monitor the network; and provide i.e. a out-of-the-box dropbear SSH server for better local access security.

One problem with the old GCC toolchain that Ralink SDK would use by default is lack of support for better CPU optimization. Contrary to the more up-to-date compiler that even Debian "Lenny" ships, GCC ver. 3.4.2 supports at most a:
 -mips32r2 -O3
... optimized build target, thereby not really exploiting more advanced capabilities of the SoC MIPS_24KEc processor.

Another alternative worthy considering would be plain adoption of an embedded Linux distribution such as OpenWRT, see for instance their useful explanation of the flash memory layout.

Support for the base mainboard was added with this commit, and compatibility with the hardware should only improve with time, as it is officially adopted for further deployments of Ralink RT5350 "router on a chip" such as this one.

Extra safety before flashing firmware from a completely different codebase would suggest first gaining access to the "Das U-Boot" bootloader serial console (and before that, the Linux getty login which appears running in the standard firmware), by opening the device as illustrated here, and connecting a TTL <-> 5V level converting serial cable to the appropriate pins. One suitable adapter should be for instance the very common, USB-ready CP2102 module, or clones.


Cool tricks:

Access through SSH:

  • SSH client for various Windows versions: try PuTTY;
  • Konqueror "FISH" sshfs -lookalike access: just use fish://root@ address in the address bar;
  • Automatic, incremental backup (Apple "Time Capsule" -alike functionality) via Back In Time, relying on the rsync protocol to reduce network traffic, SSH for data encryption during the transfer, and ext2 hard-links (as opposed to the cruder VFAT capabilities) to save disk space by only storing changes.

    "Back In Time" and rsync in particular would also work, with the stock firmware and through the SAMBA interface, making the exported VFAT partition accessible on Linux via a CIFS mountpoint. This introduces however extra overhead.
Non-interactive, safe SSH access may be configured with public key authentication.

Non-interactive CIFS access from a Linux system to the default /dev/sda1 partition made available through the SMB daemon may be set up with the "/etc/fstab" line:

//  /mnt/M2M_Backup  cifs  credentials=/home/[USERNAME]/.smbcredentials,users,iocharset=utf8,sec=ntlm,noauto 0 0

... which points to the /home/[USERNAME]/.smbcredentials file (with Samba crentials in clear text!):
password=[password chosen through the unit HTTP interface]

Package recompilation with enhanced CPU support:

Even without switching to a fully custom firmware via i.e. BuildRoot above, some critical Debian packages may easily be recompiled on the unit itself with optimization options better geared to the available hardware. Options:

-O3 -march=24kec -mdsp -mips32r2

... show some speedup.

It is sufficient to include the appropriate APT source line in /etc/apt/sources.list:
deb-src lenny main contrib non-free

... getting sources (and build dependencies) via:

apt-get source [packagename]

The package compilation flags may be changed within its debian/rules file, and a customized version prepared via:

dpkg-buildpackage -b

therefore installing the resulting pacakgename.deb via:

dpkg -i packagename.deb usual. Since the "Lenny" distribution suggested above is in "Archived" status, there will not be later package revisions from the central repository to overcome local preferences.

Alternatively, the more complete apt-build solution may also be used.

Even with these optimization, the choking point in network backups appears to be the SSH server. The embedded CPU is just not powerful enough to handle on-the-fly strong encryption at the speed otherwise supported by the WiFi network, or the local hard-disk.
Using "Back in Time" CLI interface shows:
$ backintime --benchmark-cipher 20
Back In Time
Version: 1.0.34

Back In Time comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions; type `backintime --license' for details.

create random data file
20+0 records in
20+0 records out
20971520 bytes (21 MB) copied, 1.61118 s, 13.0 MB/s

  • 3des-cbc: 20MB 585.1KB/s   00:35 
                     20MB 640.0KB/s   00:32 
  • aes128-cbc: 20MB   1.1MB/s   00:19   
                         20MB   1.1MB/s   00:18
  • aes256-cbc: 20MB   1.1MB/s   00:18   
                         20MB   1.1MB/s   00:19
  • blowfish-cbc: 20MB   1.1MB/s   00:18
                           20MB   1.1MB/s   00:18
... while the plain, unencrypted rsync protocol could be used by launching the utility in daemon mode with:
$ rsync --daemon --no-detach --port=2000 -vvv --config=rsyncd.conf

and benchmarked from the client with:
  • Highest compression, no SSH:
    $ time rsync -vvv -az --compress-level=9 /tmp/re rsync://m2m:2000/pub
    sent 20,983,554 bytes  received 34 bytes  1,678,687.04 bytes/sec
    total size is 20,971,520  speedup is 1.00
    [sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)

    real    0m11.875s
  • No compression, no SSH:
    $ time rsync -vvv -a /tmp/re rsync://m2m:2000/pub
    sent 20,976,730 bytes  received 34 bytes  1,824,066.43 bytes/sec
    total size is 20,971,520  speedup is 1.00
    [sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)

    real    0m11.107s
  • No compression, SSH (twice as slow!):
    $ time rsync -vvv -e ssh /tmp/re m2m:/tmp/testrsync
    sent 20,976,707 bytes  received 437 bytes  975,681.12 bytes/sec
    total size is 20,971,520  speedup is 1.00
    [sender] _exit_cleanup(code=0, file=main.c, line=1183): about to call exit(0)

    real    0m21.642s