June 22, 2020

The DPH153-AT Femtocell

The board I yanked out of my Femtocell has been laying on my workbench for 3 years! I got in the mood again to fool with it. I found that I could solder a header onto JP1 and get a serial console! Using this I can see all the messages from U-Boot and watch Linux booting up on the Ralink RA2150F chip. It offers me a login prompt, but I have no passwords, so we are on to more adventures.

The Ralink 2150 is a MIPS based SoC, probably intended for use in a home Wifi router. It includes a 5 port ethernet switch along with the MIPS processor running at 384 Mhz. With 16 M of RAM, this would have been an impressive system once upon a time.

Getting to the filesystem

By interrupting U-Boot, it is possible to get an interactive U-Boot console and then use the "md" command to dump the flash. I write a simple python program to issue the "md" command and capture the output (there is 4M of flash).

After inspecting the boot message, I tentatively conclude there are 5 partitions:

0x00000 - 0x20000  128K boot loader
0x20000 - 0x30000  64k config
0x30000 - 0x40000  64k config2
0x040000 - 0x220000 1152k kernel
0x220000 - 0x400000 1152 kernel2
It looks to me like config and config2 are redundant copies of each other, as are kernel and kernel2, but I will confirm this later. And they are not. Maybe they could or should be. This is definitely not the case with config since this part of flash is erased on each boot.

The first word in kernel and kernel2 is 0x27051956. This is the magic number for a U-Boot image, which is a known thing. The next step is to convert my ascii dumps into a binary image and then use some tools to further examine it. There are some hints in the following:

I write another simple python program to parse my ascii captures and generate a 4M file which is an image of the flash contents. I call it "femto.img". I extract the 34*64k bytes that are the "kernel" section above using "dd", but now I get into trouble with endian issues.

mkimage

I ought to be able to run "mkimage -l kernel.img" but the message I get is:
./mkimage: ERROR: "kernel.img" has corrupted data!
GP Header: Size 27051956 LoadAddr c4486530
I am using an mkimage from one of my ARM project builds, which are little endian. The MIPS can be either endian, but big-endian is the default and seems to be the usual thing. I could (and maybe should) get the U-Boot sources and build for a MIPS target.

binwalk

This is a new discovery that I get hints about doing various searches. It is described as a "open source firmware extraction tool that extracts embedded file systems from firmware images" This sounds like exactly what I am doing, and it is already a Fedora package and installed on my Fedora system. I have Binwalk v2.1.1 on my system. Running it, I get:
binwalk kernel.img
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             uImage header, header size: 64 bytes, header CRC: 0xC4486530, created: 2011-10-06 01:41:24, image size: 1691872 bytes, Data Address: 0x80000000,
			    Entry Point: 0x802A1000, data CRC: 0x4305B877, OS: Linux, CPU: MIPS, image type: OS Kernel Image, compression type: lzma, image name: "Linux Kernel Image"
64            0x40            LZMA compressed data, properties: 0x5D, dictionary size: 33554432 bytes, uncompressed size: 3687954 bytes
I can tell binwalk to do an extraction using the "-e" option and this gives me the following:
-rw-rw-r-- 1 tom tom  3687954 Jul 22 14:21 40
-rw-rw-r-- 1 tom tom  1966016 Jul 22 14:21 40.7z
Here the "40.lz" file is simply my kernel.img with the 64 bytes at the front trimmed off. The file "40" has been decompressed somehow and indeed, the first part of it seems to be the kernel image, ready to be loaded into memory and run. I do not see any evidence of a filesystem however and that is the mystery at present.

A filesystem must follow the kernel (where else could it be?)

We see the following messages when booting:

## Booting image at bf040000 ...
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
No initrd
## Transferring control to Linux (at address 802a1000) ...
## Giving linux memsize in MB, 16
No hint of the size of the kernel before or after booting. These strange lines appear in the U-Boot environ variables. Note that "filesize" is never defined, and the "BC" addresses are never defined. Even the "8A" addresses are mysterious.
u_fs=era bc540000 bc83ffff;cp.b 8A100000 BC540000 $(filesize)
u_b=protect off 1:0-1;era 1:0-1;cp.b 8A100000 BC400000 $(filesize)

RAM

We have 16M of it. And the best guess at this time is that it is at:
0x80000000 - 0x80ffffff
So, if we start the kernel at 802a1000 and the "data address" in the header is the load address, perhaps that tells us something, being well over 2M into the kernel image.

A clue

Running Binwalk on the extracted and uncompressed kernel image, we see this, among other things:
2904064       0x2C5000        LZMA compressed data, properties: 0x5D, dictionary size: 1048576 bytes, uncompressed size: 2874880 bytes
So the compressed image contains another compressed image after the kernel, which is sort of what we suspected. The uncompressed image (with the kernel in the front) is 3687954 bytes in size (0x384612)

I do this:

dd bs=4096 skip=709 if=40 of=fs.7z
7z e fs.7z
file fs
fs: ASCII cpio archive (SVR4 with no CRC)
How about that? Now I extract this via:
mkdir files
cd files
cpio -i --no-absolute-filenames <../fs.cpio
And now I have the root filesystem inside the "files" directory.
In particular:
root:xSCV0.l5YF7k2:0:0:root:/root:/bin/sh
sshd:xSCV0.l5YF7k2:0:0:root:/root:/bin/sh
The following link shows the entire contents of the cpio archive:
Have any comments? Questions? Drop me a line!

Tom's electronics pages / tom@mmto.org