1 #include "config.h" 2 3 #include "serialize.hpp" 4 5 #include <cereal/archives/json.hpp> 6 #include <phosphor-logging/lg2.hpp> 7 #include <sdbusplus/server.hpp> 8 9 #include <filesystem> 10 #include <fstream> 11 12 namespace phosphor 13 { 14 namespace software 15 { 16 namespace updater 17 { 18 19 PHOSPHOR_LOG2_USING; 20 namespace fs = std::filesystem; 21 22 const std::string priorityName = "priority"; 23 const std::string purposeName = "purpose"; 24 25 void storePriority(const std::string& versionId, uint8_t priority) 26 { 27 auto path = fs::path(PERSIST_DIR) / versionId; 28 if (!fs::is_directory(path)) 29 { 30 if (fs::exists(path)) 31 { 32 // Delete if it's a non-directory file 33 warning("Removing non-directory file: {PATH}", "PATH", path); 34 fs::remove_all(path); 35 } 36 fs::create_directories(path); 37 } 38 path = path / priorityName; 39 40 std::ofstream os(path.c_str()); 41 cereal::JSONOutputArchive oarchive(os); 42 oarchive(cereal::make_nvp(priorityName, priority)); 43 } 44 45 void storePurpose(const std::string& versionId, VersionPurpose purpose) 46 { 47 auto path = fs::path(PERSIST_DIR) / versionId; 48 if (!fs::is_directory(path)) 49 { 50 if (fs::exists(path)) 51 { 52 // Delete if it's a non-directory file 53 warning("Removing non-directory file: {PATH}", "PATH", path); 54 fs::remove_all(path); 55 } 56 fs::create_directories(path); 57 } 58 path = path / purposeName; 59 60 std::ofstream os(path.c_str()); 61 cereal::JSONOutputArchive oarchive(os); 62 oarchive(cereal::make_nvp(purposeName, purpose)); 63 } 64 65 bool restorePriority(const std::string& versionId, uint8_t& priority) 66 { 67 auto path = fs::path(PERSIST_DIR) / versionId / priorityName; 68 if (fs::exists(path)) 69 { 70 std::ifstream is(path.c_str(), std::ios::in); 71 try 72 { 73 cereal::JSONInputArchive iarchive(is); 74 iarchive(cereal::make_nvp(priorityName, priority)); 75 return true; 76 } 77 catch (const cereal::Exception& e) 78 { 79 fs::remove_all(path); 80 } 81 } 82 83 // Find the mtd device "u-boot-env" to retrieve the environment variables 84 std::ifstream mtdDevices("/proc/mtd"); 85 std::string device, devicePath; 86 87 try 88 { 89 while (std::getline(mtdDevices, device)) 90 { 91 if (device.find("u-boot-env") != std::string::npos) 92 { 93 devicePath = "/dev/" + device.substr(0, device.find(':')); 94 break; 95 } 96 } 97 98 if (!devicePath.empty()) 99 { 100 std::ifstream input(devicePath.c_str()); 101 std::string envVars; 102 std::getline(input, envVars); 103 104 std::string versionVar = versionId + "="; 105 auto varPosition = envVars.find(versionVar); 106 107 if (varPosition != std::string::npos) 108 { 109 // Grab the environment variable for this versionId. These 110 // variables follow the format "versionId=priority\0" 111 auto var = envVars.substr(varPosition); 112 priority = std::stoi(var.substr(versionVar.length())); 113 return true; 114 } 115 } 116 } 117 catch (const std::exception& e) 118 { 119 error("Error during processing: {ERROR}", "ERROR", e); 120 } 121 122 return false; 123 } 124 125 bool restorePurpose(const std::string& versionId, VersionPurpose& purpose) 126 { 127 auto path = fs::path(PERSIST_DIR) / versionId / purposeName; 128 if (fs::exists(path)) 129 { 130 std::ifstream is(path.c_str(), std::ios::in); 131 try 132 { 133 cereal::JSONInputArchive iarchive(is); 134 iarchive(cereal::make_nvp(purposeName, purpose)); 135 return true; 136 } 137 catch (const cereal::Exception& e) 138 { 139 fs::remove_all(path); 140 } 141 } 142 143 return false; 144 } 145 146 void removePersistDataDirectory(const std::string& versionId) 147 { 148 auto path = fs::path(PERSIST_DIR) / versionId; 149 if (fs::exists(path)) 150 { 151 fs::remove_all(path); 152 } 153 } 154 155 } // namespace updater 156 } // namespace software 157 } // namespace phosphor 158