DMS1 Hacking

From Omnifi Wiki

Jump to: navigation, search
Omnifi DMS1 Hacking --Chad 18:03, 24 May 2005 (CDT)

Contents

Overview

The Omnifi DMS1 is a digital media streamer for home use. It plays both .mp3 (MPEG audio) and .wma (Windows Media Audio) files through an Ethernet interface (wired or wireless), and can also connect to external storage devices containing media (which is beyond the scope of this for the moment).

The hardware platform is very similar to the Omnifi DMP1, which is a digital media player designed for in-car use. Almost all of the information in this paper can be applied to the DMS1 or the DMP1. Any DMP1 specific information will be called out, if the need arises.

The DMS1 was used as an initial hacking platform due to its self-containment, ease of enclosure disassembly, and the availability of “handy” PCB headers. The firmware is normally downloaded to the DMS1 via an FTP transfer using SimpleCenter, but there is also a manual method available too which is beyond the scope of this document for the moment. The firmware objects provided by Omnifi are “.sfu” files. They contain the Linux kernel and filesystem but are encrypted. This has so far thwarted any efforts to dissecting the firmware or providing user built firmware (and hence, the purpose of this document!).

Please note that the information provided here is for informational purposes only. I do not accept any liability resulting in the use of this information. Any damage you do to your DMS1/DMP1 is your own responsibility. Use with caution!

In should also be noted that any firmware discussions in this report may be specific to DMS1 version 2.1.012 (DMS1_Build_2-1-012.sfu), which is the latest version of DMS1 firmware available at the writing.

Hardware Information

The DMS1 is based upon a Cirrus Logic EP7312 ARM-based processor, running Linux. It is capable of running at speeds up to 90MHz (which the stock firmware does) and has a variety of on-chip peripherals.

Hardware Components

The major DMS1 hardware components are listed in the table below:

ComponentChip#ManufacturerDescription / Notes
CPUEP73121Cirrus LogicARM-7 based processor (90MHz)
Flash ROME28F320 J3A1101Intel32-Mbit StrataFlash® Memory
SDRAMIS42S16400A-10T2ISSI64-Mbit SDRAM
SDRAMIS41LV16100-50T1ISSI16-Mbit SDRAM (Video Memory?)
(not available on DMP1)
LCD-TVS1D135061EpsonColor LCD/CRT/TV Controller
(not available on DMP1)
USBTDUHC124B1TransDimensionUSB Host Controller
GluePIC16LF8721MicrochipBoard controller
DACCS43401Cirrus LogicStereo ΔΣ-DAC with built-in filters

Power

The DMS1 is powered by a 5V power supply, implemented on a separate PCB, which itself takes an input of 120VAC. The once on the mainboard 5V supply is further dropped by additional regulators as needed by the individual hardware components. The following table shows the power supplied to each chip and the corresponding regulator chip that supplies the power. Please note that the chip names correspond to the DMS1.

ComponentSupply DMS1 SourceNotes
CPU2.5VU2 (?)Core Voltage
3.3VU1I/O Voltage
Flash ROM3.3VU1
SDRAM3.3VU1
LCD-TV3.3VU1
USB3.3VU1
PIC3.3VU1
DAC4.0VU23U23 seems to create a 2.5V as well

So it would seem that U1 is the main supplier of 3.3V for the board. The large pin on U1 is one of the 3.3V output pins. This makes it handy to clip on to, if you require the same supply as the other chips onboard. This is important in the ROM dump section.

Cirrus Logic EP7312

The EP7312 is the heart of the DMS1 and DMP1. It is an ARM7 based processor with a plethora of peripherals. Any hacking of the DMS1/DMP1 will involve working with this processor. After initial boot, the EP7312 runs the Linux OS, which should allow for easier hacking as well, due to its available source code and well known execution.

The EP7312 can operate in Big or Little Endian mode. On the DMS1/DMP1 it is setup to operate in Little Endian mode. This is compatible with Intel x86 architectures.

