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/