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