After reset, the EP7312 begins execution at address 0x00000000 (the reset vector). Depending on the state of the nMEDCHG pin (active low), this mapped to external flash (when nMEDCHG is not active) or the EP7312’s internal boot ROM (nMEDCHG active). The internal boot ROM allows for a small serial download of program code (2KB) into internal SRAM at address 0x10000000. This allows arbitrary code to be executed on the EP7312, and allows for various things such as reading memory locations or writing a new flash image, if desired. Various exploits using this alternate boot method are used in this document.

JTAG Interface

The EP7312 has a JTAG interface (EmbeddedICE), which could allow for access to internal registers and may make it possible for memory reads/writes. The main disadvantage is that an external JTAG capable piece of hardware is required, which could be expensive. A possible home brew is also possible though, as the pin count is low (only 5 pins in the JTAG interface). So far, only a few of the JTAG pins have been traced on the DMS1 to pull-up or pull-down resistors (others may be traced to the bottom side of the board). It is reasonable to assume they are all pulled up or down and were not meant to be used. Since they are connected to pull up/down resistors, it is still possible to attach an external JTAG debugger module. The JTAG interface pins are summarized in the following table.

JTAGPin NamePinDestination
TCLKClock90R36 (4.7k pull-down)
TDIData Input11???
TDOData Output22RP11 (multiple 10k pull-up resistor pack)
nTRSTAsynchronous Reset Input125???
TMSMode Select58R35 (4.7k pull-down)

DMS1 Headers

The DMS1 has various “interesting” headers that look to be leftover from development of the DMS1 software. Looking at the mainboard, there are a number of headers and unpopulated pads: J3, J5, and SW2. These headers are quite handy, as they pull out a number of important signals. For J3, pin 1 (top) is indicated by the triangular indicator next to the ‘J3’ label. Pin 1 (bottom) is assumed to be opposite to pin 1 (top). For J5, pin 1 is the square via (pad).

J3 Header Pin Descriptions
PinConnectionNotes
1 (top)N/CNo connection
2 (top)N/CNo connection
3 (top)Pin 36 on EP7312 (RXD[1])UART1 Receive
4 (top)Pin 32 on EP7312 (TXD[1])UART1 Transmit
5 (top)Pin 155 on EP7312 (nMEDCHG/nBROM)Media Change / Boot Rom Selection
1 (bottom)Pin 62 on EP7312 (LEDFLSH)GPIO or LED Blinker Output
2 (bottom)Pin 44 on EP7312 (Ext. FIQ input)External Fast Interrupt Input
3 (bottom)Pin 44 on EP7312 (Ext. FIQ input)(same as above – shorted together)
4 (bottom)GroundVssIO on EP7312
5 (bottom)GroundVssIO on EP7312

J3 is used for using the EP7312’s boot ROM program, or at least the top side of the header is. By holding Pin 5 (top) to ground during reset, the EP7312 will start executing out of its internal boot ROM. This allows code to be downloaded via the asynchronous serial interface on Pins 3 (top) and 4 (top). It defaults to 9600 baud. This interface is described in better detail later in this document.

The bottom side of J3 is somewhat of a mystery. It doesn’t appear to have much use at the moment, as all it has is an external interrupt pin and the LED blinker output. The DMS1 firmware may do something with these pins, but it is unknown at this time.

J5 Header Pin Descriptions
PinConnectionNotes
1Pin 24 on PIC (RB3/PGM)Low Voltage Programming Enable
2Pin 27 on PIC (RB6/PGC)Programming Clock
3Pin 28 on PIC (RB7/PGD)Programming Data
4GroundGround – Vss Pins 8, 19 on PIC
53.3VPower – Vdd Pin 20 on PIC
6MCLR-/VppMaster Clear / Programming Voltage In/Out (See PIC Datasheet)
Note: this is also connected to Vdd through a 5k resistor (no protection diode)

