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
storePriority(const std::string & flashId,uint8_t priority)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
storePurpose(const std::string & flashId,VersionPurpose purpose)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
restorePriority(const std::string & flashId,uint8_t & priority)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
restorePurpose(const std::string & flashId,VersionPurpose & purpose)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
removePersistDataDirectory(const std::string & flashId)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