ember toys not necessary here.
[goodfet] / client / GoodFETADIv5.py
1 #!/usr/bin/env python
2 # GoodFET ARM Debugging Interface v5 (ADIv5) Client Library.
3 # the ideal interface to pwning ARM Cortex
4
5 # Contributions and bug reports welcome.
6 #
7
8
9 import sys, binascii, struct, time
10 import atlasutils.smartprint as asp
11 from GoodFET import GoodFET
12 from intelhex import IntelHex
13
14
15 #Global Commands
16 READ  = 0x00
17 WRITE = 0x01
18 PEEK  = 0x02
19 POKE  = 0x03
20 SETUP = 0x10
21 START = 0x20
22 STOP  = 0x21
23 CALL  = 0x30
24 EXEC  = 0x31
25 NOK   = 0x7E
26 OK    = 0x7F
27
28 # ARM7TDMI JTAG commands
29 IR_SHIFT =              0x80
30 DR_SHIFT =              0x81
31 RESETTAP =              0x82
32 RESETTARGET =           0x83
33 GET_REGISTER =          0x87
34 SET_REGISTER =          0x88
35 DEBUG_INSTR =           0x89
36 # Really ARM specific stuff
37 WAIT_DBG =              0x91
38 CHAIN0 =                0x93
39 SCANCHAIN1 =            0x94
40 EICE_READ =             0x95
41 EICE_WRITE =            0x96
42
43 #4-bit ARM JTAG INSTRUCTIONS - STANDARD
44 IR_ABORT =              0x8
45 IR_RESERVED1 =          0x9
46 IR_DPACC =              0xA
47 IR_APACC =              0xB
48 IR_RESERVED2 =          0xC
49 IR_RESERVED3 =          0xD
50 IR_IDCODE =             0xE
51 IR_BYPASS =             0xF
52 #4-bit ARM JTAG INSTRUCTIONS - IMPLEMENTATION-DEFINED
53 IR_EXTEST =             0x0
54 IR_SAMPLE =             0x1
55 IR_PRELOAD =            0x2
56 IR_RESERVED =           0x3
57 IR_INTEST =             0x4
58 IR_CLAMP =              0x5
59 IR_HIGHZ =              0x6
60 IR_CLAMPZ =             0x7
61
62 DP_CTRLSTAT_OFF =       0x4
63 DP_SELECT_OFF =         0x8
64 DP_RDBUFF_OFF =         0xC
65
66 PM_usr = 0b10000
67 PM_fiq = 0b10001
68 PM_irq = 0b10010
69 PM_svc = 0b10011
70 PM_abt = 0b10111
71 PM_und = 0b11011
72 PM_sys = 0b11111
73 proc_modes = {
74     0:      ("UNKNOWN, MESSED UP PROCESSOR MODE","fsck", "This should Never happen.  MCU is in funky state!"),
75     PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
76     PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"),
77     PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"),
78     PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"),
79     PM_abt: ("Abort Processor Mode", "abt", "Implements virtual memory and/or memory protection"),
80     PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"),
81     PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"),
82 }
83
84 PSR_bits = [ 
85     None, None, None, None, None, "Thumb", "nFIQ_int", "nIRQ_int", 
86     "nImprDataAbort_int", "BIGendian", None, None, None, None, None, None, 
87     "GE_0", "GE_1", "GE_2", "GE_3", None, None, None, None, 
88     "Jazelle", None, None, "Q (DSP-overflow)", "oVerflow", "Carry", "Zero", "Neg",
89     ]
90
91 ARM_INSTR_NOP =             0xe1a00000L
92 ARM_INSTR_BX_R0 =           0xe12fff10L
93 ARM_INSTR_STR_Rx_r14 =      0xe58f0000L # from atmel docs
94 ARM_READ_REG =              ARM_INSTR_STR_Rx_r14
95 ARM_INSTR_LDR_Rx_r14 =      0xe59f0000L # from atmel docs
96 ARM_WRITE_REG =             ARM_INSTR_LDR_Rx_r14
97 ARM_INSTR_LDR_R1_r0_4 =     0xe4901004L
98 ARM_READ_MEM =              ARM_INSTR_LDR_R1_r0_4
99 ARM_INSTR_STR_R1_r0_4 =     0xe4801004L
100 ARM_WRITE_MEM =             ARM_INSTR_STR_R1_r0_4
101 ARM_INSTR_MRS_R0_CPSR =     0xe10f0000L
102 ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
103 ARM_INSTR_STMIA_R14_r0_rx = 0xE88e0000L      # add up to 65k to indicate which registers...
104 ARM_INSTR_LDMIA_R14_r0_rx = 0xE89e0000L      # add up to 65k to indicate which registers...
105 ARM_STORE_MULTIPLE =        ARM_INSTR_STMIA_R14_r0_rx
106 ARM_INSTR_SKANKREGS =       0xE88F7fffL
107 ARM_INSTR_CLOBBEREGS =      0xE89F7fffL
108
109 ARM_INSTR_B_IMM =           0xea000000L
110 ARM_INSTR_B_PC =            0xea000000L
111 ARM_INSTR_BX_PC =           0xe1200010L      # need to set r0 to the desired address
112 THUMB_INSTR_LDR_R0_r0 =     0x68006800L
113 THUMB_WRITE_REG =           THUMB_INSTR_LDR_R0_r0
114 THUMB_INSTR_STR_R0_r0 =     0x60006000L
115 THUMB_READ_REG =            THUMB_INSTR_STR_R0_r0
116 THUMB_INSTR_MOV_R0_PC =     0x46b846b8L
117 THUMB_INSTR_MOV_PC_R0 =     0x46474647L
118 THUMB_INSTR_BX_PC =         0x47784778L
119 THUMB_INSTR_NOP =           0x1c001c00L
120 THUMB_INSTR_B_IMM =         0xe000e000L
121 ARM_REG_PC =                15
122
123
124 LDM_BITMASKS = [(1<<x)-1 for x in xrange(16)]
125
126 CSYSPWRUPACK =              1<<31
127 CSYSPWRUPACK_BIT =          31
128 CSYSPWRUPREQ =              1<<30
129 CSYSPWRUPREQ_BIT =          30
130 CDBGPWRUPACK =              1<<29
131 CDBGPWRUPACK_BIT =          29
132 CDBGPWRUPREQ =              1<<28
133 CDBGPWRUPREQ_BIT =          28
134 CSYSRSTACK =                1<<27
135 CSYSRSTACK_BIT =            27
136 CSYSRSTREQ =                1<<26
137 CSYSRSTREQ_BIT =            26
138 TRNCNT =                    0x3ff<<12
139 TRNCNT_BIT =                12
140 MASKLANE =                  0xf<<8
141 MASKLANE_BIT =              8
142 WDATAERR =                  1<<7
143 WDATAERR =                  1<<7
144 READOK =                    1<<6
145 READOK =                    1<<6
146 STICKYERR =                 1<<5
147 STICKYERR =                 1<<5
148 STICKYCMP =                 1<<4
149 STICKYCMP =                 1<<4
150 TRNMODE =                   3<<2
151 TRNMODE =                   3<<2
152 STICKYORUN =                1<<1
153 STICKYORUN =                1<<1
154 ORUNDETECT =                1<<0
155 ORUNDETECT =                1<<0
156
157
158
159 def debugstr(strng):
160     print >>sys.stderr,(strng)
161 def PSRdecode(psrval):
162     output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
163     for x in xrange(5,32):
164         if psrval & (1<<x):
165             output.append(PSR_bits[x])
166     return " ".join(output)
167    
168 fmt = ["B", "B", "<H", "<L", "<L", "<Q", "<Q", "<Q", "<Q"]
169 def chop(val,byts):
170     s = struct.pack(fmt[byts], val)
171     return [ord(b) for b in s ][:byts]
172         
173 class GoodFETADIv5(GoodFET):
174     """A GoodFET variant for use with ARM7TDMI microprocessor."""
175     def __init__(self):
176         GoodFET.__init__(self)
177         self.storedPC =         0xffffffff
178         self.current_dbgstate = 0xffffffff
179         self.flags =            0xffffffff
180         self.nothing =          0xffffffff
181         self.ir_status =        None
182         self.ap_selected =      None
183         self.ap_bank =          0
184         self.aps =              []
185
186     def __del__(self):
187         pass
188
189     def setup(self):
190         """Move the FET into the JTAG ARM application."""
191         #print "Initializing ARM."
192         self.writecmd(0x14,SETUP,0,self.data)
193
194     def getpc(self):
195         return self.ADIgetPC()
196
197     def flash(self,file):
198         """Flash an intel hex file to code memory."""
199         print "Flash not implemented.";
200
201     def dump(self,file,start=0,stop=0xffff):
202         """Dump an intel hex file from code memory."""
203         print "Dump not implemented.";
204
205     def ADIident(self):
206         """Get an ARM's ID."""
207         raise Exception("Not Implemented.  Abstract base class method called.")
208     def ADIidentstr(self):
209         ident=self.ADIident()
210         ver     = (ident >> 28)
211         partno  = (ident >> 12) & 0xffff
212         mfgid   = (ident >> 1)  & 0x7ff
213         return "Chip IDCODE: 0x%x\n\tver: %x\n\tpartno: %x\n\tmfgid: %x\n" % (ident, ver, partno, mfgid); 
214
215     def ADIget_register(self, reg):
216         """Get an ARM's Register"""
217         self.writecmd(0x14,GET_REGISTER,1,[reg&0xf])
218         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
219         return retval
220     def ADIset_register(self, reg, val):
221         """Get an ARM's Register"""
222         self.writecmd(0x14,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
223         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
224         return retval
225     def ADIget_registers(self):
226         """Get ARM Registers"""
227         regs = [ self.ADIget_register(x) for x in range(15) ]
228         regs.append(self.ADIgetPC())            # make sure we snag the "static" version of PC
229         return regs
230     def ADIset_registers(self, regs, mask):
231         """Set ARM Registers"""
232         for x in xrange(15):
233           if (1<<x) & mask:
234             self.ADIset_register(x,regs.pop(0))
235         if (1<<15) & mask:                      # make sure we set the "static" version of PC or changes will be lost
236           self.ADIsetPC(regs.pop(0))
237
238     def ADIrestart(self):
239         raise Exception("Not Implemented.  Abstract base class method called.")
240
241     ####### Common DP features #######
242     def ADIgetAPACC(self, addr, flags):         # candidate for firmware.  not sure the intelligence wants to be there, but performance may want it.
243         raise Exception("Not Implemented.  Abstract base class method called.")
244     def ADIsetAPACC(self, addr, val):
245         raise Exception("Not Implemented.  Abstract base class method called.")
246     def ADIgetDPACC(self, addr, flags):         # candidate for firmware.  not sure the intelligence wants to be there, but performance may want it.
247         raise Exception("Not Implemented.  Abstract base class method called.")
248     def ADIsetDPACC(self, addr, val):
249         raise Exception("Not Implemented.  Abstract base class method called.")
250     def ADIsetABORT(self):
251         """ ONLY use if the debugger has received WAIT responses over an extended period"""
252         raise Exception("Not Implemented.  Abstract base class method called.")
253
254     def ADIsetSELECT(self, num):
255         return self.ADIsetDPACC(0x8, num)
256     def ADIgetSELECT(self):
257         return self.ADIgetDPACC(0x8)
258     def ADIgetSELECTrepr(self):
259         raw = self.ADIgetSELECT()
260         swdp_ctrlsel = raw&1
261         apbanksel = (raw>>4) & 0xf
262         apsel = raw>>24
263         return "SWDP_CTRLSEL = %d\nAPBANKSEL = %d\nAPSEL = %d\n"
264
265     def ADIgetWCR(self):        # SWDP only
266         raise Exception("IMPLEMENT ME: ADIgetWCR")
267
268     def ADIgetRESEND(self):     # SWDP only
269         raise Exception("IMPLEMENT ME: ADIgetRESEND")
270
271 class GoodFETADIjtag(GoodFETADIv5):
272     """A GoodFET variant for use with ARM7TDMI microprocessor."""
273     def ADIshift_IR(self, IR, noretidle=0):
274         if (self.ir_status != IR):
275             self.writecmd(0x14,IR_SHIFT,2, [IR, LSB|noretidle])
276             self.ir_status = IR
277         return self.data
278     def ADIshift_DR(self, bignum, bits, flags=0):
279         data = [bits&0xff, flags&0xff,0,0]
280         data.extend(chop(data, bits/4))
281         self.writecmd(0x14,DR_SHIFT, len(data), data)
282         return self.data
283     def ADIident(self):
284         """Get an ARM's ID."""
285         self.ADIshift_IR(IR_IDCODE,0)
286         self.ADIshift_DR(0,32,LSB)
287         retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
288         return retval
289
290     def ADIdebuginstr(self,instr,bkpt):
291         """if type (instr) == int or type(instr) == long:
292             instr = struct.pack("<L", instr)
293         instr = [int("0x%x"%ord(x),16) for x in instr]
294         instr.extend([bkpt])
295         self.writecmd(0x14,DEBUG_INSTR,len(instr),instr)
296         return (self.data)"""
297         pass
298     def ADI_nop(self, bkpt=0):
299         """if self.status() & DBG_TBIT:
300             return self.ADIdebuginstr(THUMB_INSTR_NOP, bkpt)
301         return self.ADIdebuginstr(ARM_INSTR_NOP, bkpt)"""
302         pass
303
304     def ADIrestart(self):
305         self.ADIshift_IR(IR_RESTART)
306
307     ####### Common DP features #######
308     def ADIgetAPACC(self, addr):                # candidate for firmware.  not sure the intelligence wants to be there, but performance may want it.
309         self.ADIshift_IR(IR_APACC)
310         data = 1 | (addr>>1)                    # addr[3:2] goes in bits [2:1].  this *must* be a multiple of 4.
311         return self.ADIshift_DR(data, 35, LSB)
312     def ADIsetAPACC(self, addr, val):
313         """
314         0 < val < 0xffffffff
315         addr == 4*n   (ie.  multiple of four, returns the word at that register)
316         """
317         self.ADIshift_IR(IR_APACC)
318         data = (val<<3) | (addr>>1)             # addr[3:2] goes in bits [2:1].  this *must* be a multiple of 4.
319         self.ADIshift_DR(data, 35, LSB)
320     def ADIgetDPACC(self, addr, flags):         # candidate for firmware.  not sure the intelligence wants to be there, but performance may want it.
321         self.ADIshift_IR(IR_DPACC)
322         data = 1 | (addr>>1)                    # addr[3:2] goes in bits [2:1].  this *must* be a multiple of 4.
323         return self.ADIshift_DR(data, 35, LSB)
324     def ADIsetDPACC(self, addr, val):
325         """
326         0 < val < 0xffffffff
327         addr == 4*n   (ie.  multiple of four, returns the word at that register)
328         """
329         self.ADIshift_IR(IR_DPACC)
330         data = (val<<3) | (addr>>1)             # addr[3:2] goes in bits [2:1].  this *must* be a multiple of 4.
331         self.ADIshift_DR(data, 35, LSB)
332
333     def ADIsetABORT(self):
334         """ ONLY use if the debugger has received WAIT responses over an extended period"""
335         self.ADIshift_IR(self, IR_ABORT)
336         self.ADIshift_DR(self, 1, 35)
337
338     def ADIsetSELECT(self, apnum, apbank, flags="ignored for jtag"):
339         if (apnum != self.ap_selected or apbank != self.ap_bank):
340             select = (apnum<<24) | (apbank<<4)
341             self.ADIsetDPACC(0x8, select)
342             self.ap_selected = apnum
343             self.ap_bank = apbank
344     def ADIgetSELECT(self, noncached=False):
345         if (noncached):
346             return self.ADIgetDPACC(0x8)
347         return self.ap_selected
348
349
350
351 class ADI_AccessPort:           # define common AP calls
352     def __init__(self, DP, apnum):
353         self.dp = DP            # link to parent.  all calls should use this to access the underlying debug port.
354         self.apnum = apnum      # which AP am i to this DP?
355
356     def getRegister(self, bank, off):
357         self.dp.ADIsetSELECT(self.apnum, bank)
358         return self.dp.ADIgetAPACC(off)
359
360     def getRegisterByAddr(self, addr):
361         bank = addr/16
362         self.dp.ADIsetSELECT(self.apnum, bank)
363         return self.dp.ADIgetAPACC(addr&0xf)
364
365     def getIdentRegister(self):
366         ident = self.getRegisterByAddr(0xfc)
367         return ident
368
369     def getIdentRegisterrepr(self):
370         raw = self.getIdentRegister()
371         ap_rev = raw>>28
372         jep_cont = (raw>>24) & 0xf
373         jep_ident = (raw>>17) & 0x7f
374         ap_class = (raw>>16) & 1
375         ap_ident = raw & 0xff
376         return "AP Revision: 0x%x\nJEP-106 Continuation Code: 0x%x\nJEP-106 Identity Code: 0x%x\nAP Class: 0x%x\nAP Identification: %x (%s)\n"%(ap_rev,jep_cont,jep_ident,ap_class,ap_ident,AP_IDENT_TYPES[ap_ident&0xf])
377     #def 
378
379 class ADI_MEM_AP(ADI_AccessPort):
380     def __init__(self, DP, apnum):
381         ADI_AccessPort.__init__(self, DP, apnum)
382         self.cfg = self.getCFG()                    # necessary to cache endianness information
383         # FIXME: how do i determine if this adi supports multibyte access or just word?  or packed transfers?
384         self.setMemAccessSize(4)
385
386     def setMemAccessSize(self, bytecount):
387         csw = self.getCSW()
388         csw &= 0xfffffff8
389         csw |= (bytecount>>1)
390         self.setCSW(csw)
391
392     def getCSW(self):
393         pass
394     def setCSW(self, csw):
395         pass
396
397     def getTAR(self):
398         pass
399     def setTAR(self, csw):
400         pass
401
402     def getDRW(self):
403         pass
404     def setDRW(self, csw):
405         pass
406
407     def getBD0(self):
408         pass
409     def setBD0(self, csw):
410         pass
411
412     def getCFG(self):
413         pass
414     def setCFG(self, csw):
415         pass
416
417     def getBASE(self):
418         pass
419     def setBASE(self, csw):
420         pass
421
422     def getIDR(self):
423         pass
424     def setIDR(self, csw):
425         pass