2022-02-28 14:13:31 +01:00
|
|
|
#include "conf.h"
|
|
|
|
#include "CoreController.h"
|
|
|
|
#include "SdCardManager.h"
|
|
|
|
#include "event.h"
|
|
|
|
#include "libxiphos.h"
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <filesystem>
|
|
|
|
|
|
|
|
xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP;
|
|
|
|
xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY;
|
|
|
|
|
|
|
|
CoreController::CoreController() {
|
|
|
|
sdcMan = new SdCardManager();
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoreController::performRebootFileHandling(bool recreateFile) {
|
2022-02-28 16:35:16 +01:00
|
|
|
using namespace std;
|
|
|
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
|
|
|
|
if (not std::filesystem::exists(path) or recreateFile) {
|
2022-02-28 14:13:31 +01:00
|
|
|
#if OBSW_VERBOSE_LEVEL >= 1
|
2022-02-28 16:35:16 +01:00
|
|
|
std::cout << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
|
2022-02-28 14:13:31 +01:00
|
|
|
#endif
|
2022-02-28 16:35:16 +01:00
|
|
|
rebootFile.enabled = true;
|
|
|
|
rebootFile.img00Cnt = 0;
|
|
|
|
rebootFile.img01Cnt = 0;
|
|
|
|
rebootFile.img10Cnt = 0;
|
|
|
|
rebootFile.img11Cnt = 0;
|
|
|
|
rebootFile.lastChip = xsc::Chip::CHIP_0;
|
|
|
|
rebootFile.lastCopy = xsc::Copy::COPY_0;
|
|
|
|
rebootFile.bootFlag = false;
|
|
|
|
rewriteRebootFile(rebootFile);
|
|
|
|
} else {
|
|
|
|
if (not parseRebootFile(path, rebootFile)) {
|
|
|
|
performRebootFileHandling(true);
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
}
|
2022-02-28 14:13:31 +01:00
|
|
|
|
2022-02-28 16:35:16 +01:00
|
|
|
if (rebootFile.bootFlag) {
|
|
|
|
// Trigger event to inform ground that a reboot was triggered
|
|
|
|
uint32_t p1 = rebootFile.lastChip << 16 | rebootFile.lastCopy;
|
|
|
|
uint32_t p2 = rebootFile.img00Cnt << 24 | rebootFile.img01Cnt << 16 |
|
|
|
|
rebootFile.img10Cnt << 8 | rebootFile.img11Cnt;
|
|
|
|
triggerEvent(REBOOT_MECHANISM_TRIGGERED, p1, p2);
|
|
|
|
// Clear the boot flag
|
|
|
|
rebootFile.bootFlag = false;
|
|
|
|
}
|
2022-02-28 14:13:31 +01:00
|
|
|
|
2022-02-28 16:35:16 +01:00
|
|
|
switch (CURRENT_CHIP) {
|
|
|
|
case (xsc::CHIP_0): {
|
|
|
|
switch (CURRENT_COPY) {
|
|
|
|
case (xsc::COPY_0): {
|
|
|
|
rebootFile.img00Cnt++;
|
|
|
|
break;
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
case (xsc::COPY_1): {
|
|
|
|
rebootFile.img01Cnt++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
break;
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (xsc::CHIP_1): {
|
|
|
|
switch (CURRENT_COPY) {
|
|
|
|
case (xsc::COPY_0): {
|
|
|
|
rebootFile.img10Cnt++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case (xsc::COPY_1): {
|
|
|
|
rebootFile.img11Cnt++;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
|
|
|
break;
|
|
|
|
}
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
break;
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
default: {
|
|
|
|
break;
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
}
|
|
|
|
if (CURRENT_CHIP == xsc::CHIP_0 and CURRENT_COPY == xsc::COPY_0) {
|
|
|
|
}
|
|
|
|
if (rebootFile.relevantBootCnt > rebootFile.maxCount) {
|
|
|
|
// Reboot to other image
|
|
|
|
bool doReboot = false;
|
|
|
|
determineAndExecuteReboot(rebootFile, doReboot, rebootFile.lastChip, rebootFile.lastCopy);
|
|
|
|
if (doReboot) {
|
|
|
|
rebootFile.bootFlag = true;
|
2022-02-28 14:13:31 +01:00
|
|
|
#if OBSW_VERBOSE_LEVEL >= 1
|
2022-02-28 16:35:16 +01:00
|
|
|
std::cout << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
|
|
|
|
<< "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy
|
|
|
|
<< std::endl;
|
2022-02-28 14:13:31 +01:00
|
|
|
#endif
|
|
|
|
rewriteRebootFile(rebootFile);
|
2022-02-28 16:35:16 +01:00
|
|
|
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(rebootFile.lastChip),
|
|
|
|
static_cast<xsc_libnor_copy_t>(rebootFile.lastCopy));
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
2022-02-28 16:35:16 +01:00
|
|
|
} else {
|
|
|
|
rewriteRebootFile(rebootFile);
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 16:35:16 +01:00
|
|
|
|
2022-02-28 14:13:31 +01:00
|
|
|
void CoreController::determineAndExecuteReboot(RebootFile &rf, bool &needsReboot,
|
|
|
|
xsc::Chip &tgtChip, xsc::Copy &tgtCopy) {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_0;
|
|
|
|
needsReboot = false;
|
|
|
|
if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_0) and
|
|
|
|
(rf.img00Cnt >= rf.maxCount)) {
|
|
|
|
needsReboot = true;
|
|
|
|
if (rf.img01Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img10Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img11Cnt >= rf.maxCount) {
|
|
|
|
// Can't really do much here. Stay on image
|
|
|
|
std::cout << "All reboot counts too high, but already on fallback image" << std::endl;
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_1;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((CURRENT_COPY == xsc::COPY_0) and (CURRENT_CHIP == xsc::CHIP_1) and
|
|
|
|
(rf.img01Cnt >= rf.maxCount)) {
|
|
|
|
needsReboot = true;
|
|
|
|
if (rf.img00Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img10Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img11Cnt >= rf.maxCount) {
|
|
|
|
// Reboot to fallback image
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_1;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_1;
|
|
|
|
tgtCopy = xsc::COPY_0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Reboot on fallback image
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_0) and
|
|
|
|
(rf.img10Cnt >= rf.maxCount)) {
|
|
|
|
needsReboot = true;
|
|
|
|
if (rf.img11Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img00Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img01Cnt >= rf.maxCount) {
|
|
|
|
// Reboot to fallback image
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_1;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ((CURRENT_COPY == xsc::COPY_1) and (CURRENT_CHIP == xsc::CHIP_1) and
|
|
|
|
(rf.img11Cnt >= rf.maxCount)) {
|
|
|
|
needsReboot = true;
|
|
|
|
if (rf.img10Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img00Cnt >= rf.maxCount) {
|
|
|
|
if (rf.img01Cnt >= rf.maxCount) {
|
|
|
|
// Reboot to fallback image
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_0;
|
|
|
|
tgtCopy = xsc::COPY_0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tgtChip = xsc::CHIP_1;
|
|
|
|
tgtCopy = xsc::COPY_0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CoreController::parseRebootFile(std::string path, RebootFile &rf) {
|
|
|
|
using namespace std;
|
|
|
|
std::string selfMatch;
|
|
|
|
if (CURRENT_CHIP == xsc::CHIP_0) {
|
|
|
|
if (CURRENT_COPY == xsc::COPY_0) {
|
|
|
|
selfMatch = "00";
|
|
|
|
} else {
|
|
|
|
selfMatch = "01";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (CURRENT_COPY == xsc::COPY_0) {
|
|
|
|
selfMatch = "10";
|
|
|
|
} else {
|
|
|
|
selfMatch = "11";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ifstream file(path);
|
|
|
|
string word;
|
|
|
|
string line;
|
|
|
|
uint8_t lineIdx = 0;
|
|
|
|
while (std::getline(file, line)) {
|
|
|
|
istringstream iss(line);
|
|
|
|
switch (lineIdx) {
|
|
|
|
case 0: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("on:") == string::npos) {
|
|
|
|
// invalid file
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.enabled;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("maxcnt:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.maxCount;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("img00:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.img00Cnt;
|
|
|
|
if (word.find(selfMatch) != string::npos) {
|
|
|
|
rf.relevantBootCnt = rf.img00Cnt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 3: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("img01:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.img01Cnt;
|
|
|
|
if (word.find(selfMatch) != string::npos) {
|
|
|
|
rf.relevantBootCnt = rf.img01Cnt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 4: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("img10:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.img10Cnt;
|
|
|
|
if (word.find(selfMatch) != string::npos) {
|
|
|
|
rf.relevantBootCnt = rf.img10Cnt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 5: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("img11:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.img11Cnt;
|
|
|
|
if (word.find(selfMatch) != string::npos) {
|
|
|
|
rf.relevantBootCnt = rf.img11Cnt;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 6: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("bootflag:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> rf.bootFlag;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 7: {
|
|
|
|
iss >> word;
|
|
|
|
if (word.find("bootflag:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 8: {
|
|
|
|
iss >> word;
|
|
|
|
uint8_t copyRaw = 0;
|
|
|
|
uint8_t chipRaw = 0;
|
|
|
|
if (word.find("last:") == string::npos) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> chipRaw;
|
|
|
|
if (iss.fail()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
iss >> copyRaw;
|
|
|
|
if (iss.fail()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chipRaw > 1 or copyRaw > 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
rf.lastChip = static_cast<xsc::Chip>(chipRaw);
|
|
|
|
rf.lastCopy = static_cast<xsc::Copy>(copyRaw);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (iss.fail()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
lineIdx++;
|
|
|
|
}
|
|
|
|
if (lineIdx < 8) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoreController::resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy) {
|
|
|
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
|
|
|
|
// Disable the reboot file mechanism
|
|
|
|
parseRebootFile(path, rebootFile);
|
|
|
|
if (tgtChip == xsc::ALL_CHIP and tgtCopy == xsc::ALL_COPY) {
|
|
|
|
rebootFile.img00Cnt = 0;
|
|
|
|
rebootFile.img01Cnt = 0;
|
|
|
|
rebootFile.img10Cnt = 0;
|
|
|
|
rebootFile.img11Cnt = 0;
|
|
|
|
} else {
|
|
|
|
if (tgtChip == xsc::CHIP_0) {
|
|
|
|
if (tgtCopy == xsc::COPY_0) {
|
|
|
|
rebootFile.img00Cnt = 0;
|
|
|
|
} else {
|
|
|
|
rebootFile.img01Cnt = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (tgtCopy == xsc::COPY_0) {
|
|
|
|
rebootFile.img10Cnt = 0;
|
|
|
|
} else {
|
|
|
|
rebootFile.img11Cnt = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rewriteRebootFile(rebootFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CoreController::rewriteRebootFile(RebootFile file) {
|
|
|
|
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
|
|
|
|
std::ofstream rebootFile(path);
|
|
|
|
if (rebootFile.is_open()) {
|
|
|
|
// Initiate reboot file first. Reboot handling will be on on initialization
|
|
|
|
rebootFile << "on: " << file.enabled << "\nmaxcnt: " << file.maxCount
|
|
|
|
<< "\nimg00: " << file.img00Cnt << "\nimg01: " << file.img01Cnt
|
|
|
|
<< "\nimg10: " << file.img10Cnt << "\nimg11: " << file.img11Cnt
|
2022-02-28 16:47:36 +01:00
|
|
|
<< "\nbootflag: " << file.bootFlag << "\nlast: " << static_cast<int>(file.lastChip) << " "
|
|
|
|
<< static_cast<int>(file.lastCopy) << "\n";
|
2022-02-28 14:13:31 +01:00
|
|
|
}
|
|
|
|
}
|