Archives

EEPROM programmer based on the Winchiphead CH341a

In an earlier blog entry, a low-cost USB-based EEPROM programmer was examined.  It is being used to burn boot ROMs for the 2Wire modems. [1]

USB-based EEPROM programmer for just US$8

The programmer works well but its software is closed-source, only for Microsoft™ Windows®, and Chinese language to boot.

Of all those issues, it is, of course, the requirement for Microsoft® that is the greatest hindrance!  :-(

Well not any more.  A Linux tool for reading and writing EEPROMs using the i2c mode of the CH341a has been developed.  The tool is based on the popular and portable libUSB programming library.

The CH341a is not well documented. There is a solitary C header file relating to a (closed source) Windows™ DLL (with comments in Chinese), but there is no proper datasheet for the CH341a.

To understand the CH341a means sniffing the USB bus traffic to and from the device. This reveals that the CH341a is using asynchronous transfers in its USB transaction protocol. Something of an overkill for such a simple application.

That asynchronous requirement makes the programming more complicated, since periodic polling and callback functions are needed. It also means that the newer libUSB-1.0 API is required. The earlier and simpler libUSB-0.1 only supports synchronous transactions.

As it stands, the tool meets our current needs:  programming and reading the 24c32/24c64 boot ROMs used by the 2Wire modem-routers.  However it could be extended to support a wider range of EEPROMs with different addressing modes and page sizes. Please email if you would like to develop this tool.

The GPL’ed source code can be downloaded from SourceForge. [2]

asbokid@u50si1:~/ch341eepromtool_0.5$ cat README

About
=====

    Beta libUSB code for EEPROM programmers based on the WinChipHead CH341a IC

Author
======

    Written by asbokid and released under the terms of the GNU GPL, version 3, or later.
    Copyright Dec 2011, asbokid <ballymunboy@gmail.com>

Licence
=======

    This is free software: you can redistribute it and/or modify it under the terms of
    the latest GNU General Public License as published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
    without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
    See the GNU General Public License for more details.

    You should have received a copy of the GNU General Public License along with this program.
    If not, see <http://www.gnu.org/licenses/>.

Requires
========

    gcc
    GNU make
    libusb-1.0 and the libusb library development files. See http://libusb.wiki.sourceforge.net/
    libusb-1.0-dev  (on debian-based distros)

Compiling
=========

    gcc -o ch341eeprom ch341eeprom.c ch341funcs.c -lusb-1.0

Running
=======

    asbokid@u50si1:$ ./ch341eeprom

    ch341eeprom - an i2c EEPROM programming tool for the WCH CH341a IC
    Version 0.5 copyright (c) 2011  asbokid <ballymunboy@gmail.com>

    This program comes with asbolutely no warranty; This is free software,
    and you are welcome to redistribute it under certain conditions:
    GNU GPL v3 License: http://www.gnu.org/licenses/gpl.html

    Usage:
     -h, --help             display this text
     -v, --verbose          verbose output
     -d, --debug            debug output
     -s, --size             size of EEPROM {24c32|24c64}
     -e, --erase            erase EEPROM (fill with 0xff)
     -w, --write <filename> write EEPROM with image from filename
     -r, --read  <filename> read EEPROM and save image to filename

    Example:  ch341eeprom -v -s 24c64 -w bootrom.bin

    asbokid@u50si1:$ sudo ./ch341eeprom -v -s 24c64 -e

    Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
    Found [1a86:5512] as device [7] on USB bus [2]
    Opened device [1a86:5512]
    Claimed device interface [0]
    Device reported its revision [3.03]
    Configured USB device
    Set i2c bus speed to [100kHz]
    Erased [8192] bytes of [24c64] EEPROM
    Closed USB device

    asbokid@u50si1:$ sudo ./ch341eeprom -v -s 24c64 -r output.bin

    Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
    Found [1a86:5512] as device [7] on USB bus [2]
    Opened device [1a86:5512]
    Claimed device interface [0]
    Device reported its revision [3.03]
    Configured USB device
    Set i2c bus speed to [100kHz]
    Read [8192] bytes from [24c64] EEPROM
    Wrote [8192] bytes to file [output.bin]
    Closed USB device

    asbokid@u50si1:$ xxd -l 128 output.bin

    0000000: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000010: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000020: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000030: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000040: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000050: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000060: ffff ffff ffff ffff ffff ffff ffff ffff  ................
    0000070: ffff ffff ffff ffff ffff ffff ffff ffff  ................

    asbokid@u50si1:$ ./mktestimg > testimg24c64.bin

    asbokid@u50si1:$ xxd -l 128 testimg24c64.bin

    0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    0000010: 1111 1111 1111 1111 1111 1111 1111 1111  ................
    0000020: 2222 2222 2222 2222 2222 2222 2222 2222  """"""""""""""""
    0000030: 3333 3333 3333 3333 3333 3333 3333 3333  3333333333333333
    0000040: 4444 4444 4444 4444 4444 4444 4444 4444  DDDDDDDDDDDDDDDD
    0000050: 5555 5555 5555 5555 5555 5555 5555 5555  UUUUUUUUUUUUUUUU
    0000060: 6666 6666 6666 6666 6666 6666 6666 6666  ffffffffffffffff
    0000070: 7777 7777 7777 7777 7777 7777 7777 7777  wwwwwwwwwwwwwwww

    asbokid@u50si1:$ sudo ./ch341eeprom -v -s 24c64 -w testimg24c64.bin

    Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
    Found [1a86:5512] as device [7] on USB bus [2]
    Opened device [1a86:5512]
    Claimed device interface [0]
    Device reported its revision [3.03]
    Configured USB device
    Set i2c bus speed to [100kHz]
    Read [8192] bytes from file [testimg24c64.bin]
    Wrote [8192] bytes to [24c64] EEPROM
    Closed USB device

    asbokid@u50si1:$ sudo ./ch341eeprom -v -s 24c64 -r output.bin

    Searching USB buses for WCH CH341a i2c EEPROM programmer [1a86:5512]
    Found [1a86:5512] as device [7] on USB bus [2]
    Opened device [1a86:5512]
    Claimed device interface [0]
    Device reported its revision [3.03]
    Configured USB device
    Set i2c bus speed to [100kHz]
    Read [8192] bytes from [24c64] EEPROM
    Wrote [8192] bytes to file [output.bin]
    Closed USB device

    asbokid@u50si1:$ xxd -l 128 output.bin

    0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
    0000010: 1111 1111 1111 1111 1111 1111 1111 1111  ................
    0000020: 2222 2222 2222 2222 2222 2222 2222 2222  """"""""""""""""
    0000030: 3333 3333 3333 3333 3333 3333 3333 3333  3333333333333333
    0000040: 4444 4444 4444 4444 4444 4444 4444 4444  DDDDDDDDDDDDDDDD
    0000050: 5555 5555 5555 5555 5555 5555 5555 5555  UUUUUUUUUUUUUUUU
    0000060: 6666 6666 6666 6666 6666 6666 6666 6666  ffffffffffffffff
    0000070: 7777 7777 7777 7777 7777 7777 7777 7777  wwwwwwwwwwwwwwww

Concluding Notes
================

    The code handles the 3 byte addressing used by EEPROMS of 32kbit and greater (24c32-)
    It uses asynchronous USB transfers but should be portable to Microsoft Windows.

    All comments and contributions welcomed!

    asbokid <ballymunboy@gmail.com> - Dec 2011

[1] http://hackingbtbusinesshub.wordpress.com/2011/11/05/ultra-low-cost-boot-rom-programmer/

[2] http://sourceforge.net/projects/ch341eepromtool/

Low-cost boot ROM programmer

Spotted on ebay:  a USB i2c EEPROM programmer for just $8.

Irresistible!

Eight dollar EEPROM programmer

The plan is to use the programmer to burn new boot ROMs for the 2Wire.

The boot ROM on the 2Wire board is a 32Kbit device from the 24Cxx family of i2c serial CMOS EEPROM.

These devices have three address pins A0, A1 and A2. The pins can be asserted (or not) to configure the physical address of the ROM. Up to eight ROMs can be connected in series on the same i2c bus and addressed individually. [1]

24Cxx pinout - A0, A1 and A2 are address pins

We can use this addressing feature to ‘piggyback’ our clone ROM onto the 2Wire board.

If pin A0 of the board boot ROM is pulled up, its address is changed from a default of 0xA0/A1 to 0xA2/A3.

If we pin strap our ROM to assign it the original address (0xA0/A1) of the board ROM, then the Trimedia CPU will boot from our ROM instead.

Device Addressing of the 24Cxx

The contents of our piggyback ROM can hold new code, such as a JTAG debug monitor. This would leverage access to the flash device on the 2Wire PCB.

Back to that five quid programmer, though..

EEPROM programmer based on CH341A

The programmer is only supplied with software for Microsoft Windows®, and it’s Chinese language software at that. An English translation of the programmer manual is here. [2]

Some naughty soul has also been busy with the sandpaper, trying to erase the identifying marks from the programmer’s controller chip.

All in vain because the Linux tool lsusb reveals all..

The USB device controller on the programmer has a vid:pid of 1a86:5512. That Vendor ID is assigned to Nanjing QinHeng Electronics Co.,Ltd. [3]

And the controller identifies as the company’s WinChipHead CH341A in i2c mode. [4]

$ sudo lsusb -d 1a86:5512
Bus 002 Device 017: ID 1a86:5512 QinHeng Electronics

It seems that the Linux kernel already contains driver code for the CH341A, and has done for some while.[5]

The CH341 is a USB peripheral controller and multi-protocol line driver.  The IC supports the IEEE-1284 parallel printer interface as well as several two, three, four and five wire serial communication protocols, including i2c.

The Linux kernel supports RS232 comms using the CH341A but doesn’t currently include an i2c driver for the IC, which is a shame.

With no driver for the CH341A, this is one of those thankfully rare occasions when Microsoft Windows® has to be used.

HINT: here is a great project for someone – writing the i2c Linux kernel driver code for the CH341A.

  • An incomplete userspace USB driver to program EEPROMs with the CH341A has been developed and it is here.[11]
  • The IC datasheet for the CH341A is here [4].
  • The GPL’ed source code for a project by Relavak Labs draws on the userspace libUSB library to talk with the IC.[6] 
  • Another project is by Roaring Penguin Software Inc. [7]   Both the Relavak and the Roaring Penguin projects concern an i2c-based thermometer known as a TEMPer. The device communicates over a USB bus via a CH341A.   In both projects, the CH341 is used in serial mode to twiddle the RTS, DTR and DTS lines to drive an i2c peripheral.
  • Python code shared by Panda Xiong, however, drives the CH341A in its native i2c mode  [8].
  • A tiny bit of ‘official’ source code for the CH341a and what passes for a programming manual is here [9].
  • And for those who don’t have it, a RAR containing the original Windows software for the programmer is here [10].

But we digress.

Back to our task..

A low-cost source of 24Cxx EEPROMs was found. These ROMs are conveniently soldered to a prototyping board with header pins already attached for programming and pin jumpers for configuring the device address. The ROMs are actually 24C64 (8KByte) whereas the 2Wire board only uses the 24C32 (4KByte). But that hopefully won’t matter. The extra capacity might even be useful.

24C64 EEPROM for prototyping and 'piggybacking'

The EEPROM Programmer software runs fine in Windows XP Pro which was running as a guest OS in VirtualBox.

A boot ROM image was lifted from the PCB of a 2701HGV-C using a BusPirate and this image was successfully burnt into one of the virgin 24C64 devices:

PC -> USB -> CH341A -> I2C -> 24Cxx

Burning a 2Wire boot ROM clone

UPDATE:

A basic Linux tool has been coded to read and write 32kBit and 64kBit EEPROMs with this programmer.  See [11]

[1] https://docs.google.com/open?id=0B6wW18mYskvBNjhiMGM0NDQtYWY5Zi00YzBmLWEzNTktNTc2N2Y0ZjgwNzJh
[2] http://hackingbtbusinesshub.files.wordpress.com/2012/01/usbprogrammer_24cxxseries_version22.pdf
[3] http://wch-ic.com/
[4] http://wch-ic.com/download/list.asp?id=114
[5] http://lwn.net/Articles/246334/
[6] http://relavak.wordpress.com/2009/10/17/temper-temperature-sensor-linux-driver/
[7] http://www.roaringpenguin.com/products/temper-tools
[8] http://code.google.com/p/common-codebase/source/browse/#svn%2Ftrunk%2Fothers%2Fpython_test%2Fi2c
[9] https://docs.google.com/open?id=0B6wW18mYskvBMDQ2MDBjMWMtMzhjNS00MTM1LTk4OGUtODYxZDdjNjg5MTFj
[10] https://docs.google.com/open?id=0B6wW18mYskvBMmIwMGJjOTQtZDMxNS00MzNiLThkYzgtMGE4N2ZiNTEwMGM3
[11] http://hackingbtbusinesshub.wordpress.com/2011/12/08/eeprom-programmer-based-on-the-winchiphead-ch341a/

The 2700HGV and 2701HGV-C bootloaders are extracted

The boot ROMs from both the 2Wire 2700HGV and the 2701HGV-C have been extracted using Ian Lesnet’s BusPirate as an i2c master.

The 2701HGV-C has a convenient set of header pins for connecting the BusPirate probe leads to the i2c bus lines of the boot ROM.

However, the 2700HGV requires an elusive 1.0mm pitch dual row card edge connector which has yet to be sourced. (UPDATE: connector obtained. See [4])

So, for the 2700HGV, the BusPirate was connected to the board with some IC pin hooks. These were attached directly to the legs of the FM24C32a boot ROM, a serial CMOS EEPROM in a SOP-8 package from Fudan Microelectronics:

BusPirate IC probe hooks

probe hook on the leg of a (DIP-8) IC

A simple utility was designed in C to parse the bootscripts. The tool displays the script commands in human-readable form.

There are just four command types used in a Trimedia TM32 bootscript:

  • Write a 32-bit word to a memory address
  • Write a sequence of n words starting at memory address a.
  • Idle for t clock ticks.
  • Terminate bootscript

The scheme for encoding these commands is described in Ch 6: Boot Module of the Data Book for the PNX15xx/952xx CPU Series. [1]

The bootscripts for the 2700HGV and the 2701HGV-C were found to be almost identical.

The 2700 bootscripts are almost identical to the 2701 bootscripts. The 2700 addresses one more MMIO register which the 2701 does not.

To all intents, however, the L0 bootscripts (and the L1 bootloaders) for the 2700HGV and for the 2701HGV-C are essentially the same.

The C tool to parse the boot ROM contents can be found at [2]. A pre-built 32-bit Windows executable is also in the tarball.

The tool produces output like that below.

The MMIO register addresses and values are just as they are found in the bootscripts.

The processor module identities (CLOCK, RESET, DDR, PCI-XIO, JTAG, I2C, etc) are based on educated guesswork.

The register addresses and the MMIO offsets of the Ares’ modules were compared to the documented modules in the PNX15xx, PNX85xx and the PNX95xx CPU families.

This means that while the module names will largely be correct, the functional names given to the Ares’ MMIO registers may in many cases be wrong.

Most of the bootscripts concern clocking, aperture sizes and addresses, DRAM settings and PCI bus configuration. And since these work fine for the board, there is little point in changing them.

Perhaps the most interesting part, at least for the sake of this hack, are the bootscript commands which load and execute the next stage (L1) bootloader code.

The L1 code will probably load the first block from the NAND flash device. This will likely contain the operating system bootloader (the L2 bootloader).

Back to the boot ROM though..

From the output of our boot ROM dump tool, we can see that the TM32 core (still held in reset) is configured to start executing code from DRAM address 0×4000,0000.

write 1bf00048 40000000 // TM3260 - TM32_DRAM_START

A little further on in the bootscript, we find the command that copies the stage 1 bootloader (0×273 words) from the boot ROM into DRAM, starting at address 0×4000,0000.

From the Ares’ system view memory map that we determined earlier, we know that 0×4000,0000 is the lowest address in the DRAM aperture. [3]

writelist 40000000 00000273 // copy L1 code (627 words) to DRAM (0x40000000)

As expected, the last bootscript command takes the TM32 core out of reset. The CPU immediately begins executing the instructions starting from the address pointed to by its Program Counter, (0×4000,0000).

write 1bf00030 800000e3 // TM3260 - TM32_CTL

Below is the full output from the bootscript parsing tool. Source tarball at [2]

$ ./i2cdumpreader
Usage: ./i2cdumpreader   [MMIO_BASE (default 0x1be00000)]

$ ./i2cdumpreader 2700hgv_bootrom.bin

// Loaded 4096 bytes from boot ROM image file: '2700hgv_bootrom.bin'

write 1be4d500 01000003	// GLOBAL2-SCRATCH - SCRATCH0
write 1be47008 00201700	// CLOCK-PLL - PLL2_CTL
write 1be4700c 002c9500	// CLOCK-PLL - PLL3_CTL
write 1be47000 022c8b00	// CLOCK-PLL - PLL0_CTL
write 1be47004 022cc700	// CLOCK-PLL - PLL1_CTL
write 1be47008 00201701	// CLOCK-PLL - PLL2_CTL
write 1be4700c 002c9501	// CLOCK-PLL - PLL3_CTL
write 1be47000 022c8b01	// CLOCK-PLL - PLL0_CTL
write 1be47004 022cc701	// CLOCK-PLL - PLL1_CTL
delay 000015e0		    // idle for 5600 clock cycles
write 1be47008 00201700	// CLOCK-PLL - PLL2_CTL
write 1be4700c 002c9500	// CLOCK-PLL - PLL3_CTL
write 1be47000 022c8b00	// CLOCK-PLL - PLL0_CTL
write 1be47004 022cc700	// CLOCK-PLL - PLL1_CTL
delay 00000118		    // idle for 280 clock cycles
write 1be47008 00201701	// CLOCK-PLL - PLL2_CTL
write 1be4700c 002c9501	// CLOCK-PLL - PLL3_CTL
write 1be47000 022c8b01	// CLOCK-PLL - PLL0_CTL
write 1be47004 022cc701	// CLOCK-PLL - PLL1_CTL
delay 000445c0		    // idle for 280000 clock cycles
write 1be47000 002c8b01	// CLOCK-PLL - PLL0_CTL
write 1be47004 002cc701	// CLOCK-PLL - PLL1_CTL
write 1be47200 00000013	// CLOCK-CTL - CLK_MEM_CTL
write 1be47204 00000013	// CLOCK-CTL - CLK_FPI_CTL
write 1be47208 00000003	// CLOCK-CTL - CLK_???_CTL
write 1be47250 00000009	// CLOCK-CTL - CLK_PCI_CTL
write 1bf80088 ffffa70f	// UNKNOWN - UNKNOWN
write 1be4d408 06061010	// GLOBAL2-MMI - MM_SHORT_REFRESH?
write 1be4d400 0000001c	// GLOBAL2-MMI - MM_SDRAM_SIZE?
delay 00000118		    // idle for 280 clock cycles
write 1be4d400 0000001f	// GLOBAL2-MMI - MM_SDRAM_SIZE?
write 1be4d42c 28d26aa2	// GLOBAL2-MMI - MM_UNKNOWN
write 1be4d404 000005c0	// GLOBAL2-MMI - MM_REFRESH?
write 1be4d428 00000013	// GLOBAL2-MMI - UNKNOWN
write 1be4dc10 000000a1	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 000000a2	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 000000a3	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000014	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000006	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000005	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 0000013b	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000c81	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000014	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000029	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000005	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 0000003b	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000010	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 000000a1	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 000000a2	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 000000a3	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000501	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000014	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000007	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000008	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000000	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000006	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000400	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000005	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 0000053b	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000014	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000069	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000005	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 0000043b	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000c81	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000006	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000780	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000006	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000400	// GLOBAL2-MMIARB - UNKNOWN
write 1be4dc10 00000010	// GLOBAL2-MMIARB - UNKNOWN
delay 000015e0		    // idle for 5600 clock cycles
write 1be4d414 00000001	// GLOBAL2-MMI - MM_SELF_REFRESH
write 1be4d800 0000000f	// GLOBAL2-MMIARB - RAM0
write 1be4d804 00000305	// GLOBAL2-MMIARB - RAM1
write 1be4d808 00000204	// GLOBAL2-MMIARB - RAM2
write 1be4dc04 00000002	// GLOBAL2-MMIARB - MAXADDR
write 1be4dc08 0000008f	// GLOBAL2-MMIARB - DEFAULTAGENT0
write 1be4dc0c 00000082	// GLOBAL2-MMIARB - DEFAULTAGENT1
write 1be4dc00 00000140	// GLOBAL2-MMIARB - MODE
write 1be40010 01c20e83	// PCI-XIO - pci_setup
write 1be40014 fffff245	// PCI-XIO - pci_control
write 1be4006c 00001722	// PCI-XIO - subsystem_ids
write 1be40018 80000000	// PCI-XIO - pci_base1_lo
write 1be4001c c0000000	// PCI-XIO - pci_base1_hi
write 1be40050 40000000	// PCI-XIO - base10 (DRAM)
write 1be40054 1be00000	// PCI-XIO - base14 (MMIO)
write 1be40058 f0000000	// PCI-XIO - base18 (XIO)
write 1be60000 00000008	// RESET - RST_CTL
write 1bf00030 400000e3	// TM3260-CORE - TM32_CTL
delay 00000118		    // idle for 280 clock cycles
write 1be4d018 40000000	// GLOBAL2-CTL - TM_REGION_LO
write 1be4d01c 44000000	// GLOBAL2-CTL - TM_REGION_HI
write 1bf00034 40000000	// TM3260-CORE - TM32_DRAM_LO
write 1bf00038 44000000	// TM3260-CORE - TM32_DRAM_HI
write 1bf0003c 44000000	// TM3260-CORE - TM32_DRAM_CLIMIT
write 1bf00048 40000000	// TM3260-CORE - TM32_DRAM_START
write 1bf00040 00000000	// TM3260-CORE - TM32_DRAM_APERT1_LO
write 1bf00044 00000000	// TM3260-CORE - TM32_DRAM_APERT1_HI
writelist 40000000 00000273
			// copy L1 code (627 words) to DRAM (0x40000000)

0000000: c281c181 c182d1b5 c1810200 02100c00
0000010: 20000000 00202050 22220222 20a07484
0000020: 1c3c1838 10301832 14340505 05050605
0000030: 16151311 13181112 16120002 02030a06
[...]
0000990: c0c2c080 c19a7a0c f0a12020 04140100
00009a0: 00010001 00030203 00010000 00000101
00009b0: 00010100 00000001 01010000 00000000
00009c0: 426f6f74 436f6465 00000000
			            // end of writelist
write 1bf00030 800000e3	// TM3260-CORE - TM32_CTL
terminate		        // terminate bootscript

The next task is to examine the level 1 bootloader. The bootloader will contain a NAND flash driver that needs to be understood to progress this hack.

[1] http://www.nxp.com/documents/data_sheet/PNX15XX_PNX952X_SER_N.pdf
[2] https://docs.google.com/leaf?id=0B6wW18mYskvBMmIwMGJjOTQtZDMxNS00MzNiLThkYzgtMGE4N2ZiNTEwMGM3&hl=en_GB
[3] http://hackingbtbusinesshub.wordpress.com/2011/10/17/a-tentative-memory-map-for-the-2wire-ares/
[4] http://hackingbtbusinesshub.wordpress.com/2011/12/20/rejoice-the-card-edge-connector-has-arrived/

The i2c bus on the 2Wire 270x devices

The 2Wire 2700 and 2701 models both use the i2c bus. i2c is a two wire serial bus protocol designed by Philips Semiconductors (now NXP).  The i2c bus specifications can be found here. [1]

In this application, i2c is used to read and write to a 24Cxx serial EEPROM on the 2Wire PCB.

The EEPROM contains the first two stages (L0 and L1) of the bootloader for the TriMedia, the CPU that powers the 2Wire devices.

The L0 stage of the bootloader is a ‘bootscript’. It performs very basic configuration, such as setting the clock multipliers for the CPU, the DRAM and the PCI bus.

The L0 bootscript then loads the L1 bootloader.

Depending on the device configuration, the L1 bootloader is retrieved via the PCI bus from an external host (e.g. a PC), from the JTAG interface, from NAND or NOR flash, or from an IDE device.

The L1 bootloader code is loaded by the bootscript into RAM, decompressed if necessary and then executed.

Here we focus here on that very first stage of the 2Wire bootstrap process: the L0 bootscript contained in the 24Cxx EEPROM.

The boot EEPROM in the 1800 and 2700 (where fitted) as well as the 2701, 3800 and 3801, is the 24C32. This is an IC in a 8-pin SOP package from the 24Cxx series of i2c serial CMOS EEPROM.

The 24C32 provides 32Kbit of storage, organised as 4096 words of 8 bits each.

To fulfil this role, the 2Wire 2701HGV-C device utilises a Fudan Microelectronics component, FM24C32A. On the PCBs of the 2Wire 2700 and 2701, the EEPROM is identified as component U2:

24c32 boot ROM on the 2Wire 2700 board

24c32 boot ROM on the 2Wire 2701 board

The datasheet for the FM24C32A is available at [2].  It shows a pinout for the SOP-8 package as follows

datasheet for the FM24c32a serial EEPROM

FM24C32A - 32kbit i2c serial EEPROM
 A0   1 o   8   VCC
 A1   2     7   WP
 A2   3     6   SCL
GND   4     5   SDA

A0,A1,A2 are the address lines (all pulled down by default on 2700 & 2701)
WP is a Write Protect line (again pulled down)
SCL is the i2c clock line
SDA is the bi-directional data line

FM24c32a requires Vcc to be between 1.7V ~ 5.5V

The IC can operate at a clock-speed of 1MHz at 2.5V ~ 5.5V and at 400kHz at 1.7V.

On the 2Wire 2701, the IC pins of U2 connect to a set of fourteen (2 x 7) header pins which are labelled as J26.

J26 on 2Wire 2701HGV-C
2 = GND
4 = SCL
5 = SDA
7 = VCC
8 = A0

On the 2Wire 2700, the IC pins of U2 connect to a set of fingers of a card edge connector which is labelled as J1.

J1 on 2Wire 2700HGV
7 = SDA
8 = VCC
9 = SCL
12= A0
14= GND

UPDATE:

The full pinout of the card edge connector found on the 1800, 2071A, 2700, 3600, 3800 and 3801 can be found at [3]

[1] http://www.nxp.com/documents/user_manual/UM10204.pdf
[2] https://docs.google.com/open?id=0B6wW18mYskvBNzk1MTgxOTctMTFhZC00NjhiLTg0NWMtNmUxM2Y1NTMyZDZk
[3] http://hackingbtbusinesshub.wordpress.com/2012/01/16/discovering-2wire-card-edge-pinout-for-jtag-i2c/