Monday, August 9, 2010

Hacking Coradir STB CDR1000D HDTV Receiver

It's been a long time since I last wrote something 'interesting' so I'll try to start doing so more often or at least to use this blog as an ideas repository instead of my never ending TODO list :)

A couple of months ago I had the opportunity to try the Set Top Box CDR1000D from Coradir (may be this procedure works for the CDR1000, too) which is an HTDV receiver being sold in Argentina and also given for free (on certain cases) by the government to impulse the
Digital Terrestrial Television initiative. The CDR1000 uses an ARM-based processor called CSM1201 produced by Celestial Semiconductor.

There are a couple of things I usually do when I get an embedded device of any kind and I'm allowed to play with it, meaning remove it's case (as opposed to what happened when I tried to open my wife's Garmin Nuvi GPS but that's another story) :
  1. Try to identify any JTAG or Serial communication port on the board.
  2. Download any available firmware at the manufacturer/vendor page and try to reverse engineer it.
  3. Identify any EPROM memory and download it's data-sheet to dump it's content.
Step 1 is the easiest one but given that at the moment there was no firmware update available on the vendor web page then I started to look at the board and proceed with step 2 to look for any pins fooling around waiting to be used.
As you can see in the picture there are a couple of candidates so I decided to start trying with the one with four pins which looks like a serial port to me... so I took my multimeter and started to try to figure out the pinout doing the following:


  1. Unplug the device or turn off the main circuit breaker before attempting anything.
  2. Set your multimeter for continuity test to identify the GND (Ground) by looking for connectivity between anyone of those pins and the outer (metallic) part of any of the connectors outside the box. Don't worry, this won't harm the device.
  3. Turn on the device.
  4. Set your multimeter to measure VCC, then connect the (usually) black cable from the multimeter to the pin previously identified as GND. Then connect the (usually) red cable from your multimeter to each of the other pins available and when you find one measuring 3.3V then you've got VCC.
  5. The two remaining are either Tx (Transmission) or Rx (Reception) and they can be easily figured out later but you can deduce that Rx won't have any activity because it's the cable where you connect the Tx end of your RS232 adapter as explained later (or the Bus Pirate through my pythom module pyBusPirate2) to transmit the data from your computer to the STB. Opposed to this, the Tx pin should have some activity in case that the device sends any information (usually during boot sequence).
