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 <erhan.kurubas@espressif.com>
Change-Id: I80c5979e4c96d66cccdd12cc6fcd5f353e5c6b4d
Reviewed-on: https://review.openocd.org/c/openocd/+/6888
Tested-by: jenkins
Reviewed-by: Antonio Borneo <borneo.antonio@gmail.com>
This commit is contained in:
Erhan Kurubas 2022-04-05 13:49:28 +03:00 committed by Antonio Borneo
parent e5f515f990
commit ce5027ab01
4 changed files with 65 additions and 3 deletions

View File

@ -9624,6 +9624,12 @@ is valid during the run of the event handlers and is accessible with this
command. command.
@end deffn @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 @section ARMv4 and ARMv5 Architecture
@cindex ARMv4 @cindex ARMv4
@cindex ARMv5 @cindex ARMv5

View File

@ -159,6 +159,7 @@ int semihosting_common_init(struct target *target, void *setup,
semihosting->result = -1; semihosting->result = -1;
semihosting->sys_errno = -1; semihosting->sys_errno = -1;
semihosting->cmdline = NULL; semihosting->cmdline = NULL;
semihosting->basedir = NULL;
/* If possible, update it in setup(). */ /* If possible, update it in setup(). */
semihosting->setup_time = clock(); semihosting->setup_time = clock();
@ -870,17 +871,21 @@ int semihosting_common(struct target *target)
semihosting->sys_errno = EINVAL; semihosting->sys_errno = EINVAL;
break; 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) { if (!fn) {
semihosting->result = -1; semihosting->result = -1;
semihosting->sys_errno = ENOMEM; semihosting->sys_errno = ENOMEM;
} else { } 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) { if (retval != ERROR_OK) {
free(fn); free(fn);
return retval; return retval;
} }
fn[len] = 0; fn[basedir_len + len] = 0;
/* TODO: implement the :semihosting-features special file. /* TODO: implement the :semihosting-features special file.
* */ * */
if (semihosting->is_fileio) { if (semihosting->is_fileio) {
@ -2025,6 +2030,44 @@ COMMAND_HANDLER(handle_common_semihosting_read_user_param_command)
return ERROR_OK; 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[] = { const struct command_registration semihosting_common_handlers[] = {
{ {
.name = "semihosting", .name = "semihosting",
@ -2068,5 +2111,12 @@ const struct command_registration semihosting_common_handlers[] = {
.usage = "", .usage = "",
.help = "read parameters in semihosting-user-cmd-0x10X callbacks", .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 COMMAND_REGISTRATION_DONE
}; };

View File

@ -176,6 +176,9 @@ struct semihosting {
/** The current time when 'execution starts' */ /** The current time when 'execution starts' */
clock_t setup_time; clock_t setup_time;
/** Base directory for semihosting I/O operations. */
char *basedir;
int (*setup)(struct target *target, int enable); int (*setup)(struct target *target, int enable);
int (*post_result)(struct target *target); int (*post_result)(struct target *target);
}; };

View File

@ -57,6 +57,7 @@
#include "transport/transport.h" #include "transport/transport.h"
#include "arm_cti.h" #include "arm_cti.h"
#include "smp.h" #include "smp.h"
#include "semihosting_common.h"
/* default halt wait timeout (ms) */ /* default halt wait timeout (ms) */
#define DEFAULT_HALT_TIMEOUT 5000 #define DEFAULT_HALT_TIMEOUT 5000
@ -2258,6 +2259,8 @@ static void target_destroy(struct target *target)
if (target->type->deinit_target) if (target->type->deinit_target)
target->type->deinit_target(target); target->type->deinit_target(target);
if (target->semihosting)
free(target->semihosting->basedir);
free(target->semihosting); free(target->semihosting);
jtag_unregister_event_callback(jtag_enable_callback, target); jtag_unregister_event_callback(jtag_enable_callback, target);