J5 is used to program the PIC device in-circuit. See the PIC datasheet for more information. It contains a full description of this interface. There is one small concern though. In the PIC datasheet, the programming circuit puts a high voltage signal on to Vpp for programming. The circuit in the datasheet has a protection diode in place to prevent the high voltage from being applied to the rest of the circuit. It does not appear to be in place on the DMS1. There is just a 5k resistor inline between the MCLR- pin and the 3.3V source. The 3.3V source may, however, have built in protection, but this is still something to consider as it may damage the 3.3V regulator to have high back voltage applied to it. On the other hand, they probably wouldn’t have put this header here if they weren’t using it to program the PIC in-circuit.

SW2 Description
PadConnectionNotes
Next to ‘SW2’ LabelR30 (270 Ohms)R30 is connected to Pin 1 on the PIC (MCLR-/Vpp).
Far from ‘SW2’ LabelGround

SW2 looks like a reset switch. If the two pads are shorted together, then R30 acts like a pull-down resistor, and the MCLR- signal is asserted on the PIC. Since the PIC is the board controller, it also has the side affect of resetting the entire board.

RS232 / Serial Connection

The EP7312 has two UART (Universal Asynchronous Receiver and Transmitter) ports. UART 1 is connected to the DMS1 header J3 which assists in communicating with the EP7312. In order to connect a PC to the DMS1, the following must done.

The first thing to consider is the fact that the TXD/RXD pins operate at 0-3.3V (the I/O voltage of the EP7312), where as the serial port on your PC operates at the RS232 voltages, ±15V. Connecting the PC COM Port directly to the EP7312 would destroy the EP7312! Because of this fact, a RS232 transceiver must be used. Many such devices exist, due to the popularity of RS232. One such device is Maxim’s MAX3233, which operates at 3.3V and requires no external capacitors. Any such device will suffice, as long as the logic levels run at 3.3V. As an example, the pin connections of the MAX3233 to the DMS1 and to the PC are shown below. As a convenience, you can use the existing 3.3V source, DMS1 U1, on the DMS1 to power the MAX3233. This eases the requirements of having to match the exact voltage on an external power supply. However, this is a little more risky, as it may overload the U1 voltage regulator. So use at your own risk! Also, make sure the ground is matched between the DMS1, the RS232 transceiver, and your PC. There are many exposed ground pads available on the mainboard.

MAX3233 PinNameConnected ToDescription
3T2INGroundTied to ground – not used
4T1INDMS1 J3 Pin 4 (top)–TXD[1]TTL/CMOS Transmitter Input
5FORCEON3.3VUsed to keep transceiver active (can be tied to ground instead to use the auto-shutdown feature and save power)
6R1OUTDMS1 J3 Pin 3 (top)–RXD[1]TTL/CMOS Receiver Output
7T1OUTCOM Port Pin 2 (Rx)RS232 Transmitter Output
8R1INCOM Port Pin 3 (Tx)RS232 Receiver Input
9Vcc3.3VPower
10FORCEOFF-3.3VEnables the transceiver
18GNDDMS1Ground
COM Port Pin 5 (GND)Ground
20R2INGroundTied to ground – not used

Note: all other pins should be left floating (i.e. no connection). You should also connect a 0.1μF capacitor across the Vcc and GND pins. See the MAX3233 datasheet for more information on exact wiring.

Flash Memory

The EP7312 obtains program instructions and data from the Intel E28F320 4-Mbyte flash memory module. This flash device has 32 sectors (32 x 128KB), each one can be separately protected or erased. The Linux OS sees this flash memory as multiple memory technology devices (/dev/mtd) of varying size. This is important later, as various parts of the DMS1 firmware is stored in different mtds.

Chip Selects and Memory Map

The following table summarizes the memory map and chip select usage on the DMS1. The bus width column was determined via the DMS1 firmware startup code, which initializes the MEMCFG registers. Not all physical bus connections have been determined yet, via tracing on the PCB or in the code. Unknown fields are filled with “???”. Due to the hardware differences between the DMS1 and the DMP1, this memory map is probably not completely valid for the DMP1.

