semihosting: drop absolute path support

This commit is contained in:
Erhan Kurubas 2022-03-13 19:03:06 +01:00 committed by BOT
parent 0fc0254734
commit ad078c5153
10 changed files with 70 additions and 100 deletions

View File

@ -80,15 +80,6 @@ menu "Virtual file system"
default 1
help
Define maximum number of host filesystem mount points.
config VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN
int "Host FS: Maximum path length for the host base directory"
default 128
help
Define maximum path length for the host base directory which is to be mounted.
If host path passed to esp_vfs_semihost_register() is longer than this value
it will be truncated.
endmenu
endmenu

View File

@ -1,16 +1,8 @@
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
* SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
@ -24,13 +16,12 @@ extern "C" {
* @brief add virtual filesystem semihosting driver
*
* @param base_path VFS path to mount host directory
* @param host_path host path to mount; if NULL default dirctory will be used (see OpenOCD configuration)
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if esp_vfs_semihost_register was already called for specified VFS path
* - ESP_ERR_NO_MEM if there are no slots to register new mount point
*/
esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path);
esp_err_t esp_vfs_semihost_register(const char* base_path);
/**
* @brief Un-register semihosting driver from VFS

View File

@ -90,9 +90,11 @@ extern "C" {
#define ESP_SEMIHOSTING_SYS_LINK 0x114
#define ESP_SEMIHOSTING_SYS_UNLINK 0x115
/* Semihosting version bumped to 2.
In this version, memory based approach implemented as defined in the ARM standard.
Also user defined syscall numbers enumerated between 0x100-0x1FF
/* Semihosting version bumped to 2. Changelog;
1 - Memory based approach with 2 registers implemented as defined in the ARM standard.
2 - User defined syscall numbers located between 0x100-0x1FF
3 - The break instruction operands updated to (1, 14)
4 - Absolute path support is dropped
*/
#define SEMIHOSTING_DRV_VERSION 2

View File

