~aleteoryx/muditaos

e00b5ef5a46b9b3f82448f55860bcaf3a338f5f6 — Lucjan Bryndza 4 years ago 8ec5cf6
[CP-670] Fix crash dump creation on HF

Fix the crash dump on the disk partition
when phone firmware Hard Fault CM7 core
error.

Signed-off-by: Lucjan Bryndza <lucjan.bryndza@mudita.com>
M board/rt1051/crashdump/crashcatcher_impl.cpp => board/rt1051/crashdump/crashcatcher_impl.cpp +15 -15
@@ 7,24 7,25 @@

#include <log/log.hpp>
#include <date/date.h>
#include "crashdumpwriter.hpp"
#include "crashdumpwriter_vfs.hpp"
#include "consoledump.hpp"

namespace
{
    crashdump::CrashDumpWriterVFS cwrite;
}

const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
{
    // board/rt1051/ldscripts/memory.ld
    /* board/rt1051/ldscripts/memory.ld
     * NOTE: Text section and stacks sections are intentionally ommited
     * because can cause throubles in the running system
     */
    static const CrashCatcherMemoryRegion regions[] = {
        // SRAM_OC
        {0x20200000, 0x20210000, CRASH_CATCHER_BYTE},
        // SRAM_DTC
        {0x20000000, 0x20070000, CRASH_CATCHER_BYTE},
    // intentionally skip text section
    // BOARD_SDRAM_HEAP
#if defined(HW_SDRAM_64_MB) && (HW_SDRAM_64_MB == 1)
        {0x80620000, 0x84000000, CRASH_CATCHER_BYTE},
#else
        {0x80620000, 0x81000000, CRASH_CATCHER_BYTE},
#endif
        // end tag
        {0xFFFFFFFF, 0xFFFFFFFF, CRASH_CATCHER_BYTE},
    };


@@ 35,28 36,27 @@ const CrashCatcherMemoryRegion *CrashCatcher_GetMemoryRegions(void)
void CrashCatcher_DumpStart(const CrashCatcherInfo *pInfo)
{
    crashdump::printCrashInfo(pInfo);
    crashdump::CrashDumpWriter::instance().openDump();
    cwrite.openDump();
}

void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elementSize, size_t elementCount)
{
    switch (elementSize) {
    case CRASH_CATCHER_BYTE:
        crashdump::CrashDumpWriter::instance().writeBytes(static_cast<const std::uint8_t *>(pvMemory), elementCount);
        cwrite.writeBytes(static_cast<const std::uint8_t *>(pvMemory), elementCount);
        break;
    case CRASH_CATCHER_HALFWORD:
        crashdump::CrashDumpWriter::instance().writeHalfWords(static_cast<const std::uint16_t *>(pvMemory),
                                                              elementCount);
        cwrite.writeHalfWords(static_cast<const std::uint16_t *>(pvMemory), elementCount);
        break;
    case CRASH_CATCHER_WORD:
        crashdump::CrashDumpWriter::instance().writeWords(static_cast<const std::uint32_t *>(pvMemory), elementCount);
        cwrite.writeWords(static_cast<const std::uint32_t *>(pvMemory), elementCount);
        break;
    }
}

CrashCatcherReturnCodes CrashCatcher_DumpEnd(void)
{
    crashdump::CrashDumpWriter::instance().saveDump();
    cwrite.saveDump();
    abort();
    return CRASH_CATCHER_EXIT;
}

D board/rt1051/crashdump/crashdumpwriter.hpp => board/rt1051/crashdump/crashdumpwriter.hpp +0 -25
@@ 1,25 0,0 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once

#include <cstdint>

namespace crashdump
{
    class CrashDumpWriter
    {
      public:
        static CrashDumpWriter &instance();

        virtual ~CrashDumpWriter() = default;

        virtual void openDump() = 0;
        virtual void saveDump() = 0;

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

} // namespace crashdump

M board/rt1051/crashdump/crashdumpwriter_vfs.cpp => board/rt1051/crashdump/crashdumpwriter_vfs.cpp +24 -19
@@ 3,12 3,15 @@

#include "crashdumpwriter_vfs.hpp"

#include <cstdio>
#include <log/log.hpp>
#include <fcntl.h>
#include "purefs/vfs_subsystem.hpp"
#include <purefs/filesystem_paths.hpp>

#include <filesystem>
#include <stdint.h>
#include <unistd.h>

namespace crashdump
{


@@ 16,47 19,49 @@ namespace crashdump

    void CrashDumpWriterVFS::openDump()
    {
        vfs                          = purefs::subsystem::vfs_core();
        const auto crashDumpFilePath = purefs::dir::getCrashDumpsPath() / crashDumpFileName;

        LOG_INFO("Crash dump %s preparing ...", crashDumpFilePath.c_str());
        if (!rotator.rotateFile(crashDumpFilePath)) {
            LOG_FATAL("Failed to rotate crash dumps.");
            LOG_FATAL("Failed to rotate crash dumps errno: %i", errno);
            std::abort();
        }
        dumpFd = vfs->open(crashDumpFilePath.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);

        if (dumpFd < 0) {
            LOG_FATAL("Failed to open crash dump file. Won't be able to save crash info.");
        file = std::fopen(crashDumpFilePath.c_str(), "w");
        if (!file) {
            LOG_FATAL("Failed to open crash dump file errno %i", errno);
            std::abort();
        }
    }

    void CrashDumpWriterVFS::saveDump()
    {
        vfs->close(dumpFd);
        LOG_INFO("Crash dump create finished.");
        fflush(file);
        fsync(fileno(file));
        std::fclose(file);
    }

    void CrashDumpWriterVFS::writeBytes(const uint8_t *buff, std::size_t size)
    {
        vfs->write(dumpFd, reinterpret_cast<const char *>(buff), size);
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump errno: %i", errno);
            std::abort();
        }
    }

