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