This is an automated email from Gerrit.

"zapb <d...@zapb.de>" just uploaded a new patch set to Gerrit, which you can 
find at https://review.openocd.org/c/openocd/+/8634

-- gerrit

commit eae12b140c2402a58d3841e827af8fb773a75672
Author: Marc Schink <d...@zapb.de>
Date:   Sat Nov 23 14:43:51 2024 +0000

    flash/nor/tcl: Add 'read_memory' function
    
    This function allows to read non-memory mapped flash content directly
    via Tcl script. The API is the same as for the 'read_memory' function
    for targets.
    
    Change-Id: I4a8d0d7ea2f778ac8f1501227b60b964c881cb84
    Signed-off-by: Marc Schink <d...@zapb.de>

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 9b5cfbb83e..17bcdacbc5 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -5791,6 +5791,24 @@ The flash bank to use is inferred from the @var{address} 
of
 each block, and the specified length must stay within that bank.
 @end deffn
 
+@deffn {Command} {flash read_memory} address width count
+This function provides an efficient way to read flash memory from a Tcl script.
+A Tcl list containing the requested memory elements is returned by this 
function.
+
+@itemize
+@item @var{address} ... flash memory address
+@item @var{width} ... memory access bit size, can be 8, 16, 32 or 64
+@item @var{count} ... number of elements to read
+@end itemize
+
+For example, the following command reads two 32 bit words from the flash
+memory at address 0x08000000:
+
+@example
+read_memory 0x08000000 32 2
+@end example
+@end deffn
+
 @deffn {Command} {flash write_bank} num filename [offset]
 Write the binary @file{filename} to flash bank @var{num},
 starting at @var{offset} bytes from the beginning of the bank. If @var{offset}
diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c
index e21620934a..a41437213c 100644
--- a/src/flash/nor/tcl.c
+++ b/src/flash/nor/tcl.c
@@ -727,6 +727,122 @@ COMMAND_HANDLER(handle_flash_md_command)
        return retval;
 }
 
+COMMAND_HANDLER(handle_flash_read_memory_command)
+{
+       /*
+        * CMD_ARGV[0] = memory address
+        * CMD_ARGV[1] = desired element width in bits
+        * CMD_ARGV[2] = number of elements to read
+        */
+
+       if (CMD_ARGC != 3)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       /* Arg 1: Memory address. */
+       target_addr_t addr;
+       COMMAND_PARSE_NUMBER(u64, CMD_ARGV[0], addr);
+
+       /* Arg 2: Bit width of one element. */
+       unsigned int width_bits;
+       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[1], width_bits);
+
+       /* Arg 3: Number of elements to read. */
+       unsigned int count;
+       COMMAND_PARSE_NUMBER(uint, CMD_ARGV[2], count);
+
+       switch (width_bits) {
+       case 8:
+       case 16:
+       case 32:
+       case 64:
+               break;
+       default:
+               command_print(CMD, "invalid width, must be 8, 16, 32 or 64");
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
+       const unsigned int width = width_bits / 8;
+
+       if ((addr + (count * width)) < addr) {
+               command_print(CMD, "addr + count wraps to zero");
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
+       if (count > 65536) {
+               command_print(CMD, "too large read request, exceeds 64K 
elements");
+               return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+
+       struct target *target = get_current_target(CMD_CTX);
+       struct flash_bank *bank;
+       int retval = get_flash_bank_by_addr(target, addr, true, &bank);
+       if (retval != ERROR_OK)
+               return retval;
+
+       uint32_t offset = addr - bank->base;
+       uint32_t sizebytes = count * width_bits;
+       if (offset + sizebytes > bank->size) {
+               command_print(CMD, "cannot cross flash bank borders");
+               return ERROR_FAIL;
+       }
+
+       const size_t buffer_size = 4096;
+       uint8_t *buffer = malloc(buffer_size);
+
+       if (!buffer) {
+               command_print(CMD, "failed to allocate memory");
+               return ERROR_FAIL;
+       }
+
+       char *separator = "";
+       while (count > 0) {
+               const unsigned int max_chunk_len = buffer_size / width;
+               const size_t chunk_len = MIN(count, max_chunk_len);
+
+               retval = flash_driver_read(bank, buffer, offset, chunk_len * 
width);
+
+               if (retval != ERROR_OK) {
+                       LOG_DEBUG("read at " TARGET_ADDR_FMT " with width=%u 
and count=%zu failed",
+                               addr, width_bits, chunk_len);
+                       /*
+                        * FIXME: we append the errmsg to the list of value 
already read.
+                        * Add a way to flush and replace old output, but 
LOG_DEBUG() it
+                        */
+                       command_print(CMD, "failed to read memory");
+                       free(buffer);
+                       return retval;
+               }
+
+               for (size_t i = 0; i < chunk_len ; i++) {
+                       uint64_t v = 0;
+
+                       switch (width) {
+                       case 8:
+                               v = target_buffer_get_u64(target, &buffer[i * 
width]);
+                               break;
+                       case 4:
+                               v = target_buffer_get_u32(target, &buffer[i * 
width]);
+                               break;
+                       case 2:
+                               v = target_buffer_get_u16(target, &buffer[i * 
width]);
+                               break;
+                       case 1:
+                               v = buffer[i];
+                               break;
+                       }
+
+                       command_print_sameline(CMD, "%s0x%" PRIx64, separator, 
v);
+                       separator = " ";
+               }
+
+               count -= chunk_len;
+               offset += chunk_len * width;
+       }
+
+       free(buffer);
+
+       return ERROR_OK;
+}
 
 COMMAND_HANDLER(handle_flash_write_bank_command)
 {
@@ -1170,6 +1286,13 @@ static const struct command_registration 
flash_exec_command_handlers[] = {
                .usage = "address [count]",
                .help = "Display words from flash.",
        },
+       {
+               .name = "read_memory",
+               .mode = COMMAND_EXEC,
+               .handler = handle_flash_read_memory_command,
+               .help = "Read Tcl list of 8/16/32/64 bit numbers from flash 
memory",
+               .usage = "address width count",
+       },
        {
                .name = "write_bank",
                .handler = handle_flash_write_bank_command,

-- 

Reply via email to