2 # GoodFET ARM Debugging Interface v5 (ADIv5) Client Library.
3 # the ideal interface to pwning ARM Cortex
5 # Contributions and bug reports welcome.
9 import sys, binascii, struct, time
10 import atlasutils.smartprint as asp
11 from GoodFET import GoodFET
12 from intelhex import IntelHex
28 # ARM7TDMI JTAG commands
36 # Really ARM specific stuff
43 #4-bit ARM JTAG INSTRUCTIONS - STANDARD
52 #4-bit ARM JTAG INSTRUCTIONS - IMPLEMENTATION-DEFINED
76 0: ("UNKNOWN, MESSED UP PROCESSOR MODE","fsck", "This should Never happen. MCU is in funky state!"),
77 PM_usr: ("User Processor Mode", "usr", "Normal program execution mode"),
78 PM_fiq: ("FIQ Processor Mode", "fiq", "Supports a high-speed data transfer or channel process"),
79 PM_irq: ("IRQ Processor Mode", "irq", "Used for general-purpose interrupt handling"),
80 PM_svc: ("Supervisor Processor Mode", "svc", "A protected mode for the operating system"),
81 PM_abt: ("Abort Processor Mode", "abt", "Implements virtual memory and/or memory protection"),
82 PM_und: ("Undefined Processor Mode", "und", "Supports software emulation of hardware coprocessor"),
83 PM_sys: ("System Processor Mode", "sys", "Runs privileged operating system tasks (ARMv4 and above)"),
87 None, None, None, None, None, "Thumb", "nFIQ_int", "nIRQ_int",
88 "nImprDataAbort_int", "BIGendian", None, None, None, None, None, None,
89 "GE_0", "GE_1", "GE_2", "GE_3", None, None, None, None,
90 "Jazelle", None, None, "Q (DSP-overflow)", "oVerflow", "Carry", "Zero", "Neg",
93 ARM_INSTR_NOP = 0xe1a00000L
94 ARM_INSTR_BX_R0 = 0xe12fff10L
95 ARM_INSTR_STR_Rx_r14 = 0xe58f0000L # from atmel docs
96 ARM_READ_REG = ARM_INSTR_STR_Rx_r14
97 ARM_INSTR_LDR_Rx_r14 = 0xe59f0000L # from atmel docs
98 ARM_WRITE_REG = ARM_INSTR_LDR_Rx_r14
99 ARM_INSTR_LDR_R1_r0_4 = 0xe4901004L
100 ARM_READ_MEM = ARM_INSTR_LDR_R1_r0_4
101 ARM_INSTR_STR_R1_r0_4 = 0xe4801004L
102 ARM_WRITE_MEM = ARM_INSTR_STR_R1_r0_4
103 ARM_INSTR_MRS_R0_CPSR = 0xe10f0000L
104 ARM_INSTR_MSR_cpsr_cxsf_R0 =0xe12ff000L
105 ARM_INSTR_STMIA_R14_r0_rx = 0xE88e0000L # add up to 65k to indicate which registers...
106 ARM_INSTR_LDMIA_R14_r0_rx = 0xE89e0000L # add up to 65k to indicate which registers...
107 ARM_STORE_MULTIPLE = ARM_INSTR_STMIA_R14_r0_rx
108 ARM_INSTR_SKANKREGS = 0xE88F7fffL
109 ARM_INSTR_CLOBBEREGS = 0xE89F7fffL
111 ARM_INSTR_B_IMM = 0xea000000L
112 ARM_INSTR_B_PC = 0xea000000L
113 ARM_INSTR_BX_PC = 0xe1200010L # need to set r0 to the desired address
114 THUMB_INSTR_LDR_R0_r0 = 0x68006800L
115 THUMB_WRITE_REG = THUMB_INSTR_LDR_R0_r0
116 THUMB_INSTR_STR_R0_r0 = 0x60006000L
117 THUMB_READ_REG = THUMB_INSTR_STR_R0_r0
118 THUMB_INSTR_MOV_R0_PC = 0x46b846b8L
119 THUMB_INSTR_MOV_PC_R0 = 0x46474647L
120 THUMB_INSTR_BX_PC = 0x47784778L
121 THUMB_INSTR_NOP = 0x1c001c00L
122 THUMB_INSTR_B_IMM = 0xe000e000L
126 LDM_BITMASKS = [(1<<x)-1 for x in xrange(16)]
129 CSYSPWRUPACK_BIT = 31
131 CSYSPWRUPREQ_BIT = 30
133 CDBGPWRUPACK_BIT = 29
135 CDBGPWRUPREQ_BIT = 28
161 print >>sys.stderr,(strng)
162 def PSRdecode(psrval):
163 output = [ "(%s mode)"%proc_modes[psrval&0x1f][1] ]
164 for x in xrange(5,32):
166 output.append(PSR_bits[x])
167 return " ".join(output)
169 fmt = ["B", "B", "<H", "<L", "<L", "<Q", "<Q", "<Q", "<Q"]
171 s = struct.pack(fmt[byts], val)
172 return [ord(b) for b in s ][:byts]
174 class GoodFETADIv5(GoodFET):
175 """A GoodFET variant for use with ARM7TDMI microprocessor."""
177 GoodFET.__init__(self)
178 self.storedPC = 0xffffffff
179 self.current_dbgstate = 0xffffffff
180 self.flags = 0xffffffff
181 self.nothing = 0xffffffff
182 self.ir_status = None
183 self.ap_selected = None
191 """Move the FET into the JTAG ARM application."""
192 #print "Initializing ARM."
193 self.writecmd(0x14,SETUP,0,self.data)
196 return self.ADIgetPC()
198 def flash(self,file):
199 """Flash an intel hex file to code memory."""
200 print "Flash not implemented.";
202 def dump(self,file,start=0,stop=0xffff):
203 """Dump an intel hex file from code memory."""
204 print "Dump not implemented.";
207 """Get an ARM's ID."""
208 raise Exception("Not Implemented. Abstract base class method called.")
209 def ADIidentstr(self):
210 ident=self.ADIident()
212 partno = (ident >> 12) & 0xffff
213 mfgid = (ident >> 1) & 0x7ff
214 return "Chip IDCODE: 0x%x\n\tver: %x\n\tpartno: %x\n\tmfgid: %x\n" % (ident, ver, partno, mfgid);
216 def ADIget_register(self, reg):
217 """Get an ARM's Register"""
218 self.writecmd(0x14,GET_REGISTER,1,[reg&0xf])
219 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
221 def ADIset_register(self, reg, val):
222 """Get an ARM's Register"""
223 self.writecmd(0x14,SET_REGISTER,8,[val&0xff, (val>>8)&0xff, (val>>16)&0xff, val>>24, reg,0,0,0])
224 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
226 def ADIget_registers(self):
227 """Get ARM Registers"""
228 regs = [ self.ADIget_register(x) for x in range(15) ]
229 regs.append(self.ADIgetPC()) # make sure we snag the "static" version of PC
231 def ADIset_registers(self, regs, mask):
232 """Set ARM Registers"""
235 self.ADIset_register(x,regs.pop(0))
236 if (1<<15) & mask: # make sure we set the "static" version of PC or changes will be lost
237 self.ADIsetPC(regs.pop(0))
239 def ADIrestart(self):
240 raise Exception("Not Implemented. Abstract base class method called.")
242 ####### Common DP features #######
243 def ADIgetAPACC(self, addr, flags): # candidate for firmware. not sure the intelligence wants to be there, but performance may want it.
244 raise Exception("Not Implemented. Abstract base class method called.")
245 def ADIsetAPACC(self, addr, val):
246 raise Exception("Not Implemented. Abstract base class method called.")
247 def ADIgetDPACC(self, addr, flags): # candidate for firmware. not sure the intelligence wants to be there, but performance may want it.
248 raise Exception("Not Implemented. Abstract base class method called.")
249 def ADIsetDPACC(self, addr, val):
250 raise Exception("Not Implemented. Abstract base class method called.")
251 def ADIsetABORT(self):
252 """ ONLY use if the debugger has received WAIT responses over an extended period"""
253 raise Exception("Not Implemented. Abstract base class method called.")
255 def ADIsetSELECT(self, num):
256 return self.ADIsetDPACC(0x8, num)
257 def ADIgetSELECT(self):
258 return self.ADIgetDPACC(0x8)
259 def ADIgetSELECTrepr(self):
260 raw = self.ADIgetSELECT()
262 apbanksel = (raw>>4) & 0xf
264 return "SWDP_CTRLSEL = %d\nAPBANKSEL = %d\nAPSEL = %d\n"
266 def ADIgetAccessPorts(self):
268 self.aps = [createAP(self, x) for x in xrange(MAX_AP_COUNT)]
271 def ADIgetWCR(self): # SWDP only
272 raise Exception("IMPLEMENT ME: ADIgetWCR")
274 def ADIgetRESEND(self): # SWDP only
275 raise Exception("IMPLEMENT ME: ADIgetRESEND")
277 class GoodFETADIjtag(GoodFETADIv5):
278 """A GoodFET variant for use with ARM7TDMI microprocessor."""
279 def ADIshift_IR(self, IR, noretidle=0):
280 if (self.ir_status != IR):
281 self.writecmd(0x14,IR_SHIFT,2, [IR, LSB|noretidle])
284 def ADIshift_DR(self, bignum, bits, flags=0):
285 data = [bits&0xff, flags&0xff,0,0]
286 data.extend(chop(data, bits/4))
287 self.writecmd(0x14,DR_SHIFT, len(data), data)
290 """Get an ARM's ID."""
291 self.ADIshift_IR(IR_IDCODE,0)
292 self.ADIshift_DR(0,32,LSB)
293 retval = struct.unpack("<L", "".join(self.data[0:4]))[0]
296 def ADIdebuginstr(self,instr,bkpt):
297 """if type (instr) == int or type(instr) == long:
298 instr = struct.pack("<L", instr)
299 instr = [int("0x%x"%ord(x),16) for x in instr]
301 self.writecmd(0x14,DEBUG_INSTR,len(instr),instr)
302 return (self.data)"""
304 def ADI_nop(self, bkpt=0):
305 """if self.status() & DBG_TBIT:
306 return self.ADIdebuginstr(THUMB_INSTR_NOP, bkpt)
307 return self.ADIdebuginstr(ARM_INSTR_NOP, bkpt)"""
310 def ADIrestart(self):
311 self.ADIshift_IR(IR_RESTART)
313 ####### Common DP features #######
314 def ADIgetAPACC(self, addr): # candidate for firmware. not sure the intelligence wants to be there, but performance may want it.
315 self.ADIshift_IR(IR_APACC)
316 data = 1 | (addr>>1) # addr[3:2] goes in bits [2:1]. this *must* be a multiple of 4.
317 return self.ADIshift_DR(data, 35, LSB)
318 def ADIsetAPACC(self, addr, val):
321 addr == 4*n (ie. multiple of four, returns the word at that register)
323 self.ADIshift_IR(IR_APACC)
324 data = (val<<3) | (addr>>1) # addr[3:2] goes in bits [2:1]. this *must* be a multiple of 4.
325 self.ADIshift_DR(data, 35, LSB)
326 def ADIgetDPACC(self, addr, flags): # candidate for firmware. not sure the intelligence wants to be there, but performance may want it.
327 self.ADIshift_IR(IR_DPACC)
328 data = 1 | (addr>>1) # addr[3:2] goes in bits [2:1]. this *must* be a multiple of 4.
329 return self.ADIshift_DR(data, 35, LSB)
330 def ADIsetDPACC(self, addr, val):
333 addr == 4*n (ie. multiple of four, returns the word at that register)
335 self.ADIshift_IR(IR_DPACC)
336 data = (val<<3) | (addr>>1) # addr[3:2] goes in bits [2:1]. this *must* be a multiple of 4.
337 self.ADIshift_DR(data, 35, LSB)
339 def ADIsetABORT(self):
340 """ ONLY use if the debugger has received WAIT responses over an extended period"""
341 self.ADIshift_IR(self, IR_ABORT)
342 self.ADIshift_DR(self, 1, 35)
344 def ADIsetSELECT(self, apnum, apbank, flags="ignored for jtag"):
345 if (apnum != self.ap_selected or apbank != self.ap_bank):
346 select = (apnum<<24) | (apbank<<4)
347 self.ADIsetDPACC(0x8, select)
348 self.ap_selected = apnum
349 self.ap_bank = apbank
350 def ADIgetSELECT(self, noncached=False):
352 return self.ADIgetDPACC(0x8)
353 return self.ap_selected
355 def createAP(dp, apnum):
358 self.dp.ADIsetSELECT(self.apnum, bank)
359 ident = self.dp.ADIgetAPACC(idr&0xf)
361 return ADI_MEM_AP(dp, apnum)
362 return ADI_JTAG_AP(dp, apnum)
364 class ADI_AccessPort: # define common AP calls
365 def __init__(self, DP, apnum):
366 self.dp = DP # link to parent. all calls should use this to access the underlying debug port.
367 self.apnum = apnum # which AP am i to this DP?
369 def getRegister(self, bank, off):
370 self.dp.ADIsetSELECT(self.apnum, bank)
371 return self.dp.ADIgetAPACC(off)
373 def getRegisterByAddr(self, addr):
375 self.dp.ADIsetSELECT(self.apnum, bank)
376 return self.dp.ADIgetAPACC(addr&0xf)
378 def getIdentRegister(self):
379 ident = self.getRegisterByAddr(0xfc)
382 def getIdentRegisterrepr(self):
383 raw = self.getIdentRegister()
385 jep_cont = (raw>>24) & 0xf
386 jep_ident = (raw>>17) & 0x7f
387 ap_class = (raw>>16) & 1
388 ap_ident = raw & 0xff
389 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])
392 class ADI_MEM_AP(ADI_AccessPort):
401 MEMAP_BASE_REG = 0xF8
404 def __init__(self, DP, apnum):
405 ADI_AccessPort.__init__(self, DP, apnum)
406 self.cfg = self.getCFG() # necessary to cache endianness information
407 # FIXME: how do i determine if this adi supports multibyte access or just word? or packed transfers?
408 self.setMemAccessSize(4)
411 """ Control/Status Word reg """
412 return self.getRegister(self.MEMAP_CSW_REG)
413 def setCSW(self, csw):
414 """ Control/Status Word reg. Some bits are RO """
415 return self.setRegister(self.MEMAP_CSW_REG, csw)
421 """ Transfer Address Register. Used for both DRW and BDx accesses. Autoinc (see CSW) only works for DRW accesses, not Banked Regs"""
422 return self.getRegister(self.MEMAP_TAR_REG)
423 def setTAR(self, tar):
424 """ Transfer Address Register. Used for both DRW and BDx accesses. Autoinc (see CSW) only works for DRW accesses, not Banked Regs"""
425 return self.setRegister(self.MEMAP_TAR_REG, tar)
428 """ Data Read/Write reg. """
429 return self.getRegister(self.MEMAP_DRW_REG)
430 def setDRW(self, drw):
431 """ Data Read/Write reg. """
432 return self.setRegister(self.MEMAP_DRW_REG, drw)
434 #FIXME: use one set of accessors... either keep the indexed version or the individuals.
435 def getBDReg(self, index):
436 return self.getRegister(self.MEMAP_BD0_REG + (index*4))
437 def setBDReg(self, index, bd):
438 return self.setRegister(self.MEMAP_BD0_REG + (index*4), bd0)
441 return self.getRegister(self.MEMAP_BD0_REG)
442 def setBD0(self, bd0):
443 return self.setRegister(self.MEMAP_BD0_REG, bd0)
446 return self.getRegister(self.MEMAP_BD1_REG)
447 def setBD1(self, bd1):
448 return self.setRegister(self.MEMAP_BD1_REG, bd1)
451 return self.getRegister(self.MEMAP_BD2_REG)
452 def setBD2(self, bd2):
453 return self.setRegister(self.MEMAP_BD2_REG, bd2)
456 return self.getRegister(self.MEMAP_BD3_REG)
457 def setBD3(self, bd3):
458 return self.setRegister(self.MEMAP_BD3_REG, bd3)
461 return self.getRegister(self.MEMAP_CFG_REG)
462 def setCFG(self, cfg):
463 return self.setRegister(self.MEMAP_CFG_REG, cfg)
466 """ BASE debug address. RO """
467 return self.getRegister(self.MEMAP_BASE_REG)
468 def setBASE(self, base):
469 """ BASE debug address. RO """
470 return self.setRegister(self.MEMAP_BASE_REG, base)
473 return self.getRegister(self.MEMAP_IDR_REG)
476 CFG_DBGSWENABLE_BITS = 31
477 CFG_DBGSWENABLE = 1<<31
484 CFG_TRINPROG_BITS = 7
486 CFG_DEVICEEN_BITS = 6
492 CFG_ADDRINC_off = 0b00
493 CFG_ADDRINC_single = 0b01
494 CFG_ADDRINC_packed = 0b10
495 CFG_MEM_8bits = 0b000
496 CFG_MEM_16bits = 0b001
497 CFG_MEM_32bits = 0b010
498 def CSWsetDbgSwEnable(self, bit):
499 cfg = self.getCFG() & self.CFG_DBGSWENABLE
500 cfg |= (bit<<self.CFG_DBGSWENABLE_BITS)
501 def CSWgetDbgSwEnable(self):
502 cfg = (self.getCFG() & self.CFG_DBGSWENABLE) >> self.CFG_DBGSWENABLE_BITS
505 def CSWsetAddrInc(self, bits=CFG_ADDRINC_single):
506 cfg = (self.getCFG() & self.CFG_ADDRINC) >> self.CFG_ADDRINC_BITS
507 cfg |= (bit<<self.CFG_DBGSWENABLE_BITS)
508 def CSWsetMemAccessSize(self, bytecount=self.CSW_MEM_32bits): # 0b010 == 32bit words, necessary if the implementation allows for variable sizes
511 csw |= (bytecount>>1)