Start AddressEnd AddressChip SelectBus WidthDescriptionDevice End Address
0x000000000x0FFFFFFFCS[0]16Flash ROM0x003FFFFF
0x100000000x1FFFFFFFCS[1]8USB Controller???
0x200000000x2FFFFFFFCS[2]8??????
0x300000000x3FFFFFFFCS[3]16CRT Controller0x301FFFFF
Video Memory0x3029FFFF
0x400000000x4FFFFFFFCS[4]8??????
0x500000000x5FFFFFFFCS[5]8??????
0x600000000x6FFFFFFFCS[6]32Internal SRAM
(48400 bytes)
0x6000BD0F
0x700000000x7FFFFFFFCS[7]32Internal Boot ROM
(128 bytes)
0x7000007F
0x800000000x80003FFFN/A32Internal RegistersN/A
..................
0xC00000000xCFFFFFFFN/A32SDRAM0xC0FFFFFF

Note: This memory map is only valid when using external boot. (i.e. when nMEDCHG is not active). For internal boot, the memory map is almost reversed so that the internal boot ROM is at 0x00000000, CS[7]. See the EP73xx User’s Guide for details.

Note 2: Obviously the DMP1 does not have a CRT Controller or the supporting video memory. This is only available on the DMS1.

Flash Memory Map

As mentioned above, the flash memory device is organized into 32 x 128KB sectors. This is setup as multiple memory technology devices (mtd) of varying size. In Linux, they are seen as /dev/mtd/0, /dev/mtd/1, etc. The following table shows the addresses of the various sectors and the corresponding Linux mtd identifiers as setup by the DMS1 firmware. Note: These values were obtained by looking at the ROM dump, so they might not be completely correct. Your mileage may vary.

Start AddressEnd AddressLinux DeviceDescription
0x000000000x0001FFFF/dev/mtd/1ARM Boot Block (128KB)
0x000200000x0003FFFF/dev/mtd/2Rescue Linux Kernel (1.25MB)
0x000400000x0005FFFF
0x000600000x0007FFFF
0x000800000x0009FFFF
0x000A00000x000BFFFF
0x000C00000x000DFFFF
0x000E00000x000FFFFF
0x001000000x0011FFFF
0x001200000x0013FFFF
0x001400000x0015FFFF
0x001600000x0017FFFF/dev/mtd/3Production Linux Kernel (1MB)
0x001800000x0019FFFF
0x001A00000x001BFFFF
0x001C00000x001DFFFF
0x001E00000x001FFFFF
0x002000000x0021FFFF
0x002200000x0023FFFF
0x002400000x0025FFFF
0x002600000x0027FFFF/dev/mtd/4cramfs Filesystem (1.5MB)
0x002800000x0029FFFF
0x002A00000x002BFFFF
0x002C00000x002DFFFF
0x002E00000x002FFFFF
0x003000000x0031FFFF
0x003200000x0033FFFF
0x003400000x0035FFFF
0x003600000x0037FFFF
0x003800000x0039FFFF
0x003A00000x003BFFFF
0x003C00000x003DFFFF
0x003E00000x003FFFFF/dev/mtd/5User Data (128KB)

Using the EP7312 Boot ROM for Extracting ROM Image and Register Contents

The first step to hacking the Omnifi was to first get a copy of the flash ROM image. It was hoped that the image on the ROM would not be encrypted, making it easier to reverse engineer. And it turns out, it is NOT encrypted. This allowed for disassembly of the binary code and allowed for further study of the DMS1’s operation.

It is recommended that before modifying the onboard flash ROM with custom code, that you extract the entire ROM image and back it up so that it can be restored later in case of catastrophic failure!

As mentioned before, J3 is used to take advantage of the EP7312’s boot ROM feature. This allows a small binary code object (2KB) to be downloaded into internal SRAM and executed. The TXD[1] and RXD[1] pins provide the asynchronous interface for communicating with the EP7312. The code object can then read what is contained in flash, and dump that data out to the serial port.

In order to connect the EP7312 to a PC, the procedure in the RS232 / Serial Connection section may be followed. Note: direct connection is not allowed or serious damage will occur to the EP7312!

