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, devicePath; 90 91 try 92 { 93 while (std::getline(mtdDevices, device)) 94 { 95 if (device.find("u-boot-env") != std::string::npos) 96 { 97 devicePath = "/dev/" + device.substr(0, device.find(':')); 98 break; 99 } 100 } 101 102 if (!devicePath.empty()) 103 { 104 std::ifstream input(devicePath.c_str()); 105 std::string envVars; 106 std::getline(input, envVars); 107 108 std::string versionVar = flashId + "="; 109 auto varPosition = envVars.find(versionVar); 110 111 if (varPosition != std::string::npos) 112 { 113 // Grab the environment variable for this flashId. These 114 // variables follow the format "flashId=priority\0" 115 auto var = envVars.substr(varPosition); 116 priority = std::stoi(var.substr(versionVar.length())); 117 return true; 118 } 119 } 120 } 121 catch (const std::exception& e) 122 { 123 error("Error during processing: {ERROR}", "ERROR", e); 124 } 125 126 return false; 127 } 128 129 bool restorePurpose(const std::string& flashId, VersionPurpose& purpose) 130 { 131 std::error_code ec; 132 auto path = fs::path(PERSIST_DIR) / flashId / purposeName; 133 if (fs::exists(path, ec)) 134 { 135 std::ifstream is(path.c_str(), std::ios::in); 136 try 137 { 138 cereal::JSONInputArchive iarchive(is); 139 iarchive(cereal::make_nvp(purposeName, purpose)); 140 return true; 141 } 142 catch (const cereal::Exception& e) 143 { 144 fs::remove_all(path, ec); 145 } 146 } 147 148 return false; 149 } 150 151 void removePersistDataDirectory(const std::string& flashId) 152 { 153 std::error_code ec; 154 auto path = fs::path(PERSIST_DIR) / flashId; 155 if (fs::exists(path, ec)) 156 { 157 fs::remove_all(path, ec); 158 } 159 } 160 161 } // namespace updater 162 } // namespace software 163 } // namespace phosphor 164