This is an automated email from Gerrit.

"Name of user not set <zed...@gmail.com>" just uploaded a new patch set to 
Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6748

-- gerrit

commit 2c5a6911dbf676115b520d1869da2d483e033d3c
Author: Zoltán Dudás <zed...@gmail.com>
Date:   Wed Nov 24 17:13:50 2021 +0100

    semihosting: Extended operation, Tcl command exec on host
    
    Enabling user defined semihosting operation number range to be processed
    with a new semihosting command.
    
    Defining a new semihosting operation from the forementioned range:
    Execute a Tcl command on the host defined by the target.
    For example, this method can be used to automatically configure RTT
    with actual control block location from target.
    
    Signed-off-by: Zoltán Dudás <zed...@gmail.com>
    Change-Id: I10e1784b1fecd4e630d78df81cb44bf1aa2fc247

diff --git a/doc/openocd.texi b/doc/openocd.texi
index 0ab4b36ac..7eb70a7eb 100644
--- a/doc/openocd.texi
+++ b/doc/openocd.texi
@@ -9170,6 +9170,15 @@ To make the SEMIHOSTING_SYS_EXIT call return normally, 
enable
 this option (default: disabled).
 @end deffn
 
+@deffn {Command} {arm semihosting_extended} [@option{enable}|@option{disable}]
+@cindex ARM semihosting
+Display status of semihosting extended functionality, after optionally
+changing that status.
+
+This option enables the user-defined semihosting operation number
+range (0x0100 - 0x01ff) to be processed.
+@end deffn
+
 @section ARMv4 and ARMv5 Architecture
 @cindex ARMv4
 @cindex ARMv5
diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c
index 792474acf..2a613c586 100644
--- a/src/target/arm_semihosting.c
+++ b/src/target/arm_semihosting.c
@@ -367,7 +367,8 @@ int arm_semihosting(struct target *target, int *retval)
                }
 
                /* Check for ARM operation numbers. */
-               if (semihosting->op >= 0 && semihosting->op <= 0x31) {
+               if ((semihosting->op >= 0 && semihosting->op <= 0x31) ||
+                               ((semihosting->is_extended) && (semihosting->op 
>= 0x100 && semihosting->op <= 0x1FF))) {
                        *retval = semihosting_common(target);
                        if (*retval != ERROR_OK) {
                                LOG_ERROR("Failed semihosting operation 
(0x%02X)", semihosting->op);
diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c
index 5c96e1cd6..0a3ff005f 100644
--- a/src/target/semihosting_common.c
+++ b/src/target/semihosting_common.c
@@ -117,6 +117,8 @@ int semihosting_common_init(struct target *target, void 
*setup,
        semihosting->hit_fileio = false;
        semihosting->is_resumable = false;
        semihosting->has_resumable_exit = false;
+       semihosting->is_extended = false;
+       semihosting->extended_ctx = NULL;
        semihosting->word_size_bytes = 0;
        semihosting->op = -1;
        semihosting->param = 0;
@@ -1262,6 +1264,48 @@ int semihosting_common(struct target *target)
                        }
                        break;
 
+               case SEMIHOSTING_EXT_TCL_CMD:   /* 0x169 */
+                       /*
+                        * Runs a Tcl command in the context obtained from the
+                        * extended functionality enable command handler.
+                        *
+                        * Entry
+                        * On entry, the PARAMETER REGISTER contains a pointer 
to a
+                        * two-field data block:
+                        * - field 1 Contains a pointer to the command string
+                        * - field 2 Contains the command length
+                        *
+                        * Return
+                        * On exit, the RETURN REGISTER contains the return 
status.
+                        */
+                       retval = semihosting_read_fields(target, 2, fields);
+                       if (retval != ERROR_OK) {
+                               return retval;
+                       } else {
+                               uint64_t addr = semihosting_get_field(target, 
0, fields);
+                               size_t len = semihosting_get_field(target, 1, 
fields);
+
+                               if (len > 0 && len < 
SEMIHOSTING_MAX_TCL_COMMAND_LENGTH) {
+                                       char command[len];
+
+                                       retval = target_read_buffer(target, 
addr, len, (uint8_t*)command);
+
+                                       if (retval != ERROR_OK)
+                                               return retval;
+
+                                       if(target->semihosting->extended_ctx) {
+                                               
command_run_line(target->semihosting->extended_ctx, command);
+                                               LOG_DEBUG("Runnning tcl command 
from semihosting (length=%u): %s",
+                                                               (unsigned 
int)len, command);
+                                       } else {
+                                               semihosting->result = -1;
+                                               return -1;
+                                       }
+                               }
+                               semihosting->result = 0;
+                       }
+                       break;
+
                case SEMIHOSTING_SYS_ELAPSED:   /* 0x30 */
                /*
                 * Returns the number of elapsed target ticks since execution
@@ -1608,6 +1652,38 @@ static 
__COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command)
        return ERROR_OK;
 }
 
+static __COMMAND_HANDLER(handle_common_semihosting_extended_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       if (!target) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct semihosting *semihosting = target->semihosting;
+       if (!semihosting) {
+               command_print(CMD, "semihosting not supported for current 
target");
+               return ERROR_FAIL;
+       }
+
+       if (!semihosting->is_active) {
+               command_print(CMD, "semihosting not yet enabled for current 
target");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC > 0)
+               COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_extended);
+
+       command_print(CMD, "semihosting extended functionality is %s",
+               semihosting->is_extended
+               ? "enabled" : "disabled");
+
+       semihosting->extended_ctx = copy_command_context(CMD_CTX);
+
+       return ERROR_OK;
+}
+
 const struct command_registration semihosting_common_handlers[] = {
        {
                "semihosting",
@@ -1637,5 +1713,12 @@ const struct command_registration 
semihosting_common_handlers[] = {
                .usage = "['enable'|'disable']",
                .help = "activate support for semihosting resumable exit",
        },
+       {
+               "semihosting_extended",
+               .handler = handle_common_semihosting_extended_command,
+               .mode = COMMAND_EXEC,
+               .usage = "['enable'|'disable']",
+               .help = "activate support for extended semihosting operations",
+       },
        COMMAND_REGISTRATION_DONE
 };
diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h
index b83464ed5..4098afecc 100644
--- a/src/target/semihosting_common.h
+++ b/src/target/semihosting_common.h
@@ -75,8 +75,16 @@ enum semihosting_operation_numbers {
        SEMIHOSTING_SYS_WRITE = 0x05,
        SEMIHOSTING_SYS_WRITEC = 0x03,
        SEMIHOSTING_SYS_WRITE0 = 0x04,
+       /*
+        * Semihosting extension, Tcl command run. Operation number
+        * obtained from user defined area (0x100-0x1FF).
+        */
+       SEMIHOSTING_EXT_TCL_CMD = 0x169,
 };
 
+/** Maxmium allowed Tcl command length in bytes*/
+#define SEMIHOSTING_MAX_TCL_COMMAND_LENGTH 256
+
 /*
  * Codes used by SEMIHOSTING_SYS_EXIT (formerly
  * SEMIHOSTING_REPORT_EXCEPTION).
@@ -108,6 +116,9 @@ struct semihosting {
        /** Most are resumable, except the two exit calls. */
        bool is_resumable;
 
+       /** A flag reporting whether extended semihosting functionality is 
active. */
+       bool is_extended;
+
        /**
         * When SEMIHOSTING_SYS_EXIT is called outside a debug session,
         * things are simple, the openocd process calls exit() and passes
@@ -153,6 +164,9 @@ struct semihosting {
        /** The current time when 'execution starts' */
        clock_t setup_time;
 
+       /** Command context to be used in extended semihosting functionality. */
+       struct command_context * extended_ctx;
+
        int (*setup)(struct target *target, int enable);
        int (*post_result)(struct target *target);
 };

-- 

Reply via email to