~aleteoryx/muditaos

00b2deac9798781f4bbbf01abf84ed3f78d9658f — Lukasz Mastalerz 3 years ago d47d968
[CP-1512] Add information allowing identification to crashdump file

Add the serial number and generation timestamp to crashdump filename.
M board/linux/CMakeLists.txt => board/linux/CMakeLists.txt +1 -0
@@ 1,3 1,4 @@
add_library(board INTERFACE)
add_subdirectory(libiosyscalls)
add_subdirectory(crashdump-serial-number)
target_compile_definitions(board-config INTERFACE PROJECT_CONFIG_USER_DYNMEM_SIZE=0)

A board/linux/crashdump-serial-number/CMakeLists.txt => board/linux/crashdump-serial-number/CMakeLists.txt +13 -0
@@ 0,0 1,13 @@
add_library(crashdump-serial-number STATIC)

target_include_directories(crashdump-serial-number
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>/include
)

target_sources(crashdump-serial-number
    PUBLIC
        crashdump_serial_number.cpp
)



A board/linux/crashdump-serial-number/crashdump_serial_number.cpp => board/linux/crashdump-serial-number/crashdump_serial_number.cpp +15 -0
@@ 0,0 1,15 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <crashdump-serial-number/crashdump_serial_number.hpp>

namespace crashdump
{
    void setSerialNumber(const std::string &)
    {}
    std::string getSerialNumber()
    {
        return "";
    }

} // namespace crashdump

A board/linux/crashdump-serial-number/include/crashdump-serial-number/crashdump_serial_number.hpp => board/linux/crashdump-serial-number/include/crashdump-serial-number/crashdump_serial_number.hpp +13 -0
@@ 0,0 1,13 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

// Dummy file to keep linux variant compiling.

#pragma once
#include <string>
namespace crashdump
{
    void setSerialNumber(const std::string &sn);
    std::string getSerialNumber();

} // namespace crashdump

M board/rt1051/CMakeLists.txt => board/rt1051/CMakeLists.txt +2 -0
@@ 2,6 2,7 @@ add_library(board STATIC)

add_subdirectory(cmsis)
add_subdirectory(${BOARD})
add_subdirectory(crashdump-serial-number)

if (${MEMORY_LINKER_FILE_PATH} STREQUAL "")
    message(FATAL_ERROR "Linker RAM layout not provided")


