~aleteoryx/muditaos

fab9068a52eb25d3e3d3b06ce83b7c124427dc6f — Bartosz 3 years ago 178fba1
[MOS-786] Added A/B booting support in OS

Added basic support for A/B booting
M .idea/runConfigurations/JLink_server.xml => .idea/runConfigurations/JLink_server.xml +1 -1
@@ 3,4 3,4 @@
    <custom-gdb-server version="1" gdb-connect="localhost:2331" executable="JLinkGDBServerCLExe" warmup-ms="0" download-type="ALWAYS" reset-cmd="monitor reset 0" reset-after-download="false" />
    <method v="2" />
  </configuration>
</component>
</component>
\ No newline at end of file

M CMakeLists.txt => CMakeLists.txt +7 -0
@@ 29,6 29,7 @@ include(AddPackage)
include(AutoModuleOption)
include(AddDirectories)
include(AddDatabases)
include(FetchContent)
include(AddScripts)

message("Selected product: ${PRODUCT}")


@@ 124,6 125,12 @@ if (NOT ENABLE_SECURE_BOOT)
        )
endif ()

FetchContent_Declare(
        pure-core
        GIT_REPOSITORY git@github.com:mudita/pure-core
)
FetchContent_MakeAvailable(pure-core)

add_subdirectory(board)
add_subdirectory(source)
add_subdirectory(module-platform)

M module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.cpp => module-apps/application-alarm-clock/widgets/AlarmMusicOptionsItem.cpp +1 -1
@@ 93,7 93,7 @@ namespace gui

    std::vector<tags::fetcher::Tags> AlarmMusicOptionsItem::getMusicFilesList()
    {
        const auto musicFolder = (purefs::dir::getSystemDiskPath() / "assets/audio/alarm").string();
        const auto musicFolder = (purefs::dir::getAssetsPath() / "audio/alarm").string();
        std::vector<tags::fetcher::Tags> musicFiles;
        LOG_INFO("Scanning music folder: %s", musicFolder.c_str());
        for (const auto &ent : std::filesystem::directory_iterator(musicFolder)) {

M module-apps/application-meditation/widgets/MeditationTimer.cpp => module-apps/application-meditation/widgets/MeditationTimer.cpp +2 -3
@@ 86,8 86,7 @@ namespace gui
    }
    void MeditationTimer::playSound()
    {
        AudioServiceAPI::PlaybackStart(application,
                                       audio::PlaybackType::Meditation,
                                       purefs::dir::getSystemDiskPath() / "assets/audio/meditation/gong.mp3");
        AudioServiceAPI::PlaybackStart(
            application, audio::PlaybackType::Meditation, purefs::dir::getAssetsPath() / "audio/meditation/gong.mp3");
    }
} // namespace gui

M module-apps/application-settings/models/apps/SoundsModel.cpp => module-apps/application-settings/models/apps/SoundsModel.cpp +5 -5
@@ 77,16 77,16 @@ std::filesystem::path SoundsModel::getSoundPath(audio_settings::AbstractAudioSet
    assert(model);
    switch (model->getPlaybackType()) {
    case audio::PlaybackType::CallRingtone:
        return purefs::dir::getSystemDiskPath() / "assets/audio/ringtone";
        return purefs::dir::getAssetsPath() / "audio/ringtone";

    case audio::PlaybackType::TextMessageRingtone:
        return purefs::dir::getSystemDiskPath() / "assets/audio/sms";
        return purefs::dir::getAssetsPath() / "audio/sms";

    case audio::PlaybackType::Notifications:
        return purefs::dir::getSystemDiskPath() / "assets/audio/alarm";
        return purefs::dir::getAssetsPath() / "audio/alarm";

    default:
        return purefs::dir::getSystemDiskPath() / "assets/audio";
        return purefs::dir::getAssetsPath() / "audio";
    }
}



@@ 97,7 97,7 @@ void SoundsModel::applyItems(const std::vector<std::filesystem::path> &sounds,
    auto currentItemIndex  = 0;
    auto selectedItemIndex = 0;

    std::string selectedSound = purefs::dir::getSystemDiskPath() / model->getSound();
    std::string selectedSound = purefs::dir::getAssetsPath() / model->getSound();
    for (const auto &sound : sounds) {

        bool isSelected = false;

M module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp => module-services/service-evtmgr/service-evtmgr/EventManagerCommon.hpp +1 -1
@@ 52,7 52,7 @@ class EventManagerCommon : public sys::Service
    static bool messageSetApplication(sys::Service *sender, const std::string &applicationName);

  private:
    static constexpr auto stackDepth = 1024 * 4;
    static constexpr auto stackDepth = 1024 * 5;
    void handleMinuteUpdate(time_t timestamp);

    void processRTCFromTmRequest(struct tm &newTime);

M module-services/service-fileindexer/StartupIndexer.cpp => module-services/service-fileindexer/StartupIndexer.cpp +1 -1
@@ 20,7 20,7 @@ namespace service::detail
    using namespace std::literals;
    using namespace std::chrono_literals;

    const auto lock_file_name        = purefs::dir::getUserDiskPath() / "data" / ".directory_is_indexed";
    const auto lock_file_name        = purefs::dir::getSystemDiskPath() / "data" / ".directory_is_indexed";
    constexpr auto indexing_interval = 50ms;
    constexpr auto start_delay       = 10000ms;


M module-services/service-gui/ServiceGUI.cpp => module-services/service-gui/ServiceGUI.cpp +2 -3
@@ 53,9 53,8 @@ namespace service::gui

    void ServiceGUI::initAssetManagers()
    {
        const auto assetsPath = purefs::dir::getSystemDiskPath() / "assets";
        ::gui::FontManager::getInstance().init(assetsPath);
        ::gui::ImageManager::getInstance().init(assetsPath);
        ::gui::FontManager::getInstance().init(purefs::dir::getAssetsPath());
        ::gui::ImageManager::getInstance().init(purefs::dir::getAssetsPath());
    }

    void ServiceGUI::registerMessageHandlers()

M module-vfs/CMakeLists.txt => module-vfs/CMakeLists.txt +4 -2
@@ 123,10 123,12 @@ target_link_libraries(module-vfs
        module-bsp 
        module-os
        module-utils
    PUBLIC 
        pure-core

        PUBLIC
        purefs-paths
        module-sys
)
        )

if (${ENABLE_TESTS})
    add_subdirectory(tests)

M module-vfs/paths/CMakeLists.txt => module-vfs/paths/CMakeLists.txt +4 -1
@@ 5,7 5,10 @@ target_sources(purefs-paths
        filesystem_paths.cpp
        include/purefs/filesystem_paths.hpp
)

target_link_libraries(purefs-paths
        PRIVATE
        pure-core
        )
target_include_directories(purefs-paths
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>

M module-vfs/paths/filesystem_paths.cpp => module-vfs/paths/filesystem_paths.cpp +11 -0
@@ 2,6 2,7 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <purefs/filesystem_paths.hpp>
#include <hal/boot_control.h>

namespace
{


@@ 18,6 19,8 @@ namespace
        "media"; // TODO this won't work with our current non-hierarchical MTP implementation
    constexpr inline auto PATH_TMP    = "tmp";
    constexpr inline auto PATH_BACKUP = "backup";
    constexpr inline auto PATH_ASSETS  = "assets";

} // namespace

namespace purefs


@@ 88,5 91,13 @@ namespace purefs
        {
            return getUserDiskPath() / PATH_BACKUP; // TODO is it still needed?
        }
        std::filesystem::path getBootJSONPath() noexcept
        {
            return getUserDiskPath() / file::boot_json;
        }
        std::filesystem::path getAssetsPath() noexcept
        {
            return getSystemDiskPath() / PATH_ASSETS;
        }
    } // namespace dir
} // namespace purefs

M module-vfs/paths/include/purefs/filesystem_paths.hpp => module-vfs/paths/include/purefs/filesystem_paths.hpp +3 -0
@@ 20,6 20,9 @@ namespace purefs
        std::filesystem::path getFactoryDBsPath() noexcept;
        std::filesystem::path getLogsPath() noexcept;
        std::filesystem::path getCrashDumpsPath() noexcept;
        std::filesystem::path getBootJSONPath() noexcept;
        std::filesystem::path getAssetsPath() noexcept;

        std::filesystem::path getUserMediaPath() noexcept;
        std::filesystem::path getTemporaryPath() noexcept;
        std::filesystem::path getBackupOSPath() noexcept;

M module-vfs/src/purefs/vfs_subsystem.cpp => module-vfs/src/purefs/vfs_subsystem.cpp +24 -47
@@ 8,6 8,8 @@
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/vfs_subsystem.hpp>
#include <purefs/vfs_subsystem_internal.hpp>
#include <hal/boot_reason.h>
#include <hal/boot_control.h>
#include <purefs/fs/thread_local_cwd.hpp>
#include <log/log.hpp>
#include <purefs/filesystem_paths.hpp>


