Writeprotection handler in CoreController #87

Merged
meierj merged 13 commits from mueller/writeprotect-handler into develop 2021-08-20 11:08:25 +02:00
2 changed files with 300 additions and 38 deletions
Showing only changes of commit 7fc3285272 - Show all commits

View File

@ -21,12 +21,11 @@
#include <filesystem> #include <filesystem>
CoreController::Chip CoreController::currentChip = Chip::NO_CHIP; CoreController::Chip CoreController::CURRENT_CHIP = Chip::NO_CHIP;
CoreController::Copy CoreController::currentCopy = Copy::NO_COPY; CoreController::Copy CoreController::CURRENT_COPY = Copy::NO_COPY;
CoreController::CoreController(object_id_t objectId): CoreController::CoreController(object_id_t objectId):
ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), ExtendedControllerBase(objectId, objects::NO_OBJECT, 5), opDivider(5) {
opDivider(5) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
try { try {
result = initWatchdogFifo(); result = initWatchdogFifo();
@ -552,6 +551,12 @@ ReturnValue_t CoreController::initializeAfterTaskCreation() {
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::initialize: Version initialization failed" << std::endl; sif::warning << "CoreController::initialize: Version initialization failed" << std::endl;
} }
// Add script folder to path
char* currentEnvPath = getenv("PATH");
sif::info << currentEnvPath << std::endl;
std::string updatedEnvPath = std::string(currentEnvPath) + ":/home/root/scripts";
setenv("PATH", updatedEnvPath.c_str(), true);
updateProtInfo();
initPrint(); initPrint();
return result; return result;
} }
@ -614,7 +619,7 @@ ReturnValue_t CoreController::initVersionFile() {
std::to_string(FSFW_SUBVERSION) + "." + std::to_string(FSFW_REVISION); std::to_string(FSFW_SUBVERSION) + "." + std::to_string(FSFW_REVISION);
std::string systemString = "System: " + unameLine; std::string systemString = "System: " + unameLine;
std::string mountPrefix = SdCardManager::instance()->getCurrentMountPrefix(); std::string mountPrefix = SdCardManager::instance()->getCurrentMountPrefix();
std::string versionFilePath = mountPrefix + "/conf/version.txt"; std::string versionFilePath = mountPrefix + VERSION_FILE;
std::fstream versionFile; std::fstream versionFile;
if(not std::filesystem::exists(versionFilePath)) { if(not std::filesystem::exists(versionFilePath)) {
@ -731,32 +736,31 @@ ReturnValue_t CoreController::actionListDirectoryIntoFile(ActionId_t actionId,
} }
ReturnValue_t CoreController::initBootCopy() { ReturnValue_t CoreController::initBootCopy() {
std::string fileName = "/tmp/curr_copy.txt"; if(not std::filesystem::exists(CURR_COPY_FILE)) {
if(not std::filesystem::exists(fileName)) {
// Thils file is created by the systemd service eive-early-config so this should // Thils 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 > " + fileName; 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());
if(result != 0) { if(result != 0) {
utility::handleSystemError(result, "CoreController::initBootCopy"); utility::handleSystemError(result, "CoreController::initBootCopy");
} }
} }
std::ifstream file(fileName); std::ifstream file(CURR_COPY_FILE);
std::string line; std::string line;
std::getline(file, line); std::getline(file, line);
std::istringstream iss(line); std::istringstream iss(line);
int value = 0; int value = 0;
iss >> value; iss >> value;
currentChip = static_cast<Chip>(value); CURRENT_CHIP = static_cast<Chip>(value);
iss >> value; iss >> value;
currentCopy = static_cast<Copy>(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(Chip &chip, Copy &copy) {
// Not really thread-safe but it does not need to be // Not really thread-safe but it does not need to be
chip = currentChip; chip = CURRENT_CHIP;
copy = currentCopy; copy = CURRENT_COPY;
} }
ReturnValue_t CoreController::initWatchdogFifo() { ReturnValue_t CoreController::initWatchdogFifo() {
@ -795,6 +799,7 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
return HasActionsIF::INVALID_PARAMETERS; return HasActionsIF::INVALID_PARAMETERS;
} }
bool rebootSameBootCopy = data[0]; bool rebootSameBootCopy = data[0];
bool protOpPerformed;
if(rebootSameBootCopy) { if(rebootSameBootCopy) {
#if OBSW_VERBOSE_LEVEL >= 1 #if OBSW_VERBOSE_LEVEL >= 1
sif::info << "CoreController::actionPerformReboot: Rebooting on current image" << std::endl; sif::info << "CoreController::actionPerformReboot: Rebooting on current image" << std::endl;
@ -802,6 +807,12 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
// Attempt graceful shutdown by unmounting and switching off SD cards // Attempt graceful shutdown by unmounting and switching off SD cards
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
ReturnValue_t retval = checkAndSetBootCopyProtection(Chip::SELF_CHIP, Copy::SELF_COPY,
true, protOpPerformed, false);
if(retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) {
sif::info << "Running slot was writeprotected before reboot" << std::endl;
}
int result = std::system("xsc_boot_copy -r"); int result = std::system("xsc_boot_copy -r");
if(result != 0) { if(result != 0) {
utility::handleSystemError(result, "CoreController::executeAction"); utility::handleSystemError(result, "CoreController::executeAction");
@ -816,6 +827,16 @@ ReturnValue_t CoreController::actionPerformReboot(const uint8_t *data, size_t si
sif::info << "CoreController::actionPerformReboot: Rebooting on " << sif::info << "CoreController::actionPerformReboot: Rebooting on " <<
static_cast<int>(data[1]) << " " << static_cast<int>(data[2]) << std::endl; static_cast<int>(data[1]) << " " << static_cast<int>(data[2]) << std::endl;
#endif #endif
// Check that the target chip and copy is writeprotected first
generateChipStateFile();
// If any boot copies are unprotected, protect them here
ReturnValue_t retval = checkAndSetBootCopyProtection(static_cast<Chip>(data[1]),
static_cast<Copy>(data[2]), true, protOpPerformed, false);
if(retval == HasReturnvaluesIF::RETURN_OK and protOpPerformed) {
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 // The second byte in data is the target chip, the third byte is the target copy
std::string cmdString = "xsc_boot_copy " + std::to_string(data[1]) + " " + std::string cmdString = "xsc_boot_copy " + std::to_string(data[1]) + " " +
std::to_string(data[2]); std::to_string(data[2]);
@ -873,6 +894,209 @@ bool CoreController::sdInitFinished() const {
return sdInfo.initFinished; return sdInfo.initFinished;
} }
ReturnValue_t CoreController::generateChipStateFile() {
int result = std::system(CHIP_PROT_SCRIPT);
if(result != 0) {
utility::handleSystemError(result, "CoreController::generateChipStateFile");
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CoreController::checkAndSetBootCopyProtection(Chip targetChip, Copy targetCopy,
bool protect, bool& protOperationPerformed, bool updateProtFile) {
bool allChips = false;
bool allCopies = false;
bool selfChip = false;
bool selfCopy = false;
switch(targetChip) {
case(Chip::ALL_CHIP): {
allChips = true;
break;
}
case(Chip::NO_CHIP): {
return HasReturnvaluesIF::RETURN_OK;
}
case(Chip::SELF_CHIP): {
selfChip = true;
break;
}
default: {
break;
}
}
switch(targetCopy) {
case(Copy::ALL_COPY): {
allCopies = true;
break;
}
case(Copy::NO_COPY): {
return HasReturnvaluesIF::RETURN_OK;
}
case(Copy::SELF_COPY): {
selfCopy = true;
break;
}
default: {
break;
}
}
for(uint8_t arrIdx = 0; arrIdx < 4; arrIdx++) {
bool currentProt = protArray[arrIdx];
std::ostringstream oss;
if(protect == currentProt) {
continue;
}
Chip currentChip;
Copy currentCopy;
oss << "writeprotect ";
if(arrIdx == 0 or arrIdx == 1) {
oss << "0 ";
currentChip = Chip::CHIP_0;
}
else {
oss << "1 ";
currentChip = Chip::CHIP_1;
}
if(arrIdx == 0 or arrIdx == 2) {
oss << "0 ";
currentCopy = Copy::COPY_0;
}
else {
oss << "1 ";
currentCopy = Copy::COPY_1;
}
if(protect) {
oss << "1";
}
else {
oss << "0";
}
int result = 0;
if(allChips and allCopies) {
protOperationPerformed = true;
result = std::system(oss.str().c_str());
}
else if(allChips) {
if((selfCopy and CURRENT_COPY == targetCopy) or
(currentCopy == targetCopy)) {
protOperationPerformed = true;
result = std::system(oss.str().c_str());
}
}
else if(allCopies) {
if((selfChip and CURRENT_COPY == targetCopy) or
(currentChip == targetChip)) {
protOperationPerformed = true;
result = std::system(oss.str().c_str());
}
}
else if(selfChip and (CURRENT_CHIP == targetChip)) {
protOperationPerformed = true;
result = std::system(oss.str().c_str());
}
else if(selfCopy and (CURRENT_COPY == targetCopy)) {
protOperationPerformed = true;
result = std::system(oss.str().c_str());
}
if(result != 0) {
utility::handleSystemError(result, "CoreController::checkAndSetBootCopyProtection");
}
}
if(protOperationPerformed and updateProtFile) {
updateProtInfo();
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CoreController::updateProtInfo(bool regenerateChipStateFile) {
using namespace std;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(regenerateChipStateFile) {
result = generateChipStateFile();
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::updateProtInfo: Generating chip state file failed" <<
std::endl;
return result;
}
}
if(not filesystem::exists(CHIP_STATE_FILE)) {
return HasReturnvaluesIF::RETURN_FAILED;
}
ifstream chipStateFile(CHIP_STATE_FILE);
if(not chipStateFile.good()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
string nextLine;
uint8_t lineCounter = 0;
string word;
while(getline(chipStateFile, nextLine)) {
ReturnValue_t result = handleProtInfoUpdateLine(nextLine);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::warning << "CoreController::updateProtInfo: Protection info update failed!" <<
std::endl;
return result;
}
++lineCounter;
if(lineCounter > 4) {
sif::warning << "CoreController::checkAndProtectBootCopy: "
"Line counter larger than 4" << std::endl;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t CoreController::handleProtInfoUpdateLine(std::string nextLine) {
using namespace std;
string word;
uint8_t wordIdx = 0;
istringstream iss(nextLine);
Chip currentChip;
Copy currentCopy;
while(iss >> word) {
if(wordIdx == 1) {
currentChip = static_cast<Chip>(stoi(word));
}
if(wordIdx == 3) {
currentCopy = static_cast<Copy>(stoi(word));
}
uint8_t arrayIdx = 0;
if(currentChip == Chip::CHIP_0) {
if(currentCopy == Copy::COPY_1) {
arrayIdx = 1;
}
else if(currentCopy != Copy::COPY_0) {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
else if(currentChip == Chip::CHIP_1) {
if(currentCopy == Copy::COPY_0) {
arrayIdx = 2;
}
else if(currentCopy == Copy::COPY_1) {
arrayIdx = 3;
}
else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if(wordIdx == 5) {
if(word == "unlocked.") {
protArray[arrayIdx] = false;
}
else {
protArray[arrayIdx] = true;
}
}
}
return HasReturnvaluesIF::RETURN_OK;
}
void CoreController::performWatchdogControlOperation() { void CoreController::performWatchdogControlOperation() {
// Only perform each fifth iteration // Only perform each fifth iteration
if(watchdogFifoFd != 0 and opDivider.checkAndIncrement()) { if(watchdogFifoFd != 0 and opDivider.checkAndIncrement()) {

View File

@ -16,17 +16,28 @@ public:
enum Chip: uint8_t { enum Chip: uint8_t {
CHIP_0, CHIP_0,
CHIP_1, CHIP_1,
NO_CHIP NO_CHIP,
SELF_CHIP,
ALL_CHIP
}; };
enum Copy: uint8_t { enum Copy: uint8_t {
COPY_0, COPY_0,
COPY_1, COPY_1,
NO_COPY NO_COPY,
SELF_COPY,
ALL_COPY
}; };
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 CURR_COPY_FILE[] = "/tmp/curr_copy.txt";
static constexpr char VERSION_FILE[] = "/conf/sd_status";
static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0; static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 0;
static constexpr ActionId_t REBOOT_OBC = 32; static constexpr ActionId_t REBOOT_OBC = 32;
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;
@ -46,19 +57,39 @@ public:
ReturnValue_t handleCommandMessage(CommandMessage *message) override; ReturnValue_t handleCommandMessage(CommandMessage *message) override;
void performControlOperation() override; void performControlOperation() override;
/**
* Generate a file containing the chip lock/unlock states inside /tmp/chip_status.txt
* @return
*/
static ReturnValue_t generateChipStateFile();
static ReturnValue_t incrementAllocationFailureCount(); static ReturnValue_t incrementAllocationFailureCount();
static void getCurrentBootCopy(Chip& chip, Copy& copy); static void getCurrentBootCopy(Chip& chip, Copy& copy);
ReturnValue_t updateProtInfo(bool regenerateChipStateFile = true);
/**
* Checks whether the target chip and copy are writeprotected and protect them if they are
* not
* @param targetChip
* @param targetCopy
* @param protect
* @param protOperationPerformed [out] Can be used to determine whether any operation
* was performed
* @param updateProtFile Specify whether the protection info file is updated
* @return
*/
ReturnValue_t checkAndSetBootCopyProtection(Chip targetChip, Copy targetCopy,
bool protect, bool& protOperationPerformed, bool updateProtFile = true);
bool sdInitFinished() const; bool sdInitFinished() const;
private: private:
static Chip currentChip; static Chip CURRENT_CHIP;
static Copy currentCopy; static Copy CURRENT_COPY;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, // Designated value for rechecking FIFO open
LocalDataPoolManager& poolManager) override; static constexpr int RETRY_FIFO_OPEN = -2;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override; int watchdogFifoFd = 0;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
// States for SD state machine, which is used in non-blocking mode // States for SD state machine, which is used in non-blocking mode
enum class SdStates { enum class SdStates {
@ -85,9 +116,6 @@ private:
SdCardManager* sdcMan = nullptr; SdCardManager* sdcMan = nullptr;
ReturnValue_t initSdCardBlocking();
ReturnValue_t sdStateMachine();
struct SdInfo { struct SdInfo {
sd::SdCard pref = sd::SdCard::NONE; sd::SdCard pref = sd::SdCard::NONE;
sd::SdState prefState = sd::SdState::OFF; sd::SdState prefState = sd::SdState::OFF;
@ -108,9 +136,29 @@ private:
sd::SdCard commandedCard = sd::SdCard::NONE; sd::SdCard commandedCard = sd::SdCard::NONE;
sd::SdState commandedState = sd::SdState::OFF; sd::SdState commandedState = sd::SdState::OFF;
}; };
SdInfo sdInfo; SdInfo sdInfo;
/**
* Index 0: Chip 0 Copy 0
* Index 1: Chip 0 Copy 1
* Index 2: Chip 1 Copy 0
* Index 3: Chip 1 Copy 1
*/
std::array<bool, 4> protArray;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
ReturnValue_t initSdCardBlocking();
void initPrint();
ReturnValue_t sdStateMachine();
void updateSdInfoOther(); void updateSdInfoOther();
ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar, ReturnValue_t sdCardSetup(sd::SdCard sdCard, sd::SdState targetState, std::string sdChar,
bool printOutput = true); bool printOutput = true);
@ -120,24 +168,14 @@ private:
void executeNextExternalSdCommand(); void executeNextExternalSdCommand();
void checkExternalSdCommandStatus(); void checkExternalSdCommandStatus();
ReturnValue_t initVersionFile();
ReturnValue_t initBootCopy();
ReturnValue_t initWatchdogFifo();
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);
ReturnValue_t actionPerformReboot(const uint8_t *data, size_t size); ReturnValue_t actionPerformReboot(const uint8_t *data, size_t size);
void initPrint();
// Designated value for rechecking FIFO open
static constexpr int RETRY_FIFO_OPEN = -2;
int watchdogFifoFd = 0;
PeriodicOperationDivider opDivider; PeriodicOperationDivider opDivider;
void performWatchdogControlOperation(); void performWatchdogControlOperation();
ReturnValue_t handleProtInfoUpdateLine(std::string nextLine);
}; };
#endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */ #endif /* BSP_Q7S_CORE_CORECONTROLLER_H_ */