From 45c9742c2a81a04666208fac78c37498b0b38d6a Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 13 May 2020 20:28:11 -0400 Subject: [PATCH 1/4] Fix #454, Better error translation on statvfs() The statvfs() call depends on the underlying filesystem supporting this. On RTEMS, the IMFS filesystem type does not, and it returns the ENOSYS errno. This is better translated to OS_ERR_NOT_IMPLEMENTED rather than OS_ERROR. --- src/os/rtems/src/os-impl-filesys.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/os/rtems/src/os-impl-filesys.c b/src/os/rtems/src/os-impl-filesys.c index 40d127522..fb4534c2a 100644 --- a/src/os/rtems/src/os-impl-filesys.c +++ b/src/os/rtems/src/os-impl-filesys.c @@ -376,17 +376,34 @@ int32 OS_FileSysStatVolume_Impl (uint32 filesys_id, OS_statvfs_t *result) { OS_filesys_internal_record_t *local = &OS_filesys_table[filesys_id]; struct statvfs stat_buf; + int32 return_code; if ( statvfs(local->system_mountpt, &stat_buf) != 0 ) { - return OS_ERROR; + /* + * The ENOSYS error means it is not implemented at the system level. + * This should translate to the OS_ERR_NOT_IMPLEMENTED OSAL code. + */ + if (errno == ENOSYS) + { + return_code = OS_ERR_NOT_IMPLEMENTED; + } + else + { + OS_DEBUG("%s: %s\n", local->system_mountpt, strerror(errno)); + return_code = OS_ERROR; + } } + else + { + result->block_size = stat_buf.f_bsize; + result->blocks_free = stat_buf.f_bfree; + result->total_blocks = stat_buf.f_blocks; - result->block_size = stat_buf.f_bsize; - result->blocks_free = stat_buf.f_bfree; - result->total_blocks = stat_buf.f_blocks; + return_code = OS_SUCCESS; + } - return(OS_SUCCESS); + return (return_code); } /* end OS_FileSysStatVolume_Impl */ From 5f97b9b74e2dbe916bdf77b45b1039ab65f38f52 Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 13 May 2020 21:09:14 -0400 Subject: [PATCH 2/4] Fix #459, dynamically create RAM disk devices on RTEMS Rather than relying on the BSP to preallocate, the ram disk block devices can be created based on request. This correlates with the way RAM disks are implemented on VxWorks and is cleaner and more flexible by making it more independent of the BSP. --- src/bsp/pc-rtems/src/bsp_start.c | 23 ------ src/bsp/pc-rtems/src/pcrtems_bsp_internal.h | 1 - src/os/rtems/src/os-impl-filesys.c | 87 +++++++++------------ src/unit-tests/osfile-test/ut_osfile_test.c | 2 +- 4 files changed, 40 insertions(+), 73 deletions(-) diff --git a/src/bsp/pc-rtems/src/bsp_start.c b/src/bsp/pc-rtems/src/bsp_start.c index bcce3f6e2..cece37736 100644 --- a/src/bsp/pc-rtems/src/bsp_start.c +++ b/src/bsp/pc-rtems/src/bsp_start.c @@ -47,29 +47,6 @@ extern rtems_status_code rtems_ide_part_table_initialize(const char *); extern int rtems_rtl_shell_command (int argc, char* argv[]); -/* - * The RAM Disk configuration. - */ -rtems_ramdisk_config rtems_ramdisk_configuration[RTEMS_NUMBER_OF_RAMDISKS]; - -/* - * The number of RAM Disk configurations. - */ -size_t rtems_ramdisk_configuration_size = RTEMS_NUMBER_OF_RAMDISKS; - -/* -** RAM Disk IO op table. -*/ -rtems_driver_address_table rtems_ramdisk_io_ops = -{ - .initialization_entry = ramdisk_initialize, - .open_entry = rtems_blkdev_generic_open, - .close_entry = rtems_blkdev_generic_close, - .read_entry = rtems_blkdev_generic_read, - .write_entry = rtems_blkdev_generic_write, - .control_entry = rtems_blkdev_generic_ioctl -}; - /* * Additional shell commands for the RTL functionality */ diff --git a/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h b/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h index 89656d2c7..cf969525d 100644 --- a/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h +++ b/src/bsp/pc-rtems/src/pcrtems_bsp_internal.h @@ -28,7 +28,6 @@ * BSP compile-time tuning */ #define RTEMS_MAX_USER_OPTIONS 4 -#define RTEMS_NUMBER_OF_RAMDISKS 1 #define RTEMS_MAX_CMDLINE 256 /* diff --git a/src/os/rtems/src/os-impl-filesys.c b/src/os/rtems/src/os-impl-filesys.c index 40d127522..4003cf484 100644 --- a/src/os/rtems/src/os-impl-filesys.c +++ b/src/os/rtems/src/os-impl-filesys.c @@ -46,7 +46,8 @@ typedef struct { char blockdev_name[OS_MAX_PATH_LEN]; - rtems_device_minor_number minor; + + struct ramdisk *allocated_disk; /* other data to pass to "mount" when mounting this disk */ const char *mount_fstype; @@ -65,19 +66,6 @@ typedef struct */ OS_impl_filesys_internal_record_t OS_impl_filesys_table[OS_MAX_FILE_SYSTEMS]; - -/* - * These external references are for the RTEMS RAM disk device descriptor table - * This is necessary for the RAM disk. These tables can either be here, or - * in a RTEMS kernel startup file. In this case, the tables are in the - * application startup - * - * Currently, it does not appear possible to create multiple arbitrary disks - * The RAM disk driver appears to require these specific variables. - */ -extern rtems_ramdisk_config rtems_ramdisk_configuration[]; -extern size_t rtems_ramdisk_configuration_size; - /**************************************************************************************** Filesys API ***************************************************************************************/ @@ -110,7 +98,7 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id) { OS_filesys_internal_record_t *local = &OS_filesys_table[filesys_id]; OS_impl_filesys_internal_record_t *impl = &OS_impl_filesys_table[filesys_id]; - uint32 os_idx; + rtems_status_code sc; int32 return_code; return_code = OS_ERR_NOT_IMPLEMENTED; @@ -136,48 +124,41 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id) } case OS_FILESYS_TYPE_VOLATILE_DISK: { - /* - * This finds the correct driver "minor number" - * to use for the RAM disk (i.e. /dev/rd) - */ + OS_DEBUG("No RAMDISK available at address %p\n", local->address); - /* find a matching entry in the OS ramdisk table, - * (identified by the location address) */ - for (os_idx = 0; os_idx < rtems_ramdisk_configuration_size; ++os_idx) - { - if (rtems_ramdisk_configuration[os_idx].location == local->address) - { - impl->minor = os_idx; - break; - } - } + impl->allocated_disk = ramdisk_allocate( + local->address, + local->blocksize, + local->numblocks, + false + ); - if (os_idx >= rtems_ramdisk_configuration_size) + if (impl->allocated_disk == NULL) { - OS_DEBUG("No RAMDISK available at address %p\n", local->address); + OS_DEBUG("ramdisk_allocate() failed\n"); return_code = OS_INVALID_POINTER; break; } - if ( local->numblocks > rtems_ramdisk_configuration[os_idx].block_num) - { - OS_DEBUG("OSAL: Error: RAM disk too large, %lu blocks requested, %lu available.\n", - (unsigned long)local->numblocks, - (unsigned long)rtems_ramdisk_configuration[os_idx].block_num); - return_code = OS_ERROR; - break; - } - if ( local->blocksize != rtems_ramdisk_configuration[os_idx].block_size ) + + impl->mount_fstype = RTEMS_FILESYSTEM_TYPE_RFS; + impl->mount_options = RTEMS_FILESYSTEM_READ_WRITE; + snprintf(impl->blockdev_name, sizeof(impl->blockdev_name), "%s%c", RAMDISK_DEVICE_BASE_NAME, (int)filesys_id + 'a'); + + sc = rtems_blkdev_create( + impl->blockdev_name, + local->blocksize, + local->numblocks, + ramdisk_ioctl, + impl->allocated_disk + ); + if (sc != RTEMS_SUCCESSFUL) { - OS_DEBUG("OSAL: Error: RAM Disk needs a block size of %lu.\n", - (unsigned long)rtems_ramdisk_configuration[os_idx].block_size); - return_code = OS_ERROR; - break; + OS_DEBUG("rtems_blkdev_create() failed: %s.\n", rtems_status_text(sc)); + return_code = OS_ERROR; } - snprintf(impl->blockdev_name, sizeof(impl->blockdev_name), "%s%c", RAMDISK_DEVICE_BASE_NAME, (int)impl->minor + 'a'); - impl->mount_fstype = RTEMS_FILESYSTEM_TYPE_RFS; - OS_DEBUG("OSAL: RAM disk initialized: volume=%s device=%s address=0x%08lX\n", + OS_DEBUG("RAM disk initialized: volume=%s device=%s address=0x%08lX\n", local->volume_name, impl->blockdev_name, (unsigned long)local->address); return_code = OS_SUCCESS; @@ -218,7 +199,16 @@ int32 OS_FileSysStartVolume_Impl (uint32 filesys_id) *-----------------------------------------------------------------*/ int32 OS_FileSysStopVolume_Impl (uint32 filesys_id) { - /* Currently nothing to do here */ + OS_impl_filesys_internal_record_t *impl = &OS_impl_filesys_table[filesys_id]; + + /* + * If this was a dynamically allocated disk, then unlink it. + */ + if (impl->allocated_disk != NULL) + { + unlink(impl->blockdev_name); + } + return OS_SUCCESS; } /* end OS_FileSysStopVolume_Impl */ @@ -265,6 +255,7 @@ int32 OS_FileSysFormatVolume_Impl (uint32 filesys_id) ** Format the RAM disk with the RFS file system */ memset (&config, 0, sizeof(config)); + config.inode_overhead = 30; sc = rtems_rfs_format(impl->blockdev_name, &config); if ( sc < 0 ) { diff --git a/src/unit-tests/osfile-test/ut_osfile_test.c b/src/unit-tests/osfile-test/ut_osfile_test.c index 8a511a73b..4cc5ae3f9 100644 --- a/src/unit-tests/osfile-test/ut_osfile_test.c +++ b/src/unit-tests/osfile-test/ut_osfile_test.c @@ -56,7 +56,7 @@ int32 UT_os_setup_fs() { int32 res; - res = OS_mkfs(g_fsAddrPtr, g_devName, " ", 512, 20); + res = OS_mkfs(g_fsAddrPtr, g_devName, "RAM3", 512, 64); if (res != OS_SUCCESS) { UT_OS_LOG("OS_mkfs() returns %d\n", (int)res);; From 72af6d57dd7bf3522e2868c419a925554e5bd8ab Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Wed, 13 May 2020 21:23:58 -0400 Subject: [PATCH 3/4] Fix #455, correct length of device_name in filesys This string should be of OS_FS_DEV_NAME_LEN --- src/os/shared/inc/os-shared-filesys.h | 2 +- src/os/shared/src/osapi-filesys.c | 4 ++-- src/unit-test-coverage/shared/src/coveragetest-filesys.c | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/os/shared/inc/os-shared-filesys.h b/src/os/shared/inc/os-shared-filesys.h index d578e57bf..dab908db8 100644 --- a/src/os/shared/inc/os-shared-filesys.h +++ b/src/os/shared/inc/os-shared-filesys.h @@ -95,7 +95,7 @@ typedef struct typedef struct { - char device_name[OS_MAX_API_NAME]; /**< The name of the underlying block device, if applicable */ + char device_name[OS_FS_DEV_NAME_LEN]; /**< The name of the underlying block device, if applicable */ char volume_name[OS_FS_VOL_NAME_LEN]; char system_mountpt[OS_MAX_LOCAL_PATH_LEN]; /**< The name/prefix where the contents are accessible in the host operating system */ char virtual_mountpt[OS_MAX_PATH_LEN]; /**< The name/prefix in the OSAL Virtual File system exposed to applications */ diff --git a/src/os/shared/src/osapi-filesys.c b/src/os/shared/src/osapi-filesys.c index c2638ad70..cf6724bc9 100644 --- a/src/os/shared/src/osapi-filesys.c +++ b/src/os/shared/src/osapi-filesys.c @@ -443,7 +443,7 @@ int32 OS_FileSysAddFixedMap(uint32 *filesys_id, const char *phys_path, const cha return OS_INVALID_POINTER; } - if (strlen(phys_path) >= OS_MAX_PATH_LEN || + if (strlen(phys_path) >= OS_MAX_LOCAL_PATH_LEN || strlen(virt_path) >= OS_MAX_PATH_LEN) { return OS_ERR_NAME_TOO_LONG; @@ -462,7 +462,7 @@ int32 OS_FileSysAddFixedMap(uint32 *filesys_id, const char *phys_path, const cha ++dev_name; } - if (strlen(dev_name) >= OS_MAX_API_NAME) + if (strlen(dev_name) >= OS_FS_DEV_NAME_LEN) { return OS_ERR_NAME_TOO_LONG; } diff --git a/src/unit-test-coverage/shared/src/coveragetest-filesys.c b/src/unit-test-coverage/shared/src/coveragetest-filesys.c index e84d14ec7..fcf40a969 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-filesys.c +++ b/src/unit-test-coverage/shared/src/coveragetest-filesys.c @@ -51,12 +51,14 @@ void Test_OS_FileSysAddFixedMap(void) OSAPI_TEST_FUNCTION_RC(OS_FileSysAddFixedMap(&id, "/phys", "/virt"), OS_SUCCESS); OSAPI_TEST_FUNCTION_RC(OS_FileSysAddFixedMap(&id, NULL, NULL), OS_INVALID_POINTER); - UT_SetForceFail(UT_KEY(OCS_strlen), 2 + OS_MAX_PATH_LEN); + UT_SetDeferredRetcode(UT_KEY(OCS_strlen), 1, 2 + OS_MAX_LOCAL_PATH_LEN); OSAPI_TEST_FUNCTION_RC(OS_FileSysAddFixedMap(&id, "/phys", "/virt"), OS_ERR_NAME_TOO_LONG); - UT_ClearForceFail(UT_KEY(OCS_strlen)); + UT_SetDeferredRetcode(UT_KEY(OCS_strlen), 2, 2 + OS_MAX_PATH_LEN); + OSAPI_TEST_FUNCTION_RC(OS_FileSysAddFixedMap(&id, "/phys", "/virt"), OS_ERR_NAME_TOO_LONG); + UT_ResetState(UT_KEY(OCS_strlen)); UT_SetForceFail(UT_KEY(OCS_strrchr), -1); - UT_SetDeferredRetcode(UT_KEY(OCS_strlen), 3, 2 + OS_MAX_API_NAME); + UT_SetDeferredRetcode(UT_KEY(OCS_strlen), 3, 2 + OS_FS_DEV_NAME_LEN); OSAPI_TEST_FUNCTION_RC(OS_FileSysAddFixedMap(&id, "/phys", "/virt"), OS_ERR_NAME_TOO_LONG); UT_ResetState(UT_KEY(OCS_strlen)); UT_ResetState(UT_KEY(OCS_strrchr)); From 042db6b157b9c72cdccab0bfd3fe3e029104668d Mon Sep 17 00:00:00 2001 From: Joseph Hickey Date: Thu, 14 May 2020 08:06:51 -0400 Subject: [PATCH 4/4] Fix #457, provide BSP shutdown handler This provides a better method of handling test abort, in a BSP-specific manner. --- src/bsp/mcp750-vxworks/src/bsp_start.c | 11 +++++++ src/bsp/pc-linux/src/bsp_start.c | 11 +++++++ src/bsp/pc-rtems/src/bsp_start.c | 41 ++++++++++++++++++-------- src/bsp/shared/inc/bsp-impl.h | 10 +++++++ ut_assert/src/utbsp.c | 4 +-- 5 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/bsp/mcp750-vxworks/src/bsp_start.c b/src/bsp/mcp750-vxworks/src/bsp_start.c index 6c47c4eaf..4669e7a8b 100644 --- a/src/bsp/mcp750-vxworks/src/bsp_start.c +++ b/src/bsp/mcp750-vxworks/src/bsp_start.c @@ -24,6 +24,17 @@ #include "mcp750_bsp_internal.h" +/* --------------------------------------------------------- + OS_BSP_Shutdown_Impl() + + Helper function to abort the running task + --------------------------------------------------------- */ +void OS_BSP_Shutdown_Impl(void) +{ + abort(); +} + + /****************************************************************************** ** Function: OS_BSPMain() ** diff --git a/src/bsp/pc-linux/src/bsp_start.c b/src/bsp/pc-linux/src/bsp_start.c index 50d080fcb..e886eda41 100644 --- a/src/bsp/pc-linux/src/bsp_start.c +++ b/src/bsp/pc-linux/src/bsp_start.c @@ -132,6 +132,17 @@ int OS_BSP_GetReturnStatus(void) return retcode; } +/* --------------------------------------------------------- + OS_BSP_Shutdown_Impl() + + Helper function to abort the running task + --------------------------------------------------------- */ +void OS_BSP_Shutdown_Impl(void) +{ + abort(); +} + + /****************************************************************************** ** Function: main() ** diff --git a/src/bsp/pc-rtems/src/bsp_start.c b/src/bsp/pc-rtems/src/bsp_start.c index bcce3f6e2..78ffefacc 100644 --- a/src/bsp/pc-rtems/src/bsp_start.c +++ b/src/bsp/pc-rtems/src/bsp_start.c @@ -324,6 +324,30 @@ rtems_status_code OS_BSP_GetReturnStatus(void) return retcode; } +/* --------------------------------------------------------- + OS_BSP_Shutdown_Impl() + + Helper function to abort the running task + --------------------------------------------------------- */ +void OS_BSP_Shutdown_Impl(void) +{ + /* + * Not calling exit() under RTEMS, this simply shuts down the executive, + * forcing the user to reboot the system. + * + * Calling suspend causes execution to get stuck here, but the RTEMS + * shell thread will still be active so the user can poke around, read results, + * then use a shell command to reboot when ready. + */ + while (!OS_BSP_PcRtemsGlobal.BatchMode) + { + printf("\n\nInit thread idle.\nPress for shell or reset machine...\n\n"); + rtems_task_suspend(rtems_task_self()); + } + + rtems_shutdown_executive(OS_BSP_GetReturnStatus()); +} + /* ** A simple entry point to start from the loader */ @@ -355,20 +379,11 @@ rtems_task Init(rtems_task_argument ignored) OS_Application_Run(); /* - * Not calling exit() under RTEMS, this simply shuts down the executive, - * forcing the user to reboot the system. - * - * Calling suspend causes execution to get stuck here, but the RTEMS - * shell thread will still be active so the user can poke around, read results, - * then use a shell command to reboot when ready. + * Enter the BSP default shutdown mode + * depending on config, this may reset/reboot or suspend + * so the operator can use the shell. */ - while (!OS_BSP_PcRtemsGlobal.BatchMode) - { - printf("\n\nInit thread idle.\nPress for shell or reset machine...\n\n"); - rtems_task_suspend(rtems_task_self()); - } - - rtems_shutdown_executive(OS_BSP_GetReturnStatus()); + OS_BSP_Shutdown_Impl(); } /* configuration information */ diff --git a/src/bsp/shared/inc/bsp-impl.h b/src/bsp/shared/inc/bsp-impl.h index bce51a9bb..39b0ad775 100644 --- a/src/bsp/shared/inc/bsp-impl.h +++ b/src/bsp/shared/inc/bsp-impl.h @@ -133,6 +133,16 @@ void OS_BSP_ConsoleOutput_Impl(const char *Str, uint32 DataLen); ------------------------------------------------------------------*/ void OS_BSP_ConsoleSetMode_Impl(uint32 ModeBits); +/*---------------------------------------------------------------- + Function: OS_BSP_Shutdown_Impl + + Purpose: Causes the calling task to abort in a BSP-safe way. + This may map to the abort() system call, but on some systems + that causes a reboot or undesirable side effect. The + BSP may implement this call in a different manner. + ------------------------------------------------------------------*/ +void OS_BSP_Shutdown_Impl(void); + /********************* END bsp-impl.h *********************/ diff --git a/ut_assert/src/utbsp.c b/ut_assert/src/utbsp.c index 1744af8c2..f63e57923 100644 --- a/ut_assert/src/utbsp.c +++ b/ut_assert/src/utbsp.c @@ -170,11 +170,11 @@ void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage) /* * If any ABORT (major failure) message is thrown, - * then actually call abort() to stop the test and dump a core + * then call a BSP-provided routine to stop the test and possibly dump a core */ if (MessageType == UTASSERT_CASETYPE_ABORT) { - abort(); + OS_BSP_Shutdown_Impl(); } }