2 * Copyright(c) 2013 Intel Corporation.
4 * Adrian Burns (adrian.burns@intel.com)
5 * Thomas Faust (thomas.faust@intel.com)
6 * Ivan De Cesaris (ivan.de.cesaris@intel.com)
7 * Julien Carreno (julien.carreno@intel.com)
8 * Jeffrey Maxwell (jeffrey.r.maxwell@intel.com)
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of version 2 of the GNU General Public License as
12 * published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
23 * Contact Information:
29 * This implements generic x86 32 bit memory and breakpoint operations.
36 #include <helper/log.h>
39 #include "target_type.h"
41 #include "breakpoints.h"
42 #include "x86_32_common.h"
44 static int set_debug_regs(struct target
*t
, uint32_t address
,
45 uint8_t bp_num
, uint8_t bp_type
, uint8_t bp_length
);
46 static int unset_debug_regs(struct target
*t
, uint8_t bp_num
);
47 static int read_mem(struct target
*t
, uint32_t size
,
48 uint32_t addr
, uint8_t *buf
);
49 static int write_mem(struct target
*t
, uint32_t size
,
50 uint32_t addr
, const uint8_t *buf
);
51 static int calcaddr_pyhsfromlin(struct target
*t
, uint32_t addr
,
53 static int read_phys_mem(struct target
*t
, uint32_t phys_address
,
54 uint32_t size
, uint32_t count
, uint8_t *buffer
);
55 static int write_phys_mem(struct target
*t
, uint32_t phys_address
,
56 uint32_t size
, uint32_t count
, const uint8_t *buffer
);
57 static int set_breakpoint(struct target
*target
,
58 struct breakpoint
*breakpoint
);
59 static int unset_breakpoint(struct target
*target
,
60 struct breakpoint
*breakpoint
);
61 static int set_watchpoint(struct target
*target
,
62 struct watchpoint
*watchpoint
);
63 static int unset_watchpoint(struct target
*target
,
64 struct watchpoint
*watchpoint
);
65 static int read_hw_reg_to_cache(struct target
*t
, int num
);
66 static int write_hw_reg_from_cache(struct target
*t
, int num
);
68 int x86_32_get_gdb_reg_list(struct target
*t
,
69 struct reg
**reg_list
[], int *reg_list_size
,
70 enum target_register_class reg_class
)
73 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
75 *reg_list_size
= x86_32
->cache
->num_regs
;
76 LOG_DEBUG("num_regs=%d, reg_class=%d", (*reg_list_size
), reg_class
);
77 *reg_list
= malloc(sizeof(struct reg
*) * (*reg_list_size
));
78 if (*reg_list
== NULL
) {
79 LOG_ERROR("%s out of memory", __func__
);
82 /* this will copy the values from our reg list to gdbs */
83 for (i
= 0; i
< (*reg_list_size
); i
++) {
84 (*reg_list
)[i
] = &x86_32
->cache
->reg_list
[i
];
85 LOG_DEBUG("value %s = %08" PRIx32
, x86_32
->cache
->reg_list
[i
].name
,
86 buf_get_u32(x86_32
->cache
->reg_list
[i
].value
, 0, 32));
91 int x86_32_common_init_arch_info(struct target
*t
, struct x86_32_common
*x86_32
)
93 t
->arch_info
= x86_32
;
94 x86_32
->common_magic
= X86_32_COMMON_MAGIC
;
95 x86_32
->num_hw_bpoints
= MAX_DEBUG_REGS
;
96 x86_32
->hw_break_list
= calloc(x86_32
->num_hw_bpoints
,
97 sizeof(struct x86_32_dbg_reg
));
98 if (x86_32
->hw_break_list
== NULL
) {
99 LOG_ERROR("%s out of memory", __func__
);
102 x86_32
->curr_tap
= t
->tap
;
103 x86_32
->fast_data_area
= NULL
;
105 x86_32
->read_hw_reg_to_cache
= read_hw_reg_to_cache
;
106 x86_32
->write_hw_reg_from_cache
= write_hw_reg_from_cache
;
110 int x86_32_common_mmu(struct target
*t
, int *enabled
)
116 int x86_32_common_virt2phys(struct target
*t
, uint32_t address
, uint32_t *physical
)
118 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
121 * We need to ignore 'segmentation' for now, as OpenOCD can't handle
122 * segmented addresses.
123 * In protected mode that is almost OK, as (almost) any known OS is using
124 * flat segmentation. In real mode we use use the base of the DS segment,
125 * as we don't know better ...
128 uint32_t cr0
= buf_get_u32(x86_32
->cache
->reg_list
[CR0
].value
, 0, 32);
129 if (!(cr0
& CR0_PG
)) {
130 /* target halted in real mode */
131 /* TODO: needs validation !!! */
132 uint32_t dsb
= buf_get_u32(x86_32
->cache
->reg_list
[DSB
].value
, 0, 32);
133 *physical
= dsb
+ address
;
136 /* target halted in protected mode */
137 if (calcaddr_pyhsfromlin(t
, address
, physical
) != ERROR_OK
) {
138 LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32
,
146 int x86_32_common_read_phys_mem(struct target
*t
, uint32_t phys_address
,
147 uint32_t size
, uint32_t count
, uint8_t *buffer
)
149 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
152 error
= read_phys_mem(t
, phys_address
, size
, count
, buffer
);
153 if (error
!= ERROR_OK
)
156 /* After reading memory from target, we must replace software breakpoints
157 * with the original instructions again.
159 struct swbp_mem_patch
*iter
= x86_32
->swbbp_mem_patch_list
;
160 while (iter
!= NULL
) {
161 if (iter
->physaddr
>= phys_address
&& iter
->physaddr
< phys_address
+(size
*count
)) {
162 uint32_t offset
= iter
->physaddr
- phys_address
;
163 buffer
[offset
] = iter
->orig_byte
;
170 static int read_phys_mem(struct target
*t
, uint32_t phys_address
,
171 uint32_t size
, uint32_t count
, uint8_t *buffer
)
173 int retval
= ERROR_OK
;
174 bool pg_disabled
= false;
175 LOG_DEBUG("addr=%08" PRIx32
", size=%d, count=%d, buf=%p",
176 phys_address
, size
, count
, buffer
);
177 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
179 if (check_not_halted(t
))
180 return ERROR_TARGET_NOT_HALTED
;
181 if (!count
|| !buffer
|| !phys_address
) {
182 LOG_ERROR("%s invalid params count=%d, buf=%p, addr=%08" PRIx32
,
183 __func__
, count
, buffer
, phys_address
);
184 return ERROR_COMMAND_ARGUMENT_INVALID
;
187 /* to access physical memory, switch off the CR0.PG bit */
188 if (x86_32
->is_paging_enabled(t
)) {
189 retval
= x86_32
->disable_paging(t
);
190 if (retval
!= ERROR_OK
)
195 for (uint32_t i
= 0; i
< count
; i
++) {
198 retval
= read_mem(t
, size
, phys_address
+ i
, buffer
+ i
);
201 retval
= read_mem(t
, size
, phys_address
+ i
* 2, buffer
+ i
* 2);
204 retval
= read_mem(t
, size
, phys_address
+ i
* 4, buffer
+ i
* 4);
207 LOG_ERROR("%s invalid read size", __func__
);
211 /* restore CR0.PG bit if needed (regardless of retval) */
213 retval
= x86_32
->enable_paging(t
);
214 if (retval
!= ERROR_OK
)
218 /* TODO: After reading memory from target, we must replace
219 * software breakpoints with the original instructions again.
220 * Solve this with the breakpoint fix
225 int x86_32_common_write_phys_mem(struct target
*t
, uint32_t phys_address
,
226 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
228 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
229 int error
= ERROR_OK
;
230 uint8_t *newbuffer
= NULL
;
233 if (!count
|| !buffer
|| !phys_address
) {
234 LOG_ERROR("%s invalid params count=%d, buf=%p, addr=%08" PRIx32
,
235 __func__
, count
, buffer
, phys_address
);
236 return ERROR_COMMAND_ARGUMENT_INVALID
;
238 /* Before writing memory to target, we must update software breakpoints
239 * with the new instructions and patch the memory buffer with the
240 * breakpoint instruction.
242 newbuffer
= malloc(size
*count
);
243 if (newbuffer
== NULL
) {
244 LOG_ERROR("%s out of memory", __func__
);
247 memcpy(newbuffer
, buffer
, size
*count
);
248 struct swbp_mem_patch
*iter
= x86_32
->swbbp_mem_patch_list
;
249 while (iter
!= NULL
) {
250 if (iter
->physaddr
>= phys_address
&& iter
->physaddr
< phys_address
+(size
*count
)) {
251 uint32_t offset
= iter
->physaddr
- phys_address
;
252 newbuffer
[offset
] = SW_BP_OPCODE
;
254 /* update the breakpoint */
255 struct breakpoint
*pbiter
= t
->breakpoints
;
256 while (pbiter
!= NULL
&& pbiter
->unique_id
!= iter
->swbp_unique_id
)
257 pbiter
= pbiter
->next
;
259 pbiter
->orig_instr
[0] = buffer
[offset
];
264 error
= write_phys_mem(t
, phys_address
, size
, count
, newbuffer
);
269 static int write_phys_mem(struct target
*t
, uint32_t phys_address
,
270 uint32_t size
, uint32_t count
, const uint8_t *buffer
)
272 int retval
= ERROR_OK
;
273 bool pg_disabled
= false;
274 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
275 LOG_DEBUG("addr=%08" PRIx32
", size=%d, count=%d, buf=%p",
276 phys_address
, size
, count
, buffer
);
279 if (!count
|| !buffer
|| !phys_address
) {
280 LOG_ERROR("%s invalid params count=%d, buf=%p, addr=%08" PRIx32
,
281 __func__
, count
, buffer
, phys_address
);
282 return ERROR_COMMAND_ARGUMENT_INVALID
;
284 /* TODO: Before writing memory to target, we must update
285 * software breakpoints with the new instructions and
286 * patch the memory buffer with the breakpoint instruction.
287 * Solve this with the breakpoint fix
290 /* to access physical memory, switch off the CR0.PG bit */
291 if (x86_32
->is_paging_enabled(t
)) {
292 retval
= x86_32
->disable_paging(t
);
293 if (retval
!= ERROR_OK
)
297 for (uint32_t i
= 0; i
< count
; i
++) {
300 retval
= write_mem(t
, size
, phys_address
+ i
, buffer
+ i
);
303 retval
= write_mem(t
, size
, phys_address
+ i
* 2, buffer
+ i
* 2);
306 retval
= write_mem(t
, size
, phys_address
+ i
* 4, buffer
+ i
* 4);
309 LOG_DEBUG("invalid read size");
313 /* restore CR0.PG bit if needed (regardless of retval) */
315 retval
= x86_32
->enable_paging(t
);
316 if (retval
!= ERROR_OK
)
322 static int read_mem(struct target
*t
, uint32_t size
,
323 uint32_t addr
, uint8_t *buf
)
325 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
327 /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
328 bool use32
= (buf_get_u32(x86_32
->cache
->reg_list
[CSAR
].value
, 0, 32)) & CSAR_D
;
329 int retval
= x86_32
->write_hw_reg(t
, EAX
, addr
, 0);
330 if (retval
!= ERROR_OK
) {
331 LOG_ERROR("%s error write EAX", __func__
);
338 retval
= x86_32
->submit_instruction(t
, MEMRDB32
);
340 retval
= x86_32
->submit_instruction(t
, MEMRDB16
);
344 retval
= x86_32
->submit_instruction(t
, MEMRDH32
);
346 retval
= x86_32
->submit_instruction(t
, MEMRDH16
);
350 retval
= x86_32
->submit_instruction(t
, MEMRDW32
);
352 retval
= x86_32
->submit_instruction(t
, MEMRDW16
);
355 LOG_ERROR("%s invalid read mem size", __func__
);
359 /* read_hw_reg() will write to 4 bytes (uint32_t)
360 * Watch out, the buffer passed into read_mem() might be 1 or 2 bytes.
363 retval
= x86_32
->read_hw_reg(t
, EDX
, ®val
, 0);
365 if (retval
!= ERROR_OK
) {
366 LOG_ERROR("%s error read EDX", __func__
);
369 for (uint8_t i
= 0; i
< size
; i
++)
370 buf
[i
] = (regval
>> (i
*8)) & 0x000000FF;
372 retval
= x86_32
->transaction_status(t
);
373 if (retval
!= ERROR_OK
) {
374 LOG_ERROR("%s error on mem read", __func__
);
380 static int write_mem(struct target
*t
, uint32_t size
,
381 uint32_t addr
, const uint8_t *buf
)
384 uint32_t buf4bytes
= 0;
385 int retval
= ERROR_OK
;
386 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
388 for (i
= 0; i
< size
; ++i
) {
389 buf4bytes
= buf4bytes
<< 8; /* first time we only shift 0s */
390 buf4bytes
+= buf
[(size
-1)-i
]; /* it was hard to write, should be hard to read! */
392 /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
393 bool use32
= (buf_get_u32(x86_32
->cache
->reg_list
[CSAR
].value
, 0, 32)) & CSAR_D
;
394 retval
= x86_32
->write_hw_reg(t
, EAX
, addr
, 0);
395 if (retval
!= ERROR_OK
) {
396 LOG_ERROR("%s error write EAX", __func__
);
400 /* write_hw_reg() will write to 4 bytes (uint32_t)
401 * Watch out, the buffer passed into write_mem() might be 1 or 2 bytes.
403 retval
= x86_32
->write_hw_reg(t
, EDX
, buf4bytes
, 0);
404 if (retval
!= ERROR_OK
) {
405 LOG_ERROR("%s error write EDX", __func__
);
411 retval
= x86_32
->submit_instruction(t
, MEMWRB32
);
413 retval
= x86_32
->submit_instruction(t
, MEMWRB16
);
417 retval
= x86_32
->submit_instruction(t
, MEMWRH32
);
419 retval
= x86_32
->submit_instruction(t
, MEMWRH16
);
423 retval
= x86_32
->submit_instruction(t
, MEMWRW32
);
425 retval
= x86_32
->submit_instruction(t
, MEMWRW16
);
428 LOG_ERROR("%s invalid write mem size", __func__
);
431 retval
= x86_32
->transaction_status(t
);
432 if (retval
!= ERROR_OK
) {
433 LOG_ERROR("%s error on mem write", __func__
);
439 int calcaddr_pyhsfromlin(struct target
*t
, uint32_t addr
, uint32_t *physaddr
)
441 uint8_t entry_buffer
[8];
443 if (physaddr
== NULL
|| t
== NULL
)
446 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
448 /* The 'user-visible' CR0.PG should be set - otherwise the function shouldn't be called
449 * (Don't check the CR0.PG on the target, this might be temporally disabled at this point)
451 uint32_t cr0
= buf_get_u32(x86_32
->cache
->reg_list
[CR0
].value
, 0, 32);
452 if (!(cr0
& CR0_PG
)) {
453 /* you are wrong in this function, never mind */
458 uint32_t cr4
= buf_get_u32(x86_32
->cache
->reg_list
[CR4
].value
, 0, 32);
459 bool isPAE
= cr4
& 0x00000020; /* PAE - Physical Address Extension */
461 uint32_t cr3
= buf_get_u32(x86_32
->cache
->reg_list
[CR3
].value
, 0, 32);
463 uint32_t pdpt_base
= cr3
& 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */
464 uint32_t pdpt_index
= (addr
& 0xC0000000) >> 30; /* A[31:30] index to PDPT */
465 uint32_t pdpt_addr
= pdpt_base
+ (8 * pdpt_index
);
466 if (x86_32_common_read_phys_mem(t
, pdpt_addr
, 4, 2, entry_buffer
) != ERROR_OK
) {
467 LOG_ERROR("%s couldn't read page directory pointer table entry at 0x%08" PRIx32
,
468 __func__
, pdpt_addr
);
471 uint64_t pdpt_entry
= target_buffer_get_u64(t
, entry_buffer
);
472 if (!(pdpt_entry
& 0x0000000000000001)) {
473 LOG_ERROR("%s page directory pointer table entry at 0x%08" PRIx32
" is not present",
474 __func__
, pdpt_addr
);
478 uint32_t pd_base
= pdpt_entry
& 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
479 uint32_t pd_index
= (addr
& 0x3FE00000) >> 21; /* A[29:21] index to PD entry with PAE */
480 uint32_t pd_addr
= pd_base
+ (8 * pd_index
);
481 if (x86_32_common_read_phys_mem(t
, pd_addr
, 4, 2, entry_buffer
) != ERROR_OK
) {
482 LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32
,
486 uint64_t pd_entry
= target_buffer_get_u64(t
, entry_buffer
);
487 if (!(pd_entry
& 0x0000000000000001)) {
488 LOG_ERROR("%s page directory entry at 0x%08" PRIx32
" is not present",
493 /* PS bit in PD entry is indicating 4KB or 2MB page size */
494 if (pd_entry
& 0x0000000000000080) {
496 uint32_t page_base
= (uint32_t)(pd_entry
& 0x00000000FFE00000); /* [31:21] */
497 uint32_t offset
= addr
& 0x001FFFFF; /* [20:0] */
498 *physaddr
= page_base
+ offset
;
503 uint32_t pt_base
= (uint32_t)(pd_entry
& 0x00000000FFFFF000); /*[31:12]*/
504 uint32_t pt_index
= (addr
& 0x001FF000) >> 12; /*[20:12]*/
505 uint32_t pt_addr
= pt_base
+ (8 * pt_index
);
506 if (x86_32_common_read_phys_mem(t
, pt_addr
, 4, 2, entry_buffer
) != ERROR_OK
) {
507 LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32
, __func__
, pt_addr
);
510 uint64_t pt_entry
= target_buffer_get_u64(t
, entry_buffer
);
511 if (!(pt_entry
& 0x0000000000000001)) {
512 LOG_ERROR("%s page table entry at 0x%08" PRIx32
" is not present", __func__
, pt_addr
);
516 uint32_t page_base
= (uint32_t)(pt_entry
& 0x00000000FFFFF000); /*[31:12]*/
517 uint32_t offset
= addr
& 0x00000FFF; /*[11:0]*/
518 *physaddr
= page_base
+ offset
;
522 uint32_t pd_base
= cr3
& 0xFFFFF000; /* lower 12 bits of CR3 must always be 0 */
523 uint32_t pd_index
= (addr
& 0xFFC00000) >> 22; /* A[31:22] index to PD entry */
524 uint32_t pd_addr
= pd_base
+ (4 * pd_index
);
525 if (x86_32_common_read_phys_mem(t
, pd_addr
, 4, 1, entry_buffer
) != ERROR_OK
) {
526 LOG_ERROR("%s couldn't read page directory entry at 0x%08" PRIx32
, __func__
, pd_addr
);
529 uint32_t pd_entry
= target_buffer_get_u32(t
, entry_buffer
);
530 if (!(pd_entry
& 0x00000001)) {
531 LOG_ERROR("%s page directory entry at 0x%08" PRIx32
" is not present", __func__
, pd_addr
);
535 /* Bit 7 in page directory entry is page size.
537 if (pd_entry
& 0x00000080) {
539 uint32_t page_base
= pd_entry
& 0xFFC00000;
540 *physaddr
= page_base
+ (addr
& 0x003FFFFF);
544 uint32_t pt_base
= pd_entry
& 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
545 uint32_t pt_index
= (addr
& 0x003FF000) >> 12; /* A[21:12] index to page table entry */
546 uint32_t pt_addr
= pt_base
+ (4 * pt_index
);
547 if (x86_32_common_read_phys_mem(t
, pt_addr
, 4, 1, entry_buffer
) != ERROR_OK
) {
548 LOG_ERROR("%s couldn't read page table entry at 0x%08" PRIx32
, __func__
, pt_addr
);
551 uint32_t pt_entry
= target_buffer_get_u32(t
, entry_buffer
);
552 if (!(pt_entry
& 0x00000001)) {
553 LOG_ERROR("%s page table entry at 0x%08" PRIx32
" is not present", __func__
, pt_addr
);
556 uint32_t page_base
= pt_entry
& 0xFFFFF000; /* A[31:12] is PageTable/Page Base Address */
557 *physaddr
= page_base
+ (addr
& 0x00000FFF); /* A[11:0] offset to 4KB page in linear address */
563 int x86_32_common_read_memory(struct target
*t
, uint32_t addr
,
564 uint32_t size
, uint32_t count
, uint8_t *buf
)
566 int retval
= ERROR_OK
;
567 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
568 LOG_DEBUG("addr=%08" PRIx32
", size=%d, count=%d, buf=%p",
569 addr
, size
, count
, buf
);
571 if (!count
|| !buf
|| !addr
) {
572 LOG_ERROR("%s invalid params count=%d, buf=%p, addr=%08" PRIx32
,
573 __func__
, count
, buf
, addr
);
574 return ERROR_COMMAND_ARGUMENT_INVALID
;
577 if (x86_32
->is_paging_enabled(t
)) {
578 /* all memory accesses from debugger must be physical (CR0.PG == 0)
579 * conversion to physical address space needed
581 retval
= x86_32
->disable_paging(t
);
582 if (retval
!= ERROR_OK
)
584 uint32_t physaddr
= 0;
585 if (calcaddr_pyhsfromlin(t
, addr
, &physaddr
) != ERROR_OK
) {
586 LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32
, __func__
, addr
);
589 /* TODO: !!! Watch out for page boundaries
590 * for every 4kB, the physical address has to be re-calculated
591 * This should be fixed together with bulk memory reads
594 if (retval
== ERROR_OK
595 && x86_32_common_read_phys_mem(t
, physaddr
, size
, count
, buf
) != ERROR_OK
) {
596 LOG_ERROR("%s failed to read memory from physical address 0x%08" PRIx32
, __func__
, physaddr
);
599 /* restore PG bit if it was cleared prior (regardless of retval) */
600 retval
= x86_32
->enable_paging(t
);
601 if (retval
!= ERROR_OK
)
604 /* paging is off - linear address is physical address */
605 if (x86_32_common_read_phys_mem(t
, addr
, size
, count
, buf
) != ERROR_OK
) {
606 LOG_ERROR("%s failed to read memory from address 0%08" PRIx32
, __func__
, addr
);
614 int x86_32_common_write_memory(struct target
*t
, uint32_t addr
,
615 uint32_t size
, uint32_t count
, const uint8_t *buf
)
617 int retval
= ERROR_OK
;
618 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
619 LOG_DEBUG("addr=%08" PRIx32
", size=%d, count=%d, buf=%p",
620 addr
, size
, count
, buf
);
622 if (!count
|| !buf
|| !addr
) {
623 LOG_ERROR("%s invalid params count=%d, buf=%p, addr=%08" PRIx32
,
624 __func__
, count
, buf
, addr
);
625 return ERROR_COMMAND_ARGUMENT_INVALID
;
627 if (x86_32
->is_paging_enabled(t
)) {
628 /* all memory accesses from debugger must be physical (CR0.PG == 0)
629 * conversion to physical address space needed
631 retval
= x86_32
->disable_paging(t
);
632 if (retval
!= ERROR_OK
)
634 uint32_t physaddr
= 0;
635 if (calcaddr_pyhsfromlin(t
, addr
, &physaddr
) != ERROR_OK
) {
636 LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32
,
640 /* TODO: !!! Watch out for page boundaries
641 * for every 4kB, the physical address has to be re-calculated
642 * This should be fixed together with bulk memory reads
644 if (retval
== ERROR_OK
645 && x86_32_common_write_phys_mem(t
, physaddr
, size
, count
, buf
) != ERROR_OK
) {
646 LOG_ERROR("%s failed to write memory to physical address 0x%08" PRIx32
,
650 /* restore PG bit if it was cleared prior (regardless of retval) */
651 retval
= x86_32
->enable_paging(t
);
652 if (retval
!= ERROR_OK
)
656 /* paging is off - linear address is physical address */
657 if (x86_32_common_write_phys_mem(t
, addr
, size
, count
, buf
) != ERROR_OK
) {
658 LOG_ERROR("%s failed to write memory to address 0x%08" PRIx32
,
666 int x86_32_common_read_io(struct target
*t
, uint32_t addr
,
667 uint32_t size
, uint8_t *buf
)
669 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
670 /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
671 bool use32
= (buf_get_u32(x86_32
->cache
->reg_list
[CSAR
].value
, 0, 32)) & CSAR_D
;
672 int retval
= ERROR_FAIL
;
673 bool pg_disabled
= false;
674 LOG_DEBUG("addr=%08" PRIx32
", size=%d, buf=%p", addr
, size
, buf
);
677 LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32
, __func__
, buf
, addr
);
680 retval
= x86_32
->write_hw_reg(t
, EDX
, addr
, 0);
681 if (retval
!= ERROR_OK
) {
682 LOG_ERROR("%s error EDX write", __func__
);
685 /* to access physical memory, switch off the CR0.PG bit */
686 if (x86_32
->is_paging_enabled(t
)) {
687 retval
= x86_32
->disable_paging(t
);
688 if (retval
!= ERROR_OK
)
695 retval
= x86_32
->submit_instruction(t
, IORDB32
);
697 retval
= x86_32
->submit_instruction(t
, IORDB16
);
701 retval
= x86_32
->submit_instruction(t
, IORDH32
);
703 retval
= x86_32
->submit_instruction(t
, IORDH16
);
707 retval
= x86_32
->submit_instruction(t
, IORDW32
);
709 retval
= x86_32
->submit_instruction(t
, IORDW16
);
712 LOG_ERROR("%s invalid read io size", __func__
);
715 /* restore CR0.PG bit if needed */
717 retval
= x86_32
->enable_paging(t
);
718 if (retval
!= ERROR_OK
)
723 retval
= x86_32
->read_hw_reg(t
, EAX
, ®val
, 0);
724 if (retval
!= ERROR_OK
) {
725 LOG_ERROR("%s error on read EAX", __func__
);
728 for (uint8_t i
= 0; i
< size
; i
++)
729 buf
[i
] = (regval
>> (i
*8)) & 0x000000FF;
730 retval
= x86_32
->transaction_status(t
);
731 if (retval
!= ERROR_OK
) {
732 LOG_ERROR("%s error on io read", __func__
);
738 int x86_32_common_write_io(struct target
*t
, uint32_t addr
,
739 uint32_t size
, const uint8_t *buf
)
741 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
742 /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
743 bool use32
= (buf_get_u32(x86_32
->cache
->reg_list
[CSAR
].value
, 0, 32)) & CSAR_D
;
744 LOG_DEBUG("addr=%08" PRIx32
", size=%d, buf=%p", addr
, size
, buf
);
746 int retval
= ERROR_FAIL
;
747 bool pg_disabled
= false;
749 LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32
, __func__
, buf
, addr
);
752 /* no do the write */
753 retval
= x86_32
->write_hw_reg(t
, EDX
, addr
, 0);
754 if (retval
!= ERROR_OK
) {
755 LOG_ERROR("%s error on EDX write", __func__
);
759 for (uint8_t i
= 0; i
< size
; i
++)
760 regval
+= (buf
[i
] << (i
*8));
761 retval
= x86_32
->write_hw_reg(t
, EAX
, regval
, 0);
762 if (retval
!= ERROR_OK
) {
763 LOG_ERROR("%s error on EAX write", __func__
);
766 /* to access physical memory, switch off the CR0.PG bit */
767 if (x86_32
->is_paging_enabled(t
)) {
768 retval
= x86_32
->disable_paging(t
);
769 if (retval
!= ERROR_OK
)
776 retval
= x86_32
->submit_instruction(t
, IOWRB32
);
778 retval
= x86_32
->submit_instruction(t
, IOWRB16
);
782 retval
= x86_32
->submit_instruction(t
, IOWRH32
);
784 retval
= x86_32
->submit_instruction(t
, IOWRH16
);
788 retval
= x86_32
->submit_instruction(t
, IOWRW32
);
790 retval
= x86_32
->submit_instruction(t
, IOWRW16
);
793 LOG_ERROR("%s invalid write io size", __func__
);
796 /* restore CR0.PG bit if needed */
798 retval
= x86_32
->enable_paging(t
);
799 if (retval
!= ERROR_OK
)
803 retval
= x86_32
->transaction_status(t
);
804 if (retval
!= ERROR_OK
) {
805 LOG_ERROR("%s error on io write", __func__
);
811 int x86_32_common_add_watchpoint(struct target
*t
, struct watchpoint
*wp
)
814 /* set_watchpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
815 * hardware registers are gone
817 return set_watchpoint(t
, wp
);
820 int x86_32_common_remove_watchpoint(struct target
*t
, struct watchpoint
*wp
)
822 if (check_not_halted(t
))
823 return ERROR_TARGET_NOT_HALTED
;
825 unset_watchpoint(t
, wp
);
829 int x86_32_common_add_breakpoint(struct target
*t
, struct breakpoint
*bp
)
831 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
832 if (check_not_halted(t
))
833 return ERROR_TARGET_NOT_HALTED
;
834 /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
835 * hardware registers are gone (for hardware breakpoints)
837 return set_breakpoint(t
, bp
);
840 int x86_32_common_remove_breakpoint(struct target
*t
, struct breakpoint
*bp
)
842 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
843 if (check_not_halted(t
))
844 return ERROR_TARGET_NOT_HALTED
;
846 unset_breakpoint(t
, bp
);
851 static int set_debug_regs(struct target
*t
, uint32_t address
,
852 uint8_t bp_num
, uint8_t bp_type
, uint8_t bp_length
)
854 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
855 LOG_DEBUG("addr=%08" PRIx32
", bp_num=%d, bp_type=%d, pb_length=%d",
856 address
, bp_num
, bp_type
, bp_length
);
858 /* DR7 - set global enable */
859 uint32_t dr7
= buf_get_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32);
861 if (bp_length
!= 1 && bp_length
!= 2 && bp_length
!= 4)
864 if (DR7_BP_FREE(dr7
, bp_num
))
865 DR7_GLOBAL_ENABLE(dr7
, bp_num
);
867 LOG_ERROR("%s dr7 error, already enabled, val=%08" PRIx32
, __func__
, dr7
);
868 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
873 /* 00 - only on instruction execution */
874 DR7_SET_EXE(dr7
, bp_num
);
875 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
878 /* 01 - only on data writes */
879 DR7_SET_WRITE(dr7
, bp_num
);
880 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
883 /* 10 UNSUPPORTED - an I/O read and I/O write */
884 LOG_ERROR("%s unsupported feature bp_type=%d", __func__
, bp_type
);
888 /* on data read or data write */
889 DR7_SET_ACCESS(dr7
, bp_num
);
890 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
893 LOG_ERROR("%s invalid request [only 0-3] bp_type=%d", __func__
, bp_type
);
897 /* update regs in the reg cache ready to be written to hardware
900 buf_set_u32(x86_32
->cache
->reg_list
[bp_num
+DR0
].value
, 0, 32, address
);
901 x86_32
->cache
->reg_list
[bp_num
+DR0
].dirty
= 1;
902 x86_32
->cache
->reg_list
[bp_num
+DR0
].valid
= 1;
903 buf_set_u32(x86_32
->cache
->reg_list
[DR6
].value
, 0, 32, PM_DR6
);
904 x86_32
->cache
->reg_list
[DR6
].dirty
= 1;
905 x86_32
->cache
->reg_list
[DR6
].valid
= 1;
906 buf_set_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32, dr7
);
907 x86_32
->cache
->reg_list
[DR7
].dirty
= 1;
908 x86_32
->cache
->reg_list
[DR7
].valid
= 1;
912 static int unset_debug_regs(struct target
*t
, uint8_t bp_num
)
914 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
915 LOG_DEBUG("bp_num=%d", bp_num
);
917 uint32_t dr7
= buf_get_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32);
919 if (!(DR7_BP_FREE(dr7
, bp_num
))) {
920 DR7_GLOBAL_DISABLE(dr7
, bp_num
);
922 LOG_ERROR("%s dr7 error, not enabled, val=%08" PRIx32
, __func__
, dr7
);
923 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
925 /* this will clear rw and len bits */
926 DR7_RESET_RWLEN_BITS(dr7
, bp_num
);
928 /* update regs in the reg cache ready to be written to hardware
931 buf_set_u32(x86_32
->cache
->reg_list
[bp_num
+DR0
].value
, 0, 32, 0);
932 x86_32
->cache
->reg_list
[bp_num
+DR0
].dirty
= 1;
933 x86_32
->cache
->reg_list
[bp_num
+DR0
].valid
= 1;
934 buf_set_u32(x86_32
->cache
->reg_list
[DR6
].value
, 0, 32, PM_DR6
);
935 x86_32
->cache
->reg_list
[DR6
].dirty
= 1;
936 x86_32
->cache
->reg_list
[DR6
].valid
= 1;
937 buf_set_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32, dr7
);
938 x86_32
->cache
->reg_list
[DR7
].dirty
= 1;
939 x86_32
->cache
->reg_list
[DR7
].valid
= 1;
943 static int set_hwbp(struct target
*t
, struct breakpoint
*bp
)
945 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
946 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
947 uint8_t hwbp_num
= 0;
949 while (debug_reg_list
[hwbp_num
].used
&& (hwbp_num
< x86_32
->num_hw_bpoints
))
951 if (hwbp_num
>= x86_32
->num_hw_bpoints
) {
952 LOG_ERROR("%s no free hw breakpoint bpid=%d", __func__
, bp
->unique_id
);
953 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
955 if (set_debug_regs(t
, bp
->address
, hwbp_num
, DR7_BP_EXECUTE
, 1) != ERROR_OK
)
957 bp
->set
= hwbp_num
+ 1;
958 debug_reg_list
[hwbp_num
].used
= 1;
959 debug_reg_list
[hwbp_num
].bp_value
= bp
->address
;
960 LOG_USER("%s hardware breakpoint %d set at 0x%08" PRIx32
" (hwreg=%d)", __func__
,
961 bp
->unique_id
, debug_reg_list
[hwbp_num
].bp_value
, hwbp_num
);
965 static int unset_hwbp(struct target
*t
, struct breakpoint
*bp
)
967 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
968 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
969 int hwbp_num
= bp
->set
- 1;
971 if ((hwbp_num
< 0) || (hwbp_num
>= x86_32
->num_hw_bpoints
)) {
972 LOG_ERROR("%s invalid breakpoint number=%d, bpid=%d",
973 __func__
, hwbp_num
, bp
->unique_id
);
977 if (unset_debug_regs(t
, hwbp_num
) != ERROR_OK
)
979 debug_reg_list
[hwbp_num
].used
= 0;
980 debug_reg_list
[hwbp_num
].bp_value
= 0;
982 LOG_USER("%s hardware breakpoint %d removed from 0x%08" PRIx32
" (hwreg=%d)",
983 __func__
, bp
->unique_id
, bp
->address
, hwbp_num
);
987 static int set_swbp(struct target
*t
, struct breakpoint
*bp
)
989 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
990 LOG_DEBUG("id %d", bp
->unique_id
);
992 uint8_t opcode
= SW_BP_OPCODE
;
995 if (calcaddr_pyhsfromlin(t
, bp
->address
, &physaddr
) != ERROR_OK
)
997 if (read_phys_mem(t
, physaddr
, 1, 1, bp
->orig_instr
))
1000 LOG_DEBUG("set software breakpoint - orig byte=%02" PRIx8
"", *bp
->orig_instr
);
1002 /* just write the instruction trap byte */
1003 if (write_phys_mem(t
, physaddr
, 1, 1, &opcode
))
1006 /* verify that this is not invalid/read-only memory */
1007 if (read_phys_mem(t
, physaddr
, 1, 1, &readback
))
1010 if (readback
!= SW_BP_OPCODE
) {
1011 LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32
", check memory",
1012 __func__
, bp
->address
);
1013 LOG_ERROR("%s readback=%02" PRIx8
" orig=%02" PRIx8
"",
1014 __func__
, readback
, *bp
->orig_instr
);
1017 bp
->set
= SW_BP_OPCODE
; /* just non 0 */
1019 /* add the memory patch */
1020 struct swbp_mem_patch
*new_patch
= malloc(sizeof(struct swbp_mem_patch
));
1021 if (new_patch
== NULL
) {
1022 LOG_ERROR("%s out of memory", __func__
);
1025 new_patch
->next
= NULL
;
1026 new_patch
->orig_byte
= *bp
->orig_instr
;
1027 new_patch
->physaddr
= physaddr
;
1028 new_patch
->swbp_unique_id
= bp
->unique_id
;
1030 struct swbp_mem_patch
*addto
= x86_32
->swbbp_mem_patch_list
;
1032 x86_32
->swbbp_mem_patch_list
= new_patch
;
1034 while (addto
->next
!= NULL
)
1035 addto
= addto
->next
;
1036 addto
->next
= new_patch
;
1038 LOG_USER("%s software breakpoint %d set at 0x%08" PRIx32
,
1039 __func__
, bp
->unique_id
, bp
->address
);
1043 static int unset_swbp(struct target
*t
, struct breakpoint
*bp
)
1045 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1046 LOG_DEBUG("id %d", bp
->unique_id
);
1048 uint8_t current_instr
;
1050 /* check that user program has not modified breakpoint instruction */
1051 if (calcaddr_pyhsfromlin(t
, bp
->address
, &physaddr
) != ERROR_OK
)
1053 if (read_phys_mem(t
, physaddr
, 1, 1, ¤t_instr
))
1056 if (current_instr
== SW_BP_OPCODE
) {
1057 if (write_phys_mem(t
, physaddr
, 1, 1, bp
->orig_instr
))
1060 LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32
", check memory",
1061 __func__
, bp
->address
);
1062 LOG_ERROR("%s current=%02" PRIx8
" orig=%02" PRIx8
"",
1063 __func__
, current_instr
, *bp
->orig_instr
);
1067 /* remove from patch */
1068 struct swbp_mem_patch
*iter
= x86_32
->swbbp_mem_patch_list
;
1070 if (iter
->swbp_unique_id
== bp
->unique_id
) {
1071 /* it's the first item */
1072 x86_32
->swbbp_mem_patch_list
= iter
->next
;
1075 while (iter
->next
!= NULL
&& iter
->next
->swbp_unique_id
!= bp
->unique_id
)
1077 if (iter
->next
!= NULL
) {
1078 /* it's the next one */
1079 struct swbp_mem_patch
*freeme
= iter
->next
;
1080 iter
->next
= iter
->next
->next
;
1086 LOG_USER("%s software breakpoint %d removed from 0x%08" PRIx32
,
1087 __func__
, bp
->unique_id
, bp
->address
);
1091 static int set_breakpoint(struct target
*t
, struct breakpoint
*bp
)
1093 int error
= ERROR_OK
;
1094 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1095 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
1097 LOG_ERROR("breakpoint already set");
1100 if (bp
->type
== BKPT_HARD
) {
1101 error
= set_hwbp(t
, bp
);
1102 if (error
!= ERROR_OK
) {
1103 LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32
,
1104 __func__
, bp
->address
);
1108 if (x86_32
->sw_bpts_supported(t
)) {
1109 error
= set_swbp(t
, bp
);
1110 if (error
!= ERROR_OK
) {
1111 LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32
,
1112 __func__
, bp
->address
);
1116 LOG_ERROR("%s core doesn't support SW breakpoints", __func__
);
1124 static int unset_breakpoint(struct target
*t
, struct breakpoint
*bp
)
1126 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
1128 LOG_WARNING("breakpoint not set");
1132 if (bp
->type
== BKPT_HARD
) {
1133 if (unset_hwbp(t
, bp
) != ERROR_OK
) {
1134 LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32
,
1135 __func__
, bp
->address
);
1139 if (unset_swbp(t
, bp
) != ERROR_OK
) {
1140 LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32
,
1141 __func__
, bp
->address
);
1149 static int set_watchpoint(struct target
*t
, struct watchpoint
*wp
)
1151 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1152 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
1154 LOG_DEBUG("type=%d, addr=%08" PRIx32
, wp
->rw
, wp
->address
);
1157 LOG_ERROR("%s watchpoint already set", __func__
);
1161 if (wp
->rw
== WPT_READ
) {
1162 LOG_ERROR("%s no support for 'read' watchpoints, use 'access' or 'write'"
1164 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1167 while (debug_reg_list
[wp_num
].used
&& (wp_num
< x86_32
->num_hw_bpoints
))
1169 if (wp_num
>= x86_32
->num_hw_bpoints
) {
1170 LOG_ERROR("%s no debug registers left", __func__
);
1171 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1174 if (wp
->length
!= 4 && wp
->length
!= 2 && wp
->length
!= 1) {
1175 LOG_ERROR("%s only watchpoints of length 1, 2 or 4 are supported", __func__
);
1176 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1181 if (set_debug_regs(t
, wp
->address
, wp_num
,
1182 DR7_BP_WRITE
, wp
->length
) != ERROR_OK
) {
1187 if (set_debug_regs(t
, wp
->address
, wp_num
, DR7_BP_READWRITE
,
1188 wp
->length
) != ERROR_OK
) {
1193 LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__
);
1196 wp
->set
= wp_num
+ 1;
1197 debug_reg_list
[wp_num
].used
= 1;
1198 debug_reg_list
[wp_num
].bp_value
= wp
->address
;
1199 LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32
" with length %d (hwreg=%d)",
1200 wp
->rw
== WPT_READ
? "read" : wp
->rw
== WPT_WRITE
?
1201 "write" : wp
->rw
== WPT_ACCESS
? "access" : "?",
1202 wp
->unique_id
, wp
->address
, wp
->length
, wp_num
);
1206 static int unset_watchpoint(struct target
*t
, struct watchpoint
*wp
)
1208 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1209 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
1210 LOG_DEBUG("type=%d, addr=%08" PRIx32
, wp
->rw
, wp
->address
);
1212 LOG_WARNING("watchpoint not set");
1216 int wp_num
= wp
->set
- 1;
1217 if ((wp_num
< 0) || (wp_num
>= x86_32
->num_hw_bpoints
)) {
1218 LOG_DEBUG("Invalid FP Comparator number in watchpoint");
1221 if (unset_debug_regs(t
, wp_num
) != ERROR_OK
)
1224 debug_reg_list
[wp_num
].used
= 0;
1225 debug_reg_list
[wp_num
].bp_value
= 0;
1228 LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32
" with length %d (hwreg=%d)",
1229 wp
->rw
== WPT_READ
? "read" : wp
->rw
== WPT_WRITE
?
1230 "write" : wp
->rw
== WPT_ACCESS
? "access" : "?",
1231 wp
->unique_id
, wp
->address
, wp
->length
, wp_num
);
1236 static int read_hw_reg_to_cache(struct target
*t
, int num
)
1239 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1241 if (check_not_halted(t
))
1242 return ERROR_TARGET_NOT_HALTED
;
1243 if ((num
< 0) || (num
>= x86_32
->get_num_user_regs(t
)))
1244 return ERROR_COMMAND_SYNTAX_ERROR
;
1245 if (x86_32
->read_hw_reg(t
, num
, ®_value
, 1) != ERROR_OK
) {
1246 LOG_ERROR("%s fail for %s", x86_32
->cache
->reg_list
[num
].name
, __func__
);
1249 LOG_DEBUG("reg %s value 0x%08" PRIx32
,
1250 x86_32
->cache
->reg_list
[num
].name
, reg_value
);
1254 static int write_hw_reg_from_cache(struct target
*t
, int num
)
1256 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1257 if (check_not_halted(t
))
1258 return ERROR_TARGET_NOT_HALTED
;
1259 if ((num
< 0) || (num
>= x86_32
->get_num_user_regs(t
)))
1260 return ERROR_COMMAND_SYNTAX_ERROR
;
1261 if (x86_32
->write_hw_reg(t
, num
, 0, 1) != ERROR_OK
) {
1262 LOG_ERROR("%s fail for %s", x86_32
->cache
->reg_list
[num
].name
, __func__
);
1265 LOG_DEBUG("reg %s value 0x%08" PRIx32
, x86_32
->cache
->reg_list
[num
].name
,
1266 buf_get_u32(x86_32
->cache
->reg_list
[num
].value
, 0, 32));
1270 /* x86 32 commands */
1271 static void handle_iod_output(struct command_context
*cmd_ctx
,
1272 struct target
*target
, uint32_t address
, unsigned size
,
1273 unsigned count
, const uint8_t *buffer
)
1275 const unsigned line_bytecnt
= 32;
1276 unsigned line_modulo
= line_bytecnt
/ size
;
1278 char output
[line_bytecnt
* 4 + 1];
1279 unsigned output_len
= 0;
1281 const char *value_fmt
;
1284 value_fmt
= "%8.8x ";
1287 value_fmt
= "%4.4x ";
1290 value_fmt
= "%2.2x ";
1293 /* "can't happen", caller checked */
1294 LOG_ERROR("%s invalid memory read size: %u", __func__
, size
);
1298 for (unsigned i
= 0; i
< count
; i
++) {
1299 if (i
% line_modulo
== 0) {
1300 output_len
+= snprintf(output
+ output_len
,
1301 sizeof(output
) - output_len
,
1303 (unsigned)(address
+ (i
*size
)));
1307 const uint8_t *value_ptr
= buffer
+ i
* size
;
1310 value
= target_buffer_get_u32(target
, value_ptr
);
1313 value
= target_buffer_get_u16(target
, value_ptr
);
1318 output_len
+= snprintf(output
+ output_len
,
1319 sizeof(output
) - output_len
,
1322 if ((i
% line_modulo
== line_modulo
- 1) || (i
== count
- 1)) {
1323 command_print(cmd_ctx
, "%s", output
);
1329 COMMAND_HANDLER(handle_iod_command
)
1332 return ERROR_COMMAND_SYNTAX_ERROR
;
1335 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
1336 if (address
> 0xffff) {
1337 LOG_ERROR("%s IA-32 I/O space is 2^16, %08" PRIx32
" exceeds max", __func__
, address
);
1338 return ERROR_COMMAND_SYNTAX_ERROR
;
1342 switch (CMD_NAME
[2]) {
1353 return ERROR_COMMAND_SYNTAX_ERROR
;
1356 uint8_t *buffer
= calloc(count
, size
);
1357 struct target
*target
= get_current_target(CMD_CTX
);
1358 int retval
= x86_32_common_read_io(target
, address
, size
, buffer
);
1359 if (ERROR_OK
== retval
)
1360 handle_iod_output(CMD_CTX
, target
, address
, size
, count
, buffer
);
1365 static int target_fill_io(struct target
*target
,
1371 LOG_DEBUG("address=%08X, data_size=%d, b=%08X",
1372 address
, data_size
, b
);
1373 uint8_t target_buf
[data_size
];
1374 switch (data_size
) {
1376 target_buffer_set_u32(target
, target_buf
, b
);
1379 target_buffer_set_u16(target
, target_buf
, b
);
1382 target_buf
[0] = (b
& 0x0ff);
1387 return x86_32_common_write_io(target
, address
, data_size
, target_buf
);
1390 COMMAND_HANDLER(handle_iow_command
)
1393 return ERROR_COMMAND_SYNTAX_ERROR
;
1395 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
1397 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
1398 struct target
*target
= get_current_target(CMD_CTX
);
1401 switch (CMD_NAME
[2]) {
1412 return ERROR_COMMAND_SYNTAX_ERROR
;
1414 return target_fill_io(target
, address
, wordsize
, value
);
1417 static const struct command_registration x86_32_exec_command_handlers
[] = {
1420 .mode
= COMMAND_EXEC
,
1421 .handler
= handle_iow_command
,
1422 .help
= "write I/O port word",
1423 .usage
= "port data[word]",
1427 .mode
= COMMAND_EXEC
,
1428 .handler
= handle_iow_command
,
1429 .help
= "write I/O port halfword",
1430 .usage
= "port data[halfword]",
1434 .mode
= COMMAND_EXEC
,
1435 .handler
= handle_iow_command
,
1436 .help
= "write I/O port byte",
1437 .usage
= "port data[byte]",
1441 .mode
= COMMAND_EXEC
,
1442 .handler
= handle_iod_command
,
1443 .help
= "display I/O port word",
1448 .mode
= COMMAND_EXEC
,
1449 .handler
= handle_iod_command
,
1450 .help
= "display I/O port halfword",
1455 .mode
= COMMAND_EXEC
,
1456 .handler
= handle_iod_command
,
1457 .help
= "display I/O port byte",
1461 COMMAND_REGISTRATION_DONE
1464 const struct command_registration x86_32_command_handlers
[] = {
1467 .mode
= COMMAND_ANY
,
1468 .help
= "x86_32 target commands",
1470 .chain
= x86_32_exec_command_handlers
,
1472 COMMAND_REGISTRATION_DONE
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)