1 #include "config.h"
2
3 #include "serialize.hpp"
4
5 #include <cereal/archives/json.hpp>
6 #include <sdbusplus/server.hpp>
7
8 #include <filesystem>
9 #include <fstream>
10
11 namespace openpower
12 {
13 namespace software
14 {
15 namespace updater
16 {
17
storeToFile(const std::string & versionId,uint8_t priority)18 void storeToFile(const std::string& versionId, uint8_t priority)
19 {
20 auto bus = sdbusplus::bus::new_default();
21
22 if (!std::filesystem::is_directory(PERSIST_DIR))
23 {
24 std::filesystem::create_directories(PERSIST_DIR);
25 }
26
27 // store one copy in /var/lib/obmc/openpower-pnor-code-mgmt/[versionId]
28 auto varPath = PERSIST_DIR + versionId;
29 std::ofstream varOutput(varPath.c_str());
30 cereal::JSONOutputArchive varArchive(varOutput);
31 varArchive(cereal::make_nvp("priority", priority));
32
33 if (std::filesystem::is_directory(PNOR_RW_PREFIX + versionId))
34 {
35 // store another copy in /media/pnor-rw-[versionId]/[versionId]
36 auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
37 std::ofstream rwOutput(rwPath.c_str());
38 cereal::JSONOutputArchive rwArchive(rwOutput);
39 rwArchive(cereal::make_nvp("priority", priority));
40 }
41
42 // lastly, store the priority as an environment variable pnor-[versionId]
43 std::string serviceFile = "obmc-flash-bmc-setenv@pnor\\x2d" + versionId +
44 "\\x3d" + std::to_string(priority) + ".service";
45 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
46 SYSTEMD_INTERFACE, "StartUnit");
47 method.append(serviceFile, "replace");
48 bus.call_noreply(method);
49 }
50
restoreFromFile(const std::string & versionId,uint8_t & priority)51 bool restoreFromFile(const std::string& versionId, uint8_t& priority)
52 {
53 auto varPath = PERSIST_DIR + versionId;
54 if (std::filesystem::exists(varPath))
55 {
56 std::ifstream varInput(varPath.c_str(), std::ios::in);
57 try
58 {
59 cereal::JSONInputArchive varArchive(varInput);
60 varArchive(cereal::make_nvp("priority", priority));
61 return true;
62 }
63 catch (const cereal::RapidJSONException& e)
64 {
65 std::filesystem::remove(varPath);
66 }
67 }
68
69 auto rwPath = PNOR_RW_PREFIX + versionId + "/" + versionId;
70 if (std::filesystem::exists(rwPath))
71 {
72 std::ifstream rwInput(rwPath.c_str(), std::ios::in);
73 try
74 {
75 cereal::JSONInputArchive rwArchive(rwInput);
76 rwArchive(cereal::make_nvp("priority", priority));
77 return true;
78 }
79 catch (const cereal::RapidJSONException& e)
80 {
81 std::filesystem::remove(rwPath);
82 }
83 }
84
85 try
86 {
87 std::string devicePath = "/dev/mtd/u-boot-env";
88
89 if (std::filesystem::exists(devicePath) && !devicePath.empty())
90 {
91 std::ifstream input(devicePath.c_str());
92 std::string envVars;
93 std::getline(input, envVars);
94
95 std::string versionVar = "pnor-" + versionId + "=";
96 auto varPosition = envVars.find(versionVar);
97
98 if (varPosition != std::string::npos)
99 {
100 // Grab the environment variable for this versionId. These
101 // variables follow the format "pnor-[versionId]=[priority]\0"
102 auto var = envVars.substr(varPosition);
103 priority = std::stoi(var.substr(versionVar.length()));
104 return true;
105 }
106 }
107 }
108 catch (const std::exception& e)
109 {}
110
111 return false;
112 }
113
removeFile(const std::string & versionId)114 void removeFile(const std::string& versionId)
115 {
116 auto bus = sdbusplus::bus::new_default();
117
118 // Clear the environment variable pnor-[versionId].
119 std::string serviceFile =
120 "obmc-flash-bmc-setenv@pnor\\x2d" + versionId + ".service";
121 auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
122 SYSTEMD_INTERFACE, "StartUnit");
123 method.append(serviceFile, "replace");
124 bus.call_noreply(method);
125
126 // Delete the file /var/lib/obmc/openpower-pnor-code-mgmt/[versionId].
127 // Note that removeFile() is called in the case of a version being deleted,
128 // so the file /media/pnor-rw-[versionId]/[versionId] will also be deleted
129 // along with its surrounding directory.
130 std::string path = PERSIST_DIR + versionId;
131 if (std::filesystem::exists(path))
132 {
133 std::filesystem::remove(path);
134 }
135 }
136
137 } // namespace updater
138 } // namespace software
139 } // namespace openpower
140