Merge branch 'mueller/reboot-file-handling' into mueller/plpcdu-sus-updates
Some checks failed
EIVE/eive-obsw/pipeline/pr-develop There was a failure building this commit

This commit is contained in:
Robin Müller 2022-02-25 16:34:10 +01:00
commit 006e9e2229
No known key found for this signature in database
GPG Key ID: 11D4952C8CCEF814
10 changed files with 617 additions and 97 deletions

View File

@ -441,12 +441,24 @@ Beagle Bone Black for download here
Download it and unzip it somewhere in the Xilinx installation folder. Download it and unzip it somewhere in the Xilinx installation folder.
You can use the following command if `wget` can be used or for CI/CD: You can use the following command if `wget` can be used or for CI/CD:
``` ```sh
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/agnJGYeRf6fw2ci/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz
``` ```
Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path. Then, create a new environmental variables `Q7S_SYSROOT` and set it to the local system root path.
### Updating system root for CI
If the system root is updated, it needs to be manually updated on the buggy file server.
If access on `buggy.irs.uni-stuttgart.de` is possible with `ssh` and the rootfs in the cloud
[was updated](https://eive-cloud.irs.uni-stuttgart.de/index.php/apps/files/?dir=/EIVE_IRS/Software/rootfs&fileid=831849)
as well, you can update the rootfs like this:
```sh
cd /var/www/eive/tools
wget https://eive-cloud.irs.uni-stuttgart.de/index.php/s/SyXpdBBQX32xPgE/download/cortexa9hf-neon-xiphos-linux-gnueabi.tar.gz
```
## Setting up UNIX environment for real-time functionalities ## Setting up UNIX environment for real-time functionalities
Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities Please note that on most UNIX environments (e.g. Ubuntu), the real time functionalities

View File

@ -170,15 +170,15 @@ void Q7STestTask::testProtHandler() {
bool opPerformed = false; bool opPerformed = false;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
// If any chips are unlocked, lock them here // If any chips are unlocked, lock them here
result = coreController->setBootCopyProtection( result = coreController->setBootCopyProtection(xsc::Chip::ALL_CHIP, xsc::Copy::ALL_COPY, true,
CoreController::Chip::ALL_CHIP, CoreController::Copy::ALL_COPY, true, opPerformed, true); opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
} }
// unlock own copy // unlock own copy
result = coreController->setBootCopyProtection( result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, false,
CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, false, opPerformed, true); opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
} }
@ -191,8 +191,8 @@ void Q7STestTask::testProtHandler() {
} }
// lock own copy // lock own copy
result = coreController->setBootCopyProtection( result = coreController->setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
CoreController::Chip::SELF_CHIP, CoreController::Copy::SELF_COPY, true, opPerformed, true); opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
} }
@ -205,8 +205,8 @@ void Q7STestTask::testProtHandler() {
} }
// unlock specific copy // unlock specific copy
result = coreController->setBootCopyProtection( result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, false,
CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, false, opPerformed, true); opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
} }
@ -219,8 +219,8 @@ void Q7STestTask::testProtHandler() {
} }
// lock specific copy // lock specific copy
result = coreController->setBootCopyProtection( result = coreController->setBootCopyProtection(xsc::Chip::CHIP_1, xsc::Copy::COPY_1, true,
CoreController::Chip::CHIP_1, CoreController::Copy::COPY_1, true, opPerformed, true); opPerformed, true);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl; sif::warning << "Q7STestTask::testProtHandler: Op failed" << std::endl;
} }

View File

