#include "CoreController.h" #include "libxiphos.h" #include "HasActionsIF.h" #include "event.h" #include #include #include #include static constexpr bool CAT_FILE_TO_CONSOLE = false; const std::string CONF_PATH = "/tmp/conf"; const std::string REBOOT_FILE = CONF_PATH + "/reboot.txt"; void catFileToConsole(); TEST_CASE( "Core Controller Reboot File Handling", "[reboot-file]" ) { if(not std::filesystem::exists(CONF_PATH)) { std::filesystem::create_directory(CONF_PATH); } CoreController ctrl; SECTION ("Primary") { xsc_libnor_chip_t chip; xsc_libnor_copy_t copy; RebootFile rf = {}; ctrl.rewriteRebootFile(rf); REQUIRE(rf.enabled == 0); REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); REQUIRE(rf.bootFlag == 0); REQUIRE(rf.lastChip == 0); REQUIRE(rf.lastCopy == 0); // This recreates the file but should also increment the boot counter of the current image REQUIRE(ctrl.CURRENT_CHIP == xsc::CHIP_0); REQUIRE(ctrl.CURRENT_COPY == xsc::COPY_0); ctrl.performRebootFileHandling(true); catFileToConsole(); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.maxCount == RebootFile::DEFAULT_MAX_BOOT_CNT); REQUIRE(rf.img00Cnt == 1); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); REQUIRE(rf.bootFlag == 0); REQUIRE(rf.lastChip == 0); REQUIRE(rf.lastCopy == 0); uint8_t newRebootCnt = 3; CHECK(ctrl.executeAction(CoreController::SET_MAX_REBOOT_CNT, 0, &newRebootCnt, 1) == HasActionsIF::EXECUTION_FINISHED); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.maxCount == 3); REQUIRE(not getRebootWasCalled(chip, copy)); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); REQUIRE(rf.bootFlag == true); REQUIRE(rf.lastChip == xsc::CHIP_0); REQUIRE(rf.lastCopy == xsc::COPY_0); REQUIRE(getRebootWasCalled(chip, copy)); REQUIRE(chip == XSC_LIBNOR_CHIP_0); REQUIRE(copy == XSC_LIBNOR_COPY_GOLD); EventInfo info = {}; uint32_t numEvents = 0; // We are now on image 0 1 and an event will be triggered ctrl.performRebootFileHandling(false); eventWasCalled(info, numEvents); CHECK(numEvents == 1); CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0); CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_0); CHECK(((info.p2 >> 24) & 0xFF) == 3); CHECK(((info.p2 >> 16) & 0xFF) == 1); CHECK(((info.p2 >> 8) & 0xFF) == 0); CHECK((info.p2 & 0xFF) == 0); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 1); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); // Flag was cleared when event was thrown REQUIRE(rf.bootFlag == false); REQUIRE(rf.lastChip == xsc::CHIP_0); REQUIRE(rf.lastCopy == xsc::COPY_0); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); // We are now on image 1 0 and an event will be triggered ctrl.performRebootFileHandling(false); eventWasCalled(info, numEvents); CHECK(numEvents == 1); CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_0); CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_1); CHECK(((info.p2 >> 24) & 0xFF) == 3); CHECK(((info.p2 >> 16) & 0xFF) == 3); CHECK(((info.p2 >> 8) & 0xFF) == 1); CHECK((info.p2 & 0xFF) == 0); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 1); REQUIRE(rf.img11Cnt == 0); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 0); eventWasCalled(info, numEvents); // On image 1 1 now ctrl.performRebootFileHandling(false); eventWasCalled(info, numEvents); CHECK(numEvents == 1); CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1); CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_0); CHECK(((info.p2 >> 24) & 0xFF) == 3); CHECK(((info.p2 >> 16) & 0xFF) == 3); CHECK(((info.p2 >> 8) & 0xFF) == 3); CHECK((info.p2 & 0xFF) == 1); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); // Now it should fall back to 0 0 because all are invalid ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 3); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); // Should remain on image now ctrl.performRebootFileHandling(false); eventWasCalled(info, numEvents); CHECK(numEvents == 1); CHECK(info.event == CoreController::REBOOT_MECHANISM_TRIGGERED); CHECK(static_cast((info.p1 >> 16) & 0xFFFF) == xsc::CHIP_1); CHECK(static_cast(info.p1 & 0xFFFF) == xsc::COPY_1); CHECK(((info.p2 >> 24) & 0xFF) == 4); CHECK(((info.p2 >> 16) & 0xFF) == 3); CHECK(((info.p2 >> 8) & 0xFF) == 3); CHECK((info.p2 & 0xFF) == 3); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.img00Cnt == 4); REQUIRE(rf.img01Cnt == 3); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); // Reset a specific reboot counter ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_01, 0, nullptr, 0); // Reboot to 0 0 again ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 5); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 3); REQUIRE(rf.img11Cnt == 3); CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); CHECK(CoreController::CURRENT_COPY == xsc::COPY_1); ctrl.executeAction(CoreController::RESET_ALL_REBOOT_COUNTERS, 0, nullptr, 0); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); uint8_t enable = 0; ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 0); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); // Reboot to 1 0 explicitely CoreController::setCurrentBootCopy(xsc::CHIP_1, xsc::COPY_0); // Reboot three times and verify that no reboot is performed ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 0); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 4); REQUIRE(rf.img11Cnt == 0); // Now enable the functionality again and verify it reboots to 1 1 enable = 1; ctrl.executeAction(CoreController::SWITCH_REBOOT_FILE_HANDLING, 0, &enable, 1); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 5); REQUIRE(rf.img11Cnt == 0); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 5); REQUIRE(rf.img11Cnt == 1); ctrl.performRebootFileHandling(false); ctrl.performRebootFileHandling(false); // Should be on 0 0 now CHECK(CoreController::CURRENT_CHIP == xsc::CHIP_0); CHECK(CoreController::CURRENT_COPY == xsc::COPY_0); ctrl.performRebootFileHandling(false); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 1); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 5); REQUIRE(rf.img11Cnt == 3); // Now reset all reboot counters manually ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_00, 0, nullptr, 0); ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_10, 0, nullptr, 0); ctrl.executeAction(CoreController::RESET_REBOOT_COUNTER_11, 0, nullptr, 0); ctrl.parseRebootFile(REBOOT_FILE, rf); REQUIRE(rf.enabled == 1); REQUIRE(rf.img00Cnt == 0); REQUIRE(rf.img01Cnt == 0); REQUIRE(rf.img10Cnt == 0); REQUIRE(rf.img11Cnt == 0); } if(std::filesystem::exists(CONF_PATH)) { std::uintmax_t n = std::filesystem::remove_all(CONF_PATH); CHECK(n == 2); } } void catFileToConsole() { if(CAT_FILE_TO_CONSOLE) { std::ifstream file(REBOOT_FILE); if (file.is_open()) { std::cout << file.rdbuf(); } } }