diff --git a/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_DYNAMIC/main.c b/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_DYNAMIC/main.c index dc1bf2323..156ade05f 100644 --- a/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_DYNAMIC/main.c +++ b/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_DYNAMIC/main.c @@ -22,8 +22,42 @@ #include "rt_test_root.h" #include "oslib_test_root.h" +#include "nullstreams.h" + #include "startup_defs.h" +/*===========================================================================*/ +/* VFS-related. */ +/*===========================================================================*/ + +#if VFS_CFG_ENABLE_DRV_FATFS == TRUE +/* VFS FatFS driver object representing the root directory.*/ +static vfs_fatfs_driver_c root_driver; +#endif + +/* VFS overlay driver object representing the root directory.*/ +static vfs_overlay_driver_c root_overlay_driver; + +/* VFS streams driver object representing the /dev directory.*/ +static vfs_streams_driver_c dev_driver; + +/* VFS API will use this object as implicit root, defining this + symbol is expected.*/ +vfs_driver_c *vfs_root = (vfs_driver_c *)&root_overlay_driver; + +static NullStream nullstream; + +/* Stream to be exposed under /dev as files.*/ +static const drv_streams_element_t streams[] = { + {"VSD1", (BaseSequentialStream *)&LPSD1}, + {"null", (BaseSequentialStream *)&nullstream}, + {NULL, NULL} +}; + +/*===========================================================================*/ +/* SB-related. */ +/*===========================================================================*/ + /* Sandbox 1 configuration.*/ static const sb_config_t sb_config1 = { .code_region = 0U, @@ -52,9 +86,6 @@ static const sb_config_t sb_config1 = { MPU_RASR_ENABLE } }, - .stdin_stream = (SandboxStream *)&LPSD1, - .stdout_stream = (SandboxStream *)&LPSD1, - .stderr_stream = (SandboxStream *)&LPSD1 }; /* Sandbox 2 configuration.*/ @@ -85,16 +116,17 @@ static const sb_config_t sb_config2 = { MPU_RASR_ENABLE } }, - .stdin_stream = (SandboxStream *)&LPSD1, - .stdout_stream = (SandboxStream *)&LPSD1, - .stderr_stream = (SandboxStream *)&LPSD1 }; /* Sandbox objects.*/ sb_class_t sbx1, sbx2; -static THD_WORKING_AREA(waUnprivileged1, 256); -static THD_WORKING_AREA(waUnprivileged2, 256); +static THD_WORKING_AREA(waUnprivileged1, 512); +static THD_WORKING_AREA(waUnprivileged2, 512); + +/*===========================================================================*/ +/* Main and generic code. */ +/*===========================================================================*/ /* * Green LED blinker thread, times are in milliseconds. @@ -118,6 +150,8 @@ int main(void) { unsigned i = 1U; thread_t *utp1, *utp2; event_listener_t el1; + vfs_file_node_c *fnp; + msg_t ret; /* * System initializations. @@ -125,29 +159,61 @@ int main(void) { * and performs the board-specific initializations. * - Kernel initialization, the main() function becomes a thread and the * RTOS is active. + * - Virtual File System initialization. * - SandBox manager initialization. */ halInit(); chSysInit(); + vfsInit(); sbHostInit(); /* - * Listening to sandbox events. - */ - chEvtRegister(&sb.termination_es, &el1, (eventid_t)0); - - /* - * Activates the Serial driver using the default configuration. + * Starting a serial port for I/O, initializing other streams too. */ sdStart(&LPSD1, NULL); + nullObjectInit(&nullstream); /* - * Creates the blinker thread. + * Creating a blinker thread. */ chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+10, Thread1, NULL); + /* + * Initializing an overlay VFS object as a root, no overlaid driver, + * registering a streams VFS driver on the VFS overlay root as "/dev". + */ + drvOverlayObjectInit(&root_overlay_driver, NULL, NULL); + ret = drvOverlayRegisterDriver(&root_overlay_driver, + drvStreamsObjectInit(&dev_driver, &streams[0]), + "dev"); + if (CH_RET_IS_ERROR(ret)) { + chSysHalt("VFS"); + } + + /* + * Sandbox objects initialization. + */ + sbObjectInit(&sbx1, &sb_config1); + sbObjectInit(&sbx2, &sb_config2); + + /* + * Associating standard input, output and error to sandboxes. Both sandboxes + * use the same serial port in this setup. + */ + ret = vfsOpenFile("/dev/VSD1", 0, &fnp); + if (CH_RET_IS_ERROR(ret)) { + chSysHalt("VFS"); + } + sbPosixRegisterFileDescriptor(&sbx1, STDIN_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx1, STDOUT_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx1, STDERR_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDIN_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDOUT_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDERR_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + vfsCloseFile(fnp); + /* Starting sandboxed thread 1.*/ - utp1 = sbStartThread(&sbx1, &sb_config1, "sbx1", + utp1 = sbStartThread(&sbx1, "sbx1", waUnprivileged1, sizeof (waUnprivileged1), NORMALPRIO - 1); if (utp1 == NULL) { @@ -155,7 +221,7 @@ int main(void) { } /* Starting sandboxed thread 2.*/ - utp2 = sbStartThread(&sbx2, &sb_config2, "sbx2", + utp2 = sbStartThread(&sbx2, "sbx2", waUnprivileged2, sizeof (waUnprivileged2), NORMALPRIO - 1); if (utp1 == NULL) { @@ -163,7 +229,12 @@ int main(void) { } /* - * Normal main() thread activity, in this demo it monitos the user button + * Listening to sandbox events. + */ + chEvtRegister(&sb.termination_es, &el1, (eventid_t)0); + + /* + * Normal main() thread activity, in this demo it monitors the user button * and checks for sandboxes state. */ while (true) { @@ -199,4 +270,3 @@ int main(void) { i++; } } - diff --git a/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_STATIC/main.c b/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_STATIC/main.c index cfba61ca1..37d5c5267 100644 --- a/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_STATIC/main.c +++ b/demos/STM32/RT-STM32G474RE-NUCLEO64-SB_HOST_STATIC/main.c @@ -22,8 +22,42 @@ #include "rt_test_root.h" #include "oslib_test_root.h" +#include "nullstreams.h" + #include "startup_defs.h" +/*===========================================================================*/ +/* VFS-related. */ +/*===========================================================================*/ + +#if VFS_CFG_ENABLE_DRV_FATFS == TRUE +/* VFS FatFS driver object representing the root directory.*/ +static vfs_fatfs_driver_c root_driver; +#endif + +/* VFS overlay driver object representing the root directory.*/ +static vfs_overlay_driver_c root_overlay_driver; + +/* VFS streams driver object representing the /dev directory.*/ +static vfs_streams_driver_c dev_driver; + +/* VFS API will use this object as implicit root, defining this + symbol is expected.*/ +vfs_driver_c *vfs_root = (vfs_driver_c *)&root_overlay_driver; + +static NullStream nullstream; + +/* Stream to be exposed under /dev as files.*/ +static const drv_streams_element_t streams[] = { + {"VSD1", (BaseSequentialStream *)&LPSD1}, + {"null", (BaseSequentialStream *)&nullstream}, + {NULL, NULL} +}; + +/*===========================================================================*/ +/* SB-related. */ +/*===========================================================================*/ + /* Sandbox 1 configuration.*/ static const sb_config_t sb_config1 = { .code_region = 0U, @@ -38,9 +72,7 @@ static const sb_config_t sb_config1 = { .writeable = true } }, - .stdin_stream = (SandboxStream *)&LPSD1, - .stdout_stream = (SandboxStream *)&LPSD1, - .stderr_stream = (SandboxStream *)&LPSD1 + .vfs_driver = (vfs_driver_c *)&root_overlay_driver }; /* Sandbox 2 configuration.*/ @@ -57,16 +89,18 @@ static const sb_config_t sb_config2 = { .writeable = true } }, - .stdin_stream = (SandboxStream *)&LPSD1, - .stdout_stream = (SandboxStream *)&LPSD1, - .stderr_stream = (SandboxStream *)&LPSD1 + .vfs_driver = (vfs_driver_c *)&root_overlay_driver }; /* Sandbox objects.*/ sb_class_t sbx1, sbx2; -static THD_WORKING_AREA(waUnprivileged1, 256); -static THD_WORKING_AREA(waUnprivileged2, 256); +static THD_WORKING_AREA(waUnprivileged1, 512); +static THD_WORKING_AREA(waUnprivileged2, 512); + +/*===========================================================================*/ +/* Main and generic code. */ +/*===========================================================================*/ /* * Green LED blinker thread, times are in milliseconds. @@ -90,6 +124,8 @@ int main(void) { unsigned i = 1U; thread_t *utp1, *utp2; event_listener_t el1; + vfs_file_node_c *fnp; + msg_t ret; /* * System initializations. @@ -97,27 +133,59 @@ int main(void) { * and performs the board-specific initializations. * - Kernel initialization, the main() function becomes a thread and the * RTOS is active. + * - Virtual File System initialization. * - SandBox manager initialization. */ halInit(); chSysInit(); + vfsInit(); sbHostInit(); /* - * Listening to sandbox events. - */ - chEvtRegister(&sb.termination_es, &el1, (eventid_t)0); - - /* - * Activates the Serial driver using the default configuration. + * Starting a serial port for I/O, initializing other streams too. */ sdStart(&LPSD1, NULL); + nullObjectInit(&nullstream); /* - * Creates the blinker thread. + * Creating a blinker thread. */ chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO+10, Thread1, NULL); + /* + * Initializing an overlay VFS object as a root, no overlaid driver, + * registering a streams VFS driver on the VFS overlay root as "/dev". + */ + drvOverlayObjectInit(&root_overlay_driver, NULL, NULL); + ret = drvOverlayRegisterDriver(&root_overlay_driver, + drvStreamsObjectInit(&dev_driver, &streams[0]), + "dev"); + if (CH_RET_IS_ERROR(ret)) { + chSysHalt("VFS"); + } + + /* + * Sandbox objects initialization. + */ + sbObjectInit(&sbx1, &sb_config1); + sbObjectInit(&sbx2, &sb_config2); + + /* + * Associating standard input, output and error to sandboxes. Both sandboxes + * use the same serial port in this setup. + */ + ret = vfsOpenFile("/dev/VSD1", 0, &fnp); + if (CH_RET_IS_ERROR(ret)) { + chSysHalt("VFS"); + } + sbPosixRegisterFileDescriptor(&sbx1, STDIN_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx1, STDOUT_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx1, STDERR_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDIN_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDOUT_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + sbPosixRegisterFileDescriptor(&sbx2, STDERR_FILENO, (vfs_file_node_c *)roAddRef(fnp)); + vfsCloseFile(fnp); + /* * Creating **static** boxes using MPU. * Note: The two regions cover both sandbox 1 and 2, there is no @@ -137,7 +205,7 @@ int main(void) { MPU_RASR_ENABLE); /* Starting sandboxed thread 1.*/ - utp1 = sbStartThread(&sbx1, &sb_config1, "sbx1", + utp1 = sbStartThread(&sbx1, "sbx1", waUnprivileged1, sizeof (waUnprivileged1), NORMALPRIO - 1); if (utp1 == NULL) { @@ -145,7 +213,7 @@ int main(void) { } /* Starting sandboxed thread 2.*/ - utp2 = sbStartThread(&sbx2, &sb_config2, "sbx2", + utp2 = sbStartThread(&sbx2, "sbx2", waUnprivileged2, sizeof (waUnprivileged2), NORMALPRIO - 1); if (utp1 == NULL) { @@ -153,7 +221,12 @@ int main(void) { } /* - * Normal main() thread activity, in this demo it monitos the user button + * Listening to sandbox events. + */ + chEvtRegister(&sb.termination_es, &el1, (eventid_t)0); + + /* + * Normal main() thread activity, in this demo it monitors the user button * and checks for sandboxes state. */ while (true) { @@ -189,4 +262,3 @@ int main(void) { i++; } } - diff --git a/os/common/utils/include/oop_referenced_object.h b/os/common/utils/include/oop_referenced_object.h index 78c7f49b0..eeaed8d2e 100644 --- a/os/common/utils/include/oop_referenced_object.h +++ b/os/common/utils/include/oop_referenced_object.h @@ -153,24 +153,26 @@ static inline void __referenced_object_release_impl(void *ip) { /** * @brief New reference creation. * - * @param[in] rop A reference to the object. + * @param[in] ip A reference to the object. * @return A new reference to the object. */ CC_FORCE_INLINE -static inline referenced_object_c *roAddRef(referenced_object_c *rop) { +static inline referenced_object_c *roAddRef(void *ip) { + referenced_object_c *objp = (referenced_object_c *)ip; - return (referenced_object_c *)rop->vmt->addref((void *)rop); + return objp->vmt->addref(ip); } /** * @brief Reference release. * - * @param[in] rop A reference to the object. + * @param[in] ip A reference to the object. */ CC_FORCE_INLINE -static inline void roRelease(referenced_object_c *rop) { +static inline void roRelease(void *ip) { + referenced_object_c *objp = (referenced_object_c *)ip; - return rop->vmt->release((void *)rop); + return objp->vmt->release(ip); } #endif /* OOP_REFERENCED_OBJECT_H */ diff --git a/os/sb/host/sb.h b/os/sb/host/sb.h index 3b40a46da..014da0027 100644 --- a/os/sb/host/sb.h +++ b/os/sb/host/sb.h @@ -28,6 +28,10 @@ #ifndef SB_H #define SB_H +#include "hal.h" +#include "vfs.h" +#include "errcodes.h" + /*===========================================================================*/ /* Module constants. */ /*===========================================================================*/ @@ -146,6 +150,138 @@ /* Module data structures and types. */ /*===========================================================================*/ +/** + * @brief Type of a sandbox manager global structure. + */ +typedef struct { +#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) + /** + * @brief Event source for sandbox termination. + */ + event_source_t termination_es; +#endif +} sb_t; + +/** + * @brief Type of a sandbox memory region. + */ +typedef struct { + /** + * @brief Associated memory area. + */ + memory_area_t area; + /** + * @brief Writable memory range. + */ + bool writeable; +} sb_memory_region_t; + +#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) +/** + * @brief Type of a sandbox I/O structure. + */ +typedef struct { + /** + * @brief VFS nodes associated to file descriptors. + */ + vfs_node_c *vfs_nodes[SB_CFG_FD_NUM]; + /** + * @brief Extra attributes added to the VFS nodes. + */ + uint8_t attributes[SB_CFG_FD_NUM]; +} sb_ioblock_t; +#endif + +/** + * @brief Type of a sandbox configuration structure. + */ +typedef struct { + /** + * @brief Memory region for code. + * @note It is used to locate the startup header. + */ + uint32_t code_region; + /** + * @brief Memory region for data and stack. + * @note It is used for initial PSP placement. + */ + uint32_t data_region; + /** + * @brief SandBox regions. + * @note The following memory regions are used only for pointers + * validation, not for MPU setup. + */ + sb_memory_region_t regions[SB_CFG_NUM_REGIONS]; +#if (PORT_SWITCHED_REGIONS_NUMBER == SB_CFG_NUM_REGIONS) || defined(__DOXYGEN__) + /** + * @brief MPU regions initialization values. + * @note Regions initialization values must be chosen to be + * consistent with the values in the "regions" field. + */ + mpureg_t mpuregs[SB_CFG_NUM_REGIONS]; +#endif +#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) + /** + * @brief VFS driver associated to the sandbox as root. + */ + vfs_driver_c *vfs_driver; +#else + /** + * @brief Sandbox STDIN stream. + * @note Set this to @p NULL if standard I/O is not needed. + * @note By design you can use HAL streams here, you need to use + * a cast however. + */ + SandboxStream *stdin_stream; + /** + * @brief Sandbox STDOUT stream. + * @note Set this to @p NULL if standard I/O is not needed. + * @note By design you can use HAL streams here, you need to use + * a cast however. + */ + SandboxStream *stdout_stream; + /** + * @brief Sandbox STDERR stream. + * @note Set this to @p NULL if standard I/O is not needed. + * @note By design you can use HAL streams here, you need to use + * a cast however. + */ + SandboxStream *stderr_stream; +#endif +} sb_config_t; + +/** + * @brief Type of a sandbox object. + */ +typedef struct { + /** + * @brief Pointer to the sandbox configuration data. + */ + const sb_config_t *config; + /** + * @brief Thread running in the sandbox. + */ + thread_t *tp; +#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__) + /** + * @brief Thread sending a message to the sandbox. + */ + thread_t *msg_tp; +#endif +#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) + /** + * @brief Sandbox events source. + */ + event_source_t es; +#endif +#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) + /** + * @brief VFS bindings for Posix API. + */ + sb_ioblock_t io; +#endif +} sb_class_t; + /*===========================================================================*/ /* Module macros. */ /*===========================================================================*/ @@ -166,9 +302,6 @@ extern "C" { /* Module inline functions. */ /*===========================================================================*/ -#include "hal.h" -#include "errcodes.h" - #include "sbsysc.h" #include "sbposix.h" #include "sbapi.h" diff --git a/os/sb/host/sbhost.c b/os/sb/host/sbhost.c index dd382d0ae..f34b7f83c 100644 --- a/os/sb/host/sbhost.c +++ b/os/sb/host/sbhost.c @@ -100,12 +100,13 @@ bool sb_is_valid_string_range(sb_class_t *sbcp, const char *s, size_t n) { * @brief Sandbox object initialization. * * @param[out] sbcp pointer to the sandbox object + * @param[in] config pointer to the sandbox configuration * * @init */ -void sbObjectInit(sb_class_t *sbcp) { +void sbObjectInit(sb_class_t *sbcp, const sb_config_t *config) { - sbcp->config = NULL; + sbcp->config = config; sbcp->tp = NULL; #if CH_CFG_USE_MESSAGES == TRUE sbcp->msg_tp = NULL; @@ -118,16 +119,20 @@ void sbObjectInit(sb_class_t *sbcp) { /** * @brief Starts a sandboxed thread. * - * @param[out] sbcp pointer to the sandbox object - * @param[in] config pointer to the sandbox configuration + * @param[in] sbcp pointer to a @p sb_class_t structure + * @param[in] name name to be assigned to the thread + * @param[out] wsp pointer to a working area dedicated to the thread stack + * @param[in] size size of the working area + * @param[in] prio the priority level for the new thread * @return The thread pointer. * @retval NULL if the sandbox thread creation failed. */ -thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config, - const char *name, void *wsp, size_t size, +thread_t *sbStartThread(sb_class_t *sbcp, const char *name, + void *wsp, size_t size, tprio_t prio) { thread_t *utp; const sb_header_t *sbhp; + const sb_config_t *config = sbcp->config; /* Header location.*/ sbhp = (const sb_header_t *)(void *)config->regions[config->code_region].area.base; @@ -142,9 +147,6 @@ thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config, return NULL; } - /* Linking configuration information.*/ - sbcp->config = config; - unprivileged_thread_descriptor_t utd = { .name = name, .wbase = (stkalign_t *)wsp, @@ -166,12 +168,6 @@ thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config, /* For messages exchange.*/ sbcp->tp = utp; -#if CH_CFG_USE_MESSAGES == TRUE - sbcp->msg_tp = NULL; -#endif -#if CH_CFG_USE_EVENTS == TRUE - chEvtObjectInit(&sbcp->es); -#endif return utp; } diff --git a/os/sb/host/sbhost.h b/os/sb/host/sbhost.h index 728d538f0..d25bc34cb 100644 --- a/os/sb/host/sbhost.h +++ b/os/sb/host/sbhost.h @@ -52,115 +52,6 @@ /* Module data structures and types. */ /*===========================================================================*/ -/** - * @brief Type of a sandbox manager global structure. - */ -typedef struct { -#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) - /** - * @brief Event source for sandbox termination. - */ - event_source_t termination_es; -#endif -} sb_t; - -/** - * @brief Type of a sandbox memory region. - */ -typedef struct { - /** - * @brief Associated memory area. - */ - memory_area_t area; - /** - * @brief Writable memory range. - */ - bool writeable; -} sb_memory_region_t; - -/** - * @brief Type of a sandbox configuration structure. - */ -typedef struct { - /** - * @brief Memory region for code. - * @note It is used to locate the startup header. - */ - uint32_t code_region; - /** - * @brief Memory region for data and stack. - * @note It is used for initial PSP placement. - */ - uint32_t data_region; - /** - * @brief SandBox regions. - * @note The following memory regions are used only for pointers - * validation, not for MPU setup. - */ - sb_memory_region_t regions[SB_CFG_NUM_REGIONS]; -#if (PORT_SWITCHED_REGIONS_NUMBER == SB_CFG_NUM_REGIONS) || defined(__DOXYGEN__) - /** - * @brief MPU regions initialization values. - * @note Regions initialization values must be chosen to be - * consistent with the values in the "regions" field. - */ - mpureg_t mpuregs[SB_CFG_NUM_REGIONS]; -#endif - /** - * @brief Sandbox STDIN stream. - * @note Set this to @p NULL if standard I/O is not needed. - * @note By design you can use HAL streams here, you need to use - * a cast however. - */ - SandboxStream *stdin_stream; - /** - * @brief Sandbox STDOUT stream. - * @note Set this to @p NULL if standard I/O is not needed. - * @note By design you can use HAL streams here, you need to use - * a cast however. - */ - SandboxStream *stdout_stream; - /** - * @brief Sandbox STDERR stream. - * @note Set this to @p NULL if standard I/O is not needed. - * @note By design you can use HAL streams here, you need to use - * a cast however. - */ - SandboxStream *stderr_stream; -} sb_config_t; - -/** - * @brief Type of a sandbox object. - */ -typedef struct { - /** - * @brief Pointer to the sandbox configuration data. - */ - const sb_config_t *config; - /** - * @brief Thread running in the sandbox. - */ - thread_t *tp; -#if (CH_CFG_USE_MESSAGES == TRUE) || defined(__DOXYGEN__) - /** - * @brief Thread sending a message to the sandbox. - */ - thread_t *msg_tp; -#endif -#if (CH_CFG_USE_EVENTS == TRUE) || defined(__DOXYGEN__) - /** - * @brief Sandbox events source. - */ - event_source_t es; -#endif -#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) - /** - * @brief VFS bindings for Posix API. - */ - sb_ioblock_t io; -#endif -} sb_class_t; - /** * @brief Type of a sandbox binary image header. */ @@ -200,10 +91,9 @@ extern "C" { bool sb_is_valid_read_range(sb_class_t *sbcp, const void *start, size_t size); bool sb_is_valid_write_range(sb_class_t *sbcp, void *start, size_t size); bool sb_is_valid_string_range(sb_class_t *sbcp, const char *s, size_t n); - void sbObjectInit(sb_class_t *sbcp); - void sbStart(sb_class_t *sbcp, const sb_config_t *config); - thread_t *sbStartThread(sb_class_t *sbcp, const sb_config_t *config, - const char *name, void *wsp, size_t size, + void sbObjectInit(sb_class_t *sbcp, const sb_config_t *config); + thread_t *sbStartThread(sb_class_t *sbcp, const char *name, + void *wsp, size_t size, tprio_t prio); msg_t sbSendMessageTimeout(sb_class_t *sbcp, msg_t msg, diff --git a/os/sb/host/sbposix.c b/os/sb/host/sbposix.c index b17dbc89c..c296b417e 100644 --- a/os/sb/host/sbposix.c +++ b/os/sb/host/sbposix.c @@ -48,6 +48,7 @@ /* Module local functions. */ /*===========================================================================*/ +#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) static msg_t create_descriptor(sb_ioblock_t *iop, vfs_node_c *np, uint8_t attributes) { @@ -69,6 +70,7 @@ static bool is_valid_descriptor(sb_ioblock_t *iop, int fd) { return (fd >= 0) && (fd < SB_CFG_FD_NUM) && (iop->vfs_nodes[fd] != NULL); } +#endif /*===========================================================================*/ /* Module exported functions. */ @@ -85,7 +87,8 @@ int sb_posix_open(const char *path, int flags) { } do { - ret = vfsDrvOpenFile(sbp->io.vfs_driver, path, (unsigned)flags, &fnp); + ret = vfsDrvOpenFile(sbp->config->vfs_driver, path, + (unsigned)flags, &fnp); CH_BREAK_ON_ERROR(ret); ret = create_descriptor(&sbp->io, (vfs_node_c *)fnp, 0); @@ -122,7 +125,7 @@ int sb_posix_close(int fd) { ssize_t sb_posix_read(int fd, void *buf, size_t count) { sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; - if (!sb_is_valid_read_range(sbp, (void *)buf, count)) { + if (!sb_is_valid_write_range(sbp, (void *)buf, count)) { return CH_RET_EFAULT; } @@ -140,7 +143,7 @@ ssize_t sb_posix_read(int fd, void *buf, size_t count) { ssize_t sb_posix_write(int fd, const void *buf, size_t count) { sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; - if (!sb_is_valid_write_range(sbp, (void *)buf, count)) { + if (!sb_is_valid_read_range(sbp, (void *)buf, count)) { return CH_RET_EFAULT; } @@ -168,6 +171,18 @@ off_t sb_posix_lseek(int fd, off_t offset, int whence) { return CH_RET_EBADF; } +void sbPosixRegisterFileDescriptor(sb_class_t *sbp, + int fd, + vfs_file_node_c *fnp) { + + chDbgAssert(is_valid_descriptor(&sbp->io, fd) && + sbp->io.vfs_nodes[fd] == NULL, + "invalid file descriptor"); + + sbp->io.vfs_nodes[fd] = (vfs_node_c *)fnp; + sbp->io.attributes[fd] = 0; +} + #else /* Fallbacks for when there is no VFS.*/ uint32_t sb_posix_open(const char *pathname, uint32_t flags) { diff --git a/os/sb/host/sbposix.h b/os/sb/host/sbposix.h index ee40a38aa..7be7e3d4a 100644 --- a/os/sb/host/sbposix.h +++ b/os/sb/host/sbposix.h @@ -48,26 +48,6 @@ /* Module data structures and types. */ /*===========================================================================*/ -#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) -/** - * @brief Type of a sandbox I/O structure. - */ -typedef struct { - /** - * @brief VFS driver associated to the sandbox as root. - */ - vfs_driver_c *vfs_driver; - /** - * @brief VFS nodes associated to file descriptors. - */ - vfs_node_c *vfs_nodes[SB_CFG_FD_NUM]; - /** - * @brief Extra attributes added to the VFS nodes. - */ - uint8_t attributes[SB_CFG_FD_NUM]; -} sb_ioblock_t; -#endif - /*===========================================================================*/ /* Module macros. */ /*===========================================================================*/ @@ -84,6 +64,11 @@ extern "C" { ssize_t sb_posix_read(int fd, void *buf, size_t count); ssize_t sb_posix_write(int fd, const void *buf, size_t count); off_t sb_posix_lseek(int fd, off_t offset, int whence); +#if SB_CFG_ENABLE_VFS == TRUE + void sbPosixRegisterFileDescriptor(sb_class_t *sbp, + int fd, + vfs_file_node_c *fnp); +#endif #ifdef __cplusplus } #endif diff --git a/os/sb/various/syscalls.c b/os/sb/various/syscalls.c index b281cc73a..2505c91de 100644 --- a/os/sb/various/syscalls.c +++ b/os/sb/various/syscalls.c @@ -23,9 +23,23 @@ #include #include +#include "errcodes.h" #include "sbuser.h" -#define MAKERR(e) (-(int)(e)) +__attribute__((used)) +int _open_r(struct _reent *r, const char *p, int oflag, int mode) { + uint32_t err; + + (void)mode; + + err = sbFileOpen(p, oflag); + if (CH_RET_IS_ERROR(err)) { + __errno_r(r) = CH_DECODE_ERROR(err); + return -1; + } + + return err; +} __attribute__((used)) int _close_r(struct _reent *r, int file) { @@ -33,7 +47,7 @@ int _close_r(struct _reent *r, int file) { err = sbFileClose((uint32_t)file); if (CH_RET_IS_ERROR(err)) { - __errno_r(r) = MAKERR(err); + __errno_r(r) = CH_DECODE_ERROR(err); return -1; } @@ -46,7 +60,7 @@ int _write_r(struct _reent *r, int file, char * ptr, int len) { err = sbFileWrite((uint32_t)file, (const uint8_t *)ptr, (size_t)len); if (CH_RET_IS_ERROR(err)) { - __errno_r(r) = MAKERR(err); + __errno_r(r) = CH_DECODE_ERROR(err); return -1; } @@ -59,7 +73,7 @@ int _read_r(struct _reent *r, int file, char * ptr, int len) { err = sbFileRead((uint32_t)file, (uint8_t *)ptr, (size_t)len); if (CH_RET_IS_ERROR(err)) { - __errno_r(r) = MAKERR(err); + __errno_r(r) = CH_DECODE_ERROR(err); return -1; } @@ -72,7 +86,7 @@ int _lseek_r(struct _reent *r, int file, int ptr, int dir) { err = sbFileSeek((uint32_t)file, (uint32_t)ptr, (uint32_t)dir); if (CH_RET_IS_ERROR(err)) { - __errno_r(r) = MAKERR(err); + __errno_r(r) = CH_DECODE_ERROR(err); return -1; }