| #include "config.h" |
| #include <experimental/filesystem> |
| #include <cereal/archives/json.hpp> |
| #include <fstream> |
| #include "serialize.hpp" |
| #include <sdbusplus/server.hpp> |
| |
| namespace openpower |
| { |
| namespace software |
| { |
| namespace updater |
| { |
| |
| namespace fs = std::experimental::filesystem; |
| |
| void storeToFile(std::string versionId, uint8_t priority) |
| { |
| auto bus = sdbusplus::bus::new_default(); |
| |
| if (!fs::is_directory(PERSIST_DIR)) |
| { |
| fs::create_directories(PERSIST_DIR); |
| } |
| |
| // store one copy in /var/lib/obmc/openpower-pnor-code-mgmt/[versionId] |
| auto varPath = PERSIST_DIR + versionId; |
| std::ofstream varOutput(varPath.c_str()); |
| cereal::JSONOutputArchive varArchive(varOutput); |
| varArchive(cereal::make_nvp("priority", priority)); |
| |
| if (fs::is_directory(PNOR_RW_PREFIX + versionId)) |
| { |
| // store another copy in /media/pnor-rw-[versionId]/[versionId] |
| auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId; |
| std::ofstream rwOutput(rwPath.c_str()); |
| cereal::JSONOutputArchive rwArchive(rwOutput); |
| rwArchive(cereal::make_nvp("priority", priority)); |
| } |
| |
| // lastly, store the priority as an environment variable pnor-[versionId] |
| std::string serviceFile = "obmc-flash-bmc-setenv@pnor\\x2d" + versionId + |
| "\\x3d" + std::to_string(priority) + ".service"; |
| auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, |
| SYSTEMD_INTERFACE, "StartUnit"); |
| method.append(serviceFile, "replace"); |
| bus.call_noreply(method); |
| } |
| |
| bool restoreFromFile(std::string versionId, uint8_t& priority) |
| { |
| auto varPath = PERSIST_DIR + versionId; |
| if (fs::exists(varPath)) |
| { |
| std::ifstream varInput(varPath.c_str(), std::ios::in); |
| try |
| { |
| cereal::JSONInputArchive varArchive(varInput); |
| varArchive(cereal::make_nvp("priority", priority)); |
| return true; |
| } |
| catch (cereal::RapidJSONException& e) |
| { |
| fs::remove(varPath); |
| } |
| } |
| |
| auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId; |
| if (fs::exists(rwPath)) |
| { |
| std::ifstream rwInput(rwPath.c_str(), std::ios::in); |
| try |
| { |
| cereal::JSONInputArchive rwArchive(rwInput); |
| rwArchive(cereal::make_nvp("priority", priority)); |
| return true; |
| } |
| catch (cereal::RapidJSONException& e) |
| { |
| fs::remove(rwPath); |
| } |
| } |
| |
| try |
| { |
| std::string devicePath = "/dev/mtd/u-boot-env"; |
| |
| if (fs::exists(devicePath) && !devicePath.empty()) |
| { |
| std::ifstream input(devicePath.c_str()); |
| std::string envVars; |
| std::getline(input, envVars); |
| |
| std::string versionVar = "pnor-" + versionId + "="; |
| auto varPosition = envVars.find(versionVar); |
| |
| if (varPosition != std::string::npos) |
| { |
| // Grab the environment variable for this versionId. These |
| // variables follow the format "pnor-[versionId]=[priority]\0" |
| auto var = envVars.substr(varPosition); |
| priority = std::stoi(var.substr(versionVar.length())); |
| return true; |
| } |
| } |
| } |
| catch (const std::exception& e) |
| { |
| } |
| |
| return false; |
| } |
| |
| void removeFile(std::string versionId) |
| { |
| auto bus = sdbusplus::bus::new_default(); |
| |
| // Clear the environment variable pnor-[versionId]. |
| std::string serviceFile = |
| "obmc-flash-bmc-setenv@pnor\\x2d" + versionId + ".service"; |
| auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH, |
| SYSTEMD_INTERFACE, "StartUnit"); |
| method.append(serviceFile, "replace"); |
| bus.call_noreply(method); |
| |
| // Delete the file /var/lib/obmc/openpower-pnor-code-mgmt/[versionId]. |
| // Note that removeFile() is called in the case of a version being deleted, |
| // so the file /media/pnor-rw-[versionId]/[versionId] will also be deleted |
| // along with its surrounding directory. |
| std::string path = PERSIST_DIR + versionId; |
| if (fs::exists(path)) |
| { |
| fs::remove(path); |
| } |
| } |
| |
| } // namespace updater |
| } // namespace software |
| } // namespace openpower |