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:
parent
e5f515f990
commit
ce5027ab01
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue