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