Next I used my home-brew RS232 Adapter (it's just a simple TTL level converter) which is similar to the ones in this page http://www.scienceprog.com/alternatives-of-max232-in-low-budget-projects/ (or you can just Google on how to create your adapter to connect your PC to a IC).
Because my adapter needs 5v I took them from the USB connector in the read of the CDR1000D (shame on me!) and connected the GND cable from the adapter to the GND pin discovered on the board and then took the Rx cable of my adapter to one of the two still mysterious pins (remember that we've already identified GND and VCC so those two remaining pins are Tx and Rx but we still don't know which one is what).

On the computer side I opened a terminal and started cu at a baud-rate of 4800 (I didn't know the correct baud-rate yet but even if it's right or wrong you should see something in the terminal is the pin where we connected the cable is the correct one (device Tx instead of RX). Of course the first try was not correct (lucky me) so I tried the other pin and some garbage started to appear on the screen so at that moment I knew the cable was correctly connected as shown bellow and garbage was due to the incorrect baud-rate of the terminal.


I began trying all the different baud-rates until I found the correct one, 115200, which was obviously the last try. Finally I used the following parameters:

me@host $ cu -l /dev/ttyUSB0 -s 115200

... and I started to receive some output from the device so I restarted it and got the following
:

U-Boot 1.2.0 (May 13 2010 - 14:10:45)

DRAM: 256 MB
## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
Flash: 0 kB
NAND:
Bad block table found at page 131040, version 0x01

Bad block table found at page 131008, version 0x01
64 MB
SPI Booting... Speed at [R:10MHz/W:5MHz] Flash Size: 1MB
Init CSM1201 I2C!
In: serial
Out: serial
Err: serial
MAC: 00:1a:cc:08:f8:cd
Hit any key to stop autoboot: 0
Init CSM1201 I2C!

EEPROM @0x50 read: addr 00001000 off 0200 count 1 ... done
Init CSM1201 I2C!

EEPROM @0x50 read: addr 00100000 off 0004 count 1 ... done
## Booting image at 34060000 ...
Bad Magic Number
USB: ERROR : No interrupt for (0xa)
Error, couldn't init Lowlevel part

NAND read: device 0 offset 0x0, size 0x200000

Reading data from 0x1ffe00 -- 100% complete.
2097152 bytes read: OK
## Booting image at 03000000 ...
Image Name: Linux-2.6.12.5
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1586828 Bytes = 1.5 MB
Load Address: 00008000
Entry Point: 00008000
OK

Starting kernel ...

Uncompressing Linux.................................................................................................... done, booting the kernel.
Linux version 2.6.12.5 (root@localhost.localdomain) (gcc version 3.4.6) #1 Thu Apr 22 05:37:00 UTC 2010
CPU: ARM926EJ-Sid(wb) [41069265] revision 5 (ARMv5TEJ)
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
CPU0: D cache: 16384 bytes, associativity 4, 32 byte lines, 128 sets
Machine: ORION
Memory policy: ECC disabled, Data cache writeback
Built 1 zonelists
Kernel command line: root=/dev/mtdblock/1 rw rootfstype=jffs2 console=ttyS0,115200 mem=64M mtdparts=ORION:2m(Part01),-(Part02) ethaddr=00:1A:CC:08:F8:CD
ORION Readed MAC:00:1a:cc:08:f8:cd
PID hash table entries: 512 (order: 9, 8192 bytes)
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB = 64MB total
Memory: 61568KB available (2467K code, 645K data, 96K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
NET: Registered protocol family 16
SCSI subsystem initialized
Linux Kernel Card Services
options: none
usbcore: registered new driver usbfs
usbcore: registered new driver hub
NetWinder Floating Point Emulator V0.97 (extended precision)
devfs: 2004-01-31 Richard Gooch (rgooch@atnf.csiro.au)
devfs: boot_options: 0x0
NTFS driver 2.1.22 [Flags: R/O].
JFFS2 version 2.2. (NAND) (C) 2001-2003 Red Hat, Inc.
fb0: ORION frame buffer @[0xf400000, 0xc4880000] size 0xc00000
fb1: ORION frame buffer @[0xe800000, 0xc5500000] size 0xc00000
ORION GPIO at 0x101e4000, 16 lines
ORION GPIO2 at 0x10260000, 55 lines
Smart card: base address 101f0000 map to c4866000
Orion Watchdog Timer: timer margin 40 sec
Xport: Init OK [0x0e100000].
orion_video: Orion Video driver was initialized, at address@[phyical addr = 41600000, size = 100000]
csdrv audio init ok ...
Default ORION I2C at 0x10170000, 100KHZ
orion15_df: Orion Display feeder driver was initialized, at address@[phyical addr = 41800000, size = 1000]
orion15_df: Orion TVE0 driver was initialized, at address@[phyical addr = 10168000, size = 1000]
orion15_df: Orion TVE1 driver was initialized, at address@[phyical addr = 10160000, size = 1000]
pinmux0 : 0x0, pinmux1: 0x1001
dma_pool_alloc: dma_phy_addr: 3d2a000, ttx_buf: ffc00000
Serial: 8250/16550 driver $Revision: 1.90 $ 2 ports, IRQ sharing disabled
ttyS0 at MMIO 0x101f1000 (irq = 12) is a 16550A
ttyS1 at MMIO 0x101f2000 (irq = 13) is a 16550A
io scheduler noop registered
io scheduler anticipatory registered
RAMDISK driver initialized: 1 RAM disks of 16384K size 1024 blocksize
loop: loaded (max 8 devices)
ORION eth0: 0x41400000 IRQ 24 MAC:00:1a:cc:08:f8:cd
Not SST flash.<5>physmap flash device: 800000 at 34000000
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bit)
Using command line partition definition
Creating 2 MTD partitions on "ORION":
0x00000000-0x00200000 : "Part01"
0x00200000-0x04000000 : "Part02"
PCMCIA: orion_pcmcia_init called!
Succesefully create pcmcia proc entry!
orion socket ci module initializing!!!
Initializing USB Mass Storage driver...
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
usbcore: registered new driver usbhid
drivers/usb/input/hid-core.c: v2.01:USB HID core driver
drivers/usb/musb/musb_driver.c: Initializing MUSB Driver [npci=1][gadget=no][otg=no]
MUSB Drive version 1.1.0.1
mgc_controller_init: Driver instance data at 0xc3d3ce00
mgc_hdrc_init: MHDRC version 1.500 info: UTMI-8, dyn FIFOs, SoftConn
mgc_controller_init: End 00: FIFO TxSize=0040/RxSize=0040
mgc_controller_init: End 01: Shared FIFO TxSize=0200/RxSize=0200
mgc_controller_init: End 02: FIFO TxSize=0000/RxSize=0040
mgc_controller_init: End 03: Shared FIFO TxSize=0400/RxSize=0400
mgc_controller_init: New bus @0xc3d1a820
musb-hcd usb0: new USB bus registered, assigned bus number 1
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
NET: Registered protocol family 2
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP established hash table entries: 4096 (order: 3, 32768 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
NET: Registered protocol family 1
NET: Registered protocol family 17
NET: Registered protocol family 15
Empty flash at 0x017bdca0 ends at 0x017bde00
Empty flash at 0x026427d8 ends at 0x02642800
jffs2_scan_dirent_node(): Node CRC failed on node at 0x02dd53e8: Read 0xffffffff, calculated 0xacd3f548
VFS: Mounted root (jffs2 filesystem).
Freeing init memory: 96K
Warning: unable to open an initial console.
jffs2_get_inode_nodes(): Data CRC failed on node at 0x02641db0: Read 0x3444ce97, calculated 0xf1cad815
jffs2_get_inode_nodes(): Data CRC failed on node at 0x017bd4a4: Read 0xd94d27c4, calculated 0xdebb94f3
-/bin/sh: ./test_fwdebug: not found
[1] + Done(127) ./test_fwdebug 1 1
============= SBDevFonts ============
0: rbf-fixed-rrncnn-12-24-ISO8859-1, charsetname: ISO8859-1, style: 0
========== End of SBDevFonts =========

============= MBDevFonts ============
1: rbf-fixed-rrncnn-24-24-GB2312-0, charsetname: GB2312-0, style: 0
2: rbf-fixed-rrncnn-*-*-UTF-8, charsetname: UTF-8, style: 0
3: rbf-fixed-rrncnn-*-*-UTF-16LE, charsetname: UTF-16LE, style: 0
4: rbf-fixed-rrncnn-*-*-UTF-16BE, charsetname: UTF-16BE, style: 0
========== End of MBDevFonts =========
system font 0: rbf-fixed-24-ISO8859-1
system font 1: *-fixed-24-GB2312-0
warnning: You have no fip frontpanel!
IAL: Use orionfpc engine.
MiniGUIMain 27630
default key_value = 0x1c
....
default key_value = 0x2 Set Led Charecters Success
Timing mode =21
loading xport firmware
write gpio 15 to 1
readed xport fw data section size =240
readed xport fw text section size =10872
loded xport firmware
CS_CRC_Init error = 1, time[28040]
CS_DB_Init error = 1, time[28110]
CS_AV_Init error = 1, time[29080]

GPIO0 Write 1 Succeed!!!
definition_index = 1
bufsize = 9437184
read_len = 2652 ,===no data
read_len = 2652 ,===no data
read_len = 2652 ,===no data
read_len = 2652 ,===no data
AspectRatio = 15
CS_AV_Play_IFrame 29980
DB_DemuxInit error = 0, time[29980]
PDmx_SFilter->pid = 0x0
PDmx_SFilter->pid = 0x2
PDmx_SFilter->pid = 0x11
PDmx_SFilter->pid = 0x10
CS_SI_Init error = 1, time[29980]
CS_DT_Init error = 1, time[29980]

GPIO6 Write 0 Succeed!!!

GPIO6 Write 1 Succeed!!!
CS_FE_Init error = 1, time[31520]
CS_INSTALL_Init error = 1, time[31520]
PDmx_SFilter->pid = 0x12
PDmx_SFilter->pid = 0x12
CS_EIT_Init error = 1, time[31530]
-----------------------------
CS_TIMER_Init error = 1, time[31720]
PDmx_SFilter->pid = 0x14
PDmx_SFilter->pid = 0x14
CS_DT_Start

GPIO0 Write 1 Succeed!!!
definition_index = 1
[USB_CON]:UsbCon_Umount().
[USB_CON]:UsbCon_Init().
[USB_CON]:Creating usbcon thread.
$125336 Set Led Charecters Success MSG_CHECK_SERVICE_LOCK = 0 *****************************CS_MW_PlayServiceByIdx************************* CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout! CSDEMUX_Filter_ReadWait Timeout!

CSDEMUX_Filter_ReadWait Timeout!

Killed

# ls -la
drwxr-xr-x 3 528 528 0 Dec 4 2009 .
drwxr-xr-x 18 root root 0 Jan 1 00:00 ..
-rwx------ 1 root root 601945 May 14 2010 csapp.elf
-rwx------ 1 root root 127352 Jan 1 00:09 database
drwxr-xr-x 2 root root 0 May 14 2010 resource
-rwx------ 1 root root 45817 Dec 4 2009 test_fwdebug.bak
# uname -a
Linux uclibc 2.6.12.5 #1 Thu Apr 22 05:37:00 UTC 2010 armv5tejl unknown
# whoami
root



At this point I connected an Ethernet cable from my computer to the device and issued:


# ifconfig eth0 192.168.100.100 netmask 255.255.255.0 up
# ping 192.168.100.101

PING 192.168.100.101 (192.168.100.101): 56 data bytes

64 bytes from 192.168.100.101: seq=0 ttl=64 time=10.000 ms

64 bytes from 192.168.100.101: seq=1 ttl=64 time=0.000 ms
64 bytes from 192.168.100.101: seq=2 ttl=64 time=0.000 ms
64 bytes from 192.168.100.101: seq=3 ttl=64 time=0.000 ms
64 bytes from 192.168.100.101: seq=4 ttl=64 time=0.000 ms


--- 192.168.100.101 ping statistics ---

5 packets transmitted, 5 packets received, 0% packet loss

round-trip min/avg/max = 0.000/2.000/10.000 ms

#



GAME OVER!!!