    void CrashDumpWriterVFS::writeHalfWords(const uint16_t *buff, std::size_t size)
    {
        for (std::size_t n = 0; n < size; ++n) {
            writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint16_t));
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump");
            std::abort();
        }
    }

    void CrashDumpWriterVFS::writeWords(const uint32_t *buff, std::size_t size)
    {
        for (std::size_t n = 0; n < size; ++n) {
            writeBytes(reinterpret_cast<const uint8_t *>(buff + n), sizeof(uint32_t));
        if (std::fwrite(buff, sizeof(*buff), size, file) != size) {
            LOG_FATAL("Unable to write crash dump");
            std::abort();
        }
    }

    CrashDumpWriter &CrashDumpWriter::instance()
    {
        static CrashDumpWriterVFS writer;
        return writer;
    }

} // namespace crashdump

M board/rt1051/crashdump/crashdumpwriter_vfs.hpp => board/rt1051/crashdump/crashdumpwriter_vfs.hpp +8 -10
@@ 3,12 3,12 @@

#pragma once

#include "crashdumpwriter.hpp"
#include <rotator/Rotator.hpp>

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

namespace purefs::fs
{


@@ 18,23 18,21 @@ namespace purefs::fs
namespace crashdump
{
    constexpr inline auto maxRotationFilesCount = 5;
    class CrashDumpWriterVFS : public CrashDumpWriter
    class CrashDumpWriterVFS
    {
      public:
        CrashDumpWriterVFS() : rotator{".hex"}
        {}
        void openDump() override;
        void saveDump() override;
        void openDump();
        void saveDump();

        void writeBytes(const std::uint8_t *buff, std::size_t size) override;
        void writeHalfWords(const std::uint16_t *buff, std::size_t size) override;
        void writeWords(const std::uint32_t *buff, std::size_t size) override;
        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;
        int dumpFd{-1};

        std::shared_ptr<purefs::fs::filesystem> vfs;
        std::FILE *file{};
    };

} // namespace crashdump

M module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp => module-vfs/drivers/src/purefs/fs/filesystem_ext4.cpp +6 -2
@@ 130,8 130,12 @@ namespace purefs::fs::drivers
            LOG_ERROR("Unable to append volume err: %i", err);
            return err;
        }
        // Test only
        ext4_dmask_set(DEBUG_ALL);
        /** If verbosed lwext4 debug is required please uncomment
         * this line. It may cause to print a lot of messages
         * especially when the ext4 journal is recovered
         * on the log output device so it is disabled by default
         */
        // ext4_dmask_set(DEBUG_ALL);
        err = ext4_device_register(bd, disk->name().c_str());
        if (err) {
            LOG_ERROR("Unable to register device with err: %i", err);

M module-vfs/drivers/src/thirdparty/lwext4/ext4_bdev.cpp => module-vfs/drivers/src/thirdparty/lwext4/ext4_bdev.cpp +9 -2
@@ 5,6 5,7 @@
#include <ext4_config.h>
#include <ext4_blockdev.h>
#include <ext4_errno.h>
#include <stdint.h>
#include <unordered_map>
#include <log/log.hpp>
#include <mutex.hpp>


@@ 47,29 48,34 @@ namespace purefs::fs::drivers::ext4::internal
                if (!ctx) {
                    return -EIO;
                }
                cpp_freertos::LockGuard _lck(ctx->mutex);
                auto diskmm = ctx->disk.lock();
                if (!diskmm) {
                    return -EIO;
                }
                const auto err = diskmm->write(ctx->disk_h, buf, blk_id, blk_cnt);
                if (err) {
                    LOG_ERROR("Sector write error errno: %i", err);
                    LOG_ERROR(
                        "Sector write error errno: %i on block: %u cnt: %u", err, unsigned(blk_id), unsigned(blk_cnt));
                }
                return -err;
            }

            int read(struct ext4_blockdev *bdev, void *buf, uint64_t blk_id, uint32_t blk_cnt)
            {
                auto ctx = reinterpret_cast<context *>(bdev->bdif->p_user);
                if (!ctx) {
                    return -EIO;
                }
                cpp_freertos::LockGuard _lck(ctx->mutex);
                auto diskmm = ctx->disk.lock();
                if (!diskmm) {
                    return -EIO;
                }
                const auto err = diskmm->read(ctx->disk_h, buf, blk_id, blk_cnt);
                if (err) {
                    LOG_ERROR("Sector read error errno: %i", err);
                    LOG_ERROR(
                        "Sector read error errno: %i on block: %u cnt: %u", err, unsigned(blk_id), unsigned(blk_cnt));
                }
                return -err;
            }


@@ 78,6 84,7 @@ namespace purefs::fs::drivers::ext4::internal
            {
                return 0;
            }

            int close(struct ext4_blockdev *bdev)
            {
                return 0;