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.
|
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
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue