1 /***************************************************************************
2 * Copyright (C) 2005 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2008 by Spencer Oliver *
6 * spen@spen-soft.co.uk *
8 * Copyright (C) 2008 by Oyvind Harboe *
9 * oyvind.harboe@zylin.com *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * GNU General Public License for more details. *
21 * You should have received a copy of the GNU General Public License *
22 * along with this program; if not, write to the *
23 * Free Software Foundation, Inc., *
24 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
25 ***************************************************************************/
32 #include "breakpoints.h"
33 #include "arm_disassembler.h"
34 #include "binarybuffer.h"
35 #include "algorithm.h"
39 static const char *armv4_5_core_reg_list
[] =
41 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
42 "r8", "r9", "r10", "r11", "r12", "r13_usr", "lr_usr", "pc",
44 "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "r13_fiq", "lr_fiq",
54 "cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und",
56 "r13_mon", "lr_mon", "spsr_mon",
63 /* Seven modes are standard from ARM7 on. "System" and "User" share
64 * the same registers; other modes shadow from 3 to 8 registers.
68 .psr
= ARMV4_5_MODE_USR
,
72 .psr
= ARMV4_5_MODE_FIQ
,
76 .psr
= ARMV4_5_MODE_SVC
,
80 .psr
= ARMV4_5_MODE_ABT
,
84 .psr
= ARMV4_5_MODE_IRQ
,
87 .name
= "Undefined" /* instruction */,
88 .psr
= ARMV4_5_MODE_UND
,
92 .psr
= ARMV4_5_MODE_SYS
,
94 /* TrustZone "Security Extensions" add a secure monitor mode.
95 * This is distinct from a "debug monitor" which can support
96 * non-halting debug, in conjunction with some debuggers.
99 .name
= "Secure Monitor",
104 /** Map PSR mode bits to the name of an ARM processor operating mode. */
105 const char *arm_mode_name(unsigned psr_mode
)
107 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
108 if (arm_mode_data
[i
].psr
== psr_mode
)
109 return arm_mode_data
[i
].name
;
111 LOG_ERROR("unrecognized psr mode: %#02x", psr_mode
);
112 return "UNRECOGNIZED";
115 /** Return true iff the parameter denotes a valid ARM processor mode. */
116 bool is_arm_mode(unsigned psr_mode
)
118 for (unsigned i
= 0; i
< ARRAY_SIZE(arm_mode_data
); i
++) {
119 if (arm_mode_data
[i
].psr
== psr_mode
)
125 /** Map PSR mode bits to linear number indexing armv4_5_core_reg_map */
126 int armv4_5_mode_to_number(enum armv4_5_mode mode
)
129 case ARMV4_5_MODE_ANY
:
130 /* map MODE_ANY to user mode */
131 case ARMV4_5_MODE_USR
:
133 case ARMV4_5_MODE_FIQ
:
135 case ARMV4_5_MODE_IRQ
:
137 case ARMV4_5_MODE_SVC
:
139 case ARMV4_5_MODE_ABT
:
141 case ARMV4_5_MODE_UND
:
143 case ARMV4_5_MODE_SYS
:
148 LOG_ERROR("invalid mode value encountered %d", mode
);
153 /** Map linear number indexing armv4_5_core_reg_map to PSR mode bits. */
154 enum armv4_5_mode
armv4_5_number_to_mode(int number
)
158 return ARMV4_5_MODE_USR
;
160 return ARMV4_5_MODE_FIQ
;
162 return ARMV4_5_MODE_IRQ
;
164 return ARMV4_5_MODE_SVC
;
166 return ARMV4_5_MODE_ABT
;
168 return ARMV4_5_MODE_UND
;
170 return ARMV4_5_MODE_SYS
;
174 LOG_ERROR("mode index out of bounds %d", number
);
175 return ARMV4_5_MODE_ANY
;
179 char* armv4_5_state_strings
[] =
181 "ARM", "Thumb", "Jazelle"
184 static const struct armv4_5_core_reg armv4_5_core_reg_list_arch_info
[] =
186 {0, ARMV4_5_MODE_ANY
, NULL
, NULL
},
187 {1, ARMV4_5_MODE_ANY
, NULL
, NULL
},
188 {2, ARMV4_5_MODE_ANY
, NULL
, NULL
},
189 {3, ARMV4_5_MODE_ANY
, NULL
, NULL
},
190 {4, ARMV4_5_MODE_ANY
, NULL
, NULL
},
191 {5, ARMV4_5_MODE_ANY
, NULL
, NULL
},
192 {6, ARMV4_5_MODE_ANY
, NULL
, NULL
},
193 {7, ARMV4_5_MODE_ANY
, NULL
, NULL
},
194 {8, ARMV4_5_MODE_ANY
, NULL
, NULL
},
195 {9, ARMV4_5_MODE_ANY
, NULL
, NULL
},
196 {10, ARMV4_5_MODE_ANY
, NULL
, NULL
},
197 {11, ARMV4_5_MODE_ANY
, NULL
, NULL
},
198 {12, ARMV4_5_MODE_ANY
, NULL
, NULL
},
199 {13, ARMV4_5_MODE_USR
, NULL
, NULL
},
200 {14, ARMV4_5_MODE_USR
, NULL
, NULL
},
201 {15, ARMV4_5_MODE_ANY
, NULL
, NULL
},
203 {8, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
204 {9, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
205 {10, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
206 {11, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
207 {12, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
208 {13, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
209 {14, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
211 {13, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
212 {14, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
214 {13, ARMV4_5_MODE_SVC
, NULL
, NULL
},
215 {14, ARMV4_5_MODE_SVC
, NULL
, NULL
},
217 {13, ARMV4_5_MODE_ABT
, NULL
, NULL
},
218 {14, ARMV4_5_MODE_ABT
, NULL
, NULL
},
220 {13, ARMV4_5_MODE_UND
, NULL
, NULL
},
221 {14, ARMV4_5_MODE_UND
, NULL
, NULL
},
223 {16, ARMV4_5_MODE_ANY
, NULL
, NULL
},
224 {16, ARMV4_5_MODE_FIQ
, NULL
, NULL
},
225 {16, ARMV4_5_MODE_IRQ
, NULL
, NULL
},
226 {16, ARMV4_5_MODE_SVC
, NULL
, NULL
},
227 {16, ARMV4_5_MODE_ABT
, NULL
, NULL
},
228 {16, ARMV4_5_MODE_UND
, NULL
, NULL
},
230 {13, ARM_MODE_MON
, NULL
, NULL
},
231 {14, ARM_MODE_MON
, NULL
, NULL
},
232 {16, ARM_MODE_MON
, NULL
, NULL
},
235 /* map core mode (USR, FIQ, ...) and register number to indizes into the register cache */
236 const int armv4_5_core_reg_map
[8][17] =
239 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
241 { /* FIQ (8 shadows of USR, vs normal 3) */
242 0, 1, 2, 3, 4, 5, 6, 7, 16, 17, 18, 19, 20, 21, 22, 15, 32
245 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 23, 24, 15, 33
248 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 25, 26, 15, 34
251 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 27, 28, 15, 35
254 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 29, 30, 15, 36
256 { /* SYS (same registers as USR) */
257 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31
260 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 37, 38, 15, 39,
264 static const uint8_t arm_gdb_dummy_fp_value
[12];
267 * Dummy FPA registers are required to support GDB on ARM.
268 * Register packets require eight obsolete FPA register values.
269 * Modern ARM cores use Vector Floating Point (VFP), if they
270 * have any floating point support. VFP is not FPA-compatible.
272 struct reg arm_gdb_dummy_fp_reg
=
274 .name
= "GDB dummy FPA register",
275 .value
= (uint8_t *) arm_gdb_dummy_fp_value
,
280 static const uint8_t arm_gdb_dummy_fps_value
[4];
283 * Dummy FPA status registers are required to support GDB on ARM.
284 * Register packets require an obsolete FPA status register.
286 struct reg arm_gdb_dummy_fps_reg
=
288 .name
= "GDB dummy FPA status register",
289 .value
= (uint8_t *) arm_gdb_dummy_fps_value
,
294 static void arm_gdb_dummy_init(void) __attribute__ ((constructor
));
296 static void arm_gdb_dummy_init(void)
298 register_init_dummy(&arm_gdb_dummy_fp_reg
);
299 register_init_dummy(&arm_gdb_dummy_fps_reg
);
302 static int armv4_5_get_core_reg(struct reg
*reg
)
305 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
306 struct target
*target
= armv4_5
->target
;
308 if (target
->state
!= TARGET_HALTED
)
310 LOG_ERROR("Target not halted");
311 return ERROR_TARGET_NOT_HALTED
;
314 retval
= armv4_5
->armv4_5_common
->read_core_reg(target
, armv4_5
->num
, armv4_5
->mode
);
315 if (retval
== ERROR_OK
)
321 static int armv4_5_set_core_reg(struct reg
*reg
, uint8_t *buf
)
323 struct armv4_5_core_reg
*armv4_5
= reg
->arch_info
;
324 struct target
*target
= armv4_5
->target
;
325 struct armv4_5_common_s
*armv4_5_target
= target_to_armv4_5(target
);
326 uint32_t value
= buf_get_u32(buf
, 0, 32);
328 if (target
->state
!= TARGET_HALTED
)
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED
;
334 if (reg
== &armv4_5_target
->core_cache
->reg_list
[ARMV4_5_CPSR
])
338 /* T bit should be set */
339 if (armv4_5_target
->core_state
== ARMV4_5_STATE_ARM
)
341 /* change state to Thumb */
342 LOG_DEBUG("changing to Thumb state");
343 armv4_5_target
->core_state
= ARMV4_5_STATE_THUMB
;
348 /* T bit should be cleared */
349 if (armv4_5_target
->core_state
== ARMV4_5_STATE_THUMB
)
351 /* change state to ARM */
352 LOG_DEBUG("changing to ARM state");
353 armv4_5_target
->core_state
= ARMV4_5_STATE_ARM
;
357 if (armv4_5_target
->core_mode
!= (enum armv4_5_mode
)(value
& 0x1f))
359 LOG_DEBUG("changing ARM core mode to '%s'",
360 arm_mode_name(value
& 0x1f));
361 armv4_5_target
->core_mode
= value
& 0x1f;
362 armv4_5_target
->write_core_reg(target
, 16, ARMV4_5_MODE_ANY
, value
);
366 buf_set_u32(reg
->value
, 0, 32, value
);
373 static const struct reg_arch_type arm_reg_type
= {
374 .get
= armv4_5_get_core_reg
,
375 .set
= armv4_5_set_core_reg
,
378 /** Marks the contents of the register cache as invalid (and clean). */
379 int armv4_5_invalidate_core_regs(struct target
*target
)
381 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
382 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
383 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
385 for (unsigned i
= 0; i
< num_regs
; i
++, reg
++) {
390 /* FIXME don't bother returning a value then */
394 struct reg_cache
* armv4_5_build_reg_cache(struct target
*target
, struct arm
*armv4_5_common
)
396 int num_regs
= ARRAY_SIZE(armv4_5_core_reg_list_arch_info
);
397 struct reg_cache
*cache
= malloc(sizeof(struct reg_cache
));
398 struct reg
*reg_list
= calloc(num_regs
, sizeof(struct reg
));
399 struct armv4_5_core_reg
*arch_info
= calloc(num_regs
,
400 sizeof(struct armv4_5_core_reg
));
403 if (!cache
|| !reg_list
|| !arch_info
) {
410 cache
->name
= "ARM registers";
412 cache
->reg_list
= reg_list
;
415 for (i
= 0; i
< num_regs
; i
++)
417 /* Skip registers this core doesn't expose */
418 if (armv4_5_core_reg_list_arch_info
[i
].mode
== ARM_MODE_MON
419 && armv4_5_common
->core_type
!= ARM_MODE_MON
)
422 /* REVISIT handle Cortex-M, which only shadows R13/SP */
424 arch_info
[i
] = armv4_5_core_reg_list_arch_info
[i
];
425 arch_info
[i
].target
= target
;
426 arch_info
[i
].armv4_5_common
= armv4_5_common
;
427 reg_list
[i
].name
= (char *) armv4_5_core_reg_list
[i
];
428 reg_list
[i
].size
= 32;
429 reg_list
[i
].value
= calloc(1, 4);
430 reg_list
[i
].type
= &arm_reg_type
;
431 reg_list
[i
].arch_info
= &arch_info
[i
];
439 int armv4_5_arch_state(struct target
*target
)
441 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
443 if (armv4_5
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
445 LOG_ERROR("BUG: called for a non-ARMv4/5 target");
449 LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32
" pc: 0x%8.8" PRIx32
"",
450 armv4_5_state_strings
[armv4_5
->core_state
],
451 Jim_Nvp_value2name_simple(nvp_target_debug_reason
, target
->debug_reason
)->name
,
452 arm_mode_name(armv4_5
->core_mode
),
453 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
454 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
459 #define ARMV4_5_CORE_REG_MODENUM(cache, mode, num) \
460 cache->reg_list[armv4_5_core_reg_map[mode][num]]
462 COMMAND_HANDLER(handle_armv4_5_reg_command
)
467 struct target
*target
= get_current_target(CMD_CTX
);
468 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
470 if (!is_arm(armv4_5
))
472 command_print(CMD_CTX
, "current target isn't an ARM");
476 if (target
->state
!= TARGET_HALTED
)
478 command_print(CMD_CTX
, "error: target must be halted for register accesses");
482 if (!is_arm_mode(armv4_5
->core_mode
))
485 if (!armv4_5
->full_context
) {
486 command_print(CMD_CTX
, "error: target doesn't support %s",
491 for (num
= 0; num
<= 15; num
++)
494 for (mode
= 0; mode
< 6; mode
++)
496 if (!ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).valid
)
498 armv4_5
->full_context(target
);
500 output_len
+= snprintf(output
+ output_len
,
502 "%8s: %8.8" PRIx32
" ",
503 ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).name
,
504 buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5
->core_cache
, mode
, num
).value
, 0, 32));
506 command_print(CMD_CTX
, "%s", output
);
508 command_print(CMD_CTX
,
509 " cpsr: %8.8" PRIx32
" spsr_fiq: %8.8" PRIx32
" spsr_irq: %8.8" PRIx32
" spsr_svc: %8.8" PRIx32
" spsr_abt: %8.8" PRIx32
" spsr_und: %8.8" PRIx32
"",
510 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32),
511 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_FIQ
].value
, 0, 32),
512 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_IRQ
].value
, 0, 32),
513 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_SVC
].value
, 0, 32),
514 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_ABT
].value
, 0, 32),
515 buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_SPSR_UND
].value
, 0, 32));
520 COMMAND_HANDLER(handle_armv4_5_core_state_command
)
522 struct target
*target
= get_current_target(CMD_CTX
);
523 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
525 if (!is_arm(armv4_5
))
527 command_print(CMD_CTX
, "current target isn't an ARM");
533 if (strcmp(CMD_ARGV
[0], "arm") == 0)
535 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
537 if (strcmp(CMD_ARGV
[0], "thumb") == 0)
539 armv4_5
->core_state
= ARMV4_5_STATE_THUMB
;
543 command_print(CMD_CTX
, "core state: %s", armv4_5_state_strings
[armv4_5
->core_state
]);
548 COMMAND_HANDLER(handle_armv4_5_disassemble_command
)
550 int retval
= ERROR_OK
;
551 struct target
*target
= get_current_target(CMD_CTX
);
552 struct arm
*arm
= target
? target_to_arm(target
) : NULL
;
558 command_print(CMD_CTX
, "current target isn't an ARM");
564 if (strcmp(CMD_ARGV
[2], "thumb") != 0)
569 COMMAND_PARSE_NUMBER(int, CMD_ARGV
[1], count
);
572 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
573 if (address
& 0x01) {
575 command_print(CMD_CTX
, "Disassemble as Thumb");
583 command_print(CMD_CTX
,
584 "usage: arm disassemble <address> [<count> ['thumb']]");
589 while (count
-- > 0) {
590 struct arm_instruction cur_instruction
;
593 /* Always use Thumb2 disassembly for best handling
594 * of 32-bit BL/BLX, and to work with newer cores
595 * (some ARMv6, all ARMv7) that use Thumb2.
597 retval
= thumb2_opcode(target
, address
,
599 if (retval
!= ERROR_OK
)
604 retval
= target_read_u32(target
, address
, &opcode
);
605 if (retval
!= ERROR_OK
)
607 retval
= arm_evaluate_opcode(opcode
, address
,
608 &cur_instruction
) != ERROR_OK
;
609 if (retval
!= ERROR_OK
)
612 command_print(CMD_CTX
, "%s", cur_instruction
.text
);
613 address
+= cur_instruction
.instruction_size
;
619 int armv4_5_register_commands(struct command_context
*cmd_ctx
)
621 struct command
*armv4_5_cmd
;
623 armv4_5_cmd
= register_command(cmd_ctx
, NULL
, "arm",
625 "generic ARM commands");
627 register_command(cmd_ctx
, armv4_5_cmd
, "reg",
628 handle_armv4_5_reg_command
, COMMAND_EXEC
,
629 "display ARM core registers");
630 register_command(cmd_ctx
, armv4_5_cmd
, "core_state",
631 handle_armv4_5_core_state_command
, COMMAND_EXEC
,
632 "display/change ARM core state <arm | thumb>");
633 register_command(cmd_ctx
, armv4_5_cmd
, "disassemble",
634 handle_armv4_5_disassemble_command
, COMMAND_EXEC
,
635 "disassemble instructions "
636 "<address> [<count> ['thumb']]");
641 int armv4_5_get_gdb_reg_list(struct target
*target
, struct reg
**reg_list
[], int *reg_list_size
)
643 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
646 if (!is_arm_mode(armv4_5
->core_mode
))
650 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
652 for (i
= 0; i
< 16; i
++)
654 (*reg_list
)[i
] = &ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5
->core_mode
, i
);
657 for (i
= 16; i
< 24; i
++)
659 (*reg_list
)[i
] = &arm_gdb_dummy_fp_reg
;
662 (*reg_list
)[24] = &arm_gdb_dummy_fps_reg
;
663 (*reg_list
)[25] = &armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
];
668 /* wait for execution to complete and check exit point */
669 static int armv4_5_run_algorithm_completion(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
672 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
674 if ((retval
= target_wait_state(target
, TARGET_HALTED
, timeout_ms
)) != ERROR_OK
)
678 if (target
->state
!= TARGET_HALTED
)
680 if ((retval
= target_halt(target
)) != ERROR_OK
)
682 if ((retval
= target_wait_state(target
, TARGET_HALTED
, 500)) != ERROR_OK
)
686 return ERROR_TARGET_TIMEOUT
;
689 /* fast exit: ARMv5+ code can use BKPT */
690 if (exit_point
&& buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
,
691 0, 32) != exit_point
)
693 LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32
"",
694 buf_get_u32(armv4_5
->core_cache
->reg_list
[15].value
, 0, 32));
695 return ERROR_TARGET_TIMEOUT
;
701 int armv4_5_run_algorithm_inner(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
, int (*run_it
)(struct target
*target
, uint32_t exit_point
, int timeout_ms
, void *arch_info
))
703 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
704 struct armv4_5_algorithm
*armv4_5_algorithm_info
= arch_info
;
705 enum armv4_5_state core_state
= armv4_5
->core_state
;
706 enum armv4_5_mode core_mode
= armv4_5
->core_mode
;
707 uint32_t context
[17];
709 int exit_breakpoint_size
= 0;
711 int retval
= ERROR_OK
;
712 LOG_DEBUG("Running algorithm");
714 if (armv4_5_algorithm_info
->common_magic
!= ARMV4_5_COMMON_MAGIC
)
716 LOG_ERROR("current target isn't an ARMV4/5 target");
717 return ERROR_TARGET_INVALID
;
720 if (target
->state
!= TARGET_HALTED
)
722 LOG_WARNING("target not halted");
723 return ERROR_TARGET_NOT_HALTED
;
726 if (!is_arm_mode(armv4_5
->core_mode
))
729 /* armv5 and later can terminate with BKPT instruction; less overhead */
730 if (!exit_point
&& armv4_5
->is_armv4
)
732 LOG_ERROR("ARMv4 target needs HW breakpoint location");
736 for (i
= 0; i
<= 16; i
++)
738 if (!ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
)
739 armv4_5
->read_core_reg(target
, i
, armv4_5_algorithm_info
->core_mode
);
740 context
[i
] = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
742 cpsr
= buf_get_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32);
744 for (i
= 0; i
< num_mem_params
; i
++)
746 if ((retval
= target_write_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
752 for (i
= 0; i
< num_reg_params
; i
++)
754 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
757 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
758 return ERROR_INVALID_ARGUMENTS
;
761 if (reg
->size
!= reg_params
[i
].size
)
763 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
764 return ERROR_INVALID_ARGUMENTS
;
767 if ((retval
= armv4_5_set_core_reg(reg
, reg_params
[i
].value
)) != ERROR_OK
)
773 armv4_5
->core_state
= armv4_5_algorithm_info
->core_state
;
774 if (armv4_5
->core_state
== ARMV4_5_STATE_ARM
)
775 exit_breakpoint_size
= 4;
776 else if (armv4_5
->core_state
== ARMV4_5_STATE_THUMB
)
777 exit_breakpoint_size
= 2;
780 LOG_ERROR("BUG: can't execute algorithms when not in ARM or Thumb state");
781 return ERROR_INVALID_ARGUMENTS
;
784 if (armv4_5_algorithm_info
->core_mode
!= ARMV4_5_MODE_ANY
)
786 LOG_DEBUG("setting core_mode: 0x%2.2x", armv4_5_algorithm_info
->core_mode
);
787 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 5, armv4_5_algorithm_info
->core_mode
);
788 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
789 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
792 /* terminate using a hardware or (ARMv5+) software breakpoint */
793 if (exit_point
&& (retval
= breakpoint_add(target
, exit_point
,
794 exit_breakpoint_size
, BKPT_HARD
)) != ERROR_OK
)
796 LOG_ERROR("can't add HW breakpoint to terminate algorithm");
797 return ERROR_TARGET_FAILURE
;
800 if ((retval
= target_resume(target
, 0, entry_point
, 1, 1)) != ERROR_OK
)
805 retval
= run_it(target
, exit_point
, timeout_ms
, arch_info
);
808 breakpoint_remove(target
, exit_point
);
810 if (retval
!= ERROR_OK
)
813 for (i
= 0; i
< num_mem_params
; i
++)
815 if (mem_params
[i
].direction
!= PARAM_OUT
)
816 if ((retvaltemp
= target_read_buffer(target
, mem_params
[i
].address
, mem_params
[i
].size
, mem_params
[i
].value
)) != ERROR_OK
)
822 for (i
= 0; i
< num_reg_params
; i
++)
824 if (reg_params
[i
].direction
!= PARAM_OUT
)
827 struct reg
*reg
= register_get_by_name(armv4_5
->core_cache
, reg_params
[i
].reg_name
, 0);
830 LOG_ERROR("BUG: register '%s' not found", reg_params
[i
].reg_name
);
831 retval
= ERROR_INVALID_ARGUMENTS
;
835 if (reg
->size
!= reg_params
[i
].size
)
837 LOG_ERROR("BUG: register '%s' size doesn't match reg_params[i].size", reg_params
[i
].reg_name
);
838 retval
= ERROR_INVALID_ARGUMENTS
;
842 buf_set_u32(reg_params
[i
].value
, 0, 32, buf_get_u32(reg
->value
, 0, 32));
846 for (i
= 0; i
<= 16; i
++)
849 regvalue
= buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32);
850 if (regvalue
!= context
[i
])
852 LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32
"", ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).name
, context
[i
]);
853 buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).value
, 0, 32, context
[i
]);
854 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).valid
= 1;
855 ARMV4_5_CORE_REG_MODE(armv4_5
->core_cache
, armv4_5_algorithm_info
->core_mode
, i
).dirty
= 1;
858 buf_set_u32(armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].value
, 0, 32, cpsr
);
859 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].valid
= 1;
860 armv4_5
->core_cache
->reg_list
[ARMV4_5_CPSR
].dirty
= 1;
862 armv4_5
->core_state
= core_state
;
863 armv4_5
->core_mode
= core_mode
;
868 int armv4_5_run_algorithm(struct target
*target
, int num_mem_params
, struct mem_param
*mem_params
, int num_reg_params
, struct reg_param
*reg_params
, uint32_t entry_point
, uint32_t exit_point
, int timeout_ms
, void *arch_info
)
870 return armv4_5_run_algorithm_inner(target
, num_mem_params
, mem_params
, num_reg_params
, reg_params
, entry_point
, exit_point
, timeout_ms
, arch_info
, armv4_5_run_algorithm_completion
);
874 * Runs ARM code in the target to calculate a CRC32 checksum.
876 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
878 int arm_checksum_memory(struct target
*target
,
879 uint32_t address
, uint32_t count
, uint32_t *checksum
)
881 struct working_area
*crc_algorithm
;
882 struct armv4_5_algorithm armv4_5_info
;
883 struct reg_param reg_params
[2];
887 static const uint32_t arm_crc_code
[] = {
888 0xE1A02000, /* mov r2, r0 */
889 0xE3E00000, /* mov r0, #0xffffffff */
890 0xE1A03001, /* mov r3, r1 */
891 0xE3A04000, /* mov r4, #0 */
892 0xEA00000B, /* b ncomp */
894 0xE7D21004, /* ldrb r1, [r2, r4] */
895 0xE59F7030, /* ldr r7, CRC32XOR */
896 0xE0200C01, /* eor r0, r0, r1, asl 24 */
897 0xE3A05000, /* mov r5, #0 */
899 0xE3500000, /* cmp r0, #0 */
900 0xE1A06080, /* mov r6, r0, asl #1 */
901 0xE2855001, /* add r5, r5, #1 */
902 0xE1A00006, /* mov r0, r6 */
903 0xB0260007, /* eorlt r0, r6, r7 */
904 0xE3550008, /* cmp r5, #8 */
905 0x1AFFFFF8, /* bne loop */
906 0xE2844001, /* add r4, r4, #1 */
908 0xE1540003, /* cmp r4, r3 */
909 0x1AFFFFF1, /* bne nbyte */
911 0xEAFFFFFE, /* b end */
913 0x04C11DB7 /* .word 0x04C11DB7 */
916 retval
= target_alloc_working_area(target
,
917 sizeof(arm_crc_code
), &crc_algorithm
);
918 if (retval
!= ERROR_OK
)
921 /* convert code into a buffer in target endianness */
922 for (i
= 0; i
< ARRAY_SIZE(arm_crc_code
); i
++) {
923 retval
= target_write_u32(target
,
924 crc_algorithm
->address
+ i
* sizeof(uint32_t),
926 if (retval
!= ERROR_OK
)
930 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
931 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
932 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
934 init_reg_param(®_params
[0], "r0", 32, PARAM_IN_OUT
);
935 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
937 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
938 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
940 /* 20 second timeout/megabyte */
941 int timeout
= 20000 * (1 + (count
/ (1024 * 1024)));
943 retval
= target_run_algorithm(target
, 0, NULL
, 2, reg_params
,
944 crc_algorithm
->address
,
945 crc_algorithm
->address
+ sizeof(arm_crc_code
) - 8,
946 timeout
, &armv4_5_info
);
947 if (retval
!= ERROR_OK
) {
948 LOG_ERROR("error executing ARM crc algorithm");
949 destroy_reg_param(®_params
[0]);
950 destroy_reg_param(®_params
[1]);
951 target_free_working_area(target
, crc_algorithm
);
955 *checksum
= buf_get_u32(reg_params
[0].value
, 0, 32);
957 destroy_reg_param(®_params
[0]);
958 destroy_reg_param(®_params
[1]);
960 target_free_working_area(target
, crc_algorithm
);
966 * Runs ARM code in the target to check whether a memory block holds
967 * all ones. NOR flash which has been erased, and thus may be written,
970 * \todo On ARMv5+, rely on BKPT termination for reduced overhead.
972 int arm_blank_check_memory(struct target
*target
,
973 uint32_t address
, uint32_t count
, uint32_t *blank
)
975 struct working_area
*check_algorithm
;
976 struct reg_param reg_params
[3];
977 struct armv4_5_algorithm armv4_5_info
;
981 static const uint32_t check_code
[] = {
983 0xe4d03001, /* ldrb r3, [r0], #1 */
984 0xe0022003, /* and r2, r2, r3 */
985 0xe2511001, /* subs r1, r1, #1 */
986 0x1afffffb, /* bne loop */
988 0xeafffffe /* b end */
991 /* make sure we have a working area */
992 retval
= target_alloc_working_area(target
,
993 sizeof(check_code
), &check_algorithm
);
994 if (retval
!= ERROR_OK
)
997 /* convert code into a buffer in target endianness */
998 for (i
= 0; i
< ARRAY_SIZE(check_code
); i
++) {
999 retval
= target_write_u32(target
,
1000 check_algorithm
->address
1001 + i
* sizeof(uint32_t),
1003 if (retval
!= ERROR_OK
)
1007 armv4_5_info
.common_magic
= ARMV4_5_COMMON_MAGIC
;
1008 armv4_5_info
.core_mode
= ARMV4_5_MODE_SVC
;
1009 armv4_5_info
.core_state
= ARMV4_5_STATE_ARM
;
1011 init_reg_param(®_params
[0], "r0", 32, PARAM_OUT
);
1012 buf_set_u32(reg_params
[0].value
, 0, 32, address
);
1014 init_reg_param(®_params
[1], "r1", 32, PARAM_OUT
);
1015 buf_set_u32(reg_params
[1].value
, 0, 32, count
);
1017 init_reg_param(®_params
[2], "r2", 32, PARAM_IN_OUT
);
1018 buf_set_u32(reg_params
[2].value
, 0, 32, 0xff);
1020 retval
= target_run_algorithm(target
, 0, NULL
, 3, reg_params
,
1021 check_algorithm
->address
,
1022 check_algorithm
->address
+ sizeof(check_code
) - 4,
1023 10000, &armv4_5_info
);
1024 if (retval
!= ERROR_OK
) {
1025 destroy_reg_param(®_params
[0]);
1026 destroy_reg_param(®_params
[1]);
1027 destroy_reg_param(®_params
[2]);
1028 target_free_working_area(target
, check_algorithm
);
1032 *blank
= buf_get_u32(reg_params
[2].value
, 0, 32);
1034 destroy_reg_param(®_params
[0]);
1035 destroy_reg_param(®_params
[1]);
1036 destroy_reg_param(®_params
[2]);
1038 target_free_working_area(target
, check_algorithm
);
1043 static int arm_full_context(struct target
*target
)
1045 struct armv4_5_common_s
*armv4_5
= target_to_armv4_5(target
);
1046 unsigned num_regs
= armv4_5
->core_cache
->num_regs
;
1047 struct reg
*reg
= armv4_5
->core_cache
->reg_list
;
1048 int retval
= ERROR_OK
;
1050 for (; num_regs
&& retval
== ERROR_OK
; num_regs
--, reg
++) {
1053 retval
= armv4_5_get_core_reg(reg
);
1058 int armv4_5_init_arch_info(struct target
*target
, struct arm
*armv4_5
)
1060 target
->arch_info
= armv4_5
;
1062 armv4_5
->common_magic
= ARMV4_5_COMMON_MAGIC
;
1063 armv4_5
->core_state
= ARMV4_5_STATE_ARM
;
1064 armv4_5
->core_mode
= ARMV4_5_MODE_USR
;
1066 /* core_type may be overridden by subtype logic */
1067 armv4_5
->core_type
= ARMV4_5_MODE_ANY
;
1069 /* default full_context() has no core-specific optimizations */
1070 if (!armv4_5
->full_context
&& armv4_5
->read_core_reg
)
1071 armv4_5
->full_context
= arm_full_context
;
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)