Once a serial connection has been made, use your favorite PC terminal program, set the terminal to 9600 bps, hold the EP7312’s nBROM pin (DMS1 J3 Pin 5 (top)) to ground and reset the unit (either via power cycle or SW2). You should see a single ‘<’ character appear on the terminal. This is the EP7312 boot ROM’s signal that it is ready to receive a 2KB binary executable that will be relocated to internal SRAM at 0x10000000. To download, simply use a raw file transfer (or ‘cat’ it to the terminal). The file must be exactly 2KB in length. After download, the EP7312 will echo the ‘>’ character to the terminal and jump to the new code.

This binary executable can do whatever you want. In this case, we will have it read the flash memory and/or register contents. Or you could have it download a new flash ROM image and write it out to flash. The possibilities are almost endless. However, if your code requirements are more than 2KB, a two-stage download must be performed. That is, the initial 2KB object is downloaded, which in-turn downloads and executes the entire code object you want to execute.

DMS1 ROM Dump Code

In order to get the contents of the Flash ROM device, the following code can be downloaded to the EP7312. It first asks for the desired terminal bitrate, and then will perform an X-Modem-1K or X-Modem-CRC transfer of the 4MB ROM device. I have had problems trying to run at 115200 bps, most likely due to small clock differences between the EP7312 and my PC. So for a more reliable transfer, try using a slower bitrate.

Get the binary here: dumpx.zip

Once you have obtained a copy of your ROM, you may want to disassemble it and examine its operation. I would suggest using the latest distribution of binutils, which includes a disassembler (objdump). Then you need to brush up on your ARM assembly skills!

Now, it also may be possible to load your ROM image back on to the DMS1, in case something seriously gets screwed while you’re hacking away. Right now there is no program that will do this, but when it becomes available, it will be posted here (I hope!).

EP7312 Register Dump Code

If you are interested in the register contents of the EP7312, this binary executable can be used. It is useful if you want to get the contents of the 32-bit Unique ID register (UNIQID), or the four 32-bit registers that make up the 128-bit Random ID for your EP7312 device (RANDID0, RANDID1, RANDID2, and RANDID3). I doubt that it is a huge coincidence, but the EP7312 in my DMS1 reports UNIQID = RANDID0. I wonder if anyone else sees this.

Get the ARM binary here: dumpregs.zip

Software Information

Compiler

