diff --git a/os/common/startup/ARMCMx-SB/compilers/GCC/crt0.S b/os/common/startup/ARMCMx-SB/compilers/GCC/crt0.S index d113dfdb7..0be4f0224 100644 --- a/os/common/startup/ARMCMx-SB/compilers/GCC/crt0.S +++ b/os/common/startup/ARMCMx-SB/compilers/GCC/crt0.S @@ -99,13 +99,10 @@ __sandbox: .long 0xFE9154C0 .long 0x0C4519EF .long 32 .long __crt0_entry - - .thumb_func - .global _exit /* Required by newlib.*/ -_exit: - svc #1 -.exitloop: b .exitloop - .align 5 + .long __crt0_exit + .long 0 + .long 0 + .long 0 .bss @@ -121,13 +118,22 @@ environ: .ds.l 1 .text -/* - * CRT0 entry point. - */ + + /* Default exit method, calling OS exit().*/ + .align 2 + .thumb_func + .global __crt0_exit +__crt0_exit: + svc #1 +.exitloop: b .exitloop + + /* Default entry point, note, the "nop" is meant to be there + the loader could overwrite it with a "bkpt".*/ .align 2 .thumb_func .global __crt0_entry __crt0_entry: + nop /* Popping from the stack the information passed by the loader, saving the stack position as end of heap.*/ pop {r7, r8, r9, r10} @@ -200,7 +206,11 @@ endinitloop: mov r1, r8 mov r2, r9 bl main + /* Falls into _exit().*/ + .thumb_func + .global _exit /* Required by newlib.*/ +_exit: #if CRT0_CALL_DESTRUCTORS == TRUE /* Destructors invocation.*/ mov r6, r0 @@ -215,7 +225,9 @@ finiloop: mov r0, r6 endfiniloop: #endif /* CRT0_CALL_DESTRUCTORS == TRUE */ - b _exit + ldr r1, =__sandbox + ldr r2, [r1], #16 /* Predefined exit vector.*/ + bx r2 #endif /* !defined(__DOXYGEN__) */ diff --git a/os/sb/host/sbapi.c b/os/sb/host/sbapi.c index ba60aaa2f..3a2a613b2 100644 --- a/os/sb/host/sbapi.c +++ b/os/sb/host/sbapi.c @@ -52,6 +52,7 @@ #define SB_SVC9_HANDLER sb_api_wait_any_timeout #define SB_SVC10_HANDLER sb_api_wait_all_timeout #define SB_SVC11_HANDLER sb_api_broadcast_flags +#define SB_SVC12_HANDLER sb_api_loadelf /** @} */ #define __SVC(x) asm volatile ("svc " #x) @@ -1066,17 +1067,17 @@ void sb_api_sleep_until_windowed(struct port_extctx *ectxp) { void sb_api_wait_message(struct port_extctx *ectxp) { #if CH_CFG_USE_MESSAGES == TRUE - sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; chSysLock(); - if (sbcp->msg_tp == NULL) { - sbcp->msg_tp = sb_msg_wait_timeout_s(TIME_INFINITE); - ectxp->r0 = (uint32_t)chMsgGet(sbcp->msg_tp); + if (sbp->msg_tp == NULL) { + sbp->msg_tp = sb_msg_wait_timeout_s(TIME_INFINITE); + ectxp->r0 = (uint32_t)chMsgGet(sbp->msg_tp); } else { - thread_t *tp = sbcp->msg_tp; - sbcp->msg_tp = NULL; + thread_t *tp = sbp->msg_tp; + sbp->msg_tp = NULL; chMsgReleaseS(tp, MSG_RESET); ectxp->r0 = MSG_RESET; } @@ -1089,13 +1090,13 @@ void sb_api_wait_message(struct port_extctx *ectxp) { void sb_api_reply_message(struct port_extctx *ectxp) { #if CH_CFG_USE_MESSAGES == TRUE - sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; chSysLock(); - if (sbcp->msg_tp != NULL) { - thread_t *tp = sbcp->msg_tp; - sbcp->msg_tp = NULL; + if (sbp->msg_tp != NULL) { + thread_t *tp = sbp->msg_tp; + sbp->msg_tp = NULL; chMsgReleaseS(tp, (msg_t )ectxp->r0); ectxp->r0 = CH_RET_SUCCESS; } @@ -1141,13 +1142,35 @@ void sb_api_wait_all_timeout(struct port_extctx *ectxp) { void sb_api_broadcast_flags(struct port_extctx *ectxp) { #if CH_CFG_USE_EVENTS == TRUE - sb_class_t *sbcp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; - chEvtBroadcastFlags(&sbcp->es, (eventflags_t )ectxp->r0); + chEvtBroadcastFlags(&sbp->es, (eventflags_t )ectxp->r0); ectxp->r0 = CH_RET_SUCCESS; #else ectxp->r0 = CH_RET_ENOSYS; #endif } +void sb_api_loadelf(struct port_extctx *ectxp) { +#if (SB_CFG_ENABLE_VFS == TRUE) || defined(__DOXYGEN__) + sb_class_t *sbp = (sb_class_t *)chThdGetSelfX()->ctx.syscall.p; + const char *fname = (const char *)ectxp->r0; + uint8_t *buf = (uint8_t *)ectxp->r1; + size_t size = (size_t)ectxp->r2; + + if ((sb_check_string(sbp, (void *)fname, VFS_CFG_PATHLEN_MAX + 1) == (size_t)0) || + !MEM_IS_ALIGNED(buf, MEM_NATURAL_ALIGN) || + !MEM_IS_ALIGNED(size, MEM_NATURAL_ALIGN) || + !sb_is_valid_write_range(sbp, buf, size)) { + ectxp->r0 = CH_RET_EFAULT; + } + else { + memory_area_t ma = {buf, size}; + ectxp->r0 = (uint32_t)sbElfLoadFile(sbp->config->vfs_driver, fname, &ma); + } +#else + ectxp->r0 = CH_RET_ENOSYS; +#endif +} + /** @} */ diff --git a/os/sb/host/sbapi.h b/os/sb/host/sbapi.h index db4768d50..5ac6cfac0 100644 --- a/os/sb/host/sbapi.h +++ b/os/sb/host/sbapi.h @@ -114,6 +114,7 @@ extern "C" { void sb_api_wait_any_timeout(struct port_extctx *ctxp); void sb_api_wait_all_timeout(struct port_extctx *ctxp); void sb_api_broadcast_flags(struct port_extctx *ctxp); + void sb_api_loadelf(struct port_extctx *ectxp); #ifdef __cplusplus } #endif diff --git a/os/sb/user/sbuser.h b/os/sb/user/sbuser.h index 0d7beef34..325a10209 100644 --- a/os/sb/user/sbuser.h +++ b/os/sb/user/sbuser.h @@ -509,6 +509,24 @@ static inline uint32_t sbEventBroadcastFlags(eventflags_t flags) { return (uint32_t)r0; } +/** + * @brief Loads an elf file within the sandbox into the specified buffer. + * @details The file is loaded and relocated starting from the buffer + * address. + * + * @param[in] fname file to be loaded + * @param[in] buf load buffer + * @param[in] size size of the load buffer + * + * @api + */ +static inline int sbLoadElf(const char *fname, uint8_t *buf, size_t size) { + + __syscall3r(12, fname, buf, size); + return (uint32_t)r0; + +} + /** * @brief Seconds to time interval. * @details Converts from seconds to system ticks number.