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 LOG_DEBUG("addr=%08" PRIx32
", size=%d, buf=%p", addr
, size
, buf
);
676 LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32
, __func__
, buf
, addr
);
679 retval
= x86_32
->write_hw_reg(t
, EDX
, addr
, 0);
680 if (retval
!= ERROR_OK
) {
681 LOG_ERROR("%s error EDX write", __func__
);
687 retval
= x86_32
->submit_instruction(t
, IORDB32
);
689 retval
= x86_32
->submit_instruction(t
, IORDB16
);
693 retval
= x86_32
->submit_instruction(t
, IORDH32
);
695 retval
= x86_32
->submit_instruction(t
, IORDH16
);
699 retval
= x86_32
->submit_instruction(t
, IORDW32
);
701 retval
= x86_32
->submit_instruction(t
, IORDW16
);
704 LOG_ERROR("%s invalid read io size", __func__
);
708 retval
= x86_32
->read_hw_reg(t
, EAX
, ®val
, 0);
709 if (retval
!= ERROR_OK
) {
710 LOG_ERROR("%s error on read EAX", __func__
);
713 for (uint8_t i
= 0; i
< size
; i
++)
714 buf
[i
] = (regval
>> (i
*8)) & 0x000000FF;
715 retval
= x86_32
->transaction_status(t
);
716 if (retval
!= ERROR_OK
) {
717 LOG_ERROR("%s error on io read", __func__
);
723 int x86_32_common_write_io(struct target
*t
, uint32_t addr
,
724 uint32_t size
, const uint8_t *buf
)
726 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
727 /* if CS.D bit=1 then its a 32 bit code segment, else 16 */
728 bool use32
= (buf_get_u32(x86_32
->cache
->reg_list
[CSAR
].value
, 0, 32)) & CSAR_D
;
729 LOG_DEBUG("addr=%08" PRIx32
", size=%d, buf=%p", addr
, size
, buf
);
731 int retval
= ERROR_FAIL
;
733 LOG_ERROR("%s invalid params buf=%p, addr=%08" PRIx32
, __func__
, buf
, addr
);
736 /* no do the write */
737 retval
= x86_32
->write_hw_reg(t
, EDX
, addr
, 0);
738 if (retval
!= ERROR_OK
) {
739 LOG_ERROR("%s error on EDX write", __func__
);
743 for (uint8_t i
= 0; i
< size
; i
++)
744 regval
+= (buf
[i
] << (i
*8));
745 retval
= x86_32
->write_hw_reg(t
, EAX
, regval
, 0);
746 if (retval
!= ERROR_OK
) {
747 LOG_ERROR("%s error on EAX write", __func__
);
753 retval
= x86_32
->submit_instruction(t
, IOWRB32
);
755 retval
= x86_32
->submit_instruction(t
, IOWRB16
);
759 retval
= x86_32
->submit_instruction(t
, IOWRH32
);
761 retval
= x86_32
->submit_instruction(t
, IOWRH16
);
765 retval
= x86_32
->submit_instruction(t
, IOWRW32
);
767 retval
= x86_32
->submit_instruction(t
, IOWRW16
);
770 LOG_ERROR("%s invalid write io size", __func__
);
773 retval
= x86_32
->transaction_status(t
);
774 if (retval
!= ERROR_OK
) {
775 LOG_ERROR("%s error on io write", __func__
);
781 int x86_32_common_add_watchpoint(struct target
*t
, struct watchpoint
*wp
)
784 /* set_watchpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
785 * hardware registers are gone
787 return set_watchpoint(t
, wp
);
790 int x86_32_common_remove_watchpoint(struct target
*t
, struct watchpoint
*wp
)
792 if (check_not_halted(t
))
793 return ERROR_TARGET_NOT_HALTED
;
795 unset_watchpoint(t
, wp
);
799 int x86_32_common_add_breakpoint(struct target
*t
, struct breakpoint
*bp
)
801 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
802 if (check_not_halted(t
))
803 return ERROR_TARGET_NOT_HALTED
;
804 /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all
805 * hardware registers are gone (for hardware breakpoints)
807 return set_breakpoint(t
, bp
);
810 int x86_32_common_remove_breakpoint(struct target
*t
, struct breakpoint
*bp
)
812 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
813 if (check_not_halted(t
))
814 return ERROR_TARGET_NOT_HALTED
;
816 unset_breakpoint(t
, bp
);
821 static int set_debug_regs(struct target
*t
, uint32_t address
,
822 uint8_t bp_num
, uint8_t bp_type
, uint8_t bp_length
)
824 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
825 LOG_DEBUG("addr=%08" PRIx32
", bp_num=%d, bp_type=%d, pb_length=%d",
826 address
, bp_num
, bp_type
, bp_length
);
828 /* DR7 - set global enable */
829 uint32_t dr7
= buf_get_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32);
831 if (bp_length
!= 1 && bp_length
!= 2 && bp_length
!= 4)
834 if (DR7_BP_FREE(dr7
, bp_num
))
835 DR7_GLOBAL_ENABLE(dr7
, bp_num
);
837 LOG_ERROR("%s dr7 error, already enabled, val=%08" PRIx32
, __func__
, dr7
);
838 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
843 /* 00 - only on instruction execution */
844 DR7_SET_EXE(dr7
, bp_num
);
845 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
848 /* 01 - only on data writes */
849 DR7_SET_WRITE(dr7
, bp_num
);
850 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
853 /* 10 UNSUPPORTED - an I/O read and I/O write */
854 LOG_ERROR("%s unsupported feature bp_type=%d", __func__
, bp_type
);
858 /* on data read or data write */
859 DR7_SET_ACCESS(dr7
, bp_num
);
860 DR7_SET_LENGTH(dr7
, bp_num
, bp_length
);
863 LOG_ERROR("%s invalid request [only 0-3] bp_type=%d", __func__
, bp_type
);
867 /* update regs in the reg cache ready to be written to hardware
870 buf_set_u32(x86_32
->cache
->reg_list
[bp_num
+DR0
].value
, 0, 32, address
);
871 x86_32
->cache
->reg_list
[bp_num
+DR0
].dirty
= 1;
872 x86_32
->cache
->reg_list
[bp_num
+DR0
].valid
= 1;
873 buf_set_u32(x86_32
->cache
->reg_list
[DR6
].value
, 0, 32, PM_DR6
);
874 x86_32
->cache
->reg_list
[DR6
].dirty
= 1;
875 x86_32
->cache
->reg_list
[DR6
].valid
= 1;
876 buf_set_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32, dr7
);
877 x86_32
->cache
->reg_list
[DR7
].dirty
= 1;
878 x86_32
->cache
->reg_list
[DR7
].valid
= 1;
882 static int unset_debug_regs(struct target
*t
, uint8_t bp_num
)
884 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
885 LOG_DEBUG("bp_num=%d", bp_num
);
887 uint32_t dr7
= buf_get_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32);
889 if (!(DR7_BP_FREE(dr7
, bp_num
))) {
890 DR7_GLOBAL_DISABLE(dr7
, bp_num
);
892 LOG_ERROR("%s dr7 error, not enabled, val=%08" PRIx32
, __func__
, dr7
);
893 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
895 /* this will clear rw and len bits */
896 DR7_RESET_RWLEN_BITS(dr7
, bp_num
);
898 /* update regs in the reg cache ready to be written to hardware
901 buf_set_u32(x86_32
->cache
->reg_list
[bp_num
+DR0
].value
, 0, 32, 0);
902 x86_32
->cache
->reg_list
[bp_num
+DR0
].dirty
= 1;
903 x86_32
->cache
->reg_list
[bp_num
+DR0
].valid
= 1;
904 buf_set_u32(x86_32
->cache
->reg_list
[DR6
].value
, 0, 32, PM_DR6
);
905 x86_32
->cache
->reg_list
[DR6
].dirty
= 1;
906 x86_32
->cache
->reg_list
[DR6
].valid
= 1;
907 buf_set_u32(x86_32
->cache
->reg_list
[DR7
].value
, 0, 32, dr7
);
908 x86_32
->cache
->reg_list
[DR7
].dirty
= 1;
909 x86_32
->cache
->reg_list
[DR7
].valid
= 1;
913 static int set_hwbp(struct target
*t
, struct breakpoint
*bp
)
915 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
916 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
917 uint8_t hwbp_num
= 0;
919 while (debug_reg_list
[hwbp_num
].used
&& (hwbp_num
< x86_32
->num_hw_bpoints
))
921 if (hwbp_num
>= x86_32
->num_hw_bpoints
) {
922 LOG_ERROR("%s no free hw breakpoint bpid=%d", __func__
, bp
->unique_id
);
923 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
925 if (set_debug_regs(t
, bp
->address
, hwbp_num
, DR7_BP_EXECUTE
, 1) != ERROR_OK
)
927 bp
->set
= hwbp_num
+ 1;
928 debug_reg_list
[hwbp_num
].used
= 1;
929 debug_reg_list
[hwbp_num
].bp_value
= bp
->address
;
930 LOG_USER("%s hardware breakpoint %d set at 0x%08" PRIx32
" (hwreg=%d)", __func__
,
931 bp
->unique_id
, debug_reg_list
[hwbp_num
].bp_value
, hwbp_num
);
935 static int unset_hwbp(struct target
*t
, struct breakpoint
*bp
)
937 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
938 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
939 int hwbp_num
= bp
->set
- 1;
941 if ((hwbp_num
< 0) || (hwbp_num
>= x86_32
->num_hw_bpoints
)) {
942 LOG_ERROR("%s invalid breakpoint number=%d, bpid=%d",
943 __func__
, hwbp_num
, bp
->unique_id
);
947 if (unset_debug_regs(t
, hwbp_num
) != ERROR_OK
)
949 debug_reg_list
[hwbp_num
].used
= 0;
950 debug_reg_list
[hwbp_num
].bp_value
= 0;
952 LOG_USER("%s hardware breakpoint %d removed from 0x%08" PRIx32
" (hwreg=%d)",
953 __func__
, bp
->unique_id
, bp
->address
, hwbp_num
);
957 static int set_swbp(struct target
*t
, struct breakpoint
*bp
)
959 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
960 LOG_DEBUG("id %d", bp
->unique_id
);
962 uint8_t opcode
= SW_BP_OPCODE
;
965 if (calcaddr_pyhsfromlin(t
, bp
->address
, &physaddr
) != ERROR_OK
)
967 if (read_phys_mem(t
, physaddr
, 1, 1, bp
->orig_instr
))
970 LOG_DEBUG("set software breakpoint - orig byte=%02" PRIx8
"", *bp
->orig_instr
);
972 /* just write the instruction trap byte */
973 if (write_phys_mem(t
, physaddr
, 1, 1, &opcode
))
976 /* verify that this is not invalid/read-only memory */
977 if (read_phys_mem(t
, physaddr
, 1, 1, &readback
))
980 if (readback
!= SW_BP_OPCODE
) {
981 LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32
", check memory",
982 __func__
, bp
->address
);
983 LOG_ERROR("%s readback=%02" PRIx8
" orig=%02" PRIx8
"",
984 __func__
, readback
, *bp
->orig_instr
);
987 bp
->set
= SW_BP_OPCODE
; /* just non 0 */
989 /* add the memory patch */
990 struct swbp_mem_patch
*new_patch
= malloc(sizeof(struct swbp_mem_patch
));
991 if (new_patch
== NULL
) {
992 LOG_ERROR("%s out of memory", __func__
);
995 new_patch
->next
= NULL
;
996 new_patch
->orig_byte
= *bp
->orig_instr
;
997 new_patch
->physaddr
= physaddr
;
998 new_patch
->swbp_unique_id
= bp
->unique_id
;
1000 struct swbp_mem_patch
*addto
= x86_32
->swbbp_mem_patch_list
;
1002 x86_32
->swbbp_mem_patch_list
= new_patch
;
1004 while (addto
->next
!= NULL
)
1005 addto
= addto
->next
;
1006 addto
->next
= new_patch
;
1008 LOG_USER("%s software breakpoint %d set at 0x%08" PRIx32
,
1009 __func__
, bp
->unique_id
, bp
->address
);
1013 static int unset_swbp(struct target
*t
, struct breakpoint
*bp
)
1015 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1016 LOG_DEBUG("id %d", bp
->unique_id
);
1018 uint8_t current_instr
;
1020 /* check that user program has not modified breakpoint instruction */
1021 if (calcaddr_pyhsfromlin(t
, bp
->address
, &physaddr
) != ERROR_OK
)
1023 if (read_phys_mem(t
, physaddr
, 1, 1, ¤t_instr
))
1026 if (current_instr
== SW_BP_OPCODE
) {
1027 if (write_phys_mem(t
, physaddr
, 1, 1, bp
->orig_instr
))
1030 LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32
", check memory",
1031 __func__
, bp
->address
);
1032 LOG_ERROR("%s current=%02" PRIx8
" orig=%02" PRIx8
"",
1033 __func__
, current_instr
, *bp
->orig_instr
);
1037 /* remove from patch */
1038 struct swbp_mem_patch
*iter
= x86_32
->swbbp_mem_patch_list
;
1040 if (iter
->swbp_unique_id
== bp
->unique_id
) {
1041 /* it's the first item */
1042 x86_32
->swbbp_mem_patch_list
= iter
->next
;
1045 while (iter
->next
!= NULL
&& iter
->next
->swbp_unique_id
!= bp
->unique_id
)
1047 if (iter
->next
!= NULL
) {
1048 /* it's the next one */
1049 struct swbp_mem_patch
*freeme
= iter
->next
;
1050 iter
->next
= iter
->next
->next
;
1056 LOG_USER("%s software breakpoint %d removed from 0x%08" PRIx32
,
1057 __func__
, bp
->unique_id
, bp
->address
);
1061 static int set_breakpoint(struct target
*t
, struct breakpoint
*bp
)
1063 int error
= ERROR_OK
;
1064 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1065 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
1067 LOG_ERROR("breakpoint already set");
1070 if (bp
->type
== BKPT_HARD
) {
1071 error
= set_hwbp(t
, bp
);
1072 if (error
!= ERROR_OK
) {
1073 LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32
,
1074 __func__
, bp
->address
);
1078 if (x86_32
->sw_bpts_supported(t
)) {
1079 error
= set_swbp(t
, bp
);
1080 if (error
!= ERROR_OK
) {
1081 LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32
,
1082 __func__
, bp
->address
);
1086 LOG_ERROR("%s core doesn't support SW breakpoints", __func__
);
1094 static int unset_breakpoint(struct target
*t
, struct breakpoint
*bp
)
1096 LOG_DEBUG("type=%d, addr=%08" PRIx32
, bp
->type
, bp
->address
);
1098 LOG_WARNING("breakpoint not set");
1102 if (bp
->type
== BKPT_HARD
) {
1103 if (unset_hwbp(t
, bp
) != ERROR_OK
) {
1104 LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32
,
1105 __func__
, bp
->address
);
1109 if (unset_swbp(t
, bp
) != ERROR_OK
) {
1110 LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32
,
1111 __func__
, bp
->address
);
1119 static int set_watchpoint(struct target
*t
, struct watchpoint
*wp
)
1121 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1122 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
1124 LOG_DEBUG("type=%d, addr=%08" PRIx32
, wp
->rw
, wp
->address
);
1127 LOG_ERROR("%s watchpoint already set", __func__
);
1131 if (wp
->rw
== WPT_READ
) {
1132 LOG_ERROR("%s no support for 'read' watchpoints, use 'access' or 'write'"
1134 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1137 while (debug_reg_list
[wp_num
].used
&& (wp_num
< x86_32
->num_hw_bpoints
))
1139 if (wp_num
>= x86_32
->num_hw_bpoints
) {
1140 LOG_ERROR("%s no debug registers left", __func__
);
1141 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1144 if (wp
->length
!= 4 && wp
->length
!= 2 && wp
->length
!= 1) {
1145 LOG_ERROR("%s only watchpoints of length 1, 2 or 4 are supported", __func__
);
1146 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
1151 if (set_debug_regs(t
, wp
->address
, wp_num
,
1152 DR7_BP_WRITE
, wp
->length
) != ERROR_OK
) {
1157 if (set_debug_regs(t
, wp
->address
, wp_num
, DR7_BP_READWRITE
,
1158 wp
->length
) != ERROR_OK
) {
1163 LOG_ERROR("%s only 'access' or 'write' watchpoints are supported", __func__
);
1166 wp
->set
= wp_num
+ 1;
1167 debug_reg_list
[wp_num
].used
= 1;
1168 debug_reg_list
[wp_num
].bp_value
= wp
->address
;
1169 LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32
" with length %d (hwreg=%d)",
1170 wp
->rw
== WPT_READ
? "read" : wp
->rw
== WPT_WRITE
?
1171 "write" : wp
->rw
== WPT_ACCESS
? "access" : "?",
1172 wp
->unique_id
, wp
->address
, wp
->length
, wp_num
);
1176 static int unset_watchpoint(struct target
*t
, struct watchpoint
*wp
)
1178 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1179 struct x86_32_dbg_reg
*debug_reg_list
= x86_32
->hw_break_list
;
1180 LOG_DEBUG("type=%d, addr=%08" PRIx32
, wp
->rw
, wp
->address
);
1182 LOG_WARNING("watchpoint not set");
1186 int wp_num
= wp
->set
- 1;
1187 if ((wp_num
< 0) || (wp_num
>= x86_32
->num_hw_bpoints
)) {
1188 LOG_DEBUG("Invalid FP Comparator number in watchpoint");
1191 if (unset_debug_regs(t
, wp_num
) != ERROR_OK
)
1194 debug_reg_list
[wp_num
].used
= 0;
1195 debug_reg_list
[wp_num
].bp_value
= 0;
1198 LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32
" with length %d (hwreg=%d)",
1199 wp
->rw
== WPT_READ
? "read" : wp
->rw
== WPT_WRITE
?
1200 "write" : wp
->rw
== WPT_ACCESS
? "access" : "?",
1201 wp
->unique_id
, wp
->address
, wp
->length
, wp_num
);
1206 static int read_hw_reg_to_cache(struct target
*t
, int num
)
1209 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1211 if (check_not_halted(t
))
1212 return ERROR_TARGET_NOT_HALTED
;
1213 if ((num
< 0) || (num
>= x86_32
->get_num_user_regs(t
)))
1214 return ERROR_COMMAND_SYNTAX_ERROR
;
1215 if (x86_32
->read_hw_reg(t
, num
, ®_value
, 1) != ERROR_OK
) {
1216 LOG_ERROR("%s fail for %s", x86_32
->cache
->reg_list
[num
].name
, __func__
);
1219 LOG_DEBUG("reg %s value 0x%08" PRIx32
,
1220 x86_32
->cache
->reg_list
[num
].name
, reg_value
);
1224 static int write_hw_reg_from_cache(struct target
*t
, int num
)
1226 struct x86_32_common
*x86_32
= target_to_x86_32(t
);
1227 if (check_not_halted(t
))
1228 return ERROR_TARGET_NOT_HALTED
;
1229 if ((num
< 0) || (num
>= x86_32
->get_num_user_regs(t
)))
1230 return ERROR_COMMAND_SYNTAX_ERROR
;
1231 if (x86_32
->write_hw_reg(t
, num
, 0, 1) != ERROR_OK
) {
1232 LOG_ERROR("%s fail for %s", x86_32
->cache
->reg_list
[num
].name
, __func__
);
1235 LOG_DEBUG("reg %s value 0x%08" PRIx32
, x86_32
->cache
->reg_list
[num
].name
,
1236 buf_get_u32(x86_32
->cache
->reg_list
[num
].value
, 0, 32));
1240 /* x86 32 commands */
1241 static void handle_iod_output(struct command_context
*cmd_ctx
,
1242 struct target
*target
, uint32_t address
, unsigned size
,
1243 unsigned count
, const uint8_t *buffer
)
1245 const unsigned line_bytecnt
= 32;
1246 unsigned line_modulo
= line_bytecnt
/ size
;
1248 char output
[line_bytecnt
* 4 + 1];
1249 unsigned output_len
= 0;
1251 const char *value_fmt
;
1254 value_fmt
= "%8.8x ";
1257 value_fmt
= "%4.4x ";
1260 value_fmt
= "%2.2x ";
1263 /* "can't happen", caller checked */
1264 LOG_ERROR("%s invalid memory read size: %u", __func__
, size
);
1268 for (unsigned i
= 0; i
< count
; i
++) {
1269 if (i
% line_modulo
== 0) {
1270 output_len
+= snprintf(output
+ output_len
,
1271 sizeof(output
) - output_len
,
1273 (unsigned)(address
+ (i
*size
)));
1277 const uint8_t *value_ptr
= buffer
+ i
* size
;
1280 value
= target_buffer_get_u32(target
, value_ptr
);
1283 value
= target_buffer_get_u16(target
, value_ptr
);
1288 output_len
+= snprintf(output
+ output_len
,
1289 sizeof(output
) - output_len
,
1292 if ((i
% line_modulo
== line_modulo
- 1) || (i
== count
- 1)) {
1293 command_print(cmd_ctx
, "%s", output
);
1299 COMMAND_HANDLER(handle_iod_command
)
1302 return ERROR_COMMAND_SYNTAX_ERROR
;
1305 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
1306 if (address
> 0xffff) {
1307 LOG_ERROR("%s IA-32 I/O space is 2^16, %08" PRIx32
" exceeds max", __func__
, address
);
1308 return ERROR_COMMAND_SYNTAX_ERROR
;
1312 switch (CMD_NAME
[2]) {
1323 return ERROR_COMMAND_SYNTAX_ERROR
;
1326 uint8_t *buffer
= calloc(count
, size
);
1327 struct target
*target
= get_current_target(CMD_CTX
);
1328 int retval
= x86_32_common_read_io(target
, address
, size
, buffer
);
1329 if (ERROR_OK
== retval
)
1330 handle_iod_output(CMD_CTX
, target
, address
, size
, count
, buffer
);
1335 static int target_fill_io(struct target
*target
,
1341 LOG_DEBUG("address=%08X, data_size=%d, b=%08X",
1342 address
, data_size
, b
);
1343 uint8_t target_buf
[data_size
];
1344 switch (data_size
) {
1346 target_buffer_set_u32(target
, target_buf
, b
);
1349 target_buffer_set_u16(target
, target_buf
, b
);
1352 target_buf
[0] = (b
& 0x0ff);
1357 return x86_32_common_write_io(target
, address
, data_size
, target_buf
);
1360 COMMAND_HANDLER(handle_iow_command
)
1363 return ERROR_COMMAND_SYNTAX_ERROR
;
1365 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], address
);
1367 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
1368 struct target
*target
= get_current_target(CMD_CTX
);
1371 switch (CMD_NAME
[2]) {
1382 return ERROR_COMMAND_SYNTAX_ERROR
;
1384 return target_fill_io(target
, address
, wordsize
, value
);
1387 static const struct command_registration x86_32_exec_command_handlers
[] = {
1390 .mode
= COMMAND_EXEC
,
1391 .handler
= handle_iow_command
,
1392 .help
= "write I/O port word",
1393 .usage
= "port data[word]",
1397 .mode
= COMMAND_EXEC
,
1398 .handler
= handle_iow_command
,
1399 .help
= "write I/O port halfword",
1400 .usage
= "port data[halfword]",
1404 .mode
= COMMAND_EXEC
,
1405 .handler
= handle_iow_command
,
1406 .help
= "write I/O port byte",
1407 .usage
= "port data[byte]",
1411 .mode
= COMMAND_EXEC
,
1412 .handler
= handle_iod_command
,
1413 .help
= "display I/O port word",
1418 .mode
= COMMAND_EXEC
,
1419 .handler
= handle_iod_command
,
1420 .help
= "display I/O port halfword",
1425 .mode
= COMMAND_EXEC
,
1426 .handler
= handle_iod_command
,
1427 .help
= "display I/O port byte",
1431 COMMAND_REGISTRATION_DONE
1434 const struct command_registration x86_32_command_handlers
[] = {
1437 .mode
= COMMAND_ANY
,
1438 .help
= "x86_32 target commands",
1440 .chain
= x86_32_exec_command_handlers
,
1442 COMMAND_REGISTRATION_DONE