DMS1 Hacking
From Omnifi Wiki
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:
| Component | Chip | # | Manufacturer | Description / Notes |
| CPU | EP7312 | 1 | Cirrus Logic | ARM-7 based processor (90MHz) |
| Flash ROM | E28F320 J3A110 | 1 | Intel | 32-Mbit StrataFlash® Memory |
| SDRAM | IS42S16400A-10T | 2 | ISSI | 64-Mbit SDRAM |
| SDRAM | IS41LV16100-50T | 1 | ISSI | 16-Mbit SDRAM (Video Memory?) (not available on DMP1) |
| LCD-TV | S1D13506 | 1 | Epson | Color LCD/CRT/TV Controller (not available on DMP1) |
| USB | TDUHC124B | 1 | TransDimension | USB Host Controller |
| Glue | PIC16LF872 | 1 | Microchip | Board controller |
| DAC | CS4340 | 1 | Cirrus Logic | Stereo ÎΣ-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.
| Component | Supply | DMS1 Source | Notes |
| CPU | 2.5V | U2 (?) | Core Voltage |
| 3.3V | U1 | I/O Voltage | |
| Flash ROM | 3.3V | U1 | |
| SDRAM | 3.3V | U1 | |
| LCD-TV | 3.3V | U1 | |
| USB | 3.3V | U1 | |
| PIC | 3.3V | U1 | |
| DAC | 4.0V | U23 | U23 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.
| JTAG | Pin Name | Pin | Destination |
| TCLK | Clock | 90 | R36 (4.7k pull-down) |
| TDI | Data Input | 11 | ??? |
| TDO | Data Output | 22 | RP11 (multiple 10k pull-up resistor pack) |
| nTRST | Asynchronous Reset Input | 125 | ??? |
| TMS | Mode Select | 58 | R35 (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
| Pin | Connection | Notes |
| 1 (top) | N/C | No connection |
| 2 (top) | N/C | No 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) | Ground | VssIO on EP7312 |
| 5 (bottom) | Ground | VssIO 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
| Pin | Connection | Notes |
| 1 | Pin 24 on PIC (RB3/PGM) | Low Voltage Programming Enable |
| 2 | Pin 27 on PIC (RB6/PGC) | Programming Clock |
| 3 | Pin 28 on PIC (RB7/PGD) | Programming Data |
| 4 | Ground | Ground â Vss Pins 8, 19 on PIC |
| 5 | 3.3V | Power â Vdd Pin 20 on PIC |
| 6 | MCLR-/Vpp | Master 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
| Pad | Connection | Notes |
| Next to âSW2â Label | R30 (270 Ohms) | R30 is connected to Pin 1 on the PIC (MCLR-/Vpp). |
| Far from âSW2â Label | Ground |
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 Pin | Name | Connected To | Description |
| 3 | T2IN | Ground | Tied to ground â not used |
| 4 | T1IN | DMS1 J3 Pin 4 (top)âTXD[1] | TTL/CMOS Transmitter Input |
| 5 | FORCEON | 3.3V | Used to keep transceiver active (can be tied to ground instead to use the auto-shutdown feature and save power) |
| 6 | R1OUT | DMS1 J3 Pin 3 (top)âRXD[1] | TTL/CMOS Receiver Output |
| 7 | T1OUT | COM Port Pin 2 (Rx) | RS232 Transmitter Output |
| 8 | R1IN | COM Port Pin 3 (Tx) | RS232 Receiver Input |
| 9 | Vcc | 3.3V | Power |
| 10 | FORCEOFF- | 3.3V | Enables the transceiver |
| 18 | GND | DMS1 | Ground |
| COM Port Pin 5 (GND) | Ground | ||
| 20 | R2IN | Ground | Tied 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 Address | End Address | Chip Select | Bus Width | Description | Device End Address |
| 0x00000000 | 0x0FFFFFFF | CS[0] | 16 | Flash ROM | 0x003FFFFF |
| 0x10000000 | 0x1FFFFFFF | CS[1] | 8 | USB Controller | ??? |
| 0x20000000 | 0x2FFFFFFF | CS[2] | 8 | ??? | ??? |
| 0x30000000 | 0x3FFFFFFF | CS[3] | 16 | CRT Controller | 0x301FFFFF |
| Video Memory | 0x3029FFFF | ||||
| 0x40000000 | 0x4FFFFFFF | CS[4] | 8 | ??? | ??? |
| 0x50000000 | 0x5FFFFFFF | CS[5] | 8 | ??? | ??? |
| 0x60000000 | 0x6FFFFFFF | CS[6] | 32 | Internal SRAM (48400 bytes) | 0x6000BD0F |
| 0x70000000 | 0x7FFFFFFF | CS[7] | 32 | Internal Boot ROM (128 bytes) | 0x7000007F |
| 0x80000000 | 0x80003FFF | N/A | 32 | Internal Registers | N/A |
| ... | ... | ... | ... | ... | ... |
| 0xC0000000 | 0xCFFFFFFF | N/A | 32 | SDRAM | 0xC0FFFFFF |
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 Address | End Address | Linux Device | Description |
| 0x00000000 | 0x0001FFFF | /dev/mtd/1 | ARM Boot Block (128KB) |
| 0x00020000 | 0x0003FFFF | /dev/mtd/2 | Rescue Linux Kernel (1.25MB) |
| 0x00040000 | 0x0005FFFF | ||
| 0x00060000 | 0x0007FFFF | ||
| 0x00080000 | 0x0009FFFF | ||
| 0x000A0000 | 0x000BFFFF | ||
| 0x000C0000 | 0x000DFFFF | ||
| 0x000E0000 | 0x000FFFFF | ||
| 0x00100000 | 0x0011FFFF | ||
| 0x00120000 | 0x0013FFFF | ||
| 0x00140000 | 0x0015FFFF | ||
| 0x00160000 | 0x0017FFFF | /dev/mtd/3 | Production Linux Kernel (1MB) |
| 0x00180000 | 0x0019FFFF | ||
| 0x001A0000 | 0x001BFFFF | ||
| 0x001C0000 | 0x001DFFFF | ||
| 0x001E0000 | 0x001FFFFF | ||
| 0x00200000 | 0x0021FFFF | ||
| 0x00220000 | 0x0023FFFF | ||
| 0x00240000 | 0x0025FFFF | ||
| 0x00260000 | 0x0027FFFF | /dev/mtd/4 | cramfs Filesystem (1.5MB) |
| 0x00280000 | 0x0029FFFF | ||
| 0x002A0000 | 0x002BFFFF | ||
| 0x002C0000 | 0x002DFFFF | ||
| 0x002E0000 | 0x002FFFFF | ||
| 0x00300000 | 0x0031FFFF | ||
| 0x00320000 | 0x0033FFFF | ||
| 0x00340000 | 0x0035FFFF | ||
| 0x00360000 | 0x0037FFFF | ||
| 0x00380000 | 0x0039FFFF | ||
| 0x003A0000 | 0x003BFFFF | ||
| 0x003C0000 | 0x003DFFFF | ||
| 0x003E0000 | 0x003FFFFF | /dev/mtd/5 | User 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:
- 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
- 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
- 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/yuri | 1310720 | 2004-10-11 23:01:13 | rescueImage |
| -rw-r--r-- | yuri/yuri | 1048576 | 2004-10-11 23:01:13 | kernelImage |
| -rw-r--r-- | yuri/yuri | 1572864 | 2004-10-11 23:01:16 | fsImage |
| -rw-rw-r-- | yuri/yuri | 0 | 2004-10-11 23:01:16 | RAZOR |
While in the latest DMP1 release (DMP1_Build_2-0-315) contains the following files:
| -r--r--r-- | root/root | 1310720 | 2004-10-26 18:16:35 | rescueImage |
| -r--r--r-- | root/root | 1048576 | 2004-10-26 18:16:35 | kernelImage |
| -rw-r--r-- | root/root | 1572864 | 2004-10-26 18:16:36 | fsImage |
| -rw-r--r-- | root/root | 0 | 2004-10-26 18:16:36 | R2 |
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/root | 1310720 | 2004-01-06 18:18:30 | rescueImage |
| -r--r--r-- | root/root | 1048576 | 2004-01-06 18:18:30 | kernelImage |
| -rw-r--r-- | root/root | 1572864 | 2004-01-06 18:18:30 | fsImage |
| -r--r--r-- | root/root | 131072 | 2004-01-06 18:18:30 | armbootImage |
| -rw-r--r-- | root/root | 0 | 2004-01-06 18:18:30 | R2 |
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:
| Offset | Size (bits) | Description |
| 0 | 32 | Image size (actual data) in bytes |
| 4 | 32 | Number of 128K sectors of data in image |
| 8 | 32 | CRC32 for sector 0 |
| 12 | 32 | CRC32 for sector 1 |
| ... | ... | ... |
| 8+4N | 32 | CRC32 for sector N |
| ... | ... | ... |
| 8+4M | 32 | CRC32 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
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.