The DMS1/DMP1 runs Linux on the ARM architecture. This means that if you want to compile code for the DMS1 or DMP1, you will require an ARM compiler or cross-compiler (as you probably won’t be running your compiler natively on an ARM platform). The easiest way to create a cross compiler for the Linux-ARM target, you may want to pick up a copy of crosstool (http://www.kegel.com/crosstool/), which can create a cross compiler for your host (doing it by hand can be a horrific nightmare!). As the EP7312 does not have hardware floating point support, you will need to create your compiler and libraries for the “arm-softfloat-linux-gnu” target.

Stack Information

If you plan on looking at or writing assembly code, you should be aware that the stack is 4 byte address aligned, grows downwards (i.e. from high addresses to low addresses) and points to the last allocated space on the stack. That is, it does NOT point to the next available space on the stack. This is also known as a “full-descending” stack.

DMS1/DMP1 Software

GPL Sources

The bulk of the DMS1/DMP1 software consists of source code covered under the GNU General Public License (GPL). Under the GPL, Omnifi is required to provide the source code that is covered under the GPL as well as any modifications to GPL code. In email conversations with some Omnifi customers, Omnifi has indicated the following GPL code is present in their product (thanks to omnifiuser2 from Yahoo! Groups).

http://www.kernel.org  2.4.18 release
http://www.arm.linux.org.uk/developer/ patch 2.4.18-rmk7
http://www.uclibc.org  uClibc-0.9.15
http://www.stlport.org  STLport-4.5.3
http://www.busybox.net busybox-0..60.3
http://www.bftpd.org
http://www.linux-wlan.org
ftp://ftp.inr.ac.ru/ip-routing/iputils-current.tar.gz arping
http://www2.one-eyed-alien.net/~mdharm/linux-usb/ usb-storage
http://bjorn.haxx.se/isd200/  isd200/300 driver

Additional Tools:
net-tools-1.60
fileutils-4.1
sysvinit-2.83
e2fsprogs-1.29
dhcpcd-1.3.22-p13
util-linux-2.11t

Looking at the list, it is apparent that some of the source versions are not indicated and when visiting the sites, some of them are no longer active.

Recently, Omnifi has setup an FTP site, ftp://ftp2.simpledevices.com, allowing users to download the GPL sources contained in the DMP1/DMS1. It may be speculated that Omnifi must have received increased pressure to release the actual source, as required by GPL, instead of providing links to the sources.

DMS1 Firmware Layout

By examining the ROM dump of a DMS1, it is found that the DMS1 firmware image consists of a number of important sections.

Boot Code

The DMS1 boot code is located at address 0x00000000. After dissecting the boot code with a disassembler, it was discovered that the boot code is actually a freely available package known as ‘armboot’ (http://armboot.sourceforge.net/) which is no longer an active project and has been rolled into the Das U-Boot project (http://u-boot.sourceforge.net). This is not one of the packages listed in Omnifi’s GPL disclosure, even though armboot is GPL code. It is unknown at the time of this writing, which version of armboot is used in the DMS1 (and most likely the DMP1 too). Having the source code is quite a nice bonus, as it saves countless hours of assembly analysis (speaking of which, did I mention that I spent countless hours of assembly analysis before discovering that the boot code was ‘armboot’?)

(the armboot image contains this string:

       ARMboot 1.0.1 (Sep 24 2003 - 08:50:07)

which would seem to indicate the armboot version they used.)

Someone might want to fill in this section further, as I haven’t totally analyzed all that armboot does.

armboot performs a setup of the EP7312 hardware and copies itself (around 99KB) from ROM to external SDRAM at location 0xC0F00000 (1MB from the end of SDRAM). It also creates a 128KB stack and initializes the ‘C’ environment. Then, armboot looks for a valid Linux image and boot options. It determines a valid image by relying on a CRC32 calculation (same CRC as pkzip) on sections of ROM. The default boot arguments provided are:

bootargs=root=/dev/mtdblock4 devfs=mount 3
bootcmd=boots 0
bootdelay=0
baudrate=9600
ethaddr=08:00:3e:21:c7:f7

I am unsure if the Ethernet address argument is the same for all DMS1 devices or not (or if it’s actually used). Please update this section if you confirm or deny.

When connected to the EP7312 serial port, upon boot the following is displayed

*BOOTING RAZOR*
Starting Normal Boot

It appears the “RAZOR” is the code name for the DMS1, while the DMP1 is code named “R2”. The line “Starting Normal Boot” may also indicate that there are other ways of getting the DMS1 to boot. After these lines are displayed, there appears to be no other terminal activity (input or output).

Kernel Images

There are two Linux kernel images in ROM. One is a “rescue” kernel residing at 0x00020000 and the other is the “production” kernel, which is located at 0x00160000. Both kernels are compressed kernel images. It looks like gzip compression, as there appears to be a gzip bootstrap before the actual kernel code, and immediately following the bootstrap is the gzip signature of 1F 8B 08.

Currently, no decompression or analysis has been done of these kernel images.

ROM Filesystem

A “cramfs” compressed ROM filesystem is located at address 0x00260000. The signature 0x28CD3D45 is located right at 0x00260000 and the string that follows, “Compressed ROMFS” is quite apparent in the ROM dump.

By extracting the cramfs image from the ROM dump and using an existing Linux OS, the cramfs filesystem can be viewed. To get and mount the cramfs, perform the following:

  1. To extract the cramfs image from the 4MB ROM file “ROMdump.bin” to the file “cramfs.img” perform the following:
    • dd if=ROMdump.bin of=cramfs.img bs=1024 skip=2490368
  2. Create a loopback device that points to the cramfs image (substitue /dev/loop1 for another loopback device if loop1 is in use)
    • losetup /dev/loop1 cramfs.img
  3. Mount the cramfs filesystem
    • mount –t cramfs /dev/loop1 /mnt

Once the filesystem has been mounted, you can copy or archive the entire directory structure from the cramfs mount for easier analysis.

Another method is to use the cramfs tools (http://sourceforge.net/projects/cramfs). The ‘cramfsck’ tool can extract the filesystem. It also includes a ‘mkcramfs’ tool to create filesystems. It appears that the last few versions of the DMS1 firmware has included different versions of the cramfs filesystem. Linux, I think, supports both cramfs versions #1 and #2. However, mkcramfs hasn't really been tested yet with the DMP1 or DMS1, so use at your own risk!!

The filesystem is, as expected, a somewhat typical Linux filesystem having the following entries:

.etc
.persistent
app
bin
dev
etc
home
hotplug
lib
proc
root
sbin
storage
sync
tftpboot
tmp
usr
var

The player applications lie in ‘app’ ('app/bin' for DMS1 and 'app/mrd' for DMP1) while the rest of the applications are located in `bin' and ‘sbin’. It should also be noted that may of the applications are actually shell scripts, which may reveal why the DMP1/DMS1 is slow to respond to user input.

The UPnP code of media renderer application is based on the freely-available Intel UPnP SDK.

It appears that many of the scripts key off of the system type being either “RAZOR” or “R2”. Separate LCD display routines are used as well as some filesystem accesses. For this reason and the fact that the DMS1 boot message (via the serial port) is “*BOOTING RAZOR*”, it would make sense that RAZOR=DMS1 and R2=DMP1.

User Setup Information

The final section of ROM contains the non-volatile setup information such as network settings, wireless setup, WEP keys, etc.

Omnifi Firmware Objects and Encryption

And now the moment you’ve been waiting for...

One of the things that has been thwarting efforts to fix/update/improve the Omnifi code on the DMP1/DMS1, is the fact that the “.sfu” firmware files are encrypted. Usually, breaking an encryption is just a matter of finding the encryption key. However, in this case, without knowing the encryption method used, attempting to break the encryption is just about impossible.

With all that has been learned about the DMS1/DMP1 through examination of the ROM, the encryption method has been found as well as the appropriate encryption key!

Encryption / Decryption

The Omnifi DMS1/DMP1 firmware objects are an encrypted, gzip’ed, tarball. Encryption is achieved using the “blowfish” algorithm in the LibTomCrypt library version 0.77 (http://www.libtomcrypt.org/). The encryption key is shockingly (well, maybe not) a birthday and name: “16031975 Baku”. LibTomCrypt provides a demo file (encrypt.c) that appears to be modified for use on the DMP1/DMS1 do decrypt the “blowfish” encrypted firmware update before writing the contents to flash. At first it would appear that Omnifi has again violated the GPL by not stating that LibTomCrypt was used in the DMP1/DMS1. This is untrue however, as LibTomCrypt states that it is covered by TDCAL and not by GPL (TDCAL = “Tom Doesn’t Care About Licenses”). The encryption method is not quite standard however. It was found that the initialization vector (IV) is not placed at the beginning of the file (as was done in the original LibTomCrypt demo/encrypt.c). It is actually inserted at a 5.5KB offset within the file (512*11 = 5632 bytes), so when decrypting the initial data before the IV must be buffered until the IV has actually been read. Then the pre-IV data can be decrypted and then the rest of the file following the IV can be decrypted. The “omnicrypt” program has been created to encrypt/decrypt the gzip’ed DMS1/DMP1 tarballs. See the Tools for more details.

Firmware Objects

Once the DMS1/DMP1 firmware objects have been decrypted, it is possible to view their contents. Contained in the latest release (DMS1_Build_2-1-012) are the following files:

-rw-r--r-- yuri/yuri13107202004-10-11 23:01:13rescueImage
-rw-r--r-- yuri/yuri10485762004-10-11 23:01:13kernelImage
-rw-r--r-- yuri/yuri15728642004-10-11 23:01:16fsImage
-rw-rw-r-- yuri/yuri02004-10-11 23:01:16RAZOR

While in the latest DMP1 release (DMP1_Build_2-0-315) contains the following files:

-r--r--r--root/root13107202004-10-26 18:16:35rescueImage
-r--r--r--root/root10485762004-10-26 18:16:35kernelImage
-rw-r--r--root/root15728642004-10-26 18:16:36fsImage
-rw-r--r--root/root02004-10-26 18:16:36R2

This again confirms that DMS1 = “RAZOR” while the DMP1 = “R2”. One of the upgrade routine (/sbin/upgradeDaemon) keys off these zero length files to make sure that the proper firmware upgrade for the device has been received. Another thing to notice about the upgrade routine (/sbin/performupgrade) is that it will upgrade whichever files are present in the upgrade object. So there is no need to provide all objects, just the ones that you want to change. There is one caveat however, the performupgrade script does check for the presence of the rescue kernel image in ROM before upgrading the production kernel image. So if for some reason your ROM does not have the rescue kernel image present, you will need to provide it in the firmware object tarball (as rescueImage).

Now, again, looking at the performupgrade script, it also will upgrade the boot image if present in the firmware object tarball. It looks for “armbootImage”. As you can see for the latest DMS1/DMP1 releases, there is no armbootImage (I guess there was no need for them to change it, as it is more risky). However, if you look at the older DMP1 release, DMP1_301, you will notice that extra file:

-r--r--r--root/root13107202004-01-06 18:18:30rescueImage
-r--r--r--root/root10485762004-01-06 18:18:30kernelImage
-rw-r--r--root/root15728642004-01-06 18:18:30fsImage
-r--r--r--root/root1310722004-01-06 18:18:30armbootImage
-rw-r--r--root/root02004-01-06 18:18:30R2

It would appear that the rescueImage and kernelImage files are gzip’ed Linux kernels, so in order to learn more, they will have to be uncompressed and then disassembled to try figure out what’s going on. As for the fsImage, it is a cramfs, Compressed ROM, filesystem. To extract it, you will need to setup a loopback device on your Linux system and mount it as a cramfs system (as seen in ROM Filesystem, except the extraction of the filesystem from the ROM dump is not required (i.e. the ‘dd’ command)), or you can use the cramfs tools to extract the filesystem as well.

It is nice that the filesystem is made up of many shell scripts; this makes it much easier to figure out what’s going on in the DMP1/DMS1 as there is no disassembly and difficult analysis required. However, if everything is handled that way on the DMP1/DMS1, that is maybe why the response time to some events can be somewhat slow (interpreted shell script can’t compete with a compiled binary in terms of speed!).

Firmware Object Error Protection

The firmware objects themselves have been protected, to some extent, against transmission errors (although you'd think the encryption / tar / gzip might be sufficient). Each object (armbootImage, rescueImage, kernelImage, fsImage) is embedded with CRCs near the end of each image. This protection data starts at 256 bytes from the end of each image and is of the format:

OffsetSize (bits)Description
032Image size (actual data) in bytes
432Number of 128K sectors of data in image
832CRC32 for sector 0
1232CRC32 for sector 1
.........
8+4N32CRC32 for sector N
.........
8+4M32CRC32 for last sector (sector M)
(last sector CRC32 is only across actual data)

The tools 'chkimage' and 'mkimage' have been created to verify the integrity of the objects and to create new objects with the embedded CRC32 data.

Tools

There have been created a number of tools to extract, analyze, and create new DMS1/DMP1 firmware images. The DOS/Windows binaries are located here

OmniHackUtils

along with information on how to use them. The most up-to-date version and source is available on the Yahoo Omnifi Groups website.

Now the real fun can begin, analyzing the kernel images, and the programs present in the filesystem. Then maybe things can be fixed and/or improved on the DMP1/DMS1.

Personal tools