@ -22,8 +22,8 @@
#include "bsp_q7s/memory/SdCardManager.h" #include "bsp_q7s/memory/SdCardManager.h"
#include "bsp_q7s/memory/scratchApi.h" #include "bsp_q7s/memory/scratchApi.h"
CoreController::Chip CoreController::CURRENT_CHIP = Chip::NO_CHIP; xsc::Chip CoreController::CURRENT_CHIP = xsc::Chip::NO_CHIP;
CoreController::Copy CoreController::CURRENT_COPY = Copy::NO_COPY; xsc::Copy CoreController::CURRENT_COPY = xsc::Copy::NO_COPY;
CoreController::CoreController(object_id_t objectId) CoreController::CoreController(object_id_t objectId)
: ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), opDivider(5) { : ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), opDivider(5) {
@ -59,6 +59,7 @@ ReturnValue_t CoreController::handleCommandMessage(CommandMessage *message) {
void CoreController::performControlOperation() { void CoreController::performControlOperation() {
performWatchdogControlOperation(); performWatchdogControlOperation();
sdStateMachine(); sdStateMachine();
performRebootFileHandling(false);
} }
ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap, ReturnValue_t CoreController::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
@ -79,6 +80,8 @@ ReturnValue_t CoreController::initialize() {
} }
sdStateMachine(); sdStateMachine();
triggerEvent(REBOOT_SW, CURRENT_CHIP, CURRENT_COPY);
return ExtendedControllerBase::initialize(); return ExtendedControllerBase::initialize();
} }
@ -104,6 +107,59 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
return result; return result;
} }
ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case (LIST_DIRECTORY_INTO_FILE): {
return actionListDirectoryIntoFile(actionId, commandedBy, data, size);
}
case (SWITCH_REBOOT_FILE_HANDLING): {
if (size < 1) {
return HasActionsIF::INVALID_PARAMETERS;
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
// Disable the reboot file mechanism
parseRebootFile(path, rebootFile);
if (data[0] == 0) {
rebootFile.enabled = false;
rewriteRebootFile(rebootFile);
} else if (data[0] == 1) {
rebootFile.enabled = true;
rewriteRebootFile(rebootFile);
} else {
return HasActionsIF::INVALID_PARAMETERS;
}
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_ALL_REBOOT_COUNTERS): {
resetRebootCount(xsc::ALL_CHIP, xsc::ALL_COPY);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_00): {
resetRebootCount(xsc::CHIP_0, xsc::COPY_0);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_01): {
resetRebootCount(xsc::CHIP_0, xsc::COPY_1);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_10): {
resetRebootCount(xsc::CHIP_1, xsc::COPY_0);
return HasActionsIF::EXECUTION_FINISHED;
}
case (RESET_REBOOT_COUNTER_11): {
resetRebootCount(xsc::CHIP_1, xsc::COPY_1);
return HasActionsIF::EXECUTION_FINISHED;
}
case (REBOOT_OBC): {
return actionPerformReboot(data, size);
}
default: {
return HasActionsIF::INVALID_ACTION_ID;
}
}
}
ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode, ReturnValue_t CoreController::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) { uint32_t *msToReachTheMode) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
@ -502,21 +558,6 @@ ReturnValue_t CoreController::sdCardSetup(sd::SdCard sdCard, sd::SdState targetS
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t CoreController::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
switch (actionId) {
case (LIST_DIRECTORY_INTO_FILE): {
return actionListDirectoryIntoFile(actionId, commandedBy, data, size);
}
case (REBOOT_OBC): {
return actionPerformReboot(data, size);
}
default: {
return HasActionsIF::INVALID_ACTION_ID;
}
}
}
ReturnValue_t CoreController::sdColdRedundantBlockingInit() { ReturnValue_t CoreController::sdColdRedundantBlockingInit() {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
@ -691,7 +732,7 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
ReturnValue_t CoreController::initBootCopy() { ReturnValue_t CoreController::initBootCopy() {
if (not std::filesystem::exists(CURR_COPY_FILE)) { if (not std::filesystem::exists(CURR_COPY_FILE)) {
// Thils file is created by the systemd service eive-early-config so this should // This file is created by the systemd service eive-early-config so this should
// not happen normally // not happen normally
std::string cmd = "xsc_boot_copy > " + std::string(CURR_COPY_FILE); std::string cmd = "xsc_boot_copy > " + std::string(CURR_COPY_FILE);
int result = std::system(cmd.c_str()); int result = std::system(cmd.c_str());
@ -699,22 +740,18 @@ ReturnValue_t CoreController::initBootCopy() {
utility::handleSystemError(result, "CoreController::initBootCopy"); utility::handleSystemError(result, "CoreController::initBootCopy");
} }
} }
std::ifstream file(CURR_COPY_FILE);
std::string line; getCurrentBootCopy(CURRENT_CHIP, CURRENT_COPY);
std::getline(file, line);
std::istringstream iss(line);
int value = 0;
iss >> value;
CURRENT_CHIP = static_cast<Chip>(value);
iss >> value;
CURRENT_COPY = static_cast<Copy>(value);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void CoreController::getCurrentBootCopy(Chip &chip, Copy &copy) { void CoreController::getCurrentBootCopy(xsc::Chip &chip, xsc::Copy &copy) {
xsc_libnor_chip_t xscChip;
xsc_libnor_copy_t xscCopy;
xsc_boot_get_chip_copy(&xscChip, &xscCopy);
// Not really thread-safe but it does not need to be // Not really thread-safe but it does not need to be
chip = CURRENT_CHIP; chip = static_cast<xsc::Chip>(xscChip);
copy = CURRENT_COPY; copy = static_cast<xsc::Copy>(xscCopy);
} }
ReturnValue_t CoreController::initWatchdogFifo() { ReturnValue_t CoreController::initWatchdogFifo() {
@ -761,8 +798,8 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_0); SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_0);
SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_1); SdCardManager::instance()->switchOffSdCard(sd::SdCard::SLOT_1);
// If any boot copies are unprotected // If any boot copies are unprotected
ReturnValue_t retval = ReturnValue_t retval = setBootCopyProtection(xsc::Chip::SELF_CHIP, xsc::Copy::SELF_COPY, true,
setBootCopyProtection(Chip::SELF_CHIP, Copy::SELF_COPY, true, protOpPerformed, false); protOpPerformed, false);
if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) {
sif::info << "Running slot was writeprotected before reboot" << std::endl; sif::info << "Running slot was writeprotected before reboot" << std::endl;
} }
@ -773,7 +810,7 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
} }
return HasActionsIF::EXECUTION_FINISHED; return HasActionsIF::EXECUTION_FINISHED;
} }
if (size < 3) { if (size < 3 or (data[1] > 1 or data[2] > 1)) {
return HasActionsIF::INVALID_PARAMETERS; return HasActionsIF::INVALID_PARAMETERS;
} }
#if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_VERBOSE_LEVEL >= 1
@ -784,21 +821,53 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
// Check that the target chip and copy is writeprotected first // Check that the target chip and copy is writeprotected first
generateChipStateFile(); generateChipStateFile();
// If any boot copies are unprotected, protect them here // If any boot copies are unprotected, protect them here
ReturnValue_t retval = setBootCopyProtection( auto tgtChip = static_cast<xsc::Chip>(data[1]);
static_cast<Chip>(data[1]), static_cast<Copy>(data[2]), true, protOpPerformed, false); auto tgtCopy = static_cast<xsc::Copy>(data[2]);
ReturnValue_t retval =
setBootCopyProtection(static_cast<xsc::Chip>(data[1]), static_cast<xsc::Copy>(data[2]), true,
protOpPerformed, false);
if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) { if (retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) {
sif::info << "Target slot was writeprotected before reboot" << std::endl; sif::info << "Target slot was writeprotected before reboot" << std::endl;
} }
// The second byte in data is the target chip, the third byte is the target copy switch (tgtChip) {
std::string cmdString = case (xsc::Chip::CHIP_0): {
"xsc_boot_copy " + std::to_string(data[1]) + " " + std::to_string(data[2]); switch (tgtCopy) {
int result = std::system(cmdString.c_str()); case (xsc::Copy::COPY_0): {
if (result != 0) { xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_NOMINAL);
utility::handleSystemError(result, "CoreController::executeAction"); break;
return HasReturnvaluesIF::RETURN_FAILED; }
case (xsc::Copy::COPY_1): {
xsc_boot_copy(XSC_LIBNOR_CHIP_0, XSC_LIBNOR_COPY_GOLD);
break;
}
default: {
break;
}
}
break;
}
case (xsc::Chip::CHIP_1): {
switch (tgtCopy) {
case (xsc::Copy::COPY_0): {
xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_NOMINAL);
break;
}
case (xsc::Copy::COPY_1): {
xsc_boot_copy(XSC_LIBNOR_CHIP_1, XSC_LIBNOR_COPY_GOLD);
break;
}
default: {
break;
}
}
break;
}
default:
break;
} }
return HasActionsIF::EXECUTION_FINISHED; return HasReturnvaluesIF::RETURN_FAILED;
} }
CoreController::~CoreController() {} CoreController::~CoreController() {}
@ -852,8 +921,8 @@ ReturnValue_t CoreController::generateChipStateFile() {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy targetCopy, bool protect, ReturnValue_t CoreController::setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy,
bool &protOperationPerformed, bool protect, bool &protOperationPerformed,
bool updateProtFile) { bool updateProtFile) {
bool allChips = false; bool allChips = false;
bool allCopies = false; bool allCopies = false;
@ -862,14 +931,14 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target
protOperationPerformed = false; protOperationPerformed = false;
switch (targetChip) { switch (targetChip) {
case (Chip::ALL_CHIP): { case (xsc::Chip::ALL_CHIP): {
allChips = true; allChips = true;
break; break;
} }
case (Chip::NO_CHIP): { case (xsc::Chip::NO_CHIP): {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
case (Chip::SELF_CHIP): { case (xsc::Chip::SELF_CHIP): {
selfChip = true; selfChip = true;
targetChip = CURRENT_CHIP; targetChip = CURRENT_CHIP;
break; break;
@ -879,14 +948,14 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target
} }
} }
switch (targetCopy) { switch (targetCopy) {
case (Copy::ALL_COPY): { case (xsc::Copy::ALL_COPY): {
allCopies = true; allCopies = true;
break; break;
} }
case (Copy::NO_COPY): { case (xsc::Copy::NO_COPY): {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
case (Copy::SELF_COPY): { case (xsc::Copy::SELF_COPY): {
selfCopy = true; selfCopy = true;
targetCopy = CURRENT_COPY; targetCopy = CURRENT_COPY;
break; break;
@ -909,10 +978,10 @@ ReturnValue_t CoreController::setBootCopyProtection(Chip targetChip, Copy target
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
int CoreController::handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, bool protect, int CoreController::handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy,
bool &protOperationPerformed, bool selfChip, bool protect, bool &protOperationPerformed,
bool selfCopy, bool allChips, bool allCopies, bool selfChip, bool selfCopy, bool allChips,
uint8_t arrIdx) { bool allCopies, uint8_t arrIdx) {
bool currentProt = protArray[arrIdx]; bool currentProt = protArray[arrIdx];
std::ostringstream oss; std::ostringstream oss;
bool performOp = false; bool performOp = false;
@ -925,22 +994,22 @@ int CoreController::handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy,
return 1; return 1;
} }
} }
Chip currentChip; xsc::Chip currentChip;
Copy currentCopy; xsc::Copy currentCopy;
oss << "writeprotect "; oss << "writeprotect ";
if (arrIdx == 0 or arrIdx == 1) { if (arrIdx == 0 or arrIdx == 1) {
oss << "0 "; oss << "0 ";
currentChip = Chip::CHIP_0; currentChip = xsc::Chip::CHIP_0;
} else { } else {
oss << "1 "; oss << "1 ";
currentChip = Chip::CHIP_1; currentChip = xsc::Chip::CHIP_1;
} }
if (arrIdx == 0 or arrIdx == 2) { if (arrIdx == 0 or arrIdx == 2) {
oss << "0 "; oss << "0 ";
currentCopy = Copy::COPY_0; currentCopy = xsc::Copy::COPY_0;
} else { } else {
oss << "1 "; oss << "1 ";
currentCopy = Copy::COPY_1; currentCopy = xsc::Copy::COPY_1;
} }
if (protect) { if (protect) {
oss << "1"; oss << "1";
@ -1035,29 +1104,29 @@ ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
uint8_t wordIdx = 0; uint8_t wordIdx = 0;
uint8_t arrayIdx = 0; uint8_t arrayIdx = 0;
istringstream iss(nextLine); istringstream iss(nextLine);
Chip currentChip = Chip::CHIP_0; xsc::Chip currentChip = xsc::Chip::CHIP_0;
Copy currentCopy = Copy::COPY_0; xsc::Copy currentCopy = xsc::Copy::COPY_0;
while (iss >> word) { while (iss >> word) {
if (wordIdx == 1) { if (wordIdx == 1) {
currentChip = static_cast<Chip>(stoi(word)); currentChip = static_cast<xsc::Chip>(stoi(word));
} }
if (wordIdx == 3) { if (wordIdx == 3) {
currentCopy = static_cast<Copy>(stoi(word)); currentCopy = static_cast<xsc::Copy>(stoi(word));
} }
if (wordIdx == 3) { if (wordIdx == 3) {
if (currentChip == Chip::CHIP_0) { if (currentChip == xsc::Chip::CHIP_0) {
if (currentCopy == Copy::COPY_0) { if (currentCopy == xsc::Copy::COPY_0) {
arrayIdx = 0; arrayIdx = 0;
} else if (currentCopy == Copy::COPY_1) { } else if (currentCopy == xsc::Copy::COPY_1) {
arrayIdx = 1; arrayIdx = 1;
} }
} }
else if (currentChip == Chip::CHIP_1) { else if (currentChip == xsc::Chip::CHIP_1) {
if (currentCopy == Copy::COPY_0) { if (currentCopy == xsc::Copy::COPY_0) {
arrayIdx = 2; arrayIdx = 2;
} else if (currentCopy == Copy::COPY_1) { } else if (currentCopy == xsc::Copy::COPY_1) {
arrayIdx = 3; arrayIdx = 3;
} }
} }
@ -1103,3 +1172,363 @@ void CoreController::performWatchdogControlOperation() {
} }
} }
} }
void CoreController::performRebootFileHandling(bool recreateFile) {
bool sdCardMounted = false;
if (not recreateFile and doPerformRebootFileHandling) {
sdCardMounted = sdcMan->isSdCardMounted(sdInfo.pref);
}
if ((doPerformRebootFileHandling and sdCardMounted) or recreateFile) {
using namespace std;
if (recreateFile) {
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "CoreController::performRebootFileHandling: Recreating reboot file" << std::endl;
#endif
}
std::string path = sdcMan->getCurrentMountPrefix(sdInfo.pref) + REBOOT_FILE;
if (not std::filesystem::exists(path) or recreateFile) {
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);
}
}
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;
}
switch (CURRENT_CHIP) {
case (xsc::CHIP_0): {
switch (CURRENT_COPY) {
case (xsc::COPY_0): {
rebootFile.img00Cnt++;
break;
}
case (xsc::COPY_1): {
rebootFile.img01Cnt++;
break;
}
default: {
break;
}
}
break;
}
case (xsc::CHIP_1): {
switch (CURRENT_COPY) {
case (xsc::COPY_0): {
rebootFile.img10Cnt++;
break;
}
case (xsc::COPY_1): {
rebootFile.img11Cnt++;
break;
}
default: {
break;
}
}
break;
}
default: {
break;
}
}
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;
#if OBSW_VERBOSE_LEVEL >= 1
sif::info << "Boot counter for image " << CURRENT_CHIP << " " << CURRENT_COPY
<< "too high. Rebooting to " << rebootFile.lastChip << " " << rebootFile.lastCopy
<< std::endl;
#endif
rewriteRebootFile(rebootFile);
xsc_boot_copy(static_cast<xsc_libnor_chip_t>(rebootFile.lastChip),
static_cast<xsc_libnor_copy_t>(rebootFile.lastCopy));
}
} else {
rewriteRebootFile(rebootFile);
}
doPerformRebootFileHandling = false;
}
}
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
sif::warning << "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
<< "\nbootflag: " << file.bootFlag << "\nlast: " << file.lastChip << " "
<< file.lastCopy << "\n";
}
}

