M .gitmodules => .gitmodules +1 -1
@@ 54,7 54,7 @@
path = module-utils/magic_enum
url = git@github.com:Neargye/magic_enum.git
[submodule "module-vfs/board/cross/freeRTOS_FAT"]
- path = module-vfs/board/cross/freeRTOS_FAT
+ path = module-vfs/board/freeRTOS_FAT
url = ../Lab-Project-FreeRTOS-FAT.git
[submodule "module-utils/tinyexpr"]
path = module-utils/tinyexpr
M CMakeLists.txt => CMakeLists.txt +14 -0
@@ 204,6 204,20 @@ set_source_files_properties(source/main.cpp PROPERTIES COMPILE_DEFINITIONS "${EN
target_link_options(${PROJECT_NAME} PUBLIC ${TARGET_LINK_OPTIONS})
if (${PROJECT_TARGET} STREQUAL "TARGET_Linux")
+
+ set(FAT_IMAGE ${CMAKE_PROJECT_NAME}.img)
+ add_custom_command(
+ OUTPUT ${FAT_IMAGE}
+ DEPENDS assets
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate_fatfs_image.sh ${FAT_IMAGE} ${CMAKE_BINARY_DIR}
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+ COMMENT "Generate ${FAT_IMAGE}"
+ )
+ add_custom_target(
+ ${FAT_IMAGE}-target ALL
+ DEPENDS ${FAT_IMAGE}
+ )
+ add_dependencies(check ${FAT_IMAGE}-target)
install(TARGETS ${CMAKE_PROJECT_NAME} DESTINATION "./")
endif()
A generate_fatfs_image.sh => generate_fatfs_image.sh +60 -0
@@ 0,0 1,60 @@
+#!/bin/bash -e
+# Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+# For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+usage() {
+cat << ==usage
+Usage: $(basename $0) [image_dir] [assets_root_dir]
+ image_dir Target disk image
+ asset_root_dir Asset root directory
+==usage
+}
+
+ASSETS_DIR="assets country-codes.db Luts.bin"
+
+TEST_ITEMS="testfiles"
+
+if [ $# -ne 2 ]; then
+ echo "Error! Invalid argument count"
+ usage
+ exit -1
+fi
+IMAGE_NAME=$(realpath $1)
+SRC_DATA=$(realpath $2)
+
+if [ ! -d "$SRC_DATA" ]; then
+ echo "Error! asset_root_dir is not a directory"
+ usage
+ exit -1
+fi
+
+truncate -s 16G $IMAGE_NAME
+sfdisk $IMAGE_NAME << ==sfdisk
+label: dos
+label-id: 0x09650eb4
+unit: sectors
+
+/dev/sda1 : start= 2048, size= 28522496, type=b, bootable
+/dev/sda2 : start= 28524544, size= 2097152, type=b
+==sfdisk
+
+PART1="$IMAGE_NAME@@1048576"
+PART2="$IMAGE_NAME@@14604566528"
+mformat -i "$PART1" -F -T 28522496 -v PUREOS
+mformat -i "$PART2" -F -T 2097152 -v RECOVER
+mmd -i "$PART1" ::/current
+cd "$SRC_DATA"
+for i in $ASSETS_DIR; do
+ mcopy -s -i "$PART1" $i ::/current/
+done
+mcopy -s -i "$PART1" user ::
+mcopy -s -i "$PART1" .boot.json ::
+mcopy -s -i "$PART1" .boot.json.crc32 ::
+
+# Testing parts of files
+for i in $TEST_ITEMS; do
+ mcopy -s -i "$PART1" $i ::/current
+done
+mcopy -s -i "$PART1" sys/updates ::
+
+cd -
M module-apps/application-calculator/tests/CalculatorUtility_tests.cpp => module-apps/application-calculator/tests/CalculatorUtility_tests.cpp +8 -0
@@ 9,6 9,14 @@
class vfs vfs;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_initializer;
+
TEST_CASE("Calculator utilities")
{
auto calculator = Calculator();
M module-audio/Audio/test/unittest_audio.cpp => module-audio/Audio/test/unittest_audio.cpp +21 -10
@@ 19,18 19,29 @@
class vfs vfs;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_init;
+
TEST_CASE("Test audio tags")
{
- std::vector<std::string> testExtensions = {"flac", "wav", "mp3"};
- for (auto ext : testExtensions) {
- auto dec = audio::decoder::Create(("testfiles/audio." + ext).c_str());
- REQUIRE(dec);
- auto tags = dec->fetchTags();
- REQUIRE(tags);
- REQUIRE(tags->title == ext + " Test track title");
- REQUIRE(tags->artist == ext + " Test artist name");
- REQUIRE(tags->album == ext + " Test album title");
- REQUIRE(tags->year == "2020");
+ SECTION(" Encoder tests ")
+ {
+ std::vector<std::string> testExtensions = {"flac", "wav", "mp3"};
+ for (auto ext : testExtensions) {
+ auto dec = audio::decoder::Create(("testfiles/audio." + ext).c_str());
+ REQUIRE(dec);
+ auto tags = dec->fetchTags();
+ REQUIRE(tags);
+ REQUIRE(tags->title == ext + " Test track title");
+ REQUIRE(tags->artist == ext + " Test artist name");
+ REQUIRE(tags->album == ext + " Test album title");
+ REQUIRE(tags->year == "2020");
+ }
}
}
M module-db/tests/unittest.cpp => module-db/tests/unittest.cpp +8 -0
@@ 18,6 18,14 @@
class vfs vfs;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_initializer;
+
TEST_CASE("Create and destroy simple database")
{
M module-gui/test/test-catch-text/main.cpp => module-gui/test/test-catch-text/main.cpp +8 -0
@@ 8,3 8,11 @@
class vfs vfs; // needed for compilation, our vfs is global
utils::i18 localize; // needed to load any keymap - these are stored in i18
+
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_initializer;
M module-gui/test/test-catch/test-gui.cpp => module-gui/test/test-catch/test-gui.cpp +9 -1
@@ 6,6 6,7 @@
#include "mock/InitializedFontManager.hpp"
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
+#include <vfs.hpp>
#include <memory>
#include <functional>
#include <iostream>
@@ 25,7 26,6 @@
#include <module-gui/gui/widgets/Label.hpp>
#include <module-gui/gui/widgets/BoxLayout.hpp>
#include <module-gui/gui/widgets/Image.hpp>
-#include <vfs.hpp>
#include <mock/TestWindow.hpp>
@@ 33,6 33,14 @@ using namespace std;
class vfs vfs;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_init;
+
TEST_CASE("Test BoundingBox intersect")
{
gui::BoundingBox result;
M module-services/service-desktop/tests/unittest.cpp => module-services/service-desktop/tests/unittest.cpp +9 -4
@@ 19,11 19,17 @@
class vfs vfs;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_initializer;
+
TEST_CASE("System Update Tests")
{
- ServiceDesktop serviceDesktop;
- vfs.Init();
- UpdatePureOS updateOS(&serviceDesktop);
+ UpdatePureOS updateOS(nullptr);
updateos::UpdateError err = updateOS.prepareTempDirForUpdate();
REQUIRE(err == updateos::UpdateError::NoError);
@@ 39,7 45,6 @@ TEST_CASE("System Update Tests")
TEST_CASE("Factory Reset Test")
{
- vfs.Init();
std::string sysdir = purefs::dir::eMMC_disk;
sysdir += "/factory-test/sys";
M module-utils/board/linux/log.cpp => module-utils/board/linux/log.cpp +2 -1
@@ 94,7 94,8 @@ static void _log_Log(
std::cout << loggerBuffer;
}
-void log_Log(logger_level level, const char *file, int line, const char *function, const char *fmt, ...)
+__attribute__((weak)) void log_Log(
+ logger_level level, const char *file, int line, const char *function, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
M module-utils/test/test_time_conversion.cpp => module-utils/test/test_time_conversion.cpp +20 -0
@@ 4,6 4,25 @@
#include <iostream>
#include <time/time_conversion.hpp>
#include <algorithm>
+#include <thread.hpp>
+
+namespace
+{
+ thread_local void *tls_pointers[configNUM_THREAD_LOCAL_STORAGE_POINTERS];
+}
+
+extern "C"
+{
+
+ void *ff_stdio_pvTaskGetThreadLocalStoragePointer(TaskHandle_t, BaseType_t xIndex)
+ {
+ return tls_pointers[xIndex];
+ }
+ void ff_stdio_vTaskSetThreadLocalStoragePointer(TaskHandle_t, BaseType_t xIndex, void *pvValue)
+ {
+ tls_pointers[xIndex] = pvValue;
+ }
+}
/// crap null stream from internets
/// (https://stackoverflow.com/questions/8243743/is-there-a-null-stdostream-implementation-in-c-or-libraries)
@@ 213,6 232,7 @@ int main(int argc, char *argv[])
{
time_t time_today = 0;
+ vfs.Init();
// get reference Today time
if (bsp::rtc_GetCurrentTimestamp(&time_today)) {
std::cerr << "Error on gettime" << std::endl;
M module-utils/test/unittest_duration.cpp => module-utils/test/unittest_duration.cpp +8 -0
@@ 15,6 15,14 @@
class vfs vfs;
utils::i18 localize;
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_intializer;
+
TEST_CASE("Duration - creation")
{
utils::localize.Switch(utils::Lang::En);
M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +37 -2
@@ 1,9 1,44 @@
cmake_minimum_required(VERSION 3.12)
+include(thirdparty)
project(module-vfs VERSION 1.0
DESCRIPTION "VFS module library")
-set(SOURCES "" vfs-utils.cpp)
+set(FREERTOS_FAT_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_crc.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_dir.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_error.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_fat.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_file.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_format.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_ioman.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_locking.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_memory.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_stdio.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_string.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_sys.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/ff_time.c
+ )
+
+third_party_source_optimization(${FREERTOS_FAT_SOURCES})
+
+# Disable some warnings due to ugly embedded hacks
+# in the FREERTOS FAT implementation
+if(${PROJECT_TARGET} STREQUAL "TARGET_Linux")
+set_property(SOURCE ${FREERTOS_FAT_SOURCES} APPEND_STRING PROPERTY COMPILE_FLAGS
+" -Wno-overflow -Wno-type-limits -Wno-format -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast")
+endif()
+
+set(PROJECT_INCLUDES
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/freeRTOS_FAT/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/free_rtos_custom/include
+ )
+
+set(SOURCES ""
+ ${FREERTOS_FAT_SOURCES}
+ vfs-utils.cpp
+ vfs.cpp
+)
if(NOT ${PROJECT_TARGET} STREQUAL "TARGET_Linux")
include(targets/Target_Cross.cmake)
@@ 45,7 80,7 @@ target_include_directories(${PROJECT_NAME}
)
-target_link_libraries(${PROJECT_NAME} ${TARGET_LIBRARIES} module-os module-bsp module-utils)
+target_link_libraries(${PROJECT_NAME} ${TARGET_LIBRARIES} module-bsp module-utils)
if(${PROJECT_TARGET} STREQUAL "TARGET_Linux")
target_link_libraries(${PROJECT_NAME} -lstdc++fs)
D module-vfs/board/cross/freeRTOS_FAT => module-vfs/board/cross/freeRTOS_FAT +0 -1
@@ 1,1 0,0 @@
-Subproject commit 49b471939b4b3de570d34fabf97ad6e3541e19e9
A module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp => module-vfs/board/cross/free_rtos_custom/portable/vfs.cpp +50 -0
@@ 0,0 1,50 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "vfs.hpp"
+#include "ff_eMMC_user_disk.hpp"
+
+vfs::vfs() : emmc()
+{}
+
+vfs::~vfs()
+{
+ FF_eMMC_user_DiskDelete(emmcFFDisk);
+ emmc.DeInit();
+}
+
+void vfs::Init()
+{
+ emmc.Init();
+
+ emmcFFDisk = FF_eMMC_user_DiskInit(purefs::dir::eMMC_disk.c_str(), &emmc);
+
+ /* Print out information on the disk. */
+ FF_eMMC_user_DiskShowPartition(emmcFFDisk);
+
+ bootConfig.os_root_path = purefs::dir::eMMC_disk;
+
+ if (loadBootConfig(getCurrentBootJSON())) {
+ LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type.c_str(), bootConfig.os_root_path.c_str());
+ if (ff_chdir(bootConfig.os_root_path.c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path.c_str());
+ }
+ }
+ else {
+ LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path.c_str());
+ }
+
+ LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path.c_str());
+
+ // this should already exist and have user data in it
+ // if it does not create an exmpty directory so that sqlite3 does not fault
+ if (isDir(purefs::dir::user_disk.c_str()) == false) {
+ LOG_ERROR("vfs::Init looks like %s does not exist, try to create it", purefs::dir::user_disk.c_str());
+ if (ff_mkdir(purefs::dir::user_disk.c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't create %s directory", purefs::dir::user_disk.c_str());
+ }
+ }
+ else {
+ LOG_INFO("vfs::Init looks like %s exists", purefs::dir::user_disk.c_str());
+ }
+}
A module-vfs/board/freeRTOS_FAT => module-vfs/board/freeRTOS_FAT +1 -0
@@ 0,0 1,1 @@
+Subproject commit ab9206031204ee0f34b4dad8fd874db4f128d23a
R module-vfs/board/cross/free_rtos_custom/include/FreeRTOSFATConfig.h => module-vfs/board/free_rtos_custom/include/FreeRTOSFATConfig.h +0 -0
A module-vfs/board/linux/free_rtos_custom/include/ff_image_user_disk.hpp => module-vfs/board/linux/free_rtos_custom/include/ff_image_user_disk.hpp +14 -0
@@ 0,0 1,14 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+#pragma once
+
+#include "vfs.hpp"
+
+namespace freertos_fat::internals
+{
+ FF_Disk_t *diskInit(const char *pcName, const char img_path[]);
+ BaseType_t diskDelete(FF_Disk_t *pxDisk);
+ BaseType_t diskShowPartition(FF_Disk_t *pxDisk);
+ void diskFlush(FF_Disk_t *pxDisk);
+ uint8_t diskIsPresent(void);
+} // namespace freertos_fat::internals
A module-vfs/board/linux/free_rtos_custom/portable/common.cpp => module-vfs/board/linux/free_rtos_custom/portable/common.cpp +12 -0
@@ 0,0 1,12 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <ctime>
+
+extern "C"
+{
+ time_t FreeRTOS_time(time_t *pxTime)
+ {
+ return std::time(pxTime);
+ }
+}
A module-vfs/board/linux/free_rtos_custom/portable/ff_image_user_disk.cpp => module-vfs/board/linux/free_rtos_custom/portable/ff_image_user_disk.cpp +426 -0
@@ 0,0 1,426 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+//
+#include <vfs.hpp>
+#include <ff_image_user_disk.hpp>
+#include <filesystem>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+namespace
+{
+ constexpr auto FSL_SDMMC_DEFAULT_BLOCK_SIZE = 512UL;
+ constexpr auto eMMCSIGNATURE = 0x61606362;
+ constexpr auto mainIO_MANAGER_CACHE_SIZE = 15UL * FSL_SDMMC_DEFAULT_BLOCK_SIZE;
+ constexpr auto eMMCPARTITION_NUMBER = 0;
+
+ constexpr auto eMMCHIDDEN_SECTOR_COUNT = 8;
+ constexpr auto eMMCPRIMARY_PARTITIONS = 1;
+
+ constexpr auto eMMCHUNDRED_64_BIT = 100ULL;
+
+ constexpr auto eMMCBYTES_PER_MB = 1024ull * 1024ull;
+ constexpr auto eMMCSECTORS_PER_MB = eMMCBYTES_PER_MB / 512ull;
+
+ alignas(32) uint8_t emmc_user_CacheBuffer[mainIO_MANAGER_CACHE_SIZE];
+} // namespace
+
+namespace
+{
+ class file_operation
+ {
+ static constexpr auto SECT_SIZE = 512;
+
+ public:
+ file_operation(const file_operation &) = delete;
+ file_operation &operator=(const file_operation &) = delete;
+ // Constructor
+ file_operation(const char file_name[])
+ {
+ m_fd = ::open(file_name, O_RDWR, O_SYNC);
+ if (m_fd < 0) {
+ throw std::system_error();
+ }
+ }
+ // Destructor
+ ~file_operation()
+ {
+ if (m_fd) {
+ ::close(m_fd);
+ }
+ }
+ // Read sector
+ int read(void *buf, unsigned sector_number, unsigned sector_count)
+ {
+ int ret = ::lseek(m_fd, sector_number * SECT_SIZE, SEEK_SET);
+ if (ret < 0) {
+ return ret;
+ }
+ auto to_read = sector_count * SECT_SIZE;
+ auto buf_b = reinterpret_cast<uint8_t *>(buf);
+ do {
+ ret = ::read(m_fd, buf_b, to_read);
+ if (ret < 0) {
+ return ret;
+ }
+ to_read -= ret;
+ buf_b += ret;
+ } while (to_read > 0);
+ return 0;
+ }
+ // Write sector
+ int write(const void *buf, unsigned sector_number, unsigned sector_count)
+ {
+ int ret = ::lseek(m_fd, sector_number * SECT_SIZE, SEEK_SET);
+ if (ret < 0) {
+ return ret;
+ }
+ auto to_write = sector_count * SECT_SIZE;
+ auto buf_b = reinterpret_cast<const uint8_t *>(buf);
+ do {
+ ret = ::write(m_fd, buf_b, to_write);
+ if (ret < 0) {
+ return ret;
+ }
+ to_write -= ret;
+ buf_b += ret;
+ } while (to_write > 0);
+ return 0;
+ }
+
+ private:
+ int m_fd{};
+ };
+
+ int32_t writeBlocks(uint8_t *pucSource, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk)
+ {
+ int32_t lReturn = FF_ERR_NONE;
+ auto mmc_card = static_cast<file_operation *>(pxDisk->pvTag);
+
+ if (pxDisk != NULL) {
+
+ if (pxDisk->ulSignature != eMMCSIGNATURE) {
+ /* The disk structure is not valid because it doesn't contain a
+ magic number written to the disk when it was created. */
+ lReturn = FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_ERRFLAG;
+ }
+ else if (pxDisk->xStatus.bIsInitialised == pdFALSE) {
+ /* The disk has not been initialised. */
+ lReturn = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
+ }
+ else if (ulSectorNumber >= pxDisk->ulNumberOfSectors) {
+ /* The start sector is not within the bounds of the disk. */
+ lReturn = (FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG);
+ }
+ else if ((pxDisk->ulNumberOfSectors - ulSectorNumber) < ulSectorCount) {
+ /* The end sector is not within the bounds of the disk. */
+ lReturn = (FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG);
+ }
+ else {
+ if (mmc_card->write(pucSource, ulSectorNumber, ulSectorCount) < 0) {
+ lReturn = FF_ERR_DEVICE_DRIVER_FAILED;
+ }
+ }
+ }
+ else {
+ lReturn = FF_ERR_NULL_POINTER | FF_ERRFLAG;
+ }
+
+ return lReturn;
+ }
+
+ int32_t readBlocks(uint8_t *pucDestination, uint32_t ulSectorNumber, uint32_t ulSectorCount, FF_Disk_t *pxDisk)
+ {
+ int32_t lReturn = FF_ERR_NONE;
+
+ auto mmc_card = static_cast<file_operation *>(pxDisk->pvTag);
+
+ if (pxDisk != NULL) {
+ if (pxDisk->ulSignature != eMMCSIGNATURE) {
+ /* The disk structure is not valid because it doesn't contain a
+ magic number written to the disk when it was created. */
+ lReturn = FF_ERR_IOMAN_DRIVER_FATAL_ERROR | FF_ERRFLAG;
+ }
+ else if (pxDisk->xStatus.bIsInitialised == pdFALSE) {
+ /* The disk has not been initialised. */
+ lReturn = FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG;
+ }
+ else if (ulSectorNumber >= pxDisk->ulNumberOfSectors) {
+ /* The start sector is not within the bounds of the disk. */
+ lReturn = (FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG);
+ }
+ else if ((pxDisk->ulNumberOfSectors - ulSectorNumber) < ulSectorCount) {
+ /* The end sector is not within the bounds of the disk. */
+ lReturn = (FF_ERR_IOMAN_OUT_OF_BOUNDS_WRITE | FF_ERRFLAG);
+ }
+ else {
+ if (mmc_card->read(pucDestination, ulSectorNumber, ulSectorCount) < 0) {
+ lReturn = FF_ERR_DEVICE_DRIVER_FAILED;
+ }
+ }
+ }
+ else {
+ lReturn = FF_ERR_NULL_POINTER | FF_ERRFLAG;
+ }
+
+ return lReturn;
+ }
+
+ FF_Error_t prvPartitionAndFormatDisk(FF_Disk_t *pxDisk)
+ {
+ FF_PartitionParameters_t xPartition;
+ FF_Error_t xError;
+
+ /* Create a single partition that fills all available space on the disk. */
+ memset(&xPartition, '\0', sizeof(xPartition));
+ xPartition.ulSectorCount = pxDisk->ulNumberOfSectors;
+ xPartition.ulHiddenSectors = eMMCHIDDEN_SECTOR_COUNT;
+ xPartition.xPrimaryCount = eMMCPRIMARY_PARTITIONS;
+ xPartition.eSizeType = eSizeIsQuota;
+
+ /* Partition the disk */
+ xError = FF_Partition(pxDisk, &xPartition);
+ LOG_PRINTF("FF_Partition: %s\r\n", (const char *)FF_GetErrMessage(xError));
+
+ if (FF_isERR(xError) == pdFALSE) {
+ /* Format the partition. */
+ xError = FF_Format(pxDisk, eMMCPARTITION_NUMBER, pdFALSE, pdFALSE);
+ LOG_PRINTF("FF_eMMC_user_DiskInit: FF_Format: %s\r\n", (const char *)FF_GetErrMessage(xError));
+ }
+
+ return xError;
+ }
+
+ FF_Error_t FF_InvalidateCache(FF_IOManager_t *pxIOManager)
+ {
+ BaseType_t xIndex;
+ FF_Error_t xError;
+
+ if (pxIOManager == NULL) {
+ xError = FF_ERR_NULL_POINTER | FF_FLUSHCACHE;
+ }
+ else {
+ xError = FF_ERR_NONE;
+
+ FF_PendSemaphore(pxIOManager->pvSemaphore);
+ {
+ for (xIndex = 0; xIndex < pxIOManager->usCacheSize; xIndex++) {
+ /* If a buffers has no users and if it has been modified... */
+ if ((pxIOManager->pxBuffers[xIndex].usNumHandles != 0) ||
+ (pxIOManager->pxBuffers[xIndex].bModified == pdTRUE)) {
+ /* Can not flush all caches. */
+ xError++;
+ }
+ else {
+ /* Mark the buffer as invalid so that it won't be used again. */
+ pxIOManager->pxBuffers[xIndex].bValid = pdFALSE;
+ }
+ }
+ }
+
+ FF_ReleaseSemaphore(pxIOManager->pvSemaphore);
+ }
+
+ /* Function successful if it returns 0. */
+ return xError;
+ }
+} // namespace
+
+namespace freertos_fat::internals
+{
+ // *** ***
+ FF_Disk_t *diskInit(const char *pcName, const char img_path[])
+ {
+ FF_Error_t xError;
+ FF_Disk_t *pxDisk = NULL;
+ FF_CreationParameters_t xParameters;
+
+ /* Attempt to allocated the FF_Disk_t structure. */
+ pxDisk = (FF_Disk_t *)malloc(sizeof(FF_Disk_t));
+
+ if (pxDisk != NULL) {
+ /* Start with every member of the structure set to zero. */
+ memset(pxDisk, '\0', sizeof(FF_Disk_t));
+
+ /* The signature is used by the disk read and disk write functions to
+ ensure the disk being accessed is a eMMC disk. */
+ pxDisk->ulSignature = eMMCSIGNATURE;
+
+ /* The number of sectors is recorded for bounds checking in the read and
+ write functions. */
+ pxDisk->ulNumberOfSectors = std::filesystem::file_size(img_path) / FSL_SDMMC_DEFAULT_BLOCK_SIZE;
+ /* Store pointer to mmc_card_t structure */
+ pxDisk->pvTag = new file_operation(img_path);
+
+ /* Create the IO manager that will be used to control the eMMC disk. */
+ memset(&xParameters, '\0', sizeof(xParameters));
+ xParameters.pucCacheMemory = emmc_user_CacheBuffer;
+ xParameters.ulMemorySize = mainIO_MANAGER_CACHE_SIZE;
+ xParameters.ulSectorSize = FSL_SDMMC_DEFAULT_BLOCK_SIZE;
+ xParameters.fnWriteBlocks = writeBlocks;
+ xParameters.fnReadBlocks = readBlocks;
+ xParameters.pxDisk = pxDisk;
+
+ /* Driver is reentrant so xBlockDeviceIsReentrant can be set to pdTRUE.
+ In this case the semaphore is only used to protect FAT data
+ structures. */
+ xParameters.pvSemaphore = (void *)xSemaphoreCreateRecursiveMutex();
+ xParameters.xBlockDeviceIsReentrant = pdFALSE;
+
+ /* Check the validity of the xIOManagerCacheSize parameter. */
+ configASSERT((mainIO_MANAGER_CACHE_SIZE % xParameters.ulSectorSize) == 0);
+ configASSERT((mainIO_MANAGER_CACHE_SIZE >= (size_t)(2 * xParameters.ulSectorSize)));
+
+ pxDisk->pxIOManager = FF_CreateIOManger(&xParameters, &xError);
+
+ if ((pxDisk->pxIOManager != NULL) && (FF_isERR(xError) == pdFALSE)) {
+ /* Record that the eMMC disk has been initialised. */
+ pxDisk->xStatus.bIsInitialised = pdTRUE;
+
+ /* Record the partition number the FF_Disk_t structure is, then
+ mount the partition. */
+ pxDisk->xStatus.bPartitionNumber = eMMCPARTITION_NUMBER;
+
+#if 1
+ /* Mount the partition. */
+ xError = FF_Mount(pxDisk, pxDisk->xStatus.bPartitionNumber);
+ LOG_PRINTF("FF_eMMC_user_DiskInit: FF_Mount: %s\r\n", (const char *)FF_GetErrMessage(xError));
+
+ if (FF_isERR(xError) == pdFALSE) {
+ /* The partition mounted successfully, add it to the virtual
+ file system - where it will appear as a directory off the file
+ system's root directory. */
+ FF_FS_Add(pcName, pxDisk);
+ }
+ else
+#endif
+ {
+ /* This is completely new eMMC disk so at first it needs proper formatting. */
+ xError = prvPartitionAndFormatDisk(pxDisk);
+
+ /* Mount the partition again, it should complete without fault. */
+ if (FF_isERR(xError) == pdFALSE) {
+ /* Record the partition number the FF_Disk_t structure is, then
+ mount the partition. */
+ pxDisk->xStatus.bPartitionNumber = eMMCPARTITION_NUMBER;
+
+ /* Mount the partition. */
+ xError = FF_Mount(pxDisk, eMMCPARTITION_NUMBER);
+ LOG_PRINTF("FF_eMMC_user_DiskInit: FF_Mount: %s\r\n", (const char *)FF_GetErrMessage(xError));
+ }
+
+ if (FF_isERR(xError) == pdFALSE) {
+ /* The partition mounted successfully, add it to the virtual
+ file system - where it will appear as a directory off the file
+ system's root directory. */
+ FF_FS_Add(pcName, pxDisk);
+ }
+ }
+ }
+ else {
+ LOG_PRINTF("FF_eMMC_user_DiskInit: FF_CreateIOManger: %s\r\n", (const char *)FF_GetErrMessage(xError));
+
+ /* The disk structure was allocated, but the disk's IO manager could
+ not be allocated, so free the disk again. */
+ diskDelete(pxDisk);
+ pxDisk = NULL;
+ }
+ }
+ else {
+ LOG_PRINTF("FF_eMMC_user_DiskInit: Malloc failed\r\n");
+ }
+
+ return pxDisk;
+ }
+ BaseType_t diskDelete(FF_Disk_t *pxDisk)
+ {
+ if (pxDisk != NULL) {
+ pxDisk->ulSignature = 0;
+ pxDisk->xStatus.bIsInitialised = 0;
+ if (pxDisk->pvTag) {
+ auto fops = reinterpret_cast<file_operation *>(pxDisk->pvTag);
+ delete fops;
+ }
+ if (pxDisk->pxIOManager != NULL) {
+ FF_DeleteIOManager(pxDisk->pxIOManager);
+ }
+ // TODO: Fixme in the laters stage
+ free(pxDisk);
+ }
+ return pdPASS;
+ }
+
+ BaseType_t diskShowPartition(FF_Disk_t *pxDisk)
+ {
+
+ FF_Error_t xError;
+ uint64_t ullFreeSectors;
+ uint32_t ulTotalSizeMB, ulFreeSizeMB;
+ int iPercentageFree;
+ FF_IOManager_t *pxIOManager;
+ const char *pcTypeName = "unknown type";
+ BaseType_t xReturn = pdPASS;
+
+ if (pxDisk == NULL) {
+ xReturn = pdFAIL;
+ }
+ else {
+ pxIOManager = pxDisk->pxIOManager;
+
+ LOG_PRINTF("Reading FAT and calculating Free Space\r\n");
+
+ switch (pxIOManager->xPartition.ucType) {
+ case FF_T_FAT12:
+ pcTypeName = "FAT12";
+ break;
+
+ case FF_T_FAT16:
+ pcTypeName = "FAT16";
+ break;
+
+ case FF_T_FAT32:
+ pcTypeName = "FAT32";
+ break;
+
+ default:
+ pcTypeName = "UNKOWN";
+ break;
+ }
+
+ FF_GetFreeSize(pxIOManager, &xError);
+
+ ullFreeSectors = pxIOManager->xPartition.ulFreeClusterCount * pxIOManager->xPartition.ulSectorsPerCluster;
+ iPercentageFree = (int)((eMMCHUNDRED_64_BIT * ullFreeSectors + pxIOManager->xPartition.ulDataSectors / 2) /
+ ((uint64_t)pxIOManager->xPartition.ulDataSectors));
+
+ ulTotalSizeMB = pxIOManager->xPartition.ulDataSectors / eMMCSECTORS_PER_MB;
+ ulFreeSizeMB = (uint32_t)(ullFreeSectors / eMMCSECTORS_PER_MB);
+
+ /* It is better not to use the 64-bit format such as %Lu because it
+ might not be implemented. */
+
+ LOG_PRINTF("Type %8u (%s)\r\n", pxIOManager->xPartition.ucType, pcTypeName);
+ LOG_PRINTF("VolLabel '%8s' \r\n", pxIOManager->xPartition.pcVolumeLabel);
+ LOG_PRINTF("TotalSectors %8u\r\n", pxIOManager->xPartition.ulTotalSectors);
+ LOG_PRINTF("SecsPerCluster %8u\r\n", pxIOManager->xPartition.ulSectorsPerCluster);
+ LOG_PRINTF("Size %8u MB\r\n", ulTotalSizeMB);
+ LOG_PRINTF("FreeSize %8u MB ( %d perc free )\r\n", ulFreeSizeMB, iPercentageFree);
+ }
+
+ return xReturn;
+ }
+ void diskFlush(FF_Disk_t *pxDisk)
+ {
+ FF_FlushCache(pxDisk->pxIOManager);
+
+ if (FF_InvalidateCache(pxDisk->pxIOManager) != 0) {
+ /* Not all buffers could be invalidated. */
+ }
+ }
+ uint8_t diskIsPresent(void)
+ {
+ return 1;
+ }
+} // namespace freertos_fat::internals
A module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp => module-vfs/board/linux/free_rtos_custom/portable/vfs.cpp +56 -0
@@ 0,0 1,56 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+//
+#include "vfs.hpp"
+#include "ff_image_user_disk.hpp"
+
+namespace
+{
+ constexpr auto image_name = "PurePhone.img";
+}
+
+vfs::vfs()
+{}
+
+vfs::~vfs()
+{
+ freertos_fat::internals::diskDelete(emmcFFDisk);
+}
+
+void vfs::Init()
+{
+ if (emmcFFDisk) {
+ LOG_WARN("Disk manager already initialized");
+ return;
+ }
+ emmcFFDisk = freertos_fat::internals::diskInit(purefs::dir::eMMC_disk.c_str(), image_name);
+
+ /* Print out information on the disk. */
+ freertos_fat::internals::diskShowPartition(emmcFFDisk);
+
+ bootConfig.os_root_path = purefs::dir::eMMC_disk;
+
+ if (loadBootConfig(getCurrentBootJSON())) {
+ LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type.c_str(), bootConfig.os_root_path.c_str());
+ if (ff_chdir(bootConfig.os_root_path.c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path.c_str());
+ }
+ }
+ else {
+ LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path.c_str());
+ }
+
+ LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path.c_str());
+
+ // this should already exist and have user data in it
+ // if it does not create an exmpty directory so that sqlite3 does not fault
+ if (isDir(purefs::dir::user_disk.c_str()) == false) {
+ LOG_ERROR("vfs::Init looks like %s does not exist, try to create it", purefs::dir::user_disk.c_str());
+ if (ff_mkdir(purefs::dir::user_disk.c_str()) != 0) {
+ LOG_ERROR("vfs::Init can't create %s directory", purefs::dir::user_disk.c_str());
+ }
+ }
+ else {
+ LOG_INFO("vfs::Init looks like %s exists", purefs::dir::user_disk.c_str());
+ }
+}
D module-vfs/board/linux/vfs.cpp => module-vfs/board/linux/vfs.cpp +0 -256
@@ 1,256 0,0 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
-// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
-#include "../../vfs.hpp"
-
-#include <fstream>
-#include <iostream>
-#include <filesystem>
-#include <cstdio>
-#include <cstddef>
-
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <string.h>
-#include <log/log.hpp>
-
-namespace fs = std::filesystem;
-
-vfs::vfs()
-{}
-
-vfs::~vfs()
-{}
-
-void vfs::Init()
-{
- // whatever current path on Linux we treat that as the root for our app
- bootConfig.os_root_path = "./";
- LOG_DEBUG("vfs::Iinit running on Linux osRootPath: %s", bootConfig.os_root_path.c_str());
-}
-
-std::string vfs::relativeToRoot(const std::string path)
-{
- return (bootConfig.os_root_path / fs::path(path).relative_path()).relative_path();
-}
-
-vfs::FILE *vfs::fopen(const char *filename, const char *mode)
-{
- return std::fopen(relativeToRoot(filename).c_str(), mode);
-}
-
-int vfs::fclose(FILE *stream)
-{
- return std::fclose(stream);
-}
-
-int vfs::remove(const char *name)
-{
- return std::remove(relativeToRoot(name).c_str());
-}
-
-size_t vfs::fread(void *ptr, size_t size, size_t count, FILE *stream)
-{
- return std::fread(ptr, size, count, stream);
-}
-
-size_t vfs::fwrite(const void *ptr, size_t size, size_t count, FILE *stream)
-{
- return std::fwrite(ptr, size, count, stream);
-}
-
-int vfs::fseek(FILE *stream, long int offset, int origin)
-{
- return std::fseek(stream, offset, origin);
-}
-
-long int vfs::ftell(FILE *stream)
-{
- return std::ftell(stream);
-}
-
-void vfs::rewind(FILE *stream)
-{
- std::rewind(stream);
-}
-
-bool vfs::eof(FILE *stream)
-{
- return std::feof(stream);
-}
-
-size_t vfs::filelength(FILE *stream)
-{
-
- size_t currPos = std::ftell(stream);
-
- std::fseek(stream, 0, SEEK_END);
- size_t size = std::ftell(stream);
- std::fseek(stream, currPos, SEEK_SET);
-
- return size;
-}
-
-char *vfs::fgets(char *buffer, size_t count, FILE *stream)
-{
- return std::fgets(buffer, count, stream);
-}
-
-std::string vfs::getcurrdir()
-{
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) != NULL) {
- return std::string{cwd};
- }
- else {
- return "";
- }
-}
-
-static inline bool hasEnding(std::string const &fullString, std::string const &ending)
-{
- if (fullString.length() >= ending.length()) {
- return (0 == fullString.compare(fullString.length() - ending.length(), ending.length(), ending));
- }
- else {
- return false;
- }
-}
-
-std::vector<vfs::DirectoryEntry> vfs::listdir(const char *path, const std::string &ext, const bool bypassRootCheck)
-{
- std::vector<DirectoryEntry> dir_list;
- FileAttributes attribute = FileAttributes::ReadOnly;
- size_t fileSize = 0;
-
- for (auto &p : fs::directory_iterator(bypassRootCheck ? path : relativeToRoot(path))) {
- if (fs::is_directory(p)) {
- attribute = FileAttributes ::Directory;
- }
- else if ((fs::status(p).permissions() & fs::perms::owner_write) != fs::perms::none) {
- attribute = FileAttributes ::Writable;
- fileSize = std::filesystem::file_size(p);
- }
- else if ((fs::status(p).permissions() & fs::perms::owner_read) != fs::perms::none) {
- attribute = FileAttributes ::ReadOnly;
- fileSize = std::filesystem::file_size(p);
- }
-
- auto pathStr = p.path().string();
- auto path = pathStr.substr(pathStr.find_last_of("/\\") + 1);
-
- if (ext.empty()) {
- dir_list.push_back(DirectoryEntry{path, attribute, static_cast<uint32_t>(fileSize)});
- }
- else {
- if (hasEnding(path, ext))
- dir_list.push_back(DirectoryEntry{path, attribute, static_cast<uint32_t>(fileSize)});
- }
- }
-
- return dir_list;
-}
-
-std::string vfs::getline(FILE *stream, uint32_t length)
-{
- uint32_t currentPosition = ftell(stream);
-
- // allocate memory to read number of signs defined by length param. Size of buffer is increased by 1 to add string's
- // null terminator.
- std::unique_ptr<char[]> buffer(new char[length + 1]);
- memset(buffer.get(), 0, length + 1);
-
- uint32_t bytesRead = fread(buffer.get(), 1, length, stream);
-
- // search buffer for /n sign
- for (uint32_t i = 0; i < bytesRead; ++i) {
- if (buffer[i] == 0x0A) {
- buffer[i] = 0;
- fseek(stream, currentPosition + i + 1, SEEK_SET);
- break;
- }
- }
-
- std::string ret = std::string(buffer.get());
-
- return ret;
-}
-
-vfs::FilesystemStats vfs::getFilesystemStats()
-{
- return vfs::FilesystemStats();
-}
-
-bool vfs::isDir(const char *path)
-{
- if (path == nullptr)
- return false;
-
- struct stat fileStatus;
-
- const int ret = stat(relativeToRoot(path).c_str(), &fileStatus);
- if (ret == 0) {
- return (S_ISDIR(fileStatus.st_mode));
- }
- else {
- return false;
- }
-}
-
-bool vfs::fileExists(const char *path)
-{
- if (path == nullptr)
- return false;
-
- struct stat fileStatus;
- const int ret = stat(relativeToRoot(path).c_str(), &fileStatus);
- if (ret == 0) {
- return true;
- }
- return false;
-}
-
-int vfs::deltree(const char *path)
-{
- if (path != nullptr) {
- std::error_code ec;
- std::filesystem::remove_all(relativeToRoot(path), ec);
- return ec.value();
- }
- else
- return -1;
-}
-
-int vfs::mkdir(const char *dir)
-{
- if (dir != nullptr) {
- return ::mkdir(relativeToRoot(dir).c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- }
- else
- return -1;
-}
-
-int vfs::rename(const char *oldname, const char *newname)
-{
- if (oldname != nullptr && newname != nullptr)
- return std::rename(relativeToRoot(oldname).c_str(), relativeToRoot(newname).c_str());
- else
- return -1;
-}
-
-std::string vfs::lastErrnoToStr()
-{
- return strerror(errno);
-}
-
-size_t vfs::fprintf(FILE *stream, const char *format, ...)
-{
- va_list argList;
- size_t ret;
- va_start(argList, format);
- ret = std::vfprintf(stream, format, argList);
- va_end(argList);
- return ret;
-}
M module-vfs/targets/Target_Cross.cmake => module-vfs/targets/Target_Cross.cmake +3 -28
@@ 1,34 1,9 @@
-include(thirdparty)
-
-set(FREERTOS_FAT_SOURCES
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_crc.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_dir.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_error.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_fat.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_file.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_format.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_ioman.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_locking.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_memory.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_stdio.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_string.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_sys.c
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/ff_time.c
-)
-
-set(BOARD_DIR_INCLUDES
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/freeRTOS_FAT/include
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/free_rtos_custom/include
- CACHE INTERNAL ""
-)
-
-
-third_party_source_optimization(${FREERTOS_FAT_SOURCES})
set( BOARD_SOURCES
- ${FREERTOS_FAT_SOURCES}
- ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/vfs.cpp
${CMAKE_CURRENT_SOURCE_DIR}/board/cross/free_rtos_custom/portable/ff_eMMC_user_disk.cpp
${CMAKE_CURRENT_SOURCE_DIR}/board/cross/free_rtos_custom/portable/common.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/free_rtos_custom/portable/vfs.cpp
CACHE INTERNAL ""
)
+
+set(BOARD_DIR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/board/cross/free_rtos_custom/include CACHE INTERNAL "")
M module-vfs/targets/Target_Linux.cmake => module-vfs/targets/Target_Linux.cmake +7 -2
@@ 1,3 1,8 @@
-set(BOARD_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/vfs.cpp CACHE INTERNAL "")
+set(BOARD_SOURCES
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/portable/ff_image_user_disk.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/portable/common.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/portable/vfs.cpp
+ CACHE INTERNAL ""
+)
-set(BOARD_DIR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/board/linux CACHE INTERNAL "")
+set(BOARD_DIR_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/board/linux/free_rtos_custom/include CACHE INTERNAL "")
M module-vfs/tests/unittest_vfs.cpp => module-vfs/tests/unittest_vfs.cpp +38 -14
@@ 13,12 13,21 @@
#include <cstdint>
+#include <thread.hpp>
+
class vfs vfs;
-TEST_CASE("Test case 1")
+struct vfs_initializer
+{
+ vfs_initializer()
+ {
+ vfs.Init();
+ }
+} vfs_initializer;
+
+TEST_CASE("Test vfs case 1")
{
- vfs.Init();
const size_t testBufferSize = 1024 * 1024;
@@ 44,8 53,19 @@ TEST_CASE("Test case 1")
// current directory is the build dir
// vfs adds sys/ to the path we need to got outside sys (bad!)
// and look for some files there
- auto dirList = vfs.listdir("module-vfs/test_dir");
- REQUIRE(dirList.size() == 3);
+ vfs.mkdir("module-vfs");
+ vfs.mkdir("module-vfs/test_dir2");
+
+ fd = vfs.fopen("module-vfs/test1.txt", "a");
+ REQUIRE(fd != nullptr);
+ REQUIRE(vfs.fclose(fd) == 0);
+
+ fd = vfs.fopen("module-vfs/test2.txt", "a");
+ REQUIRE(fd != nullptr);
+ REQUIRE(vfs.fclose(fd) == 0);
+
+ auto dirList = vfs.listdir("module-vfs");
+ REQUIRE(dirList.size() >= 4);
for (auto &dir : dirList) {
if (dir.fileName == "test_dir2") {
REQUIRE(dir.attributes == vfs::FileAttributes::Directory);
@@ 59,7 79,6 @@ TEST_CASE("Test case 1")
#define RANDDOM_TESTS 4
TEST_CASE("Random strings")
{
- vfs.Init();
const std::string allowedChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
std::string randomIds8, randomIds16, randomIds32;
randomIds8 = vfs.generateRandomId(8);
@@ 81,7 100,6 @@ TEST_CASE("Random strings")
TEST_CASE("CRC32 tests")
{
- vfs.Init();
unsigned long crc32 = 0;
char crcBuf[purefs::buffer::crc_char_size];
std::string randomData = vfs.generateRandomId(128);
@@ 99,6 117,7 @@ TEST_CASE("CRC32 tests")
bytesWritten = vfs.fwrite(&crcBuf, 1, purefs::buffer::crc_char_size, fdCRC);
REQUIRE(bytesWritten == purefs::buffer::crc_char_size);
REQUIRE(vfs.fclose(fdCRC) == 0);
+ REQUIRE(vfs.fclose(fd) == 0);
REQUIRE(vfs.verifyCRC("testFile.txt") == true);
REQUIRE(vfs.remove("testFile.txt") == 0);
@@ 107,12 126,17 @@ TEST_CASE("CRC32 tests")
TEST_CASE("File loading and saving")
{
- vfs.Init();
- std::string fileContents = vfs.loadFileAsString("module-vfs/test_dir/test1.txt");
- REQUIRE(strcmp(fileContents.c_str(), "abcd") == 0);
-
- vfs.replaceWithString("module-vfs/test_dir/testWrite.txt", "this is a test");
- fileContents = vfs.loadFileAsString("module-vfs/test_dir/testWrite.txt");
+ static constexpr auto test_str = "abcd";
+ auto fd = vfs.fopen("test1.txt", "w");
+ REQUIRE(fd != nullptr);
+ const auto slen = std::strlen(test_str);
+ REQUIRE(vfs.fwrite(test_str, 1, slen, fd) == slen);
+ vfs.fclose(fd);
+ std::string fileContents = vfs.loadFileAsString("test1.txt");
+ REQUIRE(strcmp(fileContents.c_str(), test_str) == 0);
+ vfs.mkdir("module-vfs/test_dirx");
+ vfs.replaceWithString("module-vfs/test_dirx/testWrite.txt", "this is a test");
+ fileContents = vfs.loadFileAsString("module-vfs/test_dirx/testWrite.txt");
REQUIRE(strcmp(fileContents.c_str(), "this is a test") == 0);
- REQUIRE(vfs.remove("module-vfs/test_dir/testWrite.txt") == 0);
-}>
\ No newline at end of file
+ REQUIRE(vfs.remove("module-vfs/test_dirx/testWrite.txt") == 0);
+}
R module-vfs/board/cross/vfs.cpp => module-vfs/vfs.cpp +1 -47
@@ 1,8 1,7 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "../../vfs.hpp"
-#include "ff_eMMC_user_disk.hpp"
+#include "vfs.hpp"
#include <memory>
@@ 18,51 17,6 @@ disk. */
#define eMMCSIGNATURE 0x61606362
#define mainIO_MANAGER_CACHE_SIZE (15UL * FSL_SDMMC_DEFAULT_BLOCK_SIZE)
-vfs::vfs() : emmc()
-{}
-
-vfs::~vfs()
-{
- FF_eMMC_user_DiskDelete(emmcFFDisk);
- emmc.DeInit();
-}
-
-void vfs::Init()
-{
- emmc.Init();
-
- emmcFFDisk = FF_eMMC_user_DiskInit(purefs::dir::eMMC_disk.c_str(), &emmc);
-
- /* Print out information on the disk. */
- FF_eMMC_user_DiskShowPartition(emmcFFDisk);
-
- bootConfig.os_root_path = purefs::dir::eMMC_disk;
-
- if (loadBootConfig(getCurrentBootJSON())) {
- LOG_INFO("vfs::Init osType %s root:%s", bootConfig.os_type.c_str(), bootConfig.os_root_path.c_str());
- if (ff_chdir(bootConfig.os_root_path.c_str()) != 0) {
- LOG_ERROR("vfs::Init can't chdir to %s", bootConfig.os_root_path.c_str());
- }
- }
- else {
- LOG_ERROR("vfs::Init unable to determine OS type, fallback to %s", bootConfig.os_root_path.c_str());
- }
-
- LOG_INFO("vfs::Init running on ARM osRootPath: %s", bootConfig.os_root_path.c_str());
-
- // this should already exist and have user data in it
- // if it does not create an exmpty directory so that sqlite3 does not fault
- if (isDir(purefs::dir::user_disk.c_str()) == false) {
- LOG_ERROR("vfs::Init looks like %s does not exist, try to create it", purefs::dir::user_disk.c_str());
- if (ff_mkdir(purefs::dir::user_disk.c_str()) != 0) {
- LOG_ERROR("vfs::Init can't create %s directory", purefs::dir::user_disk.c_str());
- }
- }
- else {
- LOG_INFO("vfs::Init looks like %s exists", purefs::dir::user_disk.c_str());
- }
-}
-
vfs::FILE *vfs::fopen(const char *filename, const char *mode)
{
return ff_fopen(relativeToRoot(filename).c_str(), mode);
M module-vfs/vfs.hpp => module-vfs/vfs.hpp +5 -9
@@ 12,13 12,12 @@
#include <log/log.hpp>
#include <json/json11.hpp>
-#ifdef TARGET_Linux
-#include <cstdio>
-#else
-#include "ff_stdio.h"
+#ifndef TARGET_Linux
#include "board/cross/eMMC/eMMC.hpp"
#endif
+#include "ff_stdio.h"
+
#define PATH_SYS "/sys"
#define PATH_USER "user"
#define PATH_CURRENT "current"
@@ 107,11 106,7 @@ namespace purefs
class vfs
{
public:
-#ifdef TARGET_Linux
- using FILE = std::FILE;
-#else
using FILE = FF_FILE;
-#endif
enum class FileAttributes
{
@@ 177,9 172,10 @@ class vfs
#ifndef TARGET_Linux
bsp::eMMC emmc;
- FF_Disk_t *emmcFFDisk;
#endif
+ FF_Disk_t *emmcFFDisk{};
+
static void computeCRC32(FILE *file, unsigned long *outCrc32);
static bool verifyCRC(const std::string filePath, const unsigned long crc32);
static bool verifyCRC(const fs::path filePath);
M test/CMakeLists.txt => test/CMakeLists.txt +1 -0
@@ 51,6 51,7 @@ function(add_catch2_executable)
# disable logs in unit tests
if (NOT ${ENABLE_TEST_LOGS})
target_sources(${_TESTNAME} PRIVATE ${ROOT_TEST_DIR}/mock-logs.cpp)
+ target_sources(${_TESTNAME} PRIVATE ${ROOT_TEST_DIR}/mock-freertos-tls.cpp)
endif (NOT ${ENABLE_TEST_LOGS})
target_link_libraries(${_TESTNAME} PRIVATE Catch2::Catch2)
A test/mock-freertos-tls.cpp => test/mock-freertos-tls.cpp +22 -0
@@ 0,0 1,22 @@
+// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include <thread.hpp>
+
+namespace
+{
+ thread_local void *tls_pointers[configNUM_THREAD_LOCAL_STORAGE_POINTERS];
+}
+
+extern "C"
+{
+
+ void *ff_stdio_pvTaskGetThreadLocalStoragePointer(TaskHandle_t, BaseType_t xIndex)
+ {
+ return tls_pointers[xIndex];
+ }
+ void ff_stdio_vTaskSetThreadLocalStoragePointer(TaskHandle_t, BaseType_t xIndex, void *pvValue)
+ {
+ tls_pointers[xIndex] = pvValue;
+ }
+}
M test/mock-logs.cpp => test/mock-logs.cpp +2 -2
@@ 3,8 3,8 @@
#include <log/log.hpp>
#include <cstdarg>
-
-void log_Log(logger_level level, const char *file, int line, const char *function, const char *fmt, ...)
+__attribute__((weak)) void log_Log(
+ logger_level level, const char *file, int line, const char *function, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);