@@ 42,6 43,7 @@ target_include_directories(board
target_link_libraries(board
    PRIVATE
        utils-rotator
        crashdump-serial-number
    PUBLIC
        fsl
        module-vfs

A board/rt1051/crashdump-serial-number/CMakeLists.txt => board/rt1051/crashdump-serial-number/CMakeLists.txt +13 -0
@@ 0,0 1,13 @@
add_library(crashdump-serial-number STATIC)

target_include_directories(crashdump-serial-number
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}>/include
)

target_sources(crashdump-serial-number
    PUBLIC
        crashdump_serial_number.cpp
)



A board/rt1051/crashdump-serial-number/crashdump_serial_number.cpp => board/rt1051/crashdump-serial-number/crashdump_serial_number.cpp +21 -0
@@ 0,0 1,21 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <crashdump-serial-number/crashdump_serial_number.hpp>

namespace
{
    std::string serial_number = "0000000000000";
}
namespace crashdump
{
    void setSerialNumber(const std::string &sn)
    {
        serial_number = sn;
    }
    std::string getSerialNumber()
    {
        return serial_number;
    }

} // namespace crashdump

A board/rt1051/crashdump-serial-number/include/crashdump-serial-number/crashdump_serial_number.hpp => board/rt1051/crashdump-serial-number/include/crashdump-serial-number/crashdump_serial_number.hpp +17 -0
@@ 0,0 1,17 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

// The purpose of this file is to keep the devices serial number in the memory.
// In case of any crash, the serial number could be easily added to a crash dump filename.
// It will allow to identify the crash even after it is moved or copied from the device.
// setSerialNumber() should be called during system initialization.
// getSerialNumber() is called by the crash dump writer during file creation.

#pragma once
#include <string>
namespace crashdump
{
    void setSerialNumber(const std::string &sn);
    std::string getSerialNumber();

} // namespace crashdump

M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +2 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma GCC optimize("Og")


@@ 60,6 60,7 @@ void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elem
CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
{
    cwrite.saveDump();
    cwrite.deleteOldDump();
    _exit_backtrace(-1, false);
    return CRASH_CATCHER_EXIT;
}

M board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +41 -9
@@ 1,31 1,46 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "crashdumpwriter_vfs.hpp"

#include <crashdump-serial-number/crashdump_serial_number.hpp>
#include <cstdio>
#include <log/log.hpp>
#include <fcntl.h>
#include "purefs/vfs_subsystem.hpp"
#include <purefs/filesystem_paths.hpp>
#include <exit_backtrace.h>

#include <log/log.hpp>
#include <filesystem>
#include <stdint.h>
#include <unistd.h>
#include <chrono>
#include <set>

namespace
{
    constexpr inline auto suffix = "_crashdump.hex";

    // Crashdump filename pattern:
    // [serial-number]_[timestamp-in-seconds]_crashdump.hex

    inline std::string generate_crashdump_filename()
    {
        const auto crash_time =
            std::chrono::duration_cast<std::chrono::seconds>(std::chrono::system_clock::now().time_since_epoch())
                .count();
        auto filename = std::string("/") + crashdump::getSerialNumber() + "_" + std::to_string(crash_time) + suffix;
        return filename;
    }
} // namespace

namespace crashdump
{
    constexpr inline auto crashDumpFileName = "crashdump.hex";

    void CrashDumpWriterVFS::openDump()
    {
        const auto crashDumpFilePath = purefs::dir::getCrashDumpsPath() / crashDumpFileName;
        const auto crashDumpFilePath = purefs::dir::getCrashDumpsPath().string() + generate_crashdump_filename();

        LOG_INFO("Crash dump %s preparing ...", crashDumpFilePath.c_str());
        if (!rotator.rotateFile(crashDumpFilePath)) {
            LOG_FATAL("Failed to rotate crash dumps errno: %i", errno);
            _exit_backtrace(-1, false);
        }
        file = std::fopen(crashDumpFilePath.c_str(), "w");
        if (!file) {
            LOG_FATAL("Failed to open crash dump file errno %i", errno);


@@ 41,6 56,23 @@ namespace crashdump
        std::fclose(file);
    }

    void CrashDumpWriterVFS::deleteOldDump()
    {
        std::set<std::filesystem::path> crashdumps{};
        for (const auto &entry : std::filesystem::directory_iterator(purefs::dir::getCrashDumpsPath())) {
            std::cout << entry.path() << std::endl;
            crashdumps.insert(entry.path());
        }

        if (crashdumps.size() > maxFilesCount) {
            auto crashdump_to_delete = crashdumps.begin();
            LOG_INFO("Deleting %s ...", crashdump_to_delete->c_str());
            if (not std::filesystem::remove(crashdump_to_delete->c_str())) {
                LOG_WARN("File: %s was not deleted.", crashdump_to_delete->c_str());
            }
        }
    }

    void CrashDumpWriterVFS::writeBytes(const uint8_t *buff, std::size_t size)
    {
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {

M board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +4 -6
@@ 1,10 1,8 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <rotator/Rotator.hpp>

#include <array>
#include <ctime>
#include <memory>


@@ 17,21 15,21 @@ namespace purefs::fs

namespace crashdump
{
    constexpr inline auto maxRotationFilesCount = 5;
    constexpr inline auto maxFilesCount = 5;
    class CrashDumpWriterVFS
    {
      public:
        CrashDumpWriterVFS() : rotator{".hex"}
        CrashDumpWriterVFS()
        {}
        void openDump();
        void saveDump();
        void deleteOldDump();

        void writeBytes(const std::uint8_t *buff, std::size_t size);
        void writeHalfWords(const std::uint16_t *buff, std::size_t size);
        void writeWords(const std::uint32_t *buff, std::size_t size);

      private:
        utils::Rotator<maxRotationFilesCount> rotator;
        std::FILE *file{};
    };


M harmony_changelog.md => harmony_changelog.md +1 -0
@@ 10,6 10,7 @@
### Added

### Changed
* Added serial number and timestamp to crashdump filename

## [1.8.0 2022-12-14]


M module-services/service-db/agents/settings/FactorySettings.cpp => module-services/service-db/agents/settings/FactorySettings.cpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "FactorySettings.hpp"

M module-services/service-desktop/WorkerDesktop.cpp => module-services/service-desktop/WorkerDesktop.cpp +1 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "service-desktop/ServiceDesktop.hpp"

M products/BellHybrid/CMakeLists.txt => products/BellHybrid/CMakeLists.txt +1 -0
@@ 143,6 143,7 @@ add_subdirectory(apps)
add_subdirectory(keymap)
add_subdirectory(services)
add_subdirectory(sys)
add_subdirectory(serial-number-reader)

option(CONFIG_ENABLE_TEMP "Enable displaying temperature" OFF)
option(CONFIG_SHOW_MEMORY_INFO "Enable displaying memory info" OFF)

A products/BellHybrid/serial-number-reader/CMakeLists.txt => products/BellHybrid/serial-number-reader/CMakeLists.txt +17 -0
@@ 0,0 1,17 @@
add_library(serial-number-reader STATIC)


target_sources(serial-number-reader
    PUBLIC
        SerialNumberReader.cpp
)

target_include_directories(serial-number-reader
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
)

target_link_libraries(serial-number-reader
    PRIVATE
    module-vfs
)

A products/BellHybrid/serial-number-reader/SerialNumberReader.cpp => products/BellHybrid/serial-number-reader/SerialNumberReader.cpp +30 -0
@@ 0,0 1,30 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <purefs/vfs_subsystem.hpp>

#include <serial-number-reader/SerialNumberReader.hpp>

namespace
{
    constexpr auto DEVICE_NAME      = "emmc0sys1";
    constexpr auto EMMC_SN_LENGTH   = 13;
    constexpr auto EMMC_BUFFER_SIZE = 512;
    constexpr auto SECTOR_TO_READ   = 2;
    constexpr auto SECTOR_COUNT     = 1U;

    std::string readSerialNumberFromEmmc()
    {
        char buffer[EMMC_BUFFER_SIZE];
        purefs::subsystem::disk_mgr()->read(DEVICE_NAME, buffer, SECTOR_TO_READ, SECTOR_COUNT);
        buffer[EMMC_SN_LENGTH] = '\0';
        return std::string(buffer);
    }
} // namespace
namespace serial_number_reader
{
    std::string readSerialNumber()
    {
        return readSerialNumberFromEmmc();
    }
} // namespace serial_number_reader

A products/BellHybrid/serial-number-reader/include/serial-number-reader/SerialNumberReader.hpp => products/BellHybrid/serial-number-reader/include/serial-number-reader/SerialNumberReader.hpp +10 -0
@@ 0,0 1,10 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include <string>

namespace serial_number_reader
{
    std::string readSerialNumber();
} // namespace serial_number_reader

M products/BellHybrid/services/db/CMakeLists.txt => products/BellHybrid/services/db/CMakeLists.txt +2 -0
@@ 21,6 21,8 @@ target_link_libraries(databases
   PRIVATE
        bell::db::meditation_stats
        service-db
        serial-number-reader
        crashdump-serial-number
)

if (${ENABLE_TESTS})

M products/BellHybrid/services/db/ServiceDB.cpp => products/BellHybrid/services/db/ServiceDB.cpp +9 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <db/ServiceDB.hpp>


@@ 17,6 17,9 @@

#include <purefs/filesystem_paths.hpp>

#include <serial-number-reader/SerialNumberReader.hpp>
#include <crashdump-serial-number/crashdump_serial_number.hpp>

ServiceDB::~ServiceDB()
{
    eventsDB.reset();


@@ 90,6 93,11 @@ sys::ReturnCodes ServiceDB::InitHandler()
        dbAgent->registerMessages();
    }

    LOG_INFO("Serial number: %s", serial_number_reader::readSerialNumber().c_str());

    // Saving serial number for crashdump generation purpose.
    crashdump::setSerialNumber(serial_number_reader::readSerialNumber());

    return sys::ReturnCodes::Success;
}


M products/BellHybrid/services/desktop/endpoints/CMakeLists.txt => products/BellHybrid/services/desktop/endpoints/CMakeLists.txt +1 -0
@@ 22,6 22,7 @@ target_link_libraries(
        desktop-endpoints-common
    PRIVATE
        version-header
        serial-number-reader
)

target_compile_definitions(

M products/BellHybrid/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp => products/BellHybrid/services/desktop/endpoints/deviceInfo/DeviceInfoEndpoint.cpp +3 -18
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <endpoints/deviceInfo/DeviceInfoEndpoint.hpp>


@@ 15,31 15,16 @@
#include <sys/statvfs.h>
#include <purefs/filesystem_paths.hpp>
#include <purefs/vfs_subsystem.hpp>
#include <serial-number-reader/SerialNumberReader.hpp>

#include <ctime>
namespace
{
    constexpr auto DEVICE_NAME      = "emmc0sys1";
    constexpr auto EMMC_SN_LENGTH   = 13;
    constexpr auto EMMC_BUFFER_SIZE = 512;
    constexpr auto SECTOR_TO_READ   = 2;
    constexpr auto SECTOR_COUNT     = 1U;

    std::string readSerialNumberFromEmmc()
    {
        char buffer[EMMC_BUFFER_SIZE];
        purefs::subsystem::disk_mgr()->read(DEVICE_NAME, buffer, SECTOR_TO_READ, SECTOR_COUNT);
        buffer[EMMC_SN_LENGTH] = '\0';
        return std::string(buffer);
    }

} // namespace
namespace sdesktop::endpoints
{

    auto DeviceInfoEndpoint::getSerialNumber() -> std::string
    {
        return readSerialNumberFromEmmc();
        return serial_number_reader::readSerialNumber();
    }

    auto DeviceInfoEndpoint::getDeviceInfo(Context &context) -> http::Code

M products/PurePhone/services/db/CMakeLists.txt => products/PurePhone/services/db/CMakeLists.txt +1 -0
@@ 16,4 16,5 @@ target_link_libraries(db
   PRIVATE
        module-db
        service-db
        crashdump-serial-number
)

M products/PurePhone/services/db/ServiceDB.cpp => products/PurePhone/services/db/ServiceDB.cpp +9 -1
@@ 1,4 1,4 @@
// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <db/ServiceDB.hpp>


@@ 23,7 23,12 @@
#include <service-db/DBServiceMessage.hpp>
#include <service-db/QueryMessage.hpp>
#include <time/ScopedTime.hpp>
#include <crashdump-serial-number/crashdump_serial_number.hpp>

namespace
{
    constexpr auto serial_number_path = "factory_data/serial";
}
ServiceDB::~ServiceDB()
{
    eventsDB.reset();


@@ 276,6 281,9 @@ sys::ReturnCodes ServiceDB::InitHandler()
    auto settings = std::make_unique<settings::Settings>();
    settings->init(service::ServiceProxy(shared_from_this()));

    // Saving serial number for crashdump generation purpose.
    crashdump::setSerialNumber(settings->getValue(serial_number_path, settings::SettingsScope::Global));

    quotesRecordInterface =
        std::make_unique<Quotes::QuotesAgent>(predefinedQuotesDB.get(), customQuotesDB.get(), std::move(settings));


M pure_changelog.md => pure_changelog.md +1 -0
@@ 4,6 4,7 @@

### Changed / Improved
* Improved dialog with network via USSD
* Added serial number and timestamp to crashdump filename

### Fixed
* Fixed disappearing "confirm" button in PIN entering screen