View File

@ -2,6 +2,9 @@
#define BSP_Q7S_CORE_CORECONTROLLER_H_ #define BSP_Q7S_CORE_CORECONTROLLER_H_
#include <fsfw/globalfunctions/PeriodicOperationDivider.h> #include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <libxiphos.h>
#include <cstddef>
#include "bsp_q7s/memory/SdCardManager.h" #include "bsp_q7s/memory/SdCardManager.h"
#include "events/subsystemIdRanges.h" #include "events/subsystemIdRanges.h"
@ -10,24 +13,64 @@
class Timer; class Timer;
class SdCardManager; class SdCardManager;
namespace xsc {
enum Chip : uint8_t { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP };
enum Copy : uint8_t { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
} // namespace xsc
struct RebootFile {
static constexpr uint8_t DEFAULT_MAX_BOOT_CNT = 10;
bool enabled = false;
size_t maxCount = DEFAULT_MAX_BOOT_CNT;
uint8_t img00Cnt = 0;
uint8_t img01Cnt = 0;
uint8_t img10Cnt = 0;
uint8_t img11Cnt = 0;
uint8_t relevantBootCnt = 0;
bool bootFlag = false;
xsc::Chip lastChip = xsc::Chip::CHIP_0;
xsc::Copy lastCopy = xsc::Copy::COPY_0;
};
class CoreController : public ExtendedControllerBase { class CoreController : public ExtendedControllerBase {
public: public:
enum Chip : uint8_t { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; static xsc::Chip CURRENT_CHIP;
static xsc::Copy CURRENT_COPY;
enum Copy : uint8_t { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY };
static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh"; static constexpr char CHIP_PROT_SCRIPT[] = "/home/root/scripts/get-chip-prot-status.sh";
static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt"; static constexpr char CHIP_STATE_FILE[] = "/tmp/chip_prot_status.txt";
static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt"; static constexpr char CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
static constexpr char VERSION_FILE[] = "/conf/sd_status"; static constexpr char VERSION_FILE[] = "/conf/version.txt";
static constexpr char REBOOT_FILE[] = "/conf/reboot.txt";
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5;
static constexpr ActionId_t RESET_ALL_REBOOT_COUNTERS = 6;
static constexpr ActionId_t RESET_REBOOT_COUNTER_00 = 7;
static constexpr ActionId_t RESET_REBOOT_COUNTER_01 = 8;
static constexpr ActionId_t RESET_REBOOT_COUNTER_10 = 9;
static constexpr ActionId_t RESET_REBOOT_COUNTER_11 = 10;
static constexpr ActionId_t SET_MAX_REBOOT_CNT = 11;
static constexpr ActionId_t REBOOT_OBC = 32; static constexpr ActionId_t REBOOT_OBC = 32;
static constexpr ActionId_t MOUNT_OTHER_COPY = 33; static constexpr ActionId_t MOUNT_OTHER_COPY = 33;
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE;
static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM);
//! [EXPORT] : [COMMENT] Software reboot occured. Can also be a systemd reboot.
//! P1: Current Chip, P2: Current Copy
static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::MEDIUM);
//! [EXPORT] : [COMMENT] The reboot mechanism was triggered.
//! P1: First 16 bits: Last Chip, Last 16 bits: Last Copy,
//! P2: Each byte is the respective reboot count for the slots
static constexpr Event REBOOT_MECHANISM_TRIGGERED =
event::makeEvent(SUBSYSTEM_ID, 2, severity::MEDIUM);
//! Trying to find a way how to determine that the reboot came from ProASIC3 or PCDU..
static constexpr Event REBOOT_HW = event::makeEvent(SUBSYSTEM_ID, 3, severity::MEDIUM);
CoreController(object_id_t objectId); CoreController(object_id_t objectId);
virtual ~CoreController(); virtual ~CoreController();
@ -48,7 +91,7 @@ class CoreController : public ExtendedControllerBase {
*/ */
static ReturnValue_t generateChipStateFile(); static ReturnValue_t generateChipStateFile();
static ReturnValue_t incrementAllocationFailureCount(); static ReturnValue_t incrementAllocationFailureCount();
static void getCurrentBootCopy(Chip& chip, Copy& copy); static void getCurrentBootCopy(xsc::Chip& chip, xsc::Copy& copy);
ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true); ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true);
@ -63,15 +106,12 @@ class CoreController : public ExtendedControllerBase {
* @param updateProtFile Specify whether the protection info file is updated * @param updateProtFile Specify whether the protection info file is updated
* @return * @return
*/ */
ReturnValue_t setBootCopyProtection(Chip targetChip, Copy targetCopy, bool protect, ReturnValue_t setBootCopyProtection(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool updateProtFile = true); bool& protOperationPerformed, bool updateProtFile = true);
bool sdInitFinished() const; bool sdInitFinished() const;
private: private:
static Chip CURRENT_CHIP;
static Copy CURRENT_COPY;
// Designated value for rechecking FIFO open // Designated value for rechecking FIFO open
static constexpr int RETRY_FIFO_OPEN = -2; static constexpr int RETRY_FIFO_OPEN = -2;
int watchdogFifoFd = 0; int watchdogFifoFd = 0;
@ -122,6 +162,8 @@ class CoreController : public ExtendedControllerBase {
sd::SdState commandedState = sd::SdState::OFF; sd::SdState commandedState = sd::SdState::OFF;
}; };
SdInfo sdInfo; SdInfo sdInfo;
RebootFile rebootFile = {};
bool doPerformRebootFileHandling = true;
/** /**
* Index 0: Chip 0 Copy 0 * Index 0: Chip 0 Copy 0
@ -152,6 +194,7 @@ class CoreController : public ExtendedControllerBase {
void determinePreferredSdCard(); void determinePreferredSdCard();
void executeNextExternalSdCommand(); void executeNextExternalSdCommand();
void checkExternalSdCommandStatus(); void checkExternalSdCommandStatus();
void performRebootFileHandling(bool recreateFile);
ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t actionListDirectoryIntoFile(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size); const uint8_t* data, size_t size);
@ -160,9 +203,14 @@ class CoreController : public ExtendedControllerBase {
void performWatchdogControlOperation(); void performWatchdogControlOperation();
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine); ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
int handleBootCopyProtAtIndex(Chip targetChip, Copy targetCopy, bool protect, int handleBootCopyProtAtIndex(xsc::Chip targetChip, xsc::Copy targetCopy, bool protect,
bool& protOperationPerformed, bool selfChip, bool selfCopy, bool& protOperationPerformed, bool selfChip, bool selfCopy,
bool allChips, bool allCopies, uint8_t arrIdx); bool allChips, bool allCopies, uint8_t arrIdx);
void determineAndExecuteReboot(RebootFile& rf, bool& needsReboot, xsc::Chip& tgtChip,
xsc::Copy& tgtCopy);
void resetRebootCount(xsc::Chip tgtChip, xsc::Copy tgtCopy);
bool parseRebootFile(std::string path, RebootFile& file);
void rewriteRebootFile(RebootFile file);
}; };
#endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */ #endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */

View File

@ -7,6 +7,7 @@
#include <fstream> #include <fstream>
#include <memory> #include <memory>
#include "common/config/commonObjects.h"
#include "fsfw/ipc/MutexFactory.h" #include "fsfw/ipc/MutexFactory.h"
#include "fsfw/serviceinterface/ServiceInterface.h" #include "fsfw/serviceinterface/ServiceInterface.h"
#include "linux/utility/utility.h" #include "linux/utility/utility.h"
@ -14,7 +15,7 @@
SdCardManager* SdCardManager::factoryInstance = nullptr; SdCardManager* SdCardManager::factoryInstance = nullptr;
SdCardManager::SdCardManager() : cmdExecutor(256) {} SdCardManager::SdCardManager() : SystemObject(objects::SDC_MANAGER), cmdExecutor(256) {}
SdCardManager::~SdCardManager() {} SdCardManager::~SdCardManager() {}

View File

@ -1,6 +1,7 @@
#ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ #ifndef BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
#define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_ #define BSP_Q7S_MEMORY_SDCARDACCESSMANAGER_H_
#include <fsfw/objectmanager/SystemObject.h>
#include <poll.h> #include <poll.h>
#include <array> #include <array>
@ -23,7 +24,7 @@ class MutexIF;
* @brief Manages handling of SD cards like switching them on or off or getting the current * @brief Manages handling of SD cards like switching them on or off or getting the current
* state * state
*/ */
class SdCardManager: public SdCardMountedIF { class SdCardManager: public SystemObject, public SdCardMountedIF {
friend class SdCardAccess; friend class SdCardAccess;
public: public:
@ -55,6 +56,7 @@ class SdCardManager: public SdCardMountedIF {
static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FILE_SYSTEM;
static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW); static constexpr Event SANITIZATION_FAILED = event::makeEvent(SUBSYSTEM_ID, 0, severity::LOW);
static constexpr Event MOUNTED_SD_CARD = event::makeEvent(SUBSYSTEM_ID, 1, severity::INFO);
// C++17 does not support constexpr std::string yet // C++17 does not support constexpr std::string yet
static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1"; static constexpr char SD_0_DEV_NAME[] = "/dev/mmcblk0p1";

View File

@ -81,8 +81,19 @@ set(CMAKE_PREFIX_PATH
# "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}" # "${SYSROOT_PATH}/usr/lib/${CROSS_COMPILE}"
) )
set(C_FLAGS
-mcpu=cortex-a9
-mfpu=neon-vfpv3
-mfloat-abi=hard
${COMMON_FLAGS}
-lgpiod
-lxiphos
)
string (REPLACE ";" " " C_FLAGS "${C_FLAGS}")
set(CMAKE_C_FLAGS set(CMAKE_C_FLAGS
"-mcpu=cortex-a9 -mfpu=neon-vfpv3 -mfloat-abi=hard ${COMMON_FLAGS} -lgpiod" ${C_FLAGS}
CACHE STRING "C flags for Q7S" CACHE STRING "C flags for Q7S"
) )
set(CMAKE_CXX_FLAGS set(CMAKE_CXX_FLAGS

1
unittest/rebootLogic/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.0.0)
project(reboot-logic VERSION 0.1.0)
include(CTest)
enable_testing()
add_executable(reboot-logic main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)

View File

@ -0,0 +1,5 @@
#include <iostream>
int main(int, char**) {
std::cout << "Hello, world!\n";
}