@ -19,21 +19,11 @@
#define CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS 1
#endif
#ifndef CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN
#define CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN 128
#endif
const static char *TAG = "esp_semihost";
/* Additional open flags */
/* ESP-specific file open flag.
* Indicates that path passed to open() is absolute host path.
*/
#define ESP_O_SEMIHOST_ABSPATH 0x80000000
/* There is no O_BINARY flag defined in newlib, as well as on Linux,
* but we are leaving it to have the flags table identical to OpenOCD.
*/
@ -41,18 +31,18 @@ const static char *TAG = "esp_semihost";
/* The table is identical to the one in OpenOCD semihosting_common.c */
static const int open_modeflags[12] = {
O_RDONLY,
O_RDONLY | O_BINARY,
O_RDWR,
O_RDWR | O_BINARY,
O_WRONLY | O_CREAT | O_TRUNC,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
O_RDWR | O_CREAT | O_TRUNC,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
O_WRONLY | O_CREAT | O_APPEND,
O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
O_RDWR | O_CREAT | O_APPEND,
O_RDWR | O_CREAT | O_APPEND | O_BINARY
O_RDONLY,
O_RDONLY | O_BINARY,
O_RDWR,
O_RDWR | O_BINARY,
O_WRONLY | O_CREAT | O_TRUNC,
O_WRONLY | O_CREAT | O_TRUNC | O_BINARY,
O_RDWR | O_CREAT | O_TRUNC,
O_RDWR | O_CREAT | O_TRUNC | O_BINARY,
O_WRONLY | O_CREAT | O_APPEND,
O_WRONLY | O_CREAT | O_APPEND | O_BINARY,
O_RDWR | O_CREAT | O_APPEND,
O_RDWR | O_CREAT | O_APPEND | O_BINARY
};
/**
@ -77,7 +67,6 @@ static inline int get_o_mode(int flags) {
typedef struct {
char base_path[ESP_VFS_PATH_MAX + 1]; /* base path in VFS where host semihosting dir is mounted */
char host_path[CONFIG_VFS_SEMIHOSTFS_HOST_PATH_MAX_LEN + 1]; /* host path to use as base dir for open files */
} vfs_semihost_ctx_t;
static vfs_semihost_ctx_t s_semhost_ctx[CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS];
@ -87,11 +76,6 @@ static inline bool ctx_is_unused(const vfs_semihost_ctx_t* ctx)
return ctx->base_path[0] == 0;
}
static inline bool ctx_uses_abspath(const vfs_semihost_ctx_t* ctx)
{
return ctx->host_path[0];
}
#define FAIL_IF_NO_DEBUGGER() \
do { \
if (!cpu_hal_is_debugger_attached()) { \
@ -115,46 +99,21 @@ static esp_err_t vfs_semihost_drvinfo(vfs_semihost_ctx_t *ctx)
static int vfs_semihost_open(void* ctx, const char* path, int flags, int mode)
{
int ret_fd = -1;
char *host_path;
vfs_semihost_ctx_t *semi_ctx = ctx;
FAIL_IF_NO_DEBUGGER();
ESP_LOGV(TAG, "%s: %p '%s 0x%x 0x%x'", __func__, semi_ctx, path, flags, mode);
if (path == NULL) {
errno = ENOENT;
return ret_fd;
}
ESP_LOGV(TAG, "%s: '%s 0x%x 0x%x'", __func__, path, flags, mode);
int o_mode = get_o_mode(flags);
if (o_mode == -1) { /* if wrong flags - error */
errno = EINVAL;
} else {
if (ctx_uses_abspath(semi_ctx)) {
/* Create full absolute path on the host by concatenating host base
* path and file path relative to the filesystem root.
*/
host_path = malloc(strlen(semi_ctx->host_path) + strlen(path) + 1);
if (host_path == NULL) { /* if no valid pointer - error and return */
errno = ENOMEM;
return -1;
}
strcpy(host_path, semi_ctx->host_path);
strcat(host_path, path);
#ifdef __XTENSA__
/* By default, OpenOCD for Xtensa prepends ESP_SEMIHOST_BASEDIR to
* the path passed from the target. Adding this special flag to o_mode
* inhibits this behavior.
* This is not necessary for RISC-V since standard semihosting
* implementation is used there and paths aren't mangled on OpenOCD side.
*/
if (ctx_uses_abspath(semi_ctx)) {
o_mode |= ESP_O_SEMIHOST_ABSPATH;
}
#endif // __XTENSA__
} else {
host_path = (char *)path;
}
/* everything is ready: syscall and cleanup */
ret_fd = semihosting_open(host_path, o_mode, mode);
if (ctx_uses_abspath(semi_ctx)) {
free(host_path);
}
ret_fd = semihosting_open(path, o_mode, mode);
}
return ret_fd;
}
@ -163,6 +122,11 @@ static ssize_t vfs_semihost_write(void* ctx, int fd, const void * data, size_t s
{
FAIL_IF_NO_DEBUGGER();
if (data == NULL) {
errno = EINVAL;
return -1;
}
ESP_LOGV(TAG, "%s: %d %u bytes", __func__, fd, size);
return semihosting_write(fd, data, size);
}
@ -171,11 +135,15 @@ static ssize_t vfs_semihost_read(void* ctx, int fd, void* data, size_t size)
{
FAIL_IF_NO_DEBUGGER();
if (data == NULL) {
errno = EINVAL;
return -1;
}
ESP_LOGV(TAG, "%s: %d %u bytes", __func__, fd, size);
return semihosting_read(fd, data, size);
}
static int vfs_semihost_close(void* ctx, int fd)
{
FAIL_IF_NO_DEBUGGER();
@ -191,8 +159,10 @@ static off_t vfs_semihost_lseek(void* ctx, int fd, off_t offset, int mode)
return semihosting_seek(fd, offset, mode);
}
esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path)
esp_err_t esp_vfs_semihost_register(const char* base_path)
{
assert(base_path);
const esp_vfs_t vfs = {
.flags = ESP_VFS_FLAG_CONTEXT_PTR,
.write_p = &vfs_semihost_write,
@ -201,7 +171,7 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path
.read_p = &vfs_semihost_read,
.lseek_p = &vfs_semihost_lseek,
};
ESP_LOGD(TAG, "Register semihosting driver '%s' -> '%s'", base_path, host_path ? host_path : "null");
ESP_LOGD(TAG, "Register semihosting driver '%s'", base_path);
if (!cpu_hal_is_debugger_attached()) {
ESP_LOGE(TAG, "OpenOCD is not connected!");
return ESP_ERR_NOT_SUPPORTED;
@ -219,9 +189,7 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path
return ESP_ERR_NO_MEM;
}
strlcpy(s_semhost_ctx[i].base_path, base_path, sizeof(s_semhost_ctx[i].base_path) - 1);
if (host_path) {
strlcpy(s_semhost_ctx[i].host_path, host_path, sizeof(s_semhost_ctx[i].host_path) - 1);
}
ESP_LOGD(TAG, "Register semihosting driver %d %p", i, &s_semhost_ctx[i]);
esp_err_t err;
@ -241,6 +209,8 @@ esp_err_t esp_vfs_semihost_register(const char* base_path, const char* host_path
esp_err_t esp_vfs_semihost_unregister(const char* base_path)
{
assert(base_path);
ESP_LOGD(TAG, "Unregister semihosting driver @ '%s'", base_path);
int i = 0;
for (i = 0; i < CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS; i++) {
@ -256,7 +226,6 @@ esp_err_t esp_vfs_semihost_unregister(const char* base_path)
return ret;
}
s_semhost_ctx[i].base_path[0] = 0;
s_semhost_ctx[i].host_path[0] = 0;
ESP_LOGD(TAG, "Unregistered semihosting driver @ '%s'", base_path);
return ESP_OK;
}

View File

@ -10,6 +10,19 @@
extern "C" {
#endif
/**
* @brief Perform semihosting call
*
* See ARM semihosting spec for details.
* https://static.docs.arm.com/100863/0200/semihosting.pdf
*
* @param id semihosting call number
* @param data data block to pass to the host; number of items and their
* meaning depends on the semihosting call. See the spec for
* details.
*
* @return return value from the host
*/
static inline long semihosting_call_noerrno(long id, long *data)
{
register long a2 asm ("a2") = id;

View File

@ -12,4 +12,9 @@ New signature is ``FRESULT f_mkfs (const TCHAR* path, const MKFS_PARM* opt, void
Partition table generation no longer supports misaligned partitions
-------------------------------------------------------------------
When generating a partiton table, ``esp-idf`` will no longer accept partitions which offset does not align to 4kB. This change only affects generating new partition tables, reading and writing to already existing partitions remains unchanged.
When generating a partiton table, ``esp-idf`` will no longer accept partitions which offset does not align to 4kB. This change only affects generating new partition tables, reading and writing to already existing partitions remains unchanged.
esp_vfs_semihost_register() signature change
--------------------------------------------
New signature is ``esp_err_t esp_vfs_semihost_register(const char* base_path);`` Absolute path as a second parameter will no longer in use. Instead, the OpenOCD command ``ESP_SEMIHOST_BASEDIR`` should be used to set the full path on the host.

View File

@ -47,7 +47,7 @@ static void initialise_mdns(void)
#if CONFIG_EXAMPLE_WEB_DEPLOY_SEMIHOST
esp_err_t init_fs(void)
{
esp_err_t ret = esp_vfs_semihost_register(CONFIG_EXAMPLE_WEB_MOUNT_POINT, CONFIG_EXAMPLE_HOST_PATH_TO_MOUNT);
esp_err_t ret = esp_vfs_semihost_register(CONFIG_EXAMPLE_WEB_MOUNT_POINT);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret));
return ESP_FAIL;

View File

@ -54,7 +54,7 @@ This example also requires [OpenOCD](https://docs.espressif.com/projects/esp-idf
### Overriding the base directory for semihosting
When the example application calls `esp_vfs_semihost_register("/host", NULL)`, the path `/host` on the ESP target is mapped to the semihosting _base directory_. By default, this is the directory where OpenOCD program is started from. In the instructions above, OpenOCD is started in `data` subdirectory of the example project.
When the example application calls `esp_vfs_semihost_register("/host")`, the path `/host` on the ESP target is mapped to the semihosting _base directory_. By default, this is the directory where OpenOCD program is started from. In the instructions above, OpenOCD is started in `data` subdirectory of the example project.
When debugging with Xtensa based SoCs (ESP32, ESP32-S2, ESP32-S3) it is possible to override the semihosting base directory using an additional flag of `openocd` command. For example, on Linux and macOS:

View File

@ -26,7 +26,7 @@ static uint8_t s_buf[512];
void app_main(void)
{
// Register host FS at '/host'. On the host file will be written/read in the current semihosting dir of OpenOCD
esp_err_t ret = esp_vfs_semihost_register("/host", NULL);
esp_err_t ret = esp_vfs_semihost_register("/host");
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Failed to register semihost driver (%s)!", esp_err_to_name(ret));
return;

View File

@ -1643,7 +1643,6 @@ components/unity/unity_runner.c
components/usb/test/hcd/test_hcd_ctrl.c
components/vfs/include/esp_vfs_common.h
components/vfs/include/esp_vfs_eventfd.h
components/vfs/include/esp_vfs_semihost.h
components/vfs/test/test_vfs_lwip.c
components/vfs/test/test_vfs_paths.c
components/vfs/test/test_vfs_uart.c