<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="sodnpoo.xsl" type="text/xsl"?>
<xml page="/?t=jtag"><a href="http://sodnpoo.com/?x=html">HTML version</a><post>
  <tag value="reverse engineering"/>
  <tag value="pace4000"/>
  <tag value="jtag"/>
  <title>pace4000 testing modes</title>
  <date>
  4 Oct 2014
  </date>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes1.jpg"/>
  <p>
While researching what was already known about my <a href="/?x=&amp;n=&amp;t=pace4000">pace 4000 box</a>, I'd read that it could be booted into a test mode by pressing and holding the up and down buttons as you power it on. The 4x seven segment display on the front of the box changes to 'Ldr' and on the TV it shows this:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes2.jpg"/>
  <p>
At this point the screen goes black and the front display changes to '----'. If the up/down buttons are released it runs through what I would guess is a hardware test routine; the display changes to 'PL:XX' - where XX is an incrementing two digit number - until XX is 21. It then moves onto the 'AP:XX' tests - 00 to 52 - at AP:31 a black and white Virgin media logo is shown on the TV:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes3.jpg"/>
  <p>
If during the period '----' is displayed on the front screen, the up/down buttons continue to be pressed, the box boots instead into an 18 page diagnostic mode. The front display changes to 'diag'. Most of it is what you might expect: software versions, tuner/channel data etc - pages 9 - 12 are a bit more interesting. Here's a grab of each page:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes4.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes5.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes6.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes7.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes8.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes9.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes10.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes11.jpg"/>
  <p>
This page almost guarantees that the bootloader contains some sort of CRC check. It also helpfully provides the exact start and end memory locations for the loader and the 'platform':
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes12.jpg"/>
  <p>
The memory map should hopefully help in locating the flash, so that over jtag I can restore the image if required:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes13.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes14.jpg"/>
  <p>
The code 16 "Tuning parameters corrupt" events seem to relate to changes in the in-memory image caused by using soft-breakpoints; 'Err1' is displayed on the front display when that happens:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes15.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes16.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes17.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes18.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes19.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes20.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes21.jpg"/>
  <p>
As I don't have a cable feed, the default boot actually does very little; the front panel shows 'Er11', 'Er12' then 'nit' and the TV just shows a black screen. I believe it needs to first download the 'nit' channel information from the cable network, before it will continue to the regular UI. For this reason I decided that the 'diag' mode was likely to be more interesting, but didn't really fancy having to hold the buttons down every time I wanted to reboot the box. I decided first to locate the switch point in the binary, that could be patched out when I attached openocd/gdb.
  </p>
  <p>
The set up is the same as I <a href="/posts.xml/pace4000_display_hack_over_jtag.xml">used previously</a>: busblaster connected to the <a href="/posts.xml/pace4000_jtag.xml">jtag pins</a>; openocd configured to use the busblaster, with a simple arm config and listening for gdb on port 3333; and arm-none-eabi-gdb from the the gnu tools.
  </p>
  <p>
Openocd is executed like this, so that it halts the CPU as soon as it starts:
  </p>
  <pre>
lee@monkeybox ~/Documents $ sudo openocd -f busblaster.cfg -f conexant_arm.cfg -c init -c halt -c targets
  </pre>
  <p>
And gdb: connects to openocd and tells gdb how many hardware breakpoints we have:
  </p>
  <pre>
arm-none-eabi-gdb -ex "target remote localhost:3333" -ex "set remote hardware-breakpoint-limit 2"
  </pre>
  <p>
I'd discovered when <a href="/posts.xml/pace4000_display_hack_over_jtag.xml">playing with the front display</a> that the instruction @ 0x1c240 got hit a few times during startup and that the display changed on the 11th, 31st, 40th and 82nd hit. I also knew that the 82nd hit changed text to 'nit' - which isn't shown when booting into the test modes - the switch must be before that point.
  </p>
  <p>
I iteratively halved the number of hits before I held down the buttons until I'd isolated that the keypress detection was between hit 35 and 36. From those two points I traced forwards/backwards (the lr register is your friend) and found this likely looking assembler:
  </p>
  <pre>
0x00001154	0xe3a07000	MOV r7, #0x0
0x00001158	0xe3c050ff	BIC r5, r0, #0xff             &lt;&lt;&lt;&lt; r5 = r0 &amp; 0xffffff00
0x0000115c	0xe3550e60	CMP r5, #0x600                &lt;&lt;&lt;&lt; if r5 == 0x600
0x00001160	0x0a000033	BEQ 0x00001234
0x00001164	0x8a00000c	BHI 0x0000119c
0x00001168	0xe3550f80	CMP r5, #0x200                &lt;&lt;&lt;&lt; if r5 == 0x200
0x0000116c	0x0a00001b	BEQ 0x000011e0
0x00001170	0x8a000004	BHI 0x00001188
0x00001174	0xe3550000	CMP r5, #0x0                  &lt;&lt;&lt;&lt; if r5 == 0x0
0x00001178	0x0a000014	BEQ 0x000011d0
0x0000117c	0xe3550f40	CMP r5, #0x100                &lt;&lt;&lt;&lt; if r5 == 0x100
0x00001180	0x0a000014	BEQ 0x000011d8
0x00001184	0xea00002a	B 0x00001234
0x00001188	0xe3550fc0	CMP r5, #0x300                &lt;&lt;&lt;&lt; if r5 == 0x300
0x0000118c	0x0a000017	BEQ 0x000011f0
0x00001190	0xe3550e40	CMP r5, #0x400                &lt;&lt;&lt;&lt; if r5 == 0x400
0x00001194	0x0a000017	BEQ 0x000011f8
0x00001198	0xea000025	B 0x00001234
0x0000119c	0xe3550e90	CMP r5, #0x900                &lt;&lt;&lt;&lt; if r5 == 0x900
0x000011a0	0x0a000017	BEQ 0x00001204
0x000011a4	0x8a000004	BHI 0x000011bc
0x000011a8	0xe3550e70	CMP r5, #0x700                &lt;&lt;&lt;&lt; if r5 == 0x700
0x000011ac	0x0a00000f	BEQ 0x000011f0
0x000011b0	0xe3550e80	CMP r5, #0x800                &lt;&lt;&lt;&lt; if r5 == 0x800
0x000011b4	0x0a00000c	BEQ 0x000011ec
0x000011b8	0xea00001d	B 0x00001234
0x000011bc	0xe3550ea0	CMP r5, #0xa00                &lt;&lt;&lt;&lt; if r5 == 0xa00
0x000011c0	0x0a00000a	BEQ 0x000011f0
0x000011c4	0xe3550eb0	CMP r5, #0xb00                &lt;&lt;&lt;&lt; if r5 == 0xb00
0x000011c8	0x0a000007	BEQ 0x000011ec
0x000011cc	0xea000018	B 0x00001234
  </pre>
  <p>
Setting a breakpoint on 0x1154 revealed that r0 - before having the last eight bits masked off - is 0x300 when the box is booted normally and 0x911 when up/down is pressed. Breaking and modifying the value of r0, I could trivially boot into the diag mode, however it's quite obvious that there are more than just those two modes available.
  </p>
  <p>
0x0 and 0x100 don't appear to do very much, TV screen is black and the front display just shows 'Err1' (more on this later). 0x400 shows the blue 'NTL Loader' but the text has changed and we appear to have booted into an ethernet/serial download mode:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes22.jpg"/>
  <p>
0x600 runs the into the same mode as 0x900 but doesn't show the 'NTL Loader'.
  </p>
  <p>
0x800 and 0xb00 display the 'NTL Loader', again text is different and the box goes into a tuning mode; first through the 'Hard Coded Channel list' and then a full scan - front display changes to Err4, Er12, Er11, nit and 'H XX' (XX: 00 - 50) for the hardcoded list and 'S XX' (XX: 00 - 89) for the scan:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes23.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes24.jpg"/>
  <p>
0xa00 shows a black screen and just says 'nit'.
  </p>
  <p>
In order to gain a little more insight into the modes I've traced the first 20-30 instructions for each mode:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes25.png"/>
  <p>
Each column is the sequence of instructions executed for that mode; where a short sequence (i.e. a function) is shared between two or more mode sequences they've been highlighted in the same colour. White patches are unique to that mode.
  </p>
  <p>
It's easy to see that the five modes (0x900, 0x200, 0x400, 0x800 and 0xb00) that display the 'NTL Loader' all call the 'blue' function - analysis of this code shows it simply sets a global flag. The flag is then read in the 'yellow' function, which returns a 0 or 1 and ultimately causes the code to branch into the purple/pink code - otherwise it ends up at brown.
  </p>
  <p>
0x100 clearly shows that it enters a "while(1){}" style construct @ 0x24ac and so it's understandable why it doesn't do anything. Interestingly it tries to write "Multi-ICE Download" to the TV beforehand, even though it hasn't been initialised. 
  </p>
  <p>
0x0 does seem to be actually doing something, although as yet I haven't taken a look. Again it attempts to write a string to the TV that hints at it's real purpose: "ARM Debugger Download" :)
  </p>
  <p>
As you can see in the first image at the top of the page I was also able to modify the strings written to the TV. At 0x12bc I also found a call to what must be drawrect():
  </p>
  <pre>
0x000012a0	0xe3a03c85	MOV r3, #0x8500
0x000012a4	0xe2833054	ADD r3, r3, #0x54
0x000012a8	0xe52d3004	STR r3, [r13, #-0x4]!     &lt;&lt; r3 contains the colour
0x000012ac	0xe3a02fb4	MOV r2, #0x2d0            &lt;&lt; r2 = 720
0x000012b0	0xe3a01000	MOV r1, #0x0              &lt;&lt; r1 = 0
0x000012b4	0xe1a00001	MOV r0, r1                &lt;&lt; r0 = 0
0x000012b8	0xe3a03f90	MOV r3, #0x240            &lt;&lt; r3 = 576 - PAL :)
0x000012bc	0xeb0040e5	BL 0x00011658             &lt;&lt; drawrect(r0, r1, r2, r3)  
  </pre>
  <p>
0x12a0 through to 0x12a8 set the 16 bit colour (might be 0xRGBA?); r2 is set to the width @ 0x12ac and r3 is set to the height @ 0x12b8 - 720x576: full screen PAL; r0 and r1 are the x and y coords. Messing with the values before the call to drawrect() let me produce these:
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes26.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes27.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes28.jpg"/>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_testing_modes29.jpg"/>
</post><post>
  <tag value="reverse engineering"/>
  <tag value="pace4000"/>
  <tag value="jtag"/>
  <title>pace4000 display hack over jtag</title>
  <date>
  19 Sept 2014
  </date>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_jtag1.jpg"/>
  <p>
With the <a href="/posts.xml/pace4000_jtag.xml">jtag pins found on the pace 4000</a> I though it would be nice if I could do something with it. It can (obviously) output video to a TV but I don't have a screen with a SCART input in the lab. Instead I thought I'd exercise my vanity and write my name on the 4x seven segment LED display on the front of the box.
  </p>
  <p>
The device is a black box with no documentation regarding the hardware, boot loader or OS. I knew that the CPU was an ARM - it has 'ARM' printed on it - which means the likely initial entry point is @ 0x0. If I halted the CPU as soon as the device was powered, I could catch it in a loop @ 0x638 where it was zeroing it's memory (adding '-c init -c halt' to the end of the openocd command line will make it halt the processor immediately) :
  </p>
  <pre>
0x00000638	0xe8a007fc	STM r0!, {r2, r3, r4, r5, r6, r7, r8, r9, r10}
0x0000063c	0xe1500001	CMP r0, r1
0x00000640	0xbafffffc	BLT 0x00000638
  </pre>
  <p>
From this early point in the execution I could reset the pc register back to 0x0 and step through from the start of the firmware using gdb - any later and it seems that some globals get set and interrupts have been enabled, which cause the code to branch into an infinite loop at several points.
  </p>
  <p>
The box runs through a handful of four char strings when it's powered on. Poking round further with gdb I eventually found a breakpoint (0x1c240) where on the 11th, 31st, 40th and 82nd hit it changes the text to '----', 'PACE', 'Err1' and 'nit' respectively. From here it jumps into a general purpose memory copy function, that reads a byte from RAM and writes it to 0x31500335:
  </p>
  <pre>
0x0001c2e4	0xe1a0c00d	MOV r12, r13
0x0001c2e8	0xe92dd800	STMDB r13!, {r11, r12, r14, r15}
0x0001c2ec	0xe59f3030	LDR r3, [r15, #0x30]
0x0001c2f0	0xe24cb004	SUB r11, r12, #0x4
0x0001c2f4	0xe3a0c000	MOV r12, #0x0
0x0001c2f8	0xe5933000	LDR r3, [r3]
0x0001c2fc	0xe15c0001	CMP r12, r1
0x0001c300	0xe0800003	ADD r0, r0, r3
0x0001c304	0x2a000004	BCS 0x0001c31c
0x0001c308	0xe4d23001	LDRB r3, [r2], #0x1  &lt;&lt;&lt; read from RAM @r2 into r3
0x0001c30c	0xe4c03001	STRB r3, [r0], #0x1  &lt;&lt;&lt; write r3 to @r0 (0x31500335)
  </pre>
  <p>
As soon as the STRB (SToRe Byte) command was executed the display changed. Stepping back and forth over 0x1c30c changing the value r3 revealed something interesting: the bottom half of the first two of the segments changed and the bottom of segments three and four changed to what one and two had just been - more iterations showed changes to the top half's, along with the colon in the middle and the three status LEDs on the right.
  </p>
  <p>
It was now apparent that the display was split into four sections and I could simply write each section in turn, by writing four times to 0x31500335, pushing the data round anti-clockwise until I had updated the whole display. I'd noticed though, that this wasn't what happened when the display was updated by the firmware; the whole display updated in one go.
  </p>
  <p>
Taking a look at the 10th hit of 0x1c240 showed that another byte was being written to the address before the one in the 11th call (@0x31500334). Changes here didn't affect the display until the 11th break on 0x1c240. At this point I wrongly assumed that the display could be addressed by writing to 0x31500332, 0x31500333, 0x31500334 and 0x31500335 - where the '335 write also updated the screen. By Examining the two hits before it was demonstrated that the sequence was in fact: three writes to '334 and a final write to '335 to update the screen - all the writes caused a shift round to the next section; these gdb commands will update the whole display:
  </p>
  <pre>
set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xff
ni

set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xff
ni

set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xff
ni

set $pc = 0x1c30c
set $r0 = 0x31500335
set $r3 = 0xff
ni
  </pre>
  <image src="/posts.assets/virgin_pace_jtag_display2.png"/>
  <p>
In the above 'map' you can see the four sections - red, blue, green and pink - of a byte each, where every bit corresponds to an individual segment (A-H). Note that the two LEDs that make up the colon between the two '88' digits are addressed as a single bit (A). As an added complication bits A-C and F-H are inverted i.e. you set them off to light them up; D and E are the other way around:
  </p>
  <pre>
          ABCDEFGH
0xe7    0b11100111    A-H off
0x18    0b00011000    A-H on  
  </pre>
  <p>
Writing to the segments is done by first writing in turn pink, then green and blue to 0x31500334. Then finally red to 0x31500335 which will also update the display.
  </p>
  <p>
I now had enough information to program the display and after working out the values based on the map I could write my name using this:
  </p>
  <pre>
set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xfb
ni

set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xd7
ni

set $pc = 0x1c30c
set $r0 = 0x31500334
set $r3 = 0xe0
ni

set $pc = 0x1c30c
set $r0 = 0x31500335
set $r3 = 0x01
ni
  </pre>
  <p>
My expectation was that these byte values would be pre-calculated and hardcoded somewhere in the firmware image but I couldn't find them. I noticed in the 'strings' output the four char strings I had been seeing on the display:
  </p>
  <pre>
PRIMARY LOADER
Ldr 
Err1                                &lt;&lt;&lt;
RAM Fail
Err2
**********NVRAM Fail***********
Err3
FLASH Fail
Er40
Cache Initialise Fail
LED Initialise Fail
PACE                                &lt;&lt;&lt;
Key Initialise Fail
I2C Initialise Fail
Graphics Initialise Fail
DENC Initialise Fail
SCART Initialise Fail
REMOD Initialise Fail
Engineering mode
Failed to read keys
ENGINEERING MODE: 
0000
0000
Found platform
Decompressed platform
FAILED TO GET PROTECTED CONFIGURATION DATA
----                                &lt;&lt;&lt;
  </pre>
  <p>
I was interested to see how the conversion was done so I set a rwatch breakpoint on the address of 'PACE'. The process is split into two parts, the first part takes each of the four chars in turn and uses their value as an index into this lookup table:
  </p>
  <pre>
0x0001fc04: 4d 42 4d 32 39 4c 56 36 35 31 20 28 57 41 52 4e 49 4e 47 3a 20 55 6e 74 65 73 74 65 64 29 00 00 
0x0001fc24: 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 3f 06 5b 4f 66 6d 7d 07 7f 6f 00 00 00 00 00 00 
               A  B  C  D  E  F  G  H  I  J  K  L  M  N  O  P  Q  R  S  T  U  V  W  X  Y  Z
0x0001fc44: 00 77 7f 39 3f 79 71 3d 76 06 1f 00 38 00 37 3f 73 67 50 6d 78 3e 00 00 00 66 00 79 64 4f 00 08 
               a  b  c  d  e  f  g  h  i  j  k  l  m  n  o  p  q  r  s  t  u  v  w  x  y  z
0x0001fc64: 00 5f 7c 58 5e 7b 71 6f 74 04 0e 00 06 00 54 5c 73 67 50 6d 78 1c 00 00 00 6e 00 00 30 00 40 00 
0x0001fc84: 01 01 01 00 80 01 80 00 2d 2d 2d 2d 00 00 00 00 00 00 00 00 b7 1d c1 04 6e 3b 82 09 d9 26 43 0d 
0x0001fca4: dc 76 04 13 6b 6b c5 17 b2 4d 86 1a 05 50 47 1e b8 ed 08 26 0f f0 c9 22 d6 d6 8a 2f 61 cb 4b 2b 
0x0001fcc4: 64 9b 0c 35 d3 86 cd 31 0a a0 8e 3c bd bd 4f 38 70 db 11 4c c7 c6 d0 48 1e e0 93 45 a9 fd 52 41 
0x0001fce4: ac ad 15 5f 1b b0 d4 5b c2 96 97 56 75 8b 56 52 c8 36 19 6a 7f 2b d8 6e a6 0d 9b 63 11 10 5a  
  </pre>
  <p>
These byte values represent which parts of an individual seven-segment to light up:
  </p>
  <pre>
  7654321
0b1111111

 1
6 2
 7
5 3
 4
  </pre>
  <p>
'PACE' is translated to: 73 77 39 79 and looks like this:
  </p>
  <pre>
         7654321
P 0x73 0b1110011
A 0x77 0b1110111
C 0x39 0b0111001
E 0x79 0b1111001

 1     1     1     1
6 2   6 2   6     6
 7     7           7
5     5 3   5     5
             4     4
  </pre>
  <p>
The second part of the process uses masking and shifting to map the idealised representation of the bit sequences to the four coloured sections mapped out earlier. The four chars are first reversed (e.g. 0x79773979 becomes 0x79397779) and then split into two 16 bit words i.e. as 0xAAAABBBB. 
  </p>
  <p>
Each of A and B are further split into 0xXXYY and bits 1, 2 and 6 from both X and Y (which are the top half of the letters) are shifted into place as the pink and green sections. Bits 3, 4, 5 and 7 (the bottom half's) - again from both X and Y - are shifted to become the red and blue sections. The final values are then xor'd against 0xe7 to flip the inverted (A-C and F-H) bits.
  </p>
  <p>
The following python was written against the assembler to validate the approach:
  </p>
  <pre>
#python implementation of the PACE 4000 ASCII to 88:88 display.
#
#It first reads the 4 char ASCII string and maps that to this lookup table (base+char):
'''
0x0001fc04: 4d 42 4d 32 39 4c 56 36 35 31 20 28 57 41 52 4e 49 4e 47 3a 20 55 6e 74 65 73 74 65 64 29 00 00 
0x0001fc24: 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 3f 06 5b 4f 66 6d 7d 07 7f 6f 00 00 00 00 00 00 
0x0001fc44: 00 77 7f 39 3f 79 71 3d 76 06 1f 00 38 00 37 3f 73 67 50 6d 78 3e 00 00 00 66 00 79 64 4f 00 08 
0x0001fc64: 00 5f 7c 58 5e 7b 71 6f 74 04 0e 00 06 00 54 5c 73 67 50 6d 78 1c 00 00 00 6e 00 00 30 00 40 00 
0x0001fc84: 01 01 01 00 80 01 80 00 2d 2d 2d 2d 00 00 00 00 00 00 00 00 b7 1d c1 04 6e 3b 82 09 d9 26 43 0d 
0x0001fca4: dc 76 04 13 6b 6b c5 17 b2 4d 86 1a 05 50 47 1e b8 ed 08 26 0f f0 c9 22 d6 d6 8a 2f 61 cb 4b 2b 
0x0001fcc4: 64 9b 0c 35 d3 86 cd 31 0a a0 8e 3c bd bd 4f 38 70 db 11 4c c7 c6 d0 48 1e e0 93 45 a9 fd 52 41 
0x0001fce4: ac ad 15 5f 1b b0 d4 5b c2 96 97 56 75 8b 56 52 c8 36 19 6a 7f 2b d8 6e a6 0d 9b 63 11 10 5a 

the lookup table describes the individual LEDs that need to be lit up to show the letter - for an idealised display.

However the PACE4000 display is wacky (the digits are across byte boundaries - split around the middle and need to be shifted in) and so we then need to mangle it using masking/shifting to give us the four bytes we need to shift in.

 -   -
| | | |
 -   -
| | | |
 -   -

lookup table bit pattern:
 1
6 2
 7
5 3
 4
 
'''

lookup = [
  0x4d, 0x42, 0x4d, 0x32, 0x39, 0x4c, 0x56, 0x36, 0x35, 0x31, 0x20, 0x28, 0x57, 0x41, 0x52, 0x4e, 0x49, 0x4e,
  0x47, 0x3a, 0x20, 0x55, 0x6e, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 
  0x7d, 0x07, 0x7f, 0x6f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 0x77, #A
 0x7f, #B
 0x39, #C
 0x3f, #D
 0x79, #E
 0x71, #F
 0x3d, #G
 0x76, #H
 0x06, #I
 0x1f, #J
 0x00, #K
 0x38, #L
 0x00, #M
 0x37, #N
 0x3f, #O
 0x73, #P
 0x67, #Q
 0x50, #R
 0x6d, #S
 0x78, #T
 0x3e, #U
 0x00, #V
 0x00, #W
 0x00, #X
 0x66, #Y
 0x00, #Z
 0x79,
 0x64,
 0x4f,
 0x00,
 0x08,
 0x00,
 0x5f, #a
 0x7c, #b
 0x58, #c
 0x5e, #d
 0x7b, #e
 0x71, #f
 0x6f, #g
 0x74, #h
 0x04, #i
 0x0e, #j
 0x00, #k
 0x06, #l
 0x00, #m
 0x54, #n
 0x5c, #o
 0x73, #p
 0x67, #q
 0x50, #r
 0x6d, #s
 0x78, #t
 0x1c, #u
 0x00, #v
 0x00, #w
 0x00, #x
 0x6e, #y
 0x00, #z
 0x00, 0x30, 0x00, 0x40, 0x00, 0x01, 0x01, 0x01, 0x00, 0x80, 0x01, 0x80, 0x00, 0x2d, 0x2d, 0x2d, 0x2d, 0x00, 
 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0x1d, 0xc1, 0x04, 0x6e, 0x3b, 0x82, 0x09, 0xd9, 0x26, 0x43, 
 0x0d, 0xdc, 0x76, 0x04, 0x13, 0x6b, 0x6b, 0xc5, 0x17, 0xb2, 0x4d, 0x86, 0x1a, 0x05, 0x50, 0x47, 0x1e, 0xb8, 
 0xed, 0x08, 0x26, 0x0f, 0xf0, 0xc9, 0x22, 0xd6, 0xd6, 0x8a, 0x2f, 0x61, 0xcb, 0x4b, 0x2b, 0x64, 0x9b, 0x0c, 
 0x35, 0xd3, 0x86, 0xcd, 0x31, 0x0a, 0xa0, 0x8e, 0x3c, 0xbd, 0xbd, 0x4f, 0x38, 0x70, 0xdb, 0x11, 0x4c, 0xc7, 
 0xc6, 0xd0, 0x48, 0x1e, 0xe0, 0x93, 0x45, 0xa9, 0xfd, 0x52, 0x41, 0xac, 0xad, 0x15, 0x5f, 0x1b, 0xb0, 0xd4, 
 0x5b, 0xc2, 0x96, 0x97, 0x56, 0x75, 0x8b, 0x56, 0x52, 0xc8, 0x36, 0x19, 0x6a, 0x7f, 0x2b, 0xd8, 0x6e, 0xa6, 
 0x0d, 0x9b, 0x63, 0x11, 0x10, 0x5a]


s = 'PACE'
#s = 'LEE '

m = 0
shift = 0
for c in s:
  i = ord(c)
  #print i
  #print hex(lookup[i])
  m = m | (int(lookup[i]) &lt;&lt; shift)
  shift += 8

#print "m:", hex(m)
r0 = m

#r0 = 0x79397773
#expected = 99 db 01 34


#there are 4 segments:

#pink segment - uses last two bytes i.e. 0x????XXYY (Y=1st, X=2nd)
#top half of digits one and two
#bits 1, 2 and 6 are the top half in the source bytes (XX and YY)

#extract bit 6 from XX
r2 = r0 &amp; 0x2000        #0x0000c8a4	0xe2002d80	AND r2, r0, #0x2000
r2 = r2 &gt;&gt; 0xa          #0x0000c8a8	0xe1a02522	MOV r2, r2, LSR #0xa
#extract bits 1 and 2 from YY
r3 = r0 &amp; 0x3           #0x0000c8ac	0xe2003003	AND r3, r0, #0x3
r3 = r3 &lt;&lt; 0x5          #0x0000c8b0	0xe1a03283	MOV r3, r3, LSL #0x5
r2 = r2 | r3            #0x0000c8b4	0xe1822003	ORR r2, r2, r3
#extract bit 6 from YY
r3 = r0 &amp; 0x20          #0x0000c8b8	0xe2003020	AND r3, r0, #0x20
r3 = r3 &gt;&gt; 0x1          #0x0000c8bc	0xe1a030a3	MOV r3, r3, LSR #0x1
r2 = r2 | r3            #0x0000c8c0	0xe1822003	ORR r2, r2, r3
#extract bit 1 from XX
r3 = r0 &amp; 0x100         #0x0000c8c4	0xe2003f40	AND r3, r0, #0x100
r3 = r3 &gt;&gt; 0x6          #0x0000c8c8	0xe1a03323	MOV r3, r3, LSR #0x6
r2 = r2 | r3            #0x0000c8cc	0xe1822003	ORR r2, r2, r3
#extract bit 2 from XX
r3 = r0 &amp; 0x200         #0x0000c8d0	0xe2003f80	AND r3, r0, #0x200
r3 = r3 &gt;&gt; 0x8          #0x0000c8d4	0xe1a03423	MOV r3, r3, LSR #0x8
r2 = r2 | r3            #0x0000c8d8	0xe1822003	ORR r2, r2, r3
#flip the inverted bits
r2 = r2 ^ 0xe7          #0x0000c8dc	0xe22220e7	EOR r2, r2, #0xe7
print "pink: ",hex(r2)

#red segment - uses last two bytes i.e. 0x????XXYY (Y=1st, X=2nd)
#bottom half of digits one and two
#bits 3, 4, 5 and 7 are the bottom half in the source bytes (XX and YY)

#extract bit 3 from YY
r3 = r0 &amp; 0x4           #0x0000c8e4	0xe2003004	AND r3, r0, #0x4
#extract bit 4 from YY
r2 = r0 &amp; 0x8           #0x0000c8e8	0xe2002008	AND r2, r0, #0x8
r2 = r2 &gt;&gt; 0x1          #0x0000c8ec	0xe1a020a2	MOV r2, r2, LSR #0x1
r2 = r2 | (r3 &lt;&lt; 0x1)   #0x0000c8f0	0xe1822083	ORR r2, r2, r3, LSL #0x1
#extract bit 5 from YY
r3 = r0 &amp; 0x10          #0x0000c8f4	0xe2003010	AND r3, r0, #0x10
r3 = r3 &gt;&gt; 0x3          #0x0000c8f8	0xe1a031a3	MOV r3, r3, LSR #0x3
r2 = r2 | r3            #0x0000c8fc	0xe1822003	ORR r2, r2, r3
#extract bit 7 from YY and bits 3, 4 and 5 from XX
r3 = r0 &amp; 0x1c40        #0x0000c900	0xe2003d71	AND r3, r0, #0x1c40
r2 = r2 | (r3 &gt;&gt; 0x6)   #0x0000c904	0xe1822323	ORR r2, r2, r3, LSR #0x6
#extract bit 7 from XX
r3 = r0 &amp; 0x4000        #0x0000c908	0xe2003c40	AND r3, r0, #0x4000
r3 = r3 &gt;&gt; 0x7          #0x0000c90c	0xe1a033a3	MOV r3, r3, LSR #0x7
r2 = r2 | r3            #0x0000c910	0xe1822003	ORR r2, r2, r3
#flip the inverted bits
r2 = r2 ^ 0xe7          #0x0000c914	0xe22220e7	EOR r2, r2, #0xe7
print "red:  ",hex(r2)

#green segment - uses first two bytes i.e. 0xXXYY???? (Y=3rd, X=4th)
#top half of digits three and four
#bits 1, 2 and 6 are the top half in the source bytes (XX and YY)

#shift r0 16 bits, so that it's just working on 0xXXXX
r0 = r0 &gt;&gt; 0x10         #0x0000c91c	0xe1a00820	MOV r0, r0, LSR #0x10
#extract bits 1 and 2 from YY
r3 = r0 &amp; 0x3           #0x0000c920	0xe2003003	AND r3, r0, #0x3
r3 = r3 &lt;&lt; 0x5          #0x0000c924	0xe1a03283	MOV r3, r3, LSL #0x5
#extract bit 6 from XX
r2 = r0 &amp; 0x2000        #0x0000c928	0xe2002d80	AND r2, r0, #0x2000
r2 = r2 &gt;&gt; 0xa          #0x0000c92c	0xe1a02522	MOV r2, r2, LSR #0xa
r2 = r2 | r3            #0x0000c930	0xe1822003	ORR r2, r2, r3
#extract bit 6 from YY
r3 = r0 &amp; 0x20          #0x0000c934	0xe2003020	AND r3, r0, #0x20
r3 = r3 &gt;&gt; 0x1          #0x0000c938	0xe1a030a3	MOV r3, r3, LSR #0x1
r2 = r2 | r3            #0x0000c93c	0xe1822003	ORR r2, r2, r3
#extract bit 1 from XX
r3 = r0 &amp; 0x100         #0x0000c940	0xe2003f40	AND r3, r0, #0x100
r3 = r3 &gt;&gt; 0x6          #0x0000c944	0xe1a03323	MOV r3, r3, LSR #0x6
r2 = r2 | r3            #0x0000c948	0xe1822003	ORR r2, r2, r3
#extract bit 2 from XX
r3 = r0 &amp; 0x200         #0x0000c94c	0xe2003f80	AND r3, r0, #0x200
r3 = r3 &gt;&gt; 0x8          #0x0000c950	0xe1a03423	MOV r3, r3, LSR #0x8
r2 = r2 | r3            #0x0000c954	0xe1822003	ORR r2, r2, r3
#flip the inverted bits
r2 = r2 ^ 0xe7          #0x0000c958	0xe22220e7	EOR r2, r2, #0xe7
print "green:",hex(r2)

#blue segment - uses first two bytes i.e. 0xXXYY???? (Y=3rd, X=4th)
#bottom half of digits three and four
#bits 3, 4, 5 and 7 are the bottom half in the source bytes (XX and YY)

#extract bit 3 from YY
r3 = r0 &amp; 0x4           #0x0000c964	0xe2003004	AND r3, r0, #0x4
#extract bit 4 from YY
r2 = r0 &amp; 0x8           #0x0000c968	0xe2002008	AND r2, r0, #0x8
r2 = r2 &gt;&gt; 0x1          #0x0000c96c	0xe1a020a2	MOV r2, r2, LSR #0x1
r2 = r2 | (r3 &lt;&lt; 0x1)   #0x0000c970	0xe1822083	ORR r2, r2, r3, LSL #0x1
#extract bit 5 from YY
r3 = r0 &amp; 0x10          #0x0000c974	0xe2003010	AND r3, r0, #0x10
r3 = r3 &gt;&gt; 0x3          #0x0000c978	0xe1a031a3	MOV r3, r3, LSR #0x3
r2 = r2 | r3            #0x0000c97c	0xe1822003	ORR r2, r2, r3
#extract bit 7 from YY and bits 3, 4 and 5 from XX
r3 = r0 &amp; 0x1c40        #0x0000c980	0xe2003d71	AND r3, r0, #0x1c40
r2 = r2 | (r3 &gt;&gt; 0x6)   #0x0000c984	0xe1822323	ORR r2, r2, r3, LSR #0x6
#extract bit 7 from XX
r0 = r0 &amp; 0x4000        #0x0000c988	0xe2000c40	AND r0, r0, #0x4000
r0 = r0 &gt;&gt; 0x7          #0x0000c98c	0xe1a003a0	MOV r0, r0, LSR #0x7
r2 = r2 | r0            #0x0000c990	0xe1822000	ORR r2, r2, r0
#flip the inverted bits
r2 = r2 ^ 0xe7          #0x0000c994	0xe22220e7	EOR r2, r2, #0xe7
print "blue :",hex(r2)  
  </pre>
</post><post>
  <tag value="reverse engineering"/>
  <tag value="pace4000"/>
  <tag value="jtag"/>
  <title>pace4000 jtag</title>
  <date>
  8 Sept 2014
  </date>
  <p>
  </p>
  <image src="/posts.assets/virgin_pace_jtag1.jpg"/>
  <p>
After having <a href="/posts.xml/bt_voyager_2091_jtag.xml">success finding the jtag pads on an old router</a>, I turned my attention to some of the other old kit I have lying around. I'd had the lid off the Virgin-branded, Pace 4000 set top box previously and noticed that it had a handful of unpopulated headers on the board. The nine closest to the CPU seemed most promising, so after soldering some pins, checking the voltages (all within 3.3v) and for ground, I attached my arduino mega running <a href="https://github.com/cyphunk/JTAGenum/">jtagenum</a>. It found this:
  </p>
  <image src="/posts.assets/virgin_pace_jtag3.jpg"/>
  <pre>
#   JTAG  colour
9   TDO   red
7   TCK   blue
5   TMS   green
3   TDI   pink
  </pre>
  <p>
Using openocd I was able to hack together this config file for the Conexant 'MPEG II DECODER' ARM chip:
  </p>
  <pre>
set _CHIPNAME conexantarm
set _CPUID 0x10940027

jtag newtap $_CHIPNAME cpu -expected-id $_CPUID -irlen 4

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME arm920t -endian little -chain-position $_TARGETNAME  
  </pre>
  <p>
Dumping from 0x0, the first 256 bytes:
  </p>
  <pre>
lee@monkeybox ~/Downloads/openocd/openocd $ hexdump -C pace-virgin.bin | less
00000000  18 f0 9f e5 18 f0 9f e5  18 f0 9f e5 18 f0 9f e5  |................|
*
00000020  08 01 00 00 78 01 00 00  84 01 00 00 f4 01 00 00  |....x...........|
00000030  00 02 00 00 0c 02 00 00  18 02 00 00 24 02 00 00  |............$...|
00000040  2e 97 a0 a9 ba f4 a7 d4  30 5f 80 35 0e c3 bc 77  |........0_.5...w|
00000050  7c 57 55 68 dc 59 be f6  24 ae d1 52 85 62 c7 8d  ||WUh.Y..$..R.b..|
00000060  83 e2 75 03 75 29 e6 11  00 00 04 00 fc ff 03 00  |..u.u)..........|
00000070  00 00 00 20 00 00 00 00  00 00 00 00 00 00 00 00  |... ............|
00000080  08 08 00 00 00 00 00 00  00 00 6c 6f 61 64 65 72  |..........loader|
00000090  00 00 00 5f 37 37 37 37  37 37 37 37 37 37 37 37  |..._777777777777|
000000a0  37 37 37 37 37 37 37 37  37 37 37 37 37 37 37 37  |7777777777777777|
000000b0  37 37 37 37 37 37 37 37  37 37 37 37 2b f7 9f f4  |777777777777+...|
000000c0  4e 54 4c 20 4c 6f 61 64  65 72 20 56 31 2e 39 20  |NTL Loader V1.9 |
000000d0  52 65 6c 65 61 73 65 00  00 00 00 00 00 00 00 00  |Release.........|
000000e0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|  
  </pre>
  <p>
And through 'strings' (anyone else think the passcode for 'ENGINEERING MODE' might be '0000'? ;) ): 
  </p>
  <pre>
Stopping off air download
Paul's debug loader 
BUILDING FAT: 
Ethernet Download Not Avaliable
Changing to serial download
Serial Download
Skipping Download
RUN PLATFORM 
FAIL
Invalid platform flash is set. Deleting non platform objects
Deleted flash object of type 
Failed to delete flash object, error is 
pstHeader is 
Object size is 
CRC offset is 
*****************************************************************
                  
PRIMARY LOADER
Ldr 
Err1
RAM Fail
Err2
**********NVRAM Fail***********
Err3
FLASH Fail
Er40
Cache Initialise Fail
LED Initialise Fail
PACE
Key Initialise Fail
I2C Initialise Fail
Graphics Initialise Fail
DENC Initialise Fail
SCART Initialise Fail
REMOD Initialise Fail
Engineering mode
Failed to read keys
ENGINEERING MODE: 
0000
0000  
  </pre>
</post><post>
  <tag value="jtag"/>
  <tag value="bcm6348"/>
  <tag value="reverse engineering"/>
  <title>bt voyager 2091 jtag</title>
  <date>2 Aug 2014</date>
  <p>
  </p>
  <image src="/posts.assets/bt_voyager_2091_jtag1.jpg"/>
  <p>
Before attempting to flash a router with openwrt, I like to jtag it so I can dump and restore the flash if it all goes horribly wrong. Unlike the the <a href="/posts.xml/bt_voyager_2091_uart.xml">serial console</a>, the jtag connections on the BT voyager 2091 aren't obvious - and unlike the previous bcm6348 boards I've jtag'd, someone hasn't already documented them.
  </p>
  <p>
Although the board has a large amount of exposed pads and/or vias, very few of these are labelled. On the underside however there's a small cluster of pads labelled BTP2, BTP3, BTP4 and BTP5. As jtag usually needs a minimum of TMS, TCK, TDO and TDI these four pads seemed like the best place to start.
  </p>
  <image src="/posts.assets/bt_voyager_2091_jtag4.jpg"/>
  <p>
I didn't want to have to manually walk through all possible combinations - especially if it turned out they weren't the correct pads and I'd have to expand my search to the numerous unlabelled pads - so I looked for a way to automate. After finding a couple of dedicated (but expensive) devices I eventually found <a href="https://github.com/cyphunk/JTAGenum/">jtagenum</a> for the arduino. Jtagenum basically just brute forces it's way through all pin combinations and would be perfect if my arduino wasn't 5v; the 2091 is a 3.3v device.
  </p>
  <p>
Here's the 2091, my arduino mega and an eight-way level shifter on a breadboard, using a handful of mosfets (circuit borrowed from <a href="http://husstechlabs.com/support/tutorials/bi-directional-level-shifter/">here</a>).
  </p>
  <image src="/posts.assets/bt_voyager_2091_jtag2.jpg"/>
  <p>
Jtagenum really wants five pins: the usual four TMS/TCK/TDO/TDI and nTRST. As I don't have a candidate for nTRST I added and extra pin (40) to the pin[]/pinnames[] arrays and just left it unconnected. The four BTPx wires were connected to 24, 29, 32, and 37. Running the 'pattern scan' gave the following output:
  </p>
  <pre>
================================
Starting scan for pattern:0110011101001101101000010111001001
active  ntrst:32 tck:37 tms:24 tdo:29 tdi:40	bits toggled:3
active  ntrst:32 tck:37 tms:40 tdo:29 tdi:24	bits toggled:6
active  ntrst:40 tck:37 tms:24 tdo:29 tdi:32	bits toggled:58
active  ntrst:40 tck:37 tms:32 tdo:29 tdi:24	bits toggled:6
================================
  </pre>
  <p>
As I knew that 40 was unconnected it couldn't be either of the first two 'active' lines; one has TMS as 40 the other has TDI as 40. This left just two combinations to try with my busblaster - first one didn't work but the second one made urjtag do this:
  </p>
  <pre>
UrJTAG 0.10 #2039
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors

UrJTAG is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
There is absolutely no warranty for UrJTAG.

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag&gt; cable jtagkey vid=0x403 pid=0x6010
Connected to libftdi driver.
jtag&gt; detect
IR length: 5
Chain length: 1
Device Id: 00000110001101001000000101111111 (0x0634817F)
  Manufacturer: Broadcom (0x17F)
  Part(0):      BCM6348 (0x6348)
  Stepping:     V1
  Filename:     /usr/local/share/urjtag/broadcom/bcm6348/bcm6348
  </pre>
  <p>
Excellent :) working JTAG!
  </p>
  <p>
