This is an automated email from Gerrit. "Erhan Kurubas <erhankuru...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/6889
-- gerrit commit f1e80481d8ae9e63d9ff1f54661a8b5c6c2b8c1c Author: erhankur <erhankuru...@gmail.com> Date: Tue Apr 5 14:26:08 2022 +0300 semihosting: add custom user command handler Custom user syscalls can be handled with target events in the TCL scripts. This patch gives another opportunity to handle custom syscalls in the c files. Besides that some utility functions are also exported for the custom handlers. Signed-off-by: erhankur <erhankuru...@gmail.com> Change-Id: Ice13d527540a0de0b2a8abda912ae3dcff3834b7 diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c index bc1f417ef0..cfef7c490c 100644 --- a/src/target/semihosting_common.c +++ b/src/target/semihosting_common.c @@ -103,16 +103,6 @@ static int semihosting_common_fileio_info(struct target *target, static int semihosting_common_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c); -static int semihosting_read_fields(struct target *target, size_t number, - uint8_t *fields); -static int semihosting_write_fields(struct target *target, size_t number, - uint8_t *fields); -static uint64_t semihosting_get_field(struct target *target, size_t index, - uint8_t *fields); -static void semihosting_set_field(struct target *target, uint64_t value, - size_t index, - uint8_t *fields); - /* Attempts to include gdb_server.h failed. */ extern int gdb_actual_connections; @@ -165,6 +155,7 @@ int semihosting_common_init(struct target *target, void *setup, semihosting->setup = setup; semihosting->post_result = post_result; + semihosting->user_command_handler = NULL; target->semihosting = semihosting; @@ -936,8 +927,13 @@ int semihosting_common(struct target *target) /* cygwin requires the permission setting * otherwise it will fail to reopen a previously * written file */ + uint32_t flags = open_host_modeflags[mode]; + #ifdef _WIN32 + /* Windows needs O_BINARY flag for proper handling of EOLs */ + flags |= O_BINARY; + #endif semihosting->result = open((char *)fn, - open_host_modeflags[mode], + flags, 0644); semihosting->sys_errno = errno; LOG_DEBUG("open('%s')=%d", fn, @@ -1461,51 +1457,53 @@ int semihosting_common(struct target *target) * On exit, the RETURN REGISTER contains the return status. */ { - assert(!semihosting_user_op_params); + if (semihosting->user_command_handler) + retval = semihosting->user_command_handler(target); + else { - retval = semihosting_read_fields(target, 2, fields); - if (retval != ERROR_OK) { - LOG_ERROR("Failed to read fields for user defined command" - " op=0x%x", semihosting->op); - return retval; - } + assert(!semihosting_user_op_params); - uint64_t addr = semihosting_get_field(target, 0, fields); + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read fields for user defined command" + " op=0x%x", semihosting->op); + return retval; + } - size_t len = semihosting_get_field(target, 1, fields); - if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) { - LOG_ERROR("The maximum length for user defined command " - "parameter is %u, received length is %zu (op=0x%x)", - SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH, - len, - semihosting->op); - return ERROR_FAIL; - } + uint64_t addr = semihosting_get_field(target, 0, fields); - semihosting_user_op_params = malloc(len + 1); - if (!semihosting_user_op_params) - return ERROR_FAIL; - semihosting_user_op_params[len] = 0; + size_t len = semihosting_get_field(target, 1, fields); + if (len > SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH) { + LOG_ERROR("The maximum length for user defined command " + "parameter is %u, received length is %zu (op=0x%x)", + SEMIHOSTING_MAX_TCL_COMMAND_FIELD_LENGTH, + len, + semihosting->op); + return ERROR_FAIL; + } + + semihosting_user_op_params = malloc(len + 1); + if (!semihosting_user_op_params) + return ERROR_FAIL; + semihosting_user_op_params[len] = 0; + + retval = target_read_buffer(target, addr, len, + (uint8_t *)(semihosting_user_op_params)); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to read from target, semihosting op=0x%x", + semihosting->op); + free(semihosting_user_op_params); + semihosting_user_op_params = NULL; + return retval; + } - retval = target_read_buffer(target, addr, len, - (uint8_t *)(semihosting_user_op_params)); - if (retval != ERROR_OK) { - LOG_ERROR("Failed to read from target, semihosting op=0x%x", - semihosting->op); + target_handle_event(target, semihosting->op); free(semihosting_user_op_params); semihosting_user_op_params = NULL; - return retval; + semihosting->result = 0; } - - target_handle_event(target, semihosting->op); - free(semihosting_user_op_params); - semihosting_user_op_params = NULL; - - semihosting->result = 0; - break; } - - + break; case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */ /* * Returns the number of elapsed target ticks since execution @@ -1663,10 +1661,13 @@ static int semihosting_common_fileio_end(struct target *target, int result, return semihosting->post_result(target); } +/* ------------------------------------------------------------------------- + * Utility functions. */ + /** * Read all fields of a command from target to buffer. */ -static int semihosting_read_fields(struct target *target, size_t number, +int semihosting_read_fields(struct target *target, size_t number, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; @@ -1678,7 +1679,7 @@ static int semihosting_read_fields(struct target *target, size_t number, /** * Write all fields of a command from buffer to target. */ -static int semihosting_write_fields(struct target *target, size_t number, +int semihosting_write_fields(struct target *target, size_t number, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; @@ -1690,7 +1691,7 @@ static int semihosting_write_fields(struct target *target, size_t number, /** * Extract a field from the buffer, considering register size and endianness. */ -static uint64_t semihosting_get_field(struct target *target, size_t index, +uint64_t semihosting_get_field(struct target *target, size_t index, uint8_t *fields) { struct semihosting *semihosting = target->semihosting; @@ -1703,7 +1704,7 @@ static uint64_t semihosting_get_field(struct target *target, size_t index, /** * Store a field in the buffer, considering register size and endianness. */ -static void semihosting_set_field(struct target *target, uint64_t value, +void semihosting_set_field(struct target *target, uint64_t value, size_t index, uint8_t *fields) { diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h index 459faf656a..c14201408c 100644 --- a/src/target/semihosting_common.h +++ b/src/target/semihosting_common.h @@ -176,6 +176,7 @@ struct semihosting { /** The current time when 'execution starts' */ clock_t setup_time; + int (*user_command_handler)(struct target *target); int (*setup)(struct target *target, int enable); int (*post_result)(struct target *target); }; @@ -184,4 +185,15 @@ int semihosting_common_init(struct target *target, void *setup, void *post_result); int semihosting_common(struct target *target); +/* utility functions which may also be used by semihosting extensions (custom vendor-defined syscalls) */ +int semihosting_read_fields(struct target *target, size_t number, + uint8_t *fields); +int semihosting_write_fields(struct target *target, size_t number, + uint8_t *fields); +uint64_t semihosting_get_field(struct target *target, size_t index, + uint8_t *fields); +void semihosting_set_field(struct target *target, uint64_t value, + size_t index, + uint8_t *fields); + #endif /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */ --