From ce5027ab019ac7f96d05ec5f8f533144b3bcafdf Mon Sep 17 00:00:00 2001 From: Erhan Kurubas Date: Tue, 5 Apr 2022 13:49:28 +0300 Subject: [PATCH] semihosting: add semihosting_basedir command This command allows users to set base working directory for the semihosting I/O operations.Default is the current OpenOCD directory. Signed-off-by: Erhan Kurubas Change-Id: I80c5979e4c96d66cccdd12cc6fcd5f353e5c6b4d Reviewed-on: https://review.openocd.org/c/openocd/+/6888 Tested-by: jenkins Reviewed-by: Antonio Borneo --- doc/openocd.texi | 6 ++++ src/target/semihosting_common.c | 56 +++++++++++++++++++++++++++++++-- src/target/semihosting_common.h | 3 ++ src/target/target.c | 3 ++ 4 files changed, 65 insertions(+), 3 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index be9e5ac085..cc1d104411 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -9624,6 +9624,12 @@ is valid during the run of the event handlers and is accessible with this command. @end deffn +@deffn {Command} {arm semihosting_basedir} [dir] +@cindex ARM semihosting +Set the base directory for semihosting I/O, either an absolute path or a path relative to OpenOCD working directory. +Use "." for the current directory. +@end deffn + @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index bc1f417ef0..2df6e38aea 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -159,6 +159,7 @@ int semihosting_common_init(struct target *target, void *setup, semihosting->result = -1; semihosting->sys_errno = -1; semihosting->cmdline = NULL; + semihosting->basedir = NULL; /* If possible, update it in setup(). */ semihosting->setup_time = clock(); @@ -870,17 +871,21 @@ int semihosting_common(struct target *target) semihosting->sys_errno = EINVAL; break; } - uint8_t *fn = malloc(len+1); + size_t basedir_len = semihosting->basedir ? strlen(semihosting->basedir) : 0; + uint8_t *fn = malloc(basedir_len + len + 2); if (!fn) { semihosting->result = -1; semihosting->sys_errno = ENOMEM; } else { - retval = target_read_memory(target, addr, 1, len, fn); + strncpy((char *)fn, semihosting->basedir, basedir_len); + if (fn[basedir_len - 1] != '/') + fn[basedir_len++] = '/'; + retval = target_read_memory(target, addr, 1, len, fn + basedir_len); if (retval != ERROR_OK) { free(fn); return retval; } - fn[len] = 0; + fn[basedir_len + len] = 0; /* TODO: implement the :semihosting-features special file. * */ if (semihosting->is_fileio) { @@ -2025,6 +2030,44 @@ COMMAND_HANDLER(handle_common_semihosting_read_user_param_command) return ERROR_OK; } +COMMAND_HANDLER(handle_common_semihosting_basedir_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (CMD_ARGC > 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + 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) { + free(semihosting->basedir); + semihosting->basedir = strdup(CMD_ARGV[0]); + if (!semihosting->basedir) { + command_print(CMD, "semihosting failed to allocate memory for basedir!"); + return ERROR_FAIL; + } + } + + command_print(CMD, "semihosting base dir: %s", + semihosting->basedir ? semihosting->basedir : ""); + + return ERROR_OK; +} + const struct command_registration semihosting_common_handlers[] = { { .name = "semihosting", @@ -2068,5 +2111,12 @@ const struct command_registration semihosting_common_handlers[] = { .usage = "", .help = "read parameters in semihosting-user-cmd-0x10X callbacks", }, + { + .name = "semihosting_basedir", + .handler = handle_common_semihosting_basedir_command, + .mode = COMMAND_EXEC, + .usage = "[dir]", + .help = "set the base directory for semihosting I/O operations", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index 459faf656a..404080f023 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -176,6 +176,9 @@ struct semihosting { /** The current time when 'execution starts' */ clock_t setup_time; + /** Base directory for semihosting I/O operations. */ + char *basedir; + int (*setup)(struct target *target, int enable); int (*post_result)(struct target *target); }; diff --git a/src/target/target.c b/src/target/target.c index 8a451883ba..8edd632916 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -57,6 +57,7 @@ #include "transport/transport.h" #include "arm_cti.h" #include "smp.h" +#include "semihosting_common.h" /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 @@ -2258,6 +2259,8 @@ static void target_destroy(struct target *target) if (target->type->deinit_target) target->type->deinit_target(target); + if (target->semihosting) + free(target->semihosting->basedir); free(target->semihosting); jtag_unregister_event_callback(jtag_enable_callback, target); -- 2.30.2