Pin outs:
  </p>
  <image src="/posts.assets/bt_voyager_2091_jtag5.jpg"/>
  <pre>
BTP2 - TDI - red
BTP3 - TDO - green
BTP4 - TMS - blue
BTP5 - TCK - purple
  </pre>  
  <p>
Soldering these tiny little spots was really tricky - considering all the coffee I'd consumed at that point!
  </p>
  <image src="/posts.assets/bt_voyager_2091_jtag3.jpg"/>
</post><post>
  <tag value="bcm6348"/>
  <tag value="jtag"/>
  <title>jtag flashing and dumping with openocd 0.8.0</title>
  <date>12 Apr 2014</date>
  <p>
  A few weeks ago, Paul Fertser (one of the the <a href="http://openocd.sourceforge.net/">openocd</a> devs) mailed me to say that he had seen <a href="http://www.sodnpoo.com/posts.xml/jtag_flashing_bcm6348_devices_with_a_bus_pirate_and_openocd.xml">my post on using openocd and a buspirate to flash and dump bcm6348 boards</a> and had written a firmware recovery script to make the process much simpler. A flash/dump can now be achieved in a single command line; here's how to show the help text:
  </p>
  <pre>
  openocd -f tools/firmware-recovery.tcl -c firmware_help
  </pre>
  <p>
  And the output:
  </p>
  <pre>
lee@monkeybox ~/Downloads/openocd/openocd $ openocd -f tools/firmware-recovery.tcl -c firmware_help
Open On-Chip Debugger 0.8.0-rc1-dev-00439-ga719779-dirty (2014-04-06-12:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html


Firmware recovery helpers
Use -c firmware_help to get help

adapter speed: 1000 kHz


Your OpenOCD command should look like this:
openocd -f interface/&lt;jtag adapter&gt;.cfg -f tools/firmware-recovery.tcl -c "&lt;commands&gt;*; shutdown"

Where:
&lt;jtag adapter&gt; is one of the supported devices, e.g. ftdi/jtagkey2
&lt;commands&gt; are firmware-recovery commands separated by semicolon

Supported commands:
firmware_help			get this help
list_boards			list known boards and exit
board &lt;name&gt;			select board you work with
list_partitions			list partitions of the currently selected board
dump_part &lt;name&gt; &lt;filename&gt;	save partition's contents to a file
erase_part &lt;name&gt;		erase the given partition
flash_part &lt;name&gt; &lt;filename&gt;	erase, flash and verify the given partition
ram_boot &lt;filename&gt;		load binary file to RAM and run it
adapter_khz &lt;freq&gt;		set JTAG clock frequency in kHz

For example, to clear nvram and reflash CFE on an RT-N16 using TUMPA, run:
openocd -f interface/ftdi/tumpa.cfg -f tools/firmware-recovery.tcl \
	-c "board asus-rt-n16; erase_part nvram; flash_part CFE cfe-n16.bin; shutdown"



shutdown command invoked
Error: Debug Adapter has to be specified, see "interface" command
in procedure 'init'  
  </pre>
  <p>
  The script supports a handful of commands, that are specified using '-c' and that can be chained together by separating them with semi-colons and wrapping the whole string in quotes ("command1; command2; etc"). A list of supported boards can be seen like this: 
  </p>
  <pre>
lee@monkeybox ~/Downloads/openocd/openocd $ openocd -f tools/firmware-recovery.tcl -c list_boards
Open On-Chip Debugger 0.8.0-rc1-dev-00439-ga719779-dirty (2014-04-06-12:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html


Firmware recovery helpers
Use -c firmware_help to get help

adapter speed: 1000 kHz

List of the supported boards:

Board name		Description
-----------------------------------
asus-rt-n16		ASUS RT-N16
linksys-wrt54gl		Linksys WRT54GL v1.1
netgear-dg834v3		Netgear DG834G v3
bt-homehubv1		BT HomeHub v1



Error: Debug Adapter has to be specified, see "interface" command
in procedure 'init'  
  </pre>
  <p>
  Two commands are chained together ("board bt-homehubv1; list_partitions") to select the BT Homehub and list it's partitions (I've included the busblaster interface config - change as fit for your programmer):
  </p>
  <pre>
lee@monkeybox ~/Downloads/openocd/openocd $ openocd -f interface/busblaster.cfg -f \ 
tools/firmware-recovery.tcl -c "board bt-homehubv1; list_partitions"
Open On-Chip Debugger 0.8.0-rc1-dev-00439-ga719779-dirty (2014-04-06-12:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'


Firmware recovery helpers
Use -c firmware_help to get help

adapter speed: 1000 kHz


The currently selected board is known to have these partitions:

Name            Start         Size          Description
-------------------------------------------------------
CFE             0xbe400000    0x00020000    Bootloader
firmware        0xbe420000    0x007D0000    Kernel+rootfs
fisdir          0xbebf0000    0x0000f000    FIS Directory
nvram           0xbebff000    0x00001000    Config space



Warn : Using DEPRECATED interface driver 'ft2232'
Info : Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/...
Error: unable to open ftdi device: device not found
in procedure 'init'  
  </pre>
  <p>
  And finally, dumping the CFE bootloader (already flashed with redboot on my HomeHubv1):
  </p>
  <pre>
lee@monkeybox ~/Downloads/openocd/openocd $ time sudo openocd -f interface/busblaster.cfg -f \ 
tools/firmware-recovery.tcl -c "board bt-homehubv1;dump_part CFE redboot.fwrecovery.test.bin; shutdown"
Open On-Chip Debugger 0.8.0-rc1-dev-00439-ga719779-dirty (2014-04-06-12:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.sourceforge.net/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'


Firmware recovery helpers
Use -c firmware_help to get help

adapter speed: 1000 kHz

Warn : Using DEPRECATED interface driver 'ft2232'
Info : Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/...
Info : max TCK change to: 30000 kHz
Info : clock speed 1000 kHz
Info : JTAG tap: bcm6348.cpu tap/device found: 0x0634817f (mfg: 0x0bf, part: 0x6348, ver: 0x0)
target state: halted
target halted in MIPS32 mode due to debug-request, pc: 0x9e40a4b0
Info : JTAG tap: bcm6348.cpu tap/device found: 0x0634817f (mfg: 0x0bf, part: 0x6348, ver: 0x0)
Error: Error writing unexpected address 0xff202004
target state: halted
target halted in MIPS32 mode due to debug-request, pc: 0x9e40a4b0
dumped 131072 bytes in 668.114136s (0.192 KiB/s)
shutdown command invoked

real	11m9.933s
user	0m6.680s
sys	0m13.300s
  </pre>
  <p>
  Board config files are pretty straight forward, just defining how the target, the flash and how the flash has been carved up (usually can be extracted from the bootloader):
  </p>
  <pre>
#
# BT HomeHub v1
# 

set partition_list {
    CFE       { Bootloader        0xbe400000 0x00020000 }
    firmware  { "Kernel+rootfs"   0xbe420000 0x007D0000 }
    fisdir    { "FIS Directory"   0xbebf0000 0x0000f000 }
    nvram     { "Config space"    0xbebff000 0x00001000 }
}

source [find target/bcm6348.cfg]

set _FLASHNAME $_CHIPNAME.norflash
flash bank $_FLASHNAME cfi 0xbe400000 0x00800000 2 2 $_TARGETNAME  
  </pre>
  <p>
  The recovery script will be included in the 0.8.0 release and hopefully my patches for the bcm6348 target and the Home Hub will be too :)
  </p>
</post><post>
  <tag value="jtag"/>
  <tag value="bcm6348"/>
  <title>dump dg834v4 flash over jtag</title>
  <date>
  18 Jan 2014
  </date>
  <p>
  </p>
  <image src="/posts.assets/dg834v4_jtag1.jpg"/>
  <p>
  I've added a connector to the DG834v4 so I can use the jtag pins to dump the flash, before attempting to install openwrt. If I end up bricking it I should just be able to write the dumped image back again.
  </p>
  <image src="/posts.assets/dg834v4_jtag2.jpg"/>
  <p>
  The pins are detailed over on the <a href="http://wiki.openwrt.org/toh/netgear/dg834.v4">openwrt wiki</a>, but I've labelled them in the image above anyway. I've used <a href="http://urjtag.org/">urjtag</a> to do the heavy lifting; capture of the session below. The "cable ..." line is for my <a href="http://dangerousprototypes.com/docs/Bus_Blaster">Bus Blaster</a>, you'll probably need to change it if you use something else.
  </p>
  <pre>
UrJTAG 0.10 #2039
Copyright (C) 2002, 2003 ETC s.r.o.
Copyright (C) 2007, 2008, 2009 Kolja Waschk and the respective authors

UrJTAG is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
There is absolutely no warranty for UrJTAG.

warning: UrJTAG may damage your hardware!
Type "quit" to exit, "help" for help.

jtag&gt; cable jtagkey vid=0x403 pid=0x6010
Connected to libftdi driver.
jtag&gt; detect
IR length: 5
Chain length: 1
Device Id: 00000110001101001000000101111111 (0x0634817F)
  Manufacturer: Broadcom (0x17F)
  Part(0):      BCM6348 (0x6348)
  Stepping:     V1
  Filename:     /usr/local/share/urjtag/broadcom/bcm6348/bcm6348
jtag&gt; endian big
jtag&gt; initbus ejtag_dma
ImpCode=00000000100000000000100100000100
EJTAG version: &lt;= 2.0
EJTAG Implementation flags: R4k DMA MIPS32
Clear memory protection bit in DCR
Clear Watchdog
Potential flash base address: [0x1fc0000b], [0x0]
Processor successfully switched in debug mode.
jtag&gt; detectflash 0x1fc00000
Query identification string:
	Primary Algorithm Command Set and Control Interface ID Code: 0x0002 (AMD/Fujitsu Standard Command Set)
	Alternate Algorithm Command Set and Control Interface ID Code: 0x0000 (null)
Query system interface information:
	Vcc Logic Supply Minimum Write/Erase or Write voltage: 2700 mV
	Vcc Logic Supply Maximum Write/Erase or Write voltage: 3600 mV
	Vpp [Programming] Supply Minimum Write/Erase voltage: 0 mV
	Vpp [Programming] Supply Maximum Write/Erase voltage: 0 mV
	Typical timeout per single byte/word program: 16 us
	Typical timeout for maximum-size multi-byte program: 0 us
	Typical timeout per individual block erase: 1024 ms
	Typical timeout for full chip erase: 0 ms
	Maximum timeout for byte/word program: 512 us
	Maximum timeout for multi-byte program: 0 us
	Maximum timeout per individual block erase: 16384 ms
	Maximum timeout for chip erase: 0 ms
Device geometry definition:
	Device Size: 4194304 B (4096 KiB, 4 MiB)
	Flash Device Interface Code description: 0x0002 (x8/x16)
	Maximum number of bytes in multi-byte program: 1
	Number of Erase Block Regions within device: 2
	Erase Block Region Information:
		Region 0:
			Erase Block Size: 8192 B (8 KiB)
			Number of Erase Blocks: 8
		Region 1:
			Erase Block Size: 65536 B (64 KiB)
			Number of Erase Blocks: 63
Primary Vendor-Specific Extended Query:
	Major version number: 1
	Minor version number: 1
	Address Sensitive Unlock: Required
	Erase Suspend: Read/write
	Sector Protect: 4 sectors per group
	Sector Temporary Unprotect: Not supported
	Sector Protect/Unprotect Scheme: 29BDS640 mode (Software Command Locking)
	Simultaneous Operation: Not supported
	Burst Mode Type: Supported
	Page Mode Type: Not supported
	ACC (Acceleration) Supply Minimum: 11500 mV
	ACC (Acceleration) Supply Maximum: 12500 mV
	Top/Bottom Sector Flag: Bottom boot device
jtag&gt; readmem 0x1fc00000 0x400000 dg834v4.full.dump.4MB.bin
address: 0x1FC00000
length:  0x00400000
reading:
addr: 0x20000000
Done.
  </pre>
  <p>
  I haven't needed to do it yet but to restore the image the command should be:
  </p>
  <pre>
jtag&gt; flashmem 0x1fc00000 dg834v4.full.dump.4MB.bin
  </pre>
</post><post>
  <tag value="jtag"/>
  <tag value="bcm6348"/>
  <tag value="bus pirate"/>
  <title>jtag flashing bcm6348 devices with a bus pirate and openocd</title>
  <date>
  23 Dec 2013
  </date>
  <p>
  </p>
  <image src="/posts.assets/bthhv1_jtag1.jpg"/>
  <p>
  Having never used JTAG before I thought I'd see what I could do with my new Bus Pirate and one of the old ADSL routers I have lying around - ideally reading/writing to the flash. The v1 BT Home Hub is a Broadcom BCM6348-based device with 32MB RAM, that I'd previously <a href="/posts.xml/bt_homehub_v1_uart.xml">added headers for the serial uart</a> and replaced the bootloader with RedBoot and the OS with openwrt. You can see a small breakout with a TTL level converter and an FTDI uart&lt;-&gt;USB on the right, and the Bus Pirate on the left in the picture above.
  </p>
  <image src="/posts.assets/bthhv1_jtag2.jpg"/>
  <p>
  The JTAG pads are on the back of the board, behind the BCM6348; they are documented over on the <a href="http://wiki.openwrt.org/toh/thomson/st7g">openwrt wiki</a>. I've soldered a short length of ribbon cable - held in place with a strip of duck tape to ease the mechanical stress on them.
  </p>
  <p>
  As the v3 Bus Pirate doesn't have enough space for the openocd JTAG module in the stock build, I needed to flash the custom hex image I found <a href="http://dangerousprototypes.com/forum/viewtopic.php?f=27&amp;t=1702#p17536">here</a> that has it compiled in.
  </p>
  <p>
  The default install of openocd on Mint 20.04 doesn't support the Bus Pirate either, so it has to be built from source - remembering to add "--enable-buspirate" option:
  </p>
  <pre>
./configure --enable-buspirate
make
sudo make install
  </pre>
  <p>
  Although openocd now detects the Bus Pirate, it needs a config (openocd.cfg) putting together so it knows it's dealing with a MIPS chip and where the flash lives. After much googling and trial and error I came up with this:
  </p>
  <pre>
source [find interface/buspirate.cfg]
buspirate_port /dev/ttyUSB0

set _CHIPNAME bcm6348

jtag_nsrst_delay 100
jtag_ntrst_delay 100

reset_config trst_and_srst

jtag newtap $_CHIPNAME cpu -irlen 5 -ircapture 0x1 -irmask 0x1f -expected-id 0x0634817f

set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME

# setup working area somewhere in RAM
#$_TARGETNAME configure -work-area-phys 0xa0600000 -work-area-size 0x20000
#$_TARGETNAME configure -work-area-phys 0xa0600000 -work-area-size 0x40000

# serial SPI capable flash
# flash bank &lt;driver&gt; &lt;base&gt; &lt;size&gt; &lt;chip_width&gt; &lt;bus_width&gt;

set _FLASHNAME $_CHIPNAME.flash
#4mb
#flash bank $_FLASHNAME cfi 0x1fc00000 0x00400000 2 2 $_TARGETNAME
#8MB
flash bank $_FLASHNAME cfi 0x1f800000 0x00800000 2 2 $_TARGETNAME
  </pre>
  <p>
  I'm sure it's still very incomplete as I can't inspect the state of registers. The important bits: halting the CPU, dumping memory to file and write to flash from a file seem to work though. In the openocd telnet shell - halting:
  </p>
  <pre>
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
&gt; targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* bcm6348.cpu        mips_m4k   big    bcm6348.cpu        running
&gt; halt
target state: halted
target halted in MIPS32 mode due to debug-request, pc: 0x00000000
&gt; targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0* bcm6348.cpu        mips_m4k   big    bcm6348.cpu        halted
  </pre>
  <p>
Dumping the boot loader:
  </p>
  <pre>
&gt; dump_image bootloader 0x1fc00000 0x00020000
dumped 131072 bytes in 465.079559s (0.275 KiB/s)
  </pre>
  <p>
Restoring the boot loader:
  </p>
  <pre>
&gt; flash write_image bootloader 0x1fc00000          
No working memory available. Specify -work-area-phys to target.
not enough working area available(requested 140)
Programming at 0x1fc00000, count 0x00020000 bytes remaining
Programming at 0x1fc00100, count 0x0001ff00 bytes remaining
Programming at 0x1fc00200, count 0x0001fe00 bytes remaining

...
  </pre>
  <p>
  To final test, I zero'd out the first couple of K of the bootloader and cycled the power; device was now bricked. Nothing on the serial console and two of the LEDs wedged on. I used openocd to halt the CPU and then flash the bootloader back @ 0x1fc00000 - this took a couple of attempts and found the flash worked best when the CPU was halted as soon as possible after power on. When the flash was finished the device booted perfectly into RedBoot and then onto openwrt.
  </p>
  <image src="/posts.assets/btv220v_jtag1.jpg"/>
  <p>
  This is another BCM6348 based device, a BT Voyager 220V. Before attempting to install openwrt on it, I added the seven pin header to expose the JTAG pins and dumped the bootloader - just in case. Wasn't needed as it turned out as the CFE lets you flash openwrt images anyway.
  </p>
</post></xml>
