#ifndef MISSION_SYSDEFS_H_ #define MISSION_SYSDEFS_H_ #include #include #include #include #include #include extern std::atomic_uint16_t I2C_FATAL_ERRORS; namespace satsystem { enum Mode : Mode_t { BOOT = 5, // DO NOT CHANGE THE ORDER starting from here, breaks ACS mode checks. SAFE = 10, PTG_IDLE = 11, PTG_NADIR = 12, PTG_TARGET = 13, PTG_TARGET_GS = 14, PTG_INERTIAL = 15, }; } namespace xsc { enum Chip : int { CHIP_0, CHIP_1, NO_CHIP, SELF_CHIP, ALL_CHIP }; enum Copy : int { COPY_0, COPY_1, NO_COPY, SELF_COPY, ALL_COPY }; } // namespace xsc namespace core { extern std::atomic_bool SAVE_PUS_SEQUENCE_COUNT; extern std::atomic_bool SAVE_CFDP_SEQUENCE_COUNT; // TODO: Support for status? Or maybe some command to quickly get information whether a unit // is running. enum SystemctlCmd : uint8_t { START = 0, STOP = 1, RESTART = 2, NUM_CMDS = 3 }; static constexpr char CONF_FOLDER[] = "conf"; static constexpr char VERSION_FILE_NAME[] = "version.txt"; static constexpr char LEGACY_REBOOT_WATCHDOG_FILE_NAME[] = "reboot.txt"; static constexpr char REBOOT_WATCHDOG_FILE_NAME[] = "reboot_watchdog.txt"; static constexpr char REBOOT_COUNTER_FILE_NAME[] = "reboot_counters.txt"; static constexpr char TIME_FILE_NAME[] = "time_backup.txt"; static constexpr uint32_t SYS_ROM_BASE_ADDR = 0x80000000; static constexpr ActionId_t ANNOUNCE_VERSION = 1; static constexpr ActionId_t ANNOUNCE_CURRENT_IMAGE = 2; static constexpr ActionId_t ANNOUNCE_BOOT_COUNTS = 3; static constexpr ActionId_t SWITCH_REBOOT_FILE_HANDLING = 5; static constexpr ActionId_t RESET_REBOOT_COUNTERS = 6; static constexpr ActionId_t SWITCH_IMG_LOCK = 7; static constexpr ActionId_t SET_MAX_REBOOT_CNT = 8; static constexpr ActionId_t READ_REBOOT_MECHANISM_INFO = 9; static constexpr ActionId_t OBSW_UPDATE_FROM_SD_0 = 10; static constexpr ActionId_t OBSW_UPDATE_FROM_SD_1 = 11; static constexpr ActionId_t OBSW_UPDATE_FROM_TMP = 12; static constexpr ActionId_t SWITCH_TO_SD_0 = 16; static constexpr ActionId_t SWITCH_TO_SD_1 = 17; static constexpr ActionId_t SWITCH_TO_BOTH_SD_CARDS = 18; //! Reboot using the xsc_boot_copy command static constexpr ActionId_t XSC_REBOOT_OBC = 32; static constexpr ActionId_t MOUNT_OTHER_COPY = 33; //! Reboot using the reboot command static constexpr ActionId_t REBOOT_OBC = 34; static constexpr ActionId_t EXECUTE_SHELL_CMD_BLOCKING = 40; static constexpr ActionId_t EXECUTE_SHELL_CMD_NON_BLOCKING = 41; static constexpr ActionId_t SYSTEMCTL_CMD_EXECUTOR = 42; static constexpr ActionId_t LIST_DIRECTORY_INTO_FILE = 50; static constexpr ActionId_t LIST_DIRECTORY_DUMP_DIRECTLY = 51; static constexpr ActionId_t CP_HELPER = 52; static constexpr ActionId_t MV_HELPER = 53; static constexpr ActionId_t RM_HELPER = 54; static constexpr ActionId_t MKDIR_HELPER = 55; static constexpr uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CORE; static constexpr Event ALLOC_FAILURE = event::makeEvent(SUBSYSTEM_ID, 0, severity::MEDIUM); //! [EXPORT] : [COMMENT] Software reboot occurred. Can also be a systemd reboot. //! P1: Current Chip, P2: Current Copy static constexpr Event REBOOT_SW = event::makeEvent(SUBSYSTEM_ID, 1, severity::LOW); //! [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); //! [EXPORT] : [COMMENT] No SD card was active. Core controller will attempt to re-initialize //! a SD card. static constexpr Event NO_SD_CARD_ACTIVE = event::makeEvent(SUBSYSTEM_ID, 4, severity::HIGH); //! [EXPORT] : [COMMENT] //! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash //! P2: First four letters of Git SHA is the last byte of P1 is set. static constexpr Event VERSION_INFO = event::makeEvent(SUBSYSTEM_ID, 5, severity::INFO); //! [EXPORT] : [COMMENT] P1: Current Chip, P2: Current Copy static constexpr Event CURRENT_IMAGE_INFO = event::makeEvent(SUBSYSTEM_ID, 6, severity::INFO); //! [EXPORT] : [COMMENT] Total reboot counter, which is the sum of the boot count of all //! individual images. static constexpr Event REBOOT_COUNTER = event::makeEvent(SUBSYSTEM_ID, 7, severity::INFO); //! [EXPORT] : [COMMENT] Get the boot count of the individual images. //! P1: First 16 bits boot count of image 0 0, last 16 bits boot count of image 0 1. //! P2: First 16 bits boot count of image 1 0, last 16 bits boot count of image 1 1. static constexpr Event INDIVIDUAL_BOOT_COUNTS = event::makeEvent(SUBSYSTEM_ID, 8, severity::INFO); //! [EXPORT] : [COMMENT] I2C is unavailable. Trying recovery of I2C bus by power cycling all I2C //! devices. static constexpr Event TRYING_I2C_RECOVERY = event::makeEvent(SUBSYSTEM_ID, 10, severity::HIGH); //! [EXPORT] : [COMMENT] I2C is unavailable. Recovery did not work, performing full reboot. static constexpr Event I2C_REBOOT = event::makeEvent(SUBSYSTEM_ID, 11, severity::HIGH); //! [EXPORT] : [COMMENT] PDEC recovery through reset was not possible, performing full reboot. static constexpr Event PDEC_REBOOT = event::makeEvent(SUBSYSTEM_ID, 12, severity::HIGH); //! [EXPORT] : [COMMENT] Version information of the firmware (not OBSW). //! P1: Byte 0: Major, Byte 1: Minor, Byte 2: Patch, Byte 3: Has Git Hash //! P2: First four letters of Git SHA is the last byte of P1 is set. static constexpr Event FIRMWARE_INFO = event::makeEvent(SUBSYSTEM_ID, 13, severity::INFO); //! [EXPORT] : [COMMENT] Active SD card info. 0: OFF, 1: ON, 2: MOUNTED. //! P1: SD Card 0m P2: SD Card 2. static constexpr Event ACTIVE_SD_INFO = event::makeEvent(SUBSYSTEM_ID, 14, severity::INFO); class ListDirectoryCmdBase { public: // TODO: Packet definition for clean deserialization // 3 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with // null termination static constexpr size_t MIN_DATA_LEN = 8; ListDirectoryCmdBase(const uint8_t* data, size_t maxSize) : data(data), maxSize(maxSize) {} virtual ~ListDirectoryCmdBase() = default; virtual ReturnValue_t parse() { if (maxSize < MIN_DATA_LEN) { return SerializeIF::STREAM_TOO_SHORT; } aFlag = data[0]; rFlag = data[1]; compressOption = data[2]; repoNameLen = strnlen(reinterpret_cast(data + 3), maxSize - 3); // Last byte MUST be null terminated! if (repoNameLen >= maxSize - 3) { return HasActionsIF::INVALID_PARAMETERS; } repoName = reinterpret_cast(data + 3); return returnvalue::OK; } bool aFlagSet() const { return this->aFlag; } bool rFlagSet() const { return this->rFlag; } bool compressionOptionSet() const { return this->compressOption; } const char* getRepoName(size_t& repoNameLen) const { repoNameLen = this->repoNameLen; return this->repoName; } size_t getBaseSize() { // Include NULL termination if (repoName != nullptr) { return 3 + repoNameLen + 1; } return 0; } protected: const uint8_t* data; size_t maxSize; bool aFlag = false; bool rFlag = false; bool compressOption = false; const char* repoName = nullptr; size_t repoNameLen = 0; }; class ListDirectoryIntoFile : public ListDirectoryCmdBase { public: // TODO: Packet definition for clean deserialization // 3 bytes for a and R flag, at least 5 bytes for minimum valid path /tmp with // null termination, at least 7 bytes for minimum target file name /tmp/a with // null termination. static constexpr size_t MIN_DATA_LEN = 15; ListDirectoryIntoFile(const uint8_t* data, size_t maxSize) : ListDirectoryCmdBase(data, maxSize) {} ReturnValue_t parse() override { if (maxSize < MIN_DATA_LEN) { return SerializeIF::STREAM_TOO_SHORT; } ReturnValue_t result = ListDirectoryCmdBase::parse(); if (result != returnvalue::OK) { return result; } targetNameLen = strnlen(reinterpret_cast(data + getBaseSize()), maxSize - getBaseSize()); if (targetNameLen >= maxSize - getBaseSize()) { // Again: String MUST be null terminated. return HasActionsIF::INVALID_PARAMETERS; } targetName = reinterpret_cast(data + getBaseSize()); return result; } const char* getTargetName(size_t& targetNameLen) const { targetNameLen = this->targetNameLen; return this->targetName; } private: const char* targetName = nullptr; size_t targetNameLen = 0; }; struct SourceTargetPair { const char* sourceName = nullptr; size_t sourceNameSize = 0; const char* targetName = nullptr; size_t targetNameSize = 0; }; static ReturnValue_t parseDestTargetString(const uint8_t* data, size_t maxLen, SourceTargetPair& destTgt) { if (maxLen < 4) { return SerializeIF::STREAM_TOO_SHORT; } destTgt.sourceNameSize = strnlen(reinterpret_cast(data), maxLen); if (destTgt.sourceNameSize >= maxLen) { return HasActionsIF::INVALID_PARAMETERS; } destTgt.sourceName = reinterpret_cast(data); size_t remainingLen = maxLen - destTgt.sourceNameSize - 1; if (remainingLen == 0) { return HasActionsIF::INVALID_PARAMETERS; } destTgt.targetNameSize = strnlen(reinterpret_cast(data + destTgt.sourceNameSize + 1), remainingLen); if (destTgt.targetNameSize >= remainingLen) { return HasActionsIF::INVALID_PARAMETERS; } destTgt.targetName = reinterpret_cast(data + destTgt.sourceNameSize + 1); return returnvalue::OK; } class CpHelperParser { public: CpHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {} ReturnValue_t parse() { if (maxLen < 2) { return SerializeIF::STREAM_TOO_SHORT; } recursiveOpt = data[0]; forceOpt = data[1]; return parseDestTargetString(data + 2, maxLen - 2, destTgt); } const SourceTargetPair& destTgtPair() const { return destTgt; } bool isRecursiveOptSet() const { return recursiveOpt; } bool isForceOptSet() const { return forceOpt; } private: const uint8_t* data; size_t maxLen; bool recursiveOpt = false; bool forceOpt = false; SourceTargetPair destTgt; }; class MvHelperParser { public: MvHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {} ReturnValue_t parse() { return parseDestTargetString(data, maxLen, destTgt); } const SourceTargetPair& destTgtPair() const { return destTgt; } private: const uint8_t* data; size_t maxLen; SourceTargetPair destTgt; }; class RmHelperParser { public: RmHelperParser(const uint8_t* data, size_t maxLen) : data(data), maxLen(maxLen) {} ReturnValue_t parse() { if (maxLen < 2) { return SerializeIF::STREAM_TOO_SHORT; } recursiveOpt = data[0]; forceOpt = data[1]; removeTargetSize = strnlen(reinterpret_cast(data + 2), maxLen - 2); // Must be null-terminated if (removeTargetSize >= maxLen - 2) { return HasActionsIF::INVALID_PARAMETERS; } removeTarget = reinterpret_cast(data + 2); return returnvalue::OK; } bool isRecursiveOptSet() const { return recursiveOpt; } bool isForceOptSet() const { return forceOpt; } const char* getRemoveTarget(size_t& removeTargetSize) { removeTargetSize = this->removeTargetSize; return removeTarget; } private: const uint8_t* data; size_t maxLen; bool recursiveOpt = false; bool forceOpt = false; const char* removeTarget = nullptr; size_t removeTargetSize = 0; }; } // namespace core #endif /* MISSION_SYSDEFS_H_ */