@@ 40,30 42,6 @@ namespace purefs::subsystem
        std::weak_ptr<fs::filesystem> g_fs_core;
    } // namespace

    namespace
    {
        int read_mbr_lfs_erase_size(std::shared_ptr<blkdev::disk_manager> disk_mngr,
                                    std::string_view dev_name,
                                    int part_no)
        {
            static constexpr auto MBR_ERASE_BLK_OFFSET = 0x00E0;
            if (part_no <= 0) {
                return -EINVAL;
            }
            const auto sect_size = disk_mngr->get_info(dev_name, blkdev::info_type::sector_size);
            if (sect_size <= MBR_ERASE_BLK_OFFSET + part_no) {
                return (sect_size > 0) ? (-ERANGE) : (sect_size);
            }
            auto mbr_buf = std::make_unique<char[]>(sect_size);
            int err      = disk_mngr->read(dev_name, mbr_buf.get(), 0, 1);
            if (err < 0) {
                return err;
            }
            return mbr_buf[MBR_ERASE_BLK_OFFSET + part_no];
        }

    } // namespace

    auto initialize(std::unique_ptr<DeviceFactory> deviceFactory)
        -> std::tuple<std::shared_ptr<blkdev::disk_manager>, std::shared_ptr<fs::filesystem>>
    {


@@ 128,8 106,24 @@ namespace purefs::subsystem
            LOG_FATAL("Unknown partitions layout part size is %u", (unsigned)(parts.size()));
            return -EIO;
        }
        const auto &boot_part = parts[boot_part_index];

        auto vfs = g_fs_core.lock();
        if (!vfs) {
            LOG_FATAL("Unable to lock vfs core");
            return -EIO;
        }

        const auto &user_part = parts[user_part_index];

        vfs->mount(user_part.name, purefs::dir::getUserDiskPath().string(), "auto");

        auto ret = boot_control_init(purefs::dir::getBootJSONPath().string().c_str());
        if (ret != 0) {
            LOG_FATAL("Unable to init boot.json handling");
            return -ENOENT;
        }

        const auto &boot_part = parts[(get_current_slot() == Slot_A) ? 0 : 1];
        if ((boot_part.type != fat_part_code) && (boot_part.type != linux_part_code)) {
            LOG_FATAL("Invalid boot partition type expected code: %02X or %02X current code: %02X",
                      fat_part_code,


@@ 142,30 136,13 @@ namespace purefs::subsystem
                "Invalid user partition type expected code: %02X current code: %02X", linux_part_code, user_part.type);
            return -EIO;
        }
        auto vfs = g_fs_core.lock();
        if (!vfs) {
            LOG_FATAL("Unable to lock vfs core");
            return -EIO;
        }

        auto err = vfs->mount(boot_part.name, purefs::dir::getSystemDiskPath().string(), "auto");
        if (err) {
        if (err != 0) {
            return err;
        }
        if (user_part.type == lfs_part_code) {
            const int lfs_block_log2 = read_mbr_lfs_erase_size(disk, default_blkdev_name, user_part.physical_number);
            uint32_t lfs_block_size  = 0;
            uint32_t *lfs_block_size_ptr = nullptr;
            if (lfs_block_log2 >= block_size_min_shift && lfs_block_log2 <= block_size_max_shift) {
                lfs_block_size     = 1U << lfs_block_log2;
                lfs_block_size_ptr = &lfs_block_size;
            }
            err =
                vfs->mount(user_part.name, purefs::dir::getUserDiskPath().string(), "littlefs", 0, lfs_block_size_ptr);
        }
        else {
            err = vfs->mount(user_part.name, purefs::dir::getUserDiskPath().string(), "ext4");
        }
        fs::internal::set_default_thread_cwd(dir::getSystemDiskPath().string());

        fs::internal::set_default_thread_cwd(purefs::dir::getSystemDiskPath().string());

        // Mount NVRAM memory
        err = vfs->mount(default_nvrom_name,


@@ 173,7 150,7 @@ namespace purefs::subsystem
                         "littlefs",
                         fs::mount_flags::read_only,
                         &nvrom_lfs_block_size);
        if (err) {
        if (err != 0) {
            LOG_WARN("Unable to mount NVROM partition err %i. Possible: NVROM unavailable", err);
            err = 0;
        }

M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +1 -0
@@ 65,6 65,7 @@ target_link_libraries(BellHybrid
        bell::time
        platform
        version-header
        pure-core
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_Linux>:iosyscalls>"
        "$<$<STREQUAL:${PROJECT_TARGET},TARGET_RT1051>:CrashCatcher::CrashCatcher>"
    )