<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/sodnpoo.xsl"?>
<xml>
<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>
</xml>

