xref: /openbmc/openpower-vpd-parser/vpd-manager/src/worker.cpp (revision 043955d2f6725a239a76285574f9493535e177d9)
1fa5e4d32SSunny Srivastava #include "config.h"
2fa5e4d32SSunny Srivastava 
3fa5e4d32SSunny Srivastava #include "worker.hpp"
4fa5e4d32SSunny Srivastava 
5fa5e4d32SSunny Srivastava #include "backup_restore.hpp"
6fa5e4d32SSunny Srivastava #include "configuration.hpp"
7fa5e4d32SSunny Srivastava #include "constants.hpp"
8fa5e4d32SSunny Srivastava #include "event_logger.hpp"
9fa5e4d32SSunny Srivastava #include "exceptions.hpp"
10fa5e4d32SSunny Srivastava #include "logger.hpp"
11fa5e4d32SSunny Srivastava #include "parser.hpp"
12fa5e4d32SSunny Srivastava #include "parser_factory.hpp"
13fa5e4d32SSunny Srivastava #include "parser_interface.hpp"
14fa5e4d32SSunny Srivastava 
15fa5e4d32SSunny Srivastava #include <utility/dbus_utility.hpp>
16fa5e4d32SSunny Srivastava #include <utility/json_utility.hpp>
17fa5e4d32SSunny Srivastava #include <utility/vpd_specific_utility.hpp>
18fa5e4d32SSunny Srivastava 
19fa5e4d32SSunny Srivastava #include <filesystem>
20fa5e4d32SSunny Srivastava #include <fstream>
21fa5e4d32SSunny Srivastava #include <future>
22fa5e4d32SSunny Srivastava #include <typeindex>
23fa5e4d32SSunny Srivastava #include <unordered_set>
24fa5e4d32SSunny Srivastava 
25fa5e4d32SSunny Srivastava namespace vpd
26fa5e4d32SSunny Srivastava {
27fa5e4d32SSunny Srivastava 
Worker(std::string pathToConfigJson,uint8_t i_maxThreadCount)28765cf7b8SSunny Srivastava Worker::Worker(std::string pathToConfigJson, uint8_t i_maxThreadCount) :
29765cf7b8SSunny Srivastava     m_configJsonPath(pathToConfigJson), m_semaphore(i_maxThreadCount)
30fa5e4d32SSunny Srivastava {
31fa5e4d32SSunny Srivastava     // Implies the processing is based on some config JSON
32fa5e4d32SSunny Srivastava     if (!m_configJsonPath.empty())
33fa5e4d32SSunny Srivastava     {
34fa5e4d32SSunny Srivastava         // Check if symlink is already there to confirm fresh boot/factory
35fa5e4d32SSunny Srivastava         // reset.
36fa5e4d32SSunny Srivastava         if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK))
37fa5e4d32SSunny Srivastava         {
38fa5e4d32SSunny Srivastava             logging::logMessage("Sym Link already present");
39fa5e4d32SSunny Srivastava             m_configJsonPath = INVENTORY_JSON_SYM_LINK;
40fa5e4d32SSunny Srivastava             m_isSymlinkPresent = true;
41fa5e4d32SSunny Srivastava         }
42fa5e4d32SSunny Srivastava 
43fa5e4d32SSunny Srivastava         try
44fa5e4d32SSunny Srivastava         {
45fa5e4d32SSunny Srivastava             m_parsedJson = jsonUtility::getParsedJson(m_configJsonPath);
46fa5e4d32SSunny Srivastava 
47fa5e4d32SSunny Srivastava             // check for mandatory fields at this point itself.
48fa5e4d32SSunny Srivastava             if (!m_parsedJson.contains("frus"))
49fa5e4d32SSunny Srivastava             {
50fa5e4d32SSunny Srivastava                 throw std::runtime_error("Mandatory tag(s) missing from JSON");
51fa5e4d32SSunny Srivastava             }
52fa5e4d32SSunny Srivastava         }
53fa5e4d32SSunny Srivastava         catch (const std::exception& ex)
54fa5e4d32SSunny Srivastava         {
55fa5e4d32SSunny Srivastava             throw(JsonException(ex.what(), m_configJsonPath));
56fa5e4d32SSunny Srivastava         }
57fa5e4d32SSunny Srivastava     }
58fa5e4d32SSunny Srivastava     else
59fa5e4d32SSunny Srivastava     {
60fa5e4d32SSunny Srivastava         logging::logMessage("Processing in not based on any config JSON");
61fa5e4d32SSunny Srivastava     }
62fa5e4d32SSunny Srivastava }
63fa5e4d32SSunny Srivastava 
enableMuxChips()64fa5e4d32SSunny Srivastava void Worker::enableMuxChips()
65fa5e4d32SSunny Srivastava {
66fa5e4d32SSunny Srivastava     if (m_parsedJson.empty())
67fa5e4d32SSunny Srivastava     {
68fa5e4d32SSunny Srivastava         // config JSON should not be empty at this point of execution.
69fa5e4d32SSunny Srivastava         throw std::runtime_error("Config JSON is empty. Can't enable muxes");
70fa5e4d32SSunny Srivastava         return;
71fa5e4d32SSunny Srivastava     }
72fa5e4d32SSunny Srivastava 
73fa5e4d32SSunny Srivastava     if (!m_parsedJson.contains("muxes"))
74fa5e4d32SSunny Srivastava     {
75fa5e4d32SSunny Srivastava         logging::logMessage("No mux defined for the system in config JSON");
76fa5e4d32SSunny Srivastava         return;
77fa5e4d32SSunny Srivastava     }
78fa5e4d32SSunny Srivastava 
79fa5e4d32SSunny Srivastava     // iterate over each MUX detail and enable them.
80fa5e4d32SSunny Srivastava     for (const auto& item : m_parsedJson["muxes"])
81fa5e4d32SSunny Srivastava     {
82fa5e4d32SSunny Srivastava         if (item.contains("holdidlepath"))
83fa5e4d32SSunny Srivastava         {
84fa5e4d32SSunny Srivastava             std::string cmd = "echo 0 > ";
85fa5e4d32SSunny Srivastava             cmd += item["holdidlepath"];
86fa5e4d32SSunny Srivastava 
87fa5e4d32SSunny Srivastava             logging::logMessage("Enabling mux with command = " + cmd);
88fa5e4d32SSunny Srivastava 
89fa5e4d32SSunny Srivastava             commonUtility::executeCmd(cmd);
90fa5e4d32SSunny Srivastava             continue;
91fa5e4d32SSunny Srivastava         }
92fa5e4d32SSunny Srivastava 
93fa5e4d32SSunny Srivastava         logging::logMessage(
94fa5e4d32SSunny Srivastava             "Mux Entry does not have hold idle path. Can't enable the mux");
95fa5e4d32SSunny Srivastava     }
96fa5e4d32SSunny Srivastava }
97fa5e4d32SSunny Srivastava 
98fa5e4d32SSunny Srivastava #ifdef IBM_SYSTEM
primeSystemBlueprint()99fa5e4d32SSunny Srivastava void Worker::primeSystemBlueprint()
100fa5e4d32SSunny Srivastava {
101fa5e4d32SSunny Srivastava     if (m_parsedJson.empty())
102fa5e4d32SSunny Srivastava     {
103fa5e4d32SSunny Srivastava         return;
104fa5e4d32SSunny Srivastava     }
105fa5e4d32SSunny Srivastava 
106fa5e4d32SSunny Srivastava     const nlohmann::json& l_listOfFrus =
107fa5e4d32SSunny Srivastava         m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();
108fa5e4d32SSunny Srivastava 
109fa5e4d32SSunny Srivastava     for (const auto& l_itemFRUS : l_listOfFrus.items())
110fa5e4d32SSunny Srivastava     {
111fa5e4d32SSunny Srivastava         const std::string& l_vpdFilePath = l_itemFRUS.key();
112fa5e4d32SSunny Srivastava 
113fa5e4d32SSunny Srivastava         if (l_vpdFilePath == SYSTEM_VPD_FILE_PATH)
114fa5e4d32SSunny Srivastava         {
115fa5e4d32SSunny Srivastava             continue;
116fa5e4d32SSunny Srivastava         }
117fa5e4d32SSunny Srivastava 
118fa5e4d32SSunny Srivastava         // Prime the inventry for FRUs which
119fa5e4d32SSunny Srivastava         // are not present/processing had some error.
120fa5e4d32SSunny Srivastava         if (!primeInventory(l_vpdFilePath))
121fa5e4d32SSunny Srivastava         {
122fa5e4d32SSunny Srivastava             logging::logMessage(
123fa5e4d32SSunny Srivastava                 "Priming of inventory failed for FRU " + l_vpdFilePath);
124fa5e4d32SSunny Srivastava         }
125fa5e4d32SSunny Srivastava     }
126fa5e4d32SSunny Srivastava }
127fa5e4d32SSunny Srivastava 
performInitialSetup()128fa5e4d32SSunny Srivastava void Worker::performInitialSetup()
129fa5e4d32SSunny Srivastava {
130fa5e4d32SSunny Srivastava     try
131fa5e4d32SSunny Srivastava     {
132fa5e4d32SSunny Srivastava         if (!dbusUtility::isChassisPowerOn())
133fa5e4d32SSunny Srivastava         {
134fa5e4d32SSunny Srivastava             logging::logMessage("Chassis is in Off state.");
135fa5e4d32SSunny Srivastava             setDeviceTreeAndJson();
136fa5e4d32SSunny Srivastava             primeSystemBlueprint();
137fa5e4d32SSunny Srivastava         }
138fa5e4d32SSunny Srivastava 
139fa5e4d32SSunny Srivastava         // Enable all mux which are used for connecting to the i2c on the
140fa5e4d32SSunny Srivastava         // pcie slots for pcie cards. These are not enabled by kernel due to
141fa5e4d32SSunny Srivastava         // an issue seen with Castello cards, where the i2c line hangs on a
142fa5e4d32SSunny Srivastava         // probe.
143fa5e4d32SSunny Srivastava         enableMuxChips();
144fa5e4d32SSunny Srivastava 
145fa5e4d32SSunny Srivastava         // Nothing needs to be done. Service restarted or BMC re-booted for
146fa5e4d32SSunny Srivastava         // some reason at system power on.
147fa5e4d32SSunny Srivastava         return;
148fa5e4d32SSunny Srivastava     }
149*043955d2SSunny Srivastava     catch (const std::exception& l_ex)
150fa5e4d32SSunny Srivastava     {
151*043955d2SSunny Srivastava         // Any issue in system's inital set up is handled in this catch. Error
152*043955d2SSunny Srivastava         // will not propogate to manager.
153*043955d2SSunny Srivastava         EventLogger::createSyncPel(
154*043955d2SSunny Srivastava             EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
155*043955d2SSunny Srivastava             __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
156*043955d2SSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
157fa5e4d32SSunny Srivastava     }
158fa5e4d32SSunny Srivastava }
159fa5e4d32SSunny Srivastava #endif
160fa5e4d32SSunny Srivastava 
readFitConfigValue()161fa5e4d32SSunny Srivastava static std::string readFitConfigValue()
162fa5e4d32SSunny Srivastava {
163fa5e4d32SSunny Srivastava     std::vector<std::string> output =
164fa5e4d32SSunny Srivastava         commonUtility::executeCmd("/sbin/fw_printenv");
165fa5e4d32SSunny Srivastava     std::string fitConfigValue;
166fa5e4d32SSunny Srivastava 
167fa5e4d32SSunny Srivastava     for (const auto& entry : output)
168fa5e4d32SSunny Srivastava     {
169fa5e4d32SSunny Srivastava         auto pos = entry.find("=");
170fa5e4d32SSunny Srivastava         auto key = entry.substr(0, pos);
171fa5e4d32SSunny Srivastava         if (key != "fitconfig")
172fa5e4d32SSunny Srivastava         {
173fa5e4d32SSunny Srivastava             continue;
174fa5e4d32SSunny Srivastava         }
175fa5e4d32SSunny Srivastava 
176fa5e4d32SSunny Srivastava         if (pos + 1 < entry.size())
177fa5e4d32SSunny Srivastava         {
178fa5e4d32SSunny Srivastava             fitConfigValue = entry.substr(pos + 1);
179fa5e4d32SSunny Srivastava         }
180fa5e4d32SSunny Srivastava     }
181fa5e4d32SSunny Srivastava 
182fa5e4d32SSunny Srivastava     return fitConfigValue;
183fa5e4d32SSunny Srivastava }
184fa5e4d32SSunny Srivastava 
isSystemVPDOnDBus() const185fa5e4d32SSunny Srivastava bool Worker::isSystemVPDOnDBus() const
186fa5e4d32SSunny Srivastava {
187fa5e4d32SSunny Srivastava     const std::string& mboardPath =
188fa5e4d32SSunny Srivastava         m_parsedJson["frus"][SYSTEM_VPD_FILE_PATH].at(0).value(
189fa5e4d32SSunny Srivastava             "inventoryPath", "");
190fa5e4d32SSunny Srivastava 
191fa5e4d32SSunny Srivastava     if (mboardPath.empty())
192fa5e4d32SSunny Srivastava     {
193fa5e4d32SSunny Srivastava         throw JsonException("System vpd file path missing in JSON",
194fa5e4d32SSunny Srivastava                             INVENTORY_JSON_SYM_LINK);
195fa5e4d32SSunny Srivastava     }
196fa5e4d32SSunny Srivastava 
197fa5e4d32SSunny Srivastava     std::array<const char*, 1> interfaces = {
198fa5e4d32SSunny Srivastava         "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};
199fa5e4d32SSunny Srivastava 
200fa5e4d32SSunny Srivastava     const types::MapperGetObject& objectMap =
201fa5e4d32SSunny Srivastava         dbusUtility::getObjectMap(mboardPath, interfaces);
202fa5e4d32SSunny Srivastava 
203fa5e4d32SSunny Srivastava     if (objectMap.empty())
204fa5e4d32SSunny Srivastava     {
205fa5e4d32SSunny Srivastava         return false;
206fa5e4d32SSunny Srivastava     }
207fa5e4d32SSunny Srivastava     return true;
208fa5e4d32SSunny Srivastava }
209fa5e4d32SSunny Srivastava 
getIMValue(const types::IPZVpdMap & parsedVpd) const210fa5e4d32SSunny Srivastava std::string Worker::getIMValue(const types::IPZVpdMap& parsedVpd) const
211fa5e4d32SSunny Srivastava {
212fa5e4d32SSunny Srivastava     if (parsedVpd.empty())
213fa5e4d32SSunny Srivastava     {
214fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty VPD map. Can't Extract IM value");
215fa5e4d32SSunny Srivastava     }
216fa5e4d32SSunny Srivastava 
217fa5e4d32SSunny Srivastava     const auto& itrToVSBP = parsedVpd.find("VSBP");
218fa5e4d32SSunny Srivastava     if (itrToVSBP == parsedVpd.end())
219fa5e4d32SSunny Srivastava     {
220fa5e4d32SSunny Srivastava         throw DataException("VSBP record missing.");
221fa5e4d32SSunny Srivastava     }
222fa5e4d32SSunny Srivastava 
223fa5e4d32SSunny Srivastava     const auto& itrToIM = (itrToVSBP->second).find("IM");
224fa5e4d32SSunny Srivastava     if (itrToIM == (itrToVSBP->second).end())
225fa5e4d32SSunny Srivastava     {
226fa5e4d32SSunny Srivastava         throw DataException("IM keyword missing.");
227fa5e4d32SSunny Srivastava     }
228fa5e4d32SSunny Srivastava 
229fa5e4d32SSunny Srivastava     types::BinaryVector imVal;
230fa5e4d32SSunny Srivastava     std::copy(itrToIM->second.begin(), itrToIM->second.end(),
231fa5e4d32SSunny Srivastava               back_inserter(imVal));
232fa5e4d32SSunny Srivastava 
233fa5e4d32SSunny Srivastava     std::ostringstream imData;
234fa5e4d32SSunny Srivastava     for (auto& aByte : imVal)
235fa5e4d32SSunny Srivastava     {
236fa5e4d32SSunny Srivastava         imData << std::setw(2) << std::setfill('0') << std::hex
237fa5e4d32SSunny Srivastava                << static_cast<int>(aByte);
238fa5e4d32SSunny Srivastava     }
239fa5e4d32SSunny Srivastava 
240fa5e4d32SSunny Srivastava     return imData.str();
241fa5e4d32SSunny Srivastava }
242fa5e4d32SSunny Srivastava 
getHWVersion(const types::IPZVpdMap & parsedVpd) const243fa5e4d32SSunny Srivastava std::string Worker::getHWVersion(const types::IPZVpdMap& parsedVpd) const
244fa5e4d32SSunny Srivastava {
245fa5e4d32SSunny Srivastava     if (parsedVpd.empty())
246fa5e4d32SSunny Srivastava     {
247fa5e4d32SSunny Srivastava         throw std::runtime_error("Empty VPD map. Can't Extract HW value");
248fa5e4d32SSunny Srivastava     }
249fa5e4d32SSunny Srivastava 
250fa5e4d32SSunny Srivastava     const auto& itrToVINI = parsedVpd.find("VINI");
251fa5e4d32SSunny Srivastava     if (itrToVINI == parsedVpd.end())
252fa5e4d32SSunny Srivastava     {
253fa5e4d32SSunny Srivastava         throw DataException("VINI record missing.");
254fa5e4d32SSunny Srivastava     }
255fa5e4d32SSunny Srivastava 
256fa5e4d32SSunny Srivastava     const auto& itrToHW = (itrToVINI->second).find("HW");
257fa5e4d32SSunny Srivastava     if (itrToHW == (itrToVINI->second).end())
258fa5e4d32SSunny Srivastava     {
259fa5e4d32SSunny Srivastava         throw DataException("HW keyword missing.");
260fa5e4d32SSunny Srivastava     }
261fa5e4d32SSunny Srivastava 
262fa5e4d32SSunny Srivastava     types::BinaryVector hwVal;
263fa5e4d32SSunny Srivastava     std::copy(itrToHW->second.begin(), itrToHW->second.end(),
264fa5e4d32SSunny Srivastava               back_inserter(hwVal));
265fa5e4d32SSunny Srivastava 
266fa5e4d32SSunny Srivastava     // The planar pass only comes from the LSB of the HW keyword,
267fa5e4d32SSunny Srivastava     // where as the MSB is used for other purposes such as signifying clock
268fa5e4d32SSunny Srivastava     // termination.
269fa5e4d32SSunny Srivastava     hwVal[0] = 0x00;
270fa5e4d32SSunny Srivastava 
271fa5e4d32SSunny Srivastava     std::ostringstream hwString;
272fa5e4d32SSunny Srivastava     for (auto& aByte : hwVal)
273fa5e4d32SSunny Srivastava     {
274fa5e4d32SSunny Srivastava         hwString << std::setw(2) << std::setfill('0') << std::hex
275fa5e4d32SSunny Srivastava                  << static_cast<int>(aByte);
276fa5e4d32SSunny Srivastava     }
277fa5e4d32SSunny Srivastava 
278fa5e4d32SSunny Srivastava     return hwString.str();
279fa5e4d32SSunny Srivastava }
280fa5e4d32SSunny Srivastava 
fillVPDMap(const std::string & vpdFilePath,types::VPDMapVariant & vpdMap)281fa5e4d32SSunny Srivastava void Worker::fillVPDMap(const std::string& vpdFilePath,
282fa5e4d32SSunny Srivastava                         types::VPDMapVariant& vpdMap)
283fa5e4d32SSunny Srivastava {
284fa5e4d32SSunny Srivastava     logging::logMessage(std::string("Parsing file = ") + vpdFilePath);
285fa5e4d32SSunny Srivastava 
286fa5e4d32SSunny Srivastava     if (vpdFilePath.empty())
287fa5e4d32SSunny Srivastava     {
288fa5e4d32SSunny Srivastava         throw std::runtime_error("Invalid file path passed to fillVPDMap API.");
289fa5e4d32SSunny Srivastava     }
290fa5e4d32SSunny Srivastava 
291fa5e4d32SSunny Srivastava     if (!std::filesystem::exists(vpdFilePath))
292fa5e4d32SSunny Srivastava     {
293fa5e4d32SSunny Srivastava         throw std::runtime_error("Can't Find physical file");
294fa5e4d32SSunny Srivastava     }
295fa5e4d32SSunny Srivastava 
296fa5e4d32SSunny Srivastava     std::shared_ptr<Parser> vpdParser =
297fa5e4d32SSunny Srivastava         std::make_shared<Parser>(vpdFilePath, m_parsedJson);
298fa5e4d32SSunny Srivastava     vpdMap = vpdParser->parse();
299fa5e4d32SSunny Srivastava }
300fa5e4d32SSunny Srivastava 
getSystemJson(std::string & systemJson,const types::VPDMapVariant & parsedVpdMap)301fa5e4d32SSunny Srivastava void Worker::getSystemJson(std::string& systemJson,
302fa5e4d32SSunny Srivastava                            const types::VPDMapVariant& parsedVpdMap)
303fa5e4d32SSunny Srivastava {
304fa5e4d32SSunny Srivastava     if (auto pVal = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
305fa5e4d32SSunny Srivastava     {
306fa5e4d32SSunny Srivastava         std::string hwKWdValue = getHWVersion(*pVal);
307fa5e4d32SSunny Srivastava         if (hwKWdValue.empty())
308fa5e4d32SSunny Srivastava         {
309fa5e4d32SSunny Srivastava             throw DataException("HW value fetched is empty.");
310fa5e4d32SSunny Srivastava         }
311fa5e4d32SSunny Srivastava 
312fa5e4d32SSunny Srivastava         const std::string& imKwdValue = getIMValue(*pVal);
313fa5e4d32SSunny Srivastava         if (imKwdValue.empty())
314fa5e4d32SSunny Srivastava         {
315fa5e4d32SSunny Srivastava             throw DataException("IM value fetched is empty.");
316fa5e4d32SSunny Srivastava         }
317fa5e4d32SSunny Srivastava 
318fa5e4d32SSunny Srivastava         auto itrToIM = config::systemType.find(imKwdValue);
319fa5e4d32SSunny Srivastava         if (itrToIM == config::systemType.end())
320fa5e4d32SSunny Srivastava         {
321fa5e4d32SSunny Srivastava             throw DataException("IM keyword does not map to any system type");
322fa5e4d32SSunny Srivastava         }
323fa5e4d32SSunny Srivastava 
324fa5e4d32SSunny Srivastava         const types::HWVerList hwVersionList = itrToIM->second.second;
325fa5e4d32SSunny Srivastava         if (!hwVersionList.empty())
326fa5e4d32SSunny Srivastava         {
327fa5e4d32SSunny Srivastava             transform(hwKWdValue.begin(), hwKWdValue.end(), hwKWdValue.begin(),
328fa5e4d32SSunny Srivastava                       ::toupper);
329fa5e4d32SSunny Srivastava 
330fa5e4d32SSunny Srivastava             auto itrToHW =
331fa5e4d32SSunny Srivastava                 std::find_if(hwVersionList.begin(), hwVersionList.end(),
332fa5e4d32SSunny Srivastava                              [&hwKWdValue](const auto& aPair) {
333fa5e4d32SSunny Srivastava                                  return aPair.first == hwKWdValue;
334fa5e4d32SSunny Srivastava                              });
335fa5e4d32SSunny Srivastava 
336fa5e4d32SSunny Srivastava             if (itrToHW != hwVersionList.end())
337fa5e4d32SSunny Srivastava             {
338fa5e4d32SSunny Srivastava                 if (!(*itrToHW).second.empty())
339fa5e4d32SSunny Srivastava                 {
340fa5e4d32SSunny Srivastava                     systemJson += (*itrToIM).first + "_" + (*itrToHW).second +
341fa5e4d32SSunny Srivastava                                   ".json";
342fa5e4d32SSunny Srivastava                 }
343fa5e4d32SSunny Srivastava                 else
344fa5e4d32SSunny Srivastava                 {
345fa5e4d32SSunny Srivastava                     systemJson += (*itrToIM).first + ".json";
346fa5e4d32SSunny Srivastava                 }
347fa5e4d32SSunny Srivastava                 return;
348fa5e4d32SSunny Srivastava             }
349fa5e4d32SSunny Srivastava         }
350fa5e4d32SSunny Srivastava         systemJson += itrToIM->second.first + ".json";
351fa5e4d32SSunny Srivastava         return;
352fa5e4d32SSunny Srivastava     }
353fa5e4d32SSunny Srivastava 
354*043955d2SSunny Srivastava     throw DataException(
355*043955d2SSunny Srivastava         "Invalid VPD type returned from Parser. Can't get system JSON.");
356fa5e4d32SSunny Srivastava }
357fa5e4d32SSunny Srivastava 
setEnvAndReboot(const std::string & key,const std::string & value)358fa5e4d32SSunny Srivastava static void setEnvAndReboot(const std::string& key, const std::string& value)
359fa5e4d32SSunny Srivastava {
360fa5e4d32SSunny Srivastava     // set env and reboot and break.
361fa5e4d32SSunny Srivastava     commonUtility::executeCmd("/sbin/fw_setenv", key, value);
362fa5e4d32SSunny Srivastava     logging::logMessage("Rebooting BMC to pick up new device tree");
363fa5e4d32SSunny Srivastava 
364fa5e4d32SSunny Srivastava     // make dbus call to reboot
365fa5e4d32SSunny Srivastava     auto bus = sdbusplus::bus::new_default_system();
366fa5e4d32SSunny Srivastava     auto method = bus.new_method_call(
367fa5e4d32SSunny Srivastava         "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
368fa5e4d32SSunny Srivastava         "org.freedesktop.systemd1.Manager", "Reboot");
369fa5e4d32SSunny Srivastava     bus.call_noreply(method);
370fa5e4d32SSunny Srivastava }
371fa5e4d32SSunny Srivastava 
setJsonSymbolicLink(const std::string & i_systemJson)372fa5e4d32SSunny Srivastava void Worker::setJsonSymbolicLink(const std::string& i_systemJson)
373fa5e4d32SSunny Srivastava {
374fa5e4d32SSunny Srivastava     std::error_code l_ec;
375fa5e4d32SSunny Srivastava     l_ec.clear();
376adff7880SSunny Srivastava 
377adff7880SSunny Srivastava     // Check if symlink file path exists and if the JSON at this location is a
378adff7880SSunny Srivastava     // symlink.
379adff7880SSunny Srivastava     if (m_isSymlinkPresent &&
380adff7880SSunny Srivastava         std::filesystem::is_symlink(INVENTORY_JSON_SYM_LINK, l_ec))
381adff7880SSunny Srivastava     { // Don't care about exception in "is_symlink". Will continue with creation
382adff7880SSunny Srivastava       // of symlink.
383adff7880SSunny Srivastava 
384adff7880SSunny Srivastava         const auto& l_symlinkFilePth =
385adff7880SSunny Srivastava             std::filesystem::read_symlink(INVENTORY_JSON_SYM_LINK, l_ec);
386adff7880SSunny Srivastava 
387adff7880SSunny Srivastava         if (l_ec)
388adff7880SSunny Srivastava         {
389adff7880SSunny Srivastava             logging::logMessage(
390adff7880SSunny Srivastava                 "Can't read existing symlink. Error =" + l_ec.message() +
391adff7880SSunny Srivastava                 "Trying removal of symlink and creation of new symlink.");
392adff7880SSunny Srivastava         }
393adff7880SSunny Srivastava 
394adff7880SSunny Srivastava         // If currently set JSON is the required one. No further processing
395adff7880SSunny Srivastava         // required.
396adff7880SSunny Srivastava         if (i_systemJson == l_symlinkFilePth)
397adff7880SSunny Srivastava         {
398adff7880SSunny Srivastava             // Correct symlink already set.
399adff7880SSunny Srivastava             return;
400adff7880SSunny Srivastava         }
401adff7880SSunny Srivastava 
402adff7880SSunny Srivastava         if (!std::filesystem::remove(INVENTORY_JSON_SYM_LINK, l_ec))
403adff7880SSunny Srivastava         {
404adff7880SSunny Srivastava             // No point going further. If removal fails for existing symlink,
405adff7880SSunny Srivastava             // create will anyways throw.
406adff7880SSunny Srivastava             throw std::runtime_error(
407adff7880SSunny Srivastava                 "Removal of symlink failed with Error = " + l_ec.message() +
408adff7880SSunny Srivastava                 ". Can't proceed with create_symlink.");
409adff7880SSunny Srivastava         }
410adff7880SSunny Srivastava     }
411adff7880SSunny Srivastava 
412fa5e4d32SSunny Srivastava     if (!std::filesystem::exists(VPD_SYMLIMK_PATH, l_ec))
413fa5e4d32SSunny Srivastava     {
414fa5e4d32SSunny Srivastava         if (l_ec)
415fa5e4d32SSunny Srivastava         {
416fa5e4d32SSunny Srivastava             throw std::runtime_error(
417fa5e4d32SSunny Srivastava                 "File system call to exist failed with error = " +
418fa5e4d32SSunny Srivastava                 l_ec.message());
419fa5e4d32SSunny Srivastava         }
420fa5e4d32SSunny Srivastava 
421fa5e4d32SSunny Srivastava         // implies it is a fresh boot/factory reset.
422fa5e4d32SSunny Srivastava         // Create the directory for hosting the symlink
423fa5e4d32SSunny Srivastava         if (!std::filesystem::create_directories(VPD_SYMLIMK_PATH, l_ec))
424fa5e4d32SSunny Srivastava         {
425fa5e4d32SSunny Srivastava             if (l_ec)
426fa5e4d32SSunny Srivastava             {
427fa5e4d32SSunny Srivastava                 throw std::runtime_error(
428fa5e4d32SSunny Srivastava                     "File system call to create directory failed with error = " +
429fa5e4d32SSunny Srivastava                     l_ec.message());
430fa5e4d32SSunny Srivastava             }
431fa5e4d32SSunny Srivastava         }
432fa5e4d32SSunny Srivastava     }
433fa5e4d32SSunny Srivastava 
434fa5e4d32SSunny Srivastava     // create a new symlink based on the system
435fa5e4d32SSunny Srivastava     std::filesystem::create_symlink(i_systemJson, INVENTORY_JSON_SYM_LINK,
436fa5e4d32SSunny Srivastava                                     l_ec);
437fa5e4d32SSunny Srivastava 
438fa5e4d32SSunny Srivastava     if (l_ec)
439fa5e4d32SSunny Srivastava     {
440fa5e4d32SSunny Srivastava         throw std::runtime_error(
441fa5e4d32SSunny Srivastava             "create_symlink system call failed with error: " + l_ec.message());
442fa5e4d32SSunny Srivastava     }
443fa5e4d32SSunny Srivastava 
444fa5e4d32SSunny Srivastava     // If the flow is at this point implies the symlink was not present there.
445fa5e4d32SSunny Srivastava     // Considering this as factory reset.
446fa5e4d32SSunny Srivastava     m_isFactoryResetDone = true;
447fa5e4d32SSunny Srivastava }
448fa5e4d32SSunny Srivastava 
setDeviceTreeAndJson()449fa5e4d32SSunny Srivastava void Worker::setDeviceTreeAndJson()
450fa5e4d32SSunny Srivastava {
451fa5e4d32SSunny Srivastava     // JSON is madatory for processing of this API.
452fa5e4d32SSunny Srivastava     if (m_parsedJson.empty())
453fa5e4d32SSunny Srivastava     {
454*043955d2SSunny Srivastava         throw JsonException("System config JSON is empty", m_configJsonPath);
455fa5e4d32SSunny Srivastava     }
456fa5e4d32SSunny Srivastava 
457fa5e4d32SSunny Srivastava     types::VPDMapVariant parsedVpdMap;
458fa5e4d32SSunny Srivastava     fillVPDMap(SYSTEM_VPD_FILE_PATH, parsedVpdMap);
459fa5e4d32SSunny Srivastava 
460fa5e4d32SSunny Srivastava     // Implies it is default JSON.
461fa5e4d32SSunny Srivastava     std::string systemJson{JSON_ABSOLUTE_PATH_PREFIX};
462fa5e4d32SSunny Srivastava 
463fa5e4d32SSunny Srivastava     // ToDo: Need to check if INVENTORY_JSON_SYM_LINK pointing to correct system
464fa5e4d32SSunny Srivastava     // This is required to support movement from rainier to Blue Ridge on the
465fa5e4d32SSunny Srivastava     // fly.
466fa5e4d32SSunny Srivastava 
467fa5e4d32SSunny Srivastava     getSystemJson(systemJson, parsedVpdMap);
468fa5e4d32SSunny Srivastava 
469fa5e4d32SSunny Srivastava     if (!systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
470fa5e4d32SSunny Srivastava     {
471*043955d2SSunny Srivastava         throw DataException(
472*043955d2SSunny Srivastava             "No system JSON found corresponding to IM read from VPD.");
473fa5e4d32SSunny Srivastava     }
474fa5e4d32SSunny Srivastava 
475fa5e4d32SSunny Srivastava     // re-parse the JSON once appropriate JSON has been selected.
476fa5e4d32SSunny Srivastava     m_parsedJson = jsonUtility::getParsedJson(systemJson);
4771ef21008SRekhaAparna01 
4781ef21008SRekhaAparna01     if (m_parsedJson.empty())
479fa5e4d32SSunny Srivastava     {
480fa5e4d32SSunny Srivastava         throw(JsonException("Json parsing failed", systemJson));
481fa5e4d32SSunny Srivastava     }
482fa5e4d32SSunny Srivastava 
483fa5e4d32SSunny Srivastava     std::string devTreeFromJson;
484fa5e4d32SSunny Srivastava     if (m_parsedJson.contains("devTree"))
485fa5e4d32SSunny Srivastava     {
486fa5e4d32SSunny Srivastava         devTreeFromJson = m_parsedJson["devTree"];
487fa5e4d32SSunny Srivastava 
488fa5e4d32SSunny Srivastava         if (devTreeFromJson.empty())
489fa5e4d32SSunny Srivastava         {
490*043955d2SSunny Srivastava             EventLogger::createSyncPel(
491*043955d2SSunny Srivastava                 types::ErrorType::JsonFailure, types::SeverityType::Error,
492*043955d2SSunny Srivastava                 __FILE__, __FUNCTION__, 0,
493fa5e4d32SSunny Srivastava                 "Mandatory value for device tree missing from JSON[" +
494*043955d2SSunny Srivastava                     systemJson + "]",
495*043955d2SSunny Srivastava                 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
496fa5e4d32SSunny Srivastava         }
497fa5e4d32SSunny Srivastava     }
498fa5e4d32SSunny Srivastava 
499fa5e4d32SSunny Srivastava     auto fitConfigVal = readFitConfigValue();
500fa5e4d32SSunny Srivastava 
501fa5e4d32SSunny Srivastava     if (devTreeFromJson.empty() ||
502fa5e4d32SSunny Srivastava         fitConfigVal.find(devTreeFromJson) != std::string::npos)
503fa5e4d32SSunny Srivastava     { // Skipping setting device tree as either devtree info is missing from
504fa5e4d32SSunny Srivastava       // Json or it is rightly set.
505fa5e4d32SSunny Srivastava 
506fa5e4d32SSunny Srivastava         setJsonSymbolicLink(systemJson);
507fa5e4d32SSunny Srivastava 
508fa5e4d32SSunny Srivastava         if (isSystemVPDOnDBus() &&
509fa5e4d32SSunny Srivastava             jsonUtility::isBackupAndRestoreRequired(m_parsedJson))
510fa5e4d32SSunny Srivastava         {
511fa5e4d32SSunny Srivastava             performBackupAndRestore(parsedVpdMap);
512fa5e4d32SSunny Srivastava         }
513fa5e4d32SSunny Srivastava 
514fa5e4d32SSunny Srivastava         // proceed to publish system VPD.
515fa5e4d32SSunny Srivastava         publishSystemVPD(parsedVpdMap);
516fa5e4d32SSunny Srivastava         return;
517fa5e4d32SSunny Srivastava     }
518fa5e4d32SSunny Srivastava 
519fa5e4d32SSunny Srivastava     setEnvAndReboot("fitconfig", devTreeFromJson);
520fa5e4d32SSunny Srivastava     exit(EXIT_SUCCESS);
521fa5e4d32SSunny Srivastava }
522fa5e4d32SSunny Srivastava 
populateIPZVPDpropertyMap(types::InterfaceMap & interfacePropMap,const types::IPZKwdValueMap & keyordValueMap,const std::string & interfaceName)523fa5e4d32SSunny Srivastava void Worker::populateIPZVPDpropertyMap(
524fa5e4d32SSunny Srivastava     types::InterfaceMap& interfacePropMap,
525fa5e4d32SSunny Srivastava     const types::IPZKwdValueMap& keyordValueMap,
526fa5e4d32SSunny Srivastava     const std::string& interfaceName)
527fa5e4d32SSunny Srivastava {
528fa5e4d32SSunny Srivastava     types::PropertyMap propertyValueMap;
529fa5e4d32SSunny Srivastava     for (const auto& kwdVal : keyordValueMap)
530fa5e4d32SSunny Srivastava     {
531fa5e4d32SSunny Srivastava         auto kwd = kwdVal.first;
532fa5e4d32SSunny Srivastava 
533fa5e4d32SSunny Srivastava         if (kwd[0] == '#')
534fa5e4d32SSunny Srivastava         {
535fa5e4d32SSunny Srivastava             kwd = std::string("PD_") + kwd[1];
536fa5e4d32SSunny Srivastava         }
537fa5e4d32SSunny Srivastava         else if (isdigit(kwd[0]))
538fa5e4d32SSunny Srivastava         {
539fa5e4d32SSunny Srivastava             kwd = std::string("N_") + kwd;
540fa5e4d32SSunny Srivastava         }
541fa5e4d32SSunny Srivastava 
542fa5e4d32SSunny Srivastava         types::BinaryVector value(kwdVal.second.begin(), kwdVal.second.end());
543fa5e4d32SSunny Srivastava         propertyValueMap.emplace(move(kwd), move(value));
544fa5e4d32SSunny Srivastava     }
545fa5e4d32SSunny Srivastava 
546fa5e4d32SSunny Srivastava     if (!propertyValueMap.empty())
547fa5e4d32SSunny Srivastava     {
548fa5e4d32SSunny Srivastava         interfacePropMap.emplace(interfaceName, propertyValueMap);
549fa5e4d32SSunny Srivastava     }
550fa5e4d32SSunny Srivastava }
551fa5e4d32SSunny Srivastava 
populateKwdVPDpropertyMap(const types::KeywordVpdMap & keyordVPDMap,types::InterfaceMap & interfaceMap)552fa5e4d32SSunny Srivastava void Worker::populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
553fa5e4d32SSunny Srivastava                                        types::InterfaceMap& interfaceMap)
554fa5e4d32SSunny Srivastava {
555fa5e4d32SSunny Srivastava     for (const auto& kwdValMap : keyordVPDMap)
556fa5e4d32SSunny Srivastava     {
557fa5e4d32SSunny Srivastava         types::PropertyMap propertyValueMap;
558fa5e4d32SSunny Srivastava         auto kwd = kwdValMap.first;
559fa5e4d32SSunny Srivastava 
560fa5e4d32SSunny Srivastava         if (kwd[0] == '#')
561fa5e4d32SSunny Srivastava         {
562fa5e4d32SSunny Srivastava             kwd = std::string("PD_") + kwd[1];
563fa5e4d32SSunny Srivastava         }
564fa5e4d32SSunny Srivastava         else if (isdigit(kwd[0]))
565fa5e4d32SSunny Srivastava         {
566fa5e4d32SSunny Srivastava             kwd = std::string("N_") + kwd;
567fa5e4d32SSunny Srivastava         }
568fa5e4d32SSunny Srivastava 
569fa5e4d32SSunny Srivastava         if (auto keywordValue = get_if<types::BinaryVector>(&kwdValMap.second))
570fa5e4d32SSunny Srivastava         {
571fa5e4d32SSunny Srivastava             types::BinaryVector value((*keywordValue).begin(),
572fa5e4d32SSunny Srivastava                                       (*keywordValue).end());
573fa5e4d32SSunny Srivastava             propertyValueMap.emplace(move(kwd), move(value));
574fa5e4d32SSunny Srivastava         }
575fa5e4d32SSunny Srivastava         else if (auto keywordValue = get_if<std::string>(&kwdValMap.second))
576fa5e4d32SSunny Srivastava         {
577fa5e4d32SSunny Srivastava             types::BinaryVector value((*keywordValue).begin(),
578fa5e4d32SSunny Srivastava                                       (*keywordValue).end());
579fa5e4d32SSunny Srivastava             propertyValueMap.emplace(move(kwd), move(value));
580fa5e4d32SSunny Srivastava         }
581fa5e4d32SSunny Srivastava         else if (auto keywordValue = get_if<size_t>(&kwdValMap.second))
582fa5e4d32SSunny Srivastava         {
583fa5e4d32SSunny Srivastava             if (kwd == "MemorySizeInKB")
584fa5e4d32SSunny Srivastava             {
585fa5e4d32SSunny Srivastava                 types::PropertyMap memProp;
586fa5e4d32SSunny Srivastava                 memProp.emplace(move(kwd), ((*keywordValue)));
587fa5e4d32SSunny Srivastava                 interfaceMap.emplace("xyz.openbmc_project.Inventory.Item.Dimm",
588fa5e4d32SSunny Srivastava                                      move(memProp));
589fa5e4d32SSunny Srivastava                 continue;
590fa5e4d32SSunny Srivastava             }
591fa5e4d32SSunny Srivastava             else
592fa5e4d32SSunny Srivastava             {
593fa5e4d32SSunny Srivastava                 logging::logMessage(
594fa5e4d32SSunny Srivastava                     "Unknown Keyword =" + kwd + " found in keyword VPD map");
595fa5e4d32SSunny Srivastava                 continue;
596fa5e4d32SSunny Srivastava             }
597fa5e4d32SSunny Srivastava         }
598fa5e4d32SSunny Srivastava         else
599fa5e4d32SSunny Srivastava         {
600fa5e4d32SSunny Srivastava             logging::logMessage(
601fa5e4d32SSunny Srivastava                 "Unknown variant type found in keyword VPD map.");
602fa5e4d32SSunny Srivastava             continue;
603fa5e4d32SSunny Srivastava         }
604fa5e4d32SSunny Srivastava 
605fa5e4d32SSunny Srivastava         if (!propertyValueMap.empty())
606fa5e4d32SSunny Srivastava         {
607fa5e4d32SSunny Srivastava             vpdSpecificUtility::insertOrMerge(
608fa5e4d32SSunny Srivastava                 interfaceMap, constants::kwdVpdInf, move(propertyValueMap));
609fa5e4d32SSunny Srivastava         }
610fa5e4d32SSunny Srivastava     }
611fa5e4d32SSunny Srivastava }
612fa5e4d32SSunny Srivastava 
populateInterfaces(const nlohmann::json & interfaceJson,types::InterfaceMap & interfaceMap,const types::VPDMapVariant & parsedVpdMap)613fa5e4d32SSunny Srivastava void Worker::populateInterfaces(const nlohmann::json& interfaceJson,
614fa5e4d32SSunny Srivastava                                 types::InterfaceMap& interfaceMap,
615fa5e4d32SSunny Srivastava                                 const types::VPDMapVariant& parsedVpdMap)
616fa5e4d32SSunny Srivastava {
617fa5e4d32SSunny Srivastava     for (const auto& interfacesPropPair : interfaceJson.items())
618fa5e4d32SSunny Srivastava     {
619fa5e4d32SSunny Srivastava         const std::string& interface = interfacesPropPair.key();
620fa5e4d32SSunny Srivastava         types::PropertyMap propertyMap;
621fa5e4d32SSunny Srivastava 
622fa5e4d32SSunny Srivastava         for (const auto& propValuePair : interfacesPropPair.value().items())
623fa5e4d32SSunny Srivastava         {
624fa5e4d32SSunny Srivastava             const std::string property = propValuePair.key();
625fa5e4d32SSunny Srivastava 
626fa5e4d32SSunny Srivastava             if (propValuePair.value().is_boolean())
627fa5e4d32SSunny Srivastava             {
628fa5e4d32SSunny Srivastava                 propertyMap.emplace(property,
629fa5e4d32SSunny Srivastava                                     propValuePair.value().get<bool>());
630fa5e4d32SSunny Srivastava             }
631fa5e4d32SSunny Srivastava             else if (propValuePair.value().is_string())
632fa5e4d32SSunny Srivastava             {
633fa5e4d32SSunny Srivastava                 if (property.compare("LocationCode") == 0 &&
634fa5e4d32SSunny Srivastava                     interface.compare("com.ibm.ipzvpd.Location") == 0)
635fa5e4d32SSunny Srivastava                 {
636fa5e4d32SSunny Srivastava                     std::string value =
637fa5e4d32SSunny Srivastava                         vpdSpecificUtility::getExpandedLocationCode(
638fa5e4d32SSunny Srivastava                             propValuePair.value().get<std::string>(),
639fa5e4d32SSunny Srivastava                             parsedVpdMap);
640fa5e4d32SSunny Srivastava                     propertyMap.emplace(property, value);
641fa5e4d32SSunny Srivastava 
642fa5e4d32SSunny Srivastava                     auto l_locCodeProperty = propertyMap;
643fa5e4d32SSunny Srivastava                     vpdSpecificUtility::insertOrMerge(
644fa5e4d32SSunny Srivastava                         interfaceMap,
645fa5e4d32SSunny Srivastava                         std::string(constants::xyzLocationCodeInf),
646fa5e4d32SSunny Srivastava                         move(l_locCodeProperty));
647fa5e4d32SSunny Srivastava                 }
648fa5e4d32SSunny Srivastava                 else
649fa5e4d32SSunny Srivastava                 {
650fa5e4d32SSunny Srivastava                     propertyMap.emplace(
651fa5e4d32SSunny Srivastava                         property, propValuePair.value().get<std::string>());
652fa5e4d32SSunny Srivastava                 }
653fa5e4d32SSunny Srivastava             }
654fa5e4d32SSunny Srivastava             else if (propValuePair.value().is_array())
655fa5e4d32SSunny Srivastava             {
656fa5e4d32SSunny Srivastava                 try
657fa5e4d32SSunny Srivastava                 {
658fa5e4d32SSunny Srivastava                     propertyMap.emplace(
659fa5e4d32SSunny Srivastava                         property,
660fa5e4d32SSunny Srivastava                         propValuePair.value().get<types::BinaryVector>());
661fa5e4d32SSunny Srivastava                 }
662fa5e4d32SSunny Srivastava                 catch (const nlohmann::detail::type_error& e)
663fa5e4d32SSunny Srivastava                 {
664fa5e4d32SSunny Srivastava                     std::cerr << "Type exception: " << e.what() << "\n";
665fa5e4d32SSunny Srivastava                 }
666fa5e4d32SSunny Srivastava             }
667fa5e4d32SSunny Srivastava             else if (propValuePair.value().is_number())
668fa5e4d32SSunny Srivastava             {
669fa5e4d32SSunny Srivastava                 // For now assume the value is a size_t.  In the future it would
670fa5e4d32SSunny Srivastava                 // be nice to come up with a way to get the type from the JSON.
671fa5e4d32SSunny Srivastava                 propertyMap.emplace(property,
672fa5e4d32SSunny Srivastava                                     propValuePair.value().get<size_t>());
673fa5e4d32SSunny Srivastava             }
674fa5e4d32SSunny Srivastava             else if (propValuePair.value().is_object())
675fa5e4d32SSunny Srivastava             {
676fa5e4d32SSunny Srivastava                 const std::string& record =
677fa5e4d32SSunny Srivastava                     propValuePair.value().value("recordName", "");
678fa5e4d32SSunny Srivastava                 const std::string& keyword =
679fa5e4d32SSunny Srivastava                     propValuePair.value().value("keywordName", "");
680fa5e4d32SSunny Srivastava                 const std::string& encoding =
681fa5e4d32SSunny Srivastava                     propValuePair.value().value("encoding", "");
682fa5e4d32SSunny Srivastava 
683fa5e4d32SSunny Srivastava                 if (auto ipzVpdMap =
684fa5e4d32SSunny Srivastava                         std::get_if<types::IPZVpdMap>(&parsedVpdMap))
685fa5e4d32SSunny Srivastava                 {
686fa5e4d32SSunny Srivastava                     if (!record.empty() && !keyword.empty() &&
687fa5e4d32SSunny Srivastava                         (*ipzVpdMap).count(record) &&
688fa5e4d32SSunny Srivastava                         (*ipzVpdMap).at(record).count(keyword))
689fa5e4d32SSunny Srivastava                     {
690fa5e4d32SSunny Srivastava                         auto encoded = vpdSpecificUtility::encodeKeyword(
691fa5e4d32SSunny Srivastava                             ((*ipzVpdMap).at(record).at(keyword)), encoding);
692fa5e4d32SSunny Srivastava                         propertyMap.emplace(property, encoded);
693fa5e4d32SSunny Srivastava                     }
694fa5e4d32SSunny Srivastava                 }
695fa5e4d32SSunny Srivastava                 else if (auto kwdVpdMap =
696fa5e4d32SSunny Srivastava                              std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
697fa5e4d32SSunny Srivastava                 {
698fa5e4d32SSunny Srivastava                     if (!keyword.empty() && (*kwdVpdMap).count(keyword))
699fa5e4d32SSunny Srivastava                     {
700fa5e4d32SSunny Srivastava                         if (auto kwValue = std::get_if<types::BinaryVector>(
701fa5e4d32SSunny Srivastava                                 &(*kwdVpdMap).at(keyword)))
702fa5e4d32SSunny Srivastava                         {
703fa5e4d32SSunny Srivastava                             auto encodedValue =
704fa5e4d32SSunny Srivastava                                 vpdSpecificUtility::encodeKeyword(
705fa5e4d32SSunny Srivastava                                     std::string((*kwValue).begin(),
706fa5e4d32SSunny Srivastava                                                 (*kwValue).end()),
707fa5e4d32SSunny Srivastava                                     encoding);
708fa5e4d32SSunny Srivastava 
709fa5e4d32SSunny Srivastava                             propertyMap.emplace(property, encodedValue);
710fa5e4d32SSunny Srivastava                         }
711fa5e4d32SSunny Srivastava                         else if (auto kwValue = std::get_if<std::string>(
712fa5e4d32SSunny Srivastava                                      &(*kwdVpdMap).at(keyword)))
713fa5e4d32SSunny Srivastava                         {
714fa5e4d32SSunny Srivastava                             auto encodedValue =
715fa5e4d32SSunny Srivastava                                 vpdSpecificUtility::encodeKeyword(
716fa5e4d32SSunny Srivastava                                     std::string((*kwValue).begin(),
717fa5e4d32SSunny Srivastava                                                 (*kwValue).end()),
718fa5e4d32SSunny Srivastava                                     encoding);
719fa5e4d32SSunny Srivastava 
720fa5e4d32SSunny Srivastava                             propertyMap.emplace(property, encodedValue);
721fa5e4d32SSunny Srivastava                         }
722fa5e4d32SSunny Srivastava                         else if (auto uintValue = std::get_if<size_t>(
723fa5e4d32SSunny Srivastava                                      &(*kwdVpdMap).at(keyword)))
724fa5e4d32SSunny Srivastava                         {
725fa5e4d32SSunny Srivastava                             propertyMap.emplace(property, *uintValue);
726fa5e4d32SSunny Srivastava                         }
727fa5e4d32SSunny Srivastava                         else
728fa5e4d32SSunny Srivastava                         {
729fa5e4d32SSunny Srivastava                             logging::logMessage(
730fa5e4d32SSunny Srivastava                                 "Unknown keyword found, Keywrod = " + keyword);
731fa5e4d32SSunny Srivastava                         }
732fa5e4d32SSunny Srivastava                     }
733fa5e4d32SSunny Srivastava                 }
734fa5e4d32SSunny Srivastava             }
735fa5e4d32SSunny Srivastava         }
736fa5e4d32SSunny Srivastava         vpdSpecificUtility::insertOrMerge(interfaceMap, interface,
737fa5e4d32SSunny Srivastava                                           move(propertyMap));
738fa5e4d32SSunny Srivastava     }
739fa5e4d32SSunny Srivastava }
740fa5e4d32SSunny Srivastava 
isCPUIOGoodOnly(const std::string & i_pgKeyword)741fa5e4d32SSunny Srivastava bool Worker::isCPUIOGoodOnly(const std::string& i_pgKeyword)
742fa5e4d32SSunny Srivastava {
743fa5e4d32SSunny Srivastava     const unsigned char l_io[] = {
744fa5e4d32SSunny Srivastava         0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF,
745fa5e4d32SSunny Srivastava         0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF};
746fa5e4d32SSunny Srivastava 
747fa5e4d32SSunny Srivastava     // EQ0 index (in PG keyword) starts at 97 (with offset starting from 0).
748fa5e4d32SSunny Srivastava     // Each EQ carries 3 bytes of data. Totally there are 8 EQs. If all EQs'
749fa5e4d32SSunny Srivastava     // value equals 0xE7F9FF, then the cpu has no good cores and its treated as
750fa5e4d32SSunny Srivastava     // IO.
751fa5e4d32SSunny Srivastava     if (memcmp(l_io, i_pgKeyword.data() + constants::INDEX_OF_EQ0_IN_PG,
752fa5e4d32SSunny Srivastava                constants::SIZE_OF_8EQ_IN_PG) == 0)
753fa5e4d32SSunny Srivastava     {
754fa5e4d32SSunny Srivastava         return true;
755fa5e4d32SSunny Srivastava     }
756fa5e4d32SSunny Srivastava 
757fa5e4d32SSunny Srivastava     // The CPU is not an IO
758fa5e4d32SSunny Srivastava     return false;
759fa5e4d32SSunny Srivastava }
760fa5e4d32SSunny Srivastava 
primeInventory(const std::string & i_vpdFilePath)761fa5e4d32SSunny Srivastava bool Worker::primeInventory(const std::string& i_vpdFilePath)
762fa5e4d32SSunny Srivastava {
763fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty())
764fa5e4d32SSunny Srivastava     {
765fa5e4d32SSunny Srivastava         logging::logMessage("Empty VPD file path given");
766fa5e4d32SSunny Srivastava         return false;
767fa5e4d32SSunny Srivastava     }
768fa5e4d32SSunny Srivastava 
769fa5e4d32SSunny Srivastava     if (m_parsedJson.empty())
770fa5e4d32SSunny Srivastava     {
771fa5e4d32SSunny Srivastava         logging::logMessage("Empty JSON detected for " + i_vpdFilePath);
772fa5e4d32SSunny Srivastava         return false;
773fa5e4d32SSunny Srivastava     }
774fa5e4d32SSunny Srivastava     else if (!m_parsedJson["frus"].contains(i_vpdFilePath))
775fa5e4d32SSunny Srivastava     {
776fa5e4d32SSunny Srivastava         logging::logMessage("File " + i_vpdFilePath +
777fa5e4d32SSunny Srivastava                             ", is not found in the system config JSON file.");
778fa5e4d32SSunny Srivastava         return false;
779fa5e4d32SSunny Srivastava     }
780fa5e4d32SSunny Srivastava 
781fa5e4d32SSunny Srivastava     types::ObjectMap l_objectInterfaceMap;
782fa5e4d32SSunny Srivastava     for (const auto& l_Fru : m_parsedJson["frus"][i_vpdFilePath])
783fa5e4d32SSunny Srivastava     {
784fa5e4d32SSunny Srivastava         types::InterfaceMap l_interfaces;
785fa5e4d32SSunny Srivastava         sdbusplus::message::object_path l_fruObjectPath(l_Fru["inventoryPath"]);
786fa5e4d32SSunny Srivastava 
787fa5e4d32SSunny Srivastava         if (l_Fru.contains("ccin"))
788fa5e4d32SSunny Srivastava         {
789fa5e4d32SSunny Srivastava             continue;
790fa5e4d32SSunny Srivastava         }
791fa5e4d32SSunny Srivastava 
792fa5e4d32SSunny Srivastava         if (l_Fru.contains("noprime") && l_Fru.value("noprime", false))
793fa5e4d32SSunny Srivastava         {
794fa5e4d32SSunny Srivastava             continue;
795fa5e4d32SSunny Srivastava         }
796fa5e4d32SSunny Srivastava 
7976a9553c8SSouvik Roy         // Reset data under PIM for this FRU only if the FRU is not synthesized
7986a9553c8SSouvik Roy         // and we handle it's Present property.
7996a9553c8SSouvik Roy         if (isPresentPropertyHandlingRequired(l_Fru))
8006a9553c8SSouvik Roy         {
801fa5e4d32SSunny Srivastava             // Clear data under PIM if already exists.
802fa5e4d32SSunny Srivastava             vpdSpecificUtility::resetDataUnderPIM(
803fa5e4d32SSunny Srivastava                 std::string(l_Fru["inventoryPath"]), l_interfaces);
8046a9553c8SSouvik Roy         }
805fa5e4d32SSunny Srivastava 
806fa5e4d32SSunny Srivastava         // Add extra interfaces mentioned in the Json config file
807fa5e4d32SSunny Srivastava         if (l_Fru.contains("extraInterfaces"))
808fa5e4d32SSunny Srivastava         {
809fa5e4d32SSunny Srivastava             populateInterfaces(l_Fru["extraInterfaces"], l_interfaces,
810fa5e4d32SSunny Srivastava                                std::monostate{});
811fa5e4d32SSunny Srivastava         }
812fa5e4d32SSunny Srivastava 
813fa5e4d32SSunny Srivastava         types::PropertyMap l_propertyValueMap;
8146a9553c8SSouvik Roy 
8156a9553c8SSouvik Roy         // Update Present property for this FRU only if we handle Present
8166a9553c8SSouvik Roy         // property for the FRU.
8176a9553c8SSouvik Roy         if (isPresentPropertyHandlingRequired(l_Fru))
8186a9553c8SSouvik Roy         {
819fa5e4d32SSunny Srivastava             l_propertyValueMap.emplace("Present", false);
820d159bb49SSunny Srivastava 
821d159bb49SSunny Srivastava             // TODO: Present based on file will be taken care in future.
822d159bb49SSunny Srivastava             // By default present is set to false for FRU at the time of
8236a9553c8SSouvik Roy             // priming. Once collection goes through, it will be set to true in
8246a9553c8SSouvik Roy             // that flow.
825d159bb49SSunny Srivastava             /*if (std::filesystem::exists(i_vpdFilePath))
826fa5e4d32SSunny Srivastava             {
827fa5e4d32SSunny Srivastava                 l_propertyValueMap["Present"] = true;
828d159bb49SSunny Srivastava             }*/
8296a9553c8SSouvik Roy         }
830fa5e4d32SSunny Srivastava 
831fa5e4d32SSunny Srivastava         vpdSpecificUtility::insertOrMerge(l_interfaces,
832fa5e4d32SSunny Srivastava                                           "xyz.openbmc_project.Inventory.Item",
833fa5e4d32SSunny Srivastava                                           move(l_propertyValueMap));
834fa5e4d32SSunny Srivastava 
835fa5e4d32SSunny Srivastava         if (l_Fru.value("inherit", true) &&
836fa5e4d32SSunny Srivastava             m_parsedJson.contains("commonInterfaces"))
837fa5e4d32SSunny Srivastava         {
838fa5e4d32SSunny Srivastava             populateInterfaces(m_parsedJson["commonInterfaces"], l_interfaces,
839fa5e4d32SSunny Srivastava                                std::monostate{});
840fa5e4d32SSunny Srivastava         }
841fa5e4d32SSunny Srivastava 
842fa5e4d32SSunny Srivastava         processFunctionalProperty(l_Fru["inventoryPath"], l_interfaces);
843fa5e4d32SSunny Srivastava         processEnabledProperty(l_Fru["inventoryPath"], l_interfaces);
844fa5e4d32SSunny Srivastava 
8451aad7834SPriyanga Ramasamy         // Emplace the default state of FRU VPD collection
8461aad7834SPriyanga Ramasamy         types::PropertyMap l_fruCollectionProperty = {
8471aad7834SPriyanga Ramasamy             {"CollectionStatus", constants::vpdCollectionNotStarted}};
8481aad7834SPriyanga Ramasamy 
8491aad7834SPriyanga Ramasamy         vpdSpecificUtility::insertOrMerge(l_interfaces,
8501aad7834SPriyanga Ramasamy                                           constants::vpdCollectionInterface,
8511aad7834SPriyanga Ramasamy                                           std::move(l_fruCollectionProperty));
8521aad7834SPriyanga Ramasamy 
853fa5e4d32SSunny Srivastava         l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
854fa5e4d32SSunny Srivastava                                      std::move(l_interfaces));
855fa5e4d32SSunny Srivastava     }
856fa5e4d32SSunny Srivastava 
857fa5e4d32SSunny Srivastava     // Notify PIM
858fa5e4d32SSunny Srivastava     if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
859fa5e4d32SSunny Srivastava     {
860fa5e4d32SSunny Srivastava         logging::logMessage("Call to PIM failed for VPD file " + i_vpdFilePath);
861fa5e4d32SSunny Srivastava         return false;
862fa5e4d32SSunny Srivastava     }
863fa5e4d32SSunny Srivastava 
864fa5e4d32SSunny Srivastava     return true;
865fa5e4d32SSunny Srivastava }
866fa5e4d32SSunny Srivastava 
processEmbeddedAndSynthesizedFrus(const nlohmann::json & singleFru,types::InterfaceMap & interfaces)867fa5e4d32SSunny Srivastava void Worker::processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
868fa5e4d32SSunny Srivastava                                                types::InterfaceMap& interfaces)
869fa5e4d32SSunny Srivastava {
870fa5e4d32SSunny Srivastava     // embedded property(true or false) says whether the subfru is embedded
871fa5e4d32SSunny Srivastava     // into the parent fru (or) not. VPD sets Present property only for
872fa5e4d32SSunny Srivastava     // embedded frus. If the subfru is not an embedded FRU, the subfru may
873fa5e4d32SSunny Srivastava     // or may not be physically present. Those non embedded frus will always
874fa5e4d32SSunny Srivastava     // have Present=false irrespective of its physical presence or absence.
875fa5e4d32SSunny Srivastava     // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
876fa5e4d32SSunny Srivastava     // Present to true for such sub frus.
877fa5e4d32SSunny Srivastava     // Eg: ethernet port is embedded into bmc card. So set Present to true
878fa5e4d32SSunny Srivastava     // for such sub frus. Also donot populate present property for embedded
879fa5e4d32SSunny Srivastava     // subfru which is synthesized. Currently there is no subfru which are
880fa5e4d32SSunny Srivastava     // both embedded and synthesized. But still the case is handled here.
881fa5e4d32SSunny Srivastava 
882fa5e4d32SSunny Srivastava     // Check if its required to handle presence for this FRU.
883fa5e4d32SSunny Srivastava     if (singleFru.value("handlePresence", true))
884fa5e4d32SSunny Srivastava     {
885fa5e4d32SSunny Srivastava         types::PropertyMap presProp;
886fa5e4d32SSunny Srivastava         presProp.emplace("Present", true);
887fa5e4d32SSunny Srivastava         vpdSpecificUtility::insertOrMerge(
888fa5e4d32SSunny Srivastava             interfaces, "xyz.openbmc_project.Inventory.Item", move(presProp));
889fa5e4d32SSunny Srivastava     }
890fa5e4d32SSunny Srivastava }
891fa5e4d32SSunny Srivastava 
processExtraInterfaces(const nlohmann::json & singleFru,types::InterfaceMap & interfaces,const types::VPDMapVariant & parsedVpdMap)892fa5e4d32SSunny Srivastava void Worker::processExtraInterfaces(const nlohmann::json& singleFru,
893fa5e4d32SSunny Srivastava                                     types::InterfaceMap& interfaces,
894fa5e4d32SSunny Srivastava                                     const types::VPDMapVariant& parsedVpdMap)
895fa5e4d32SSunny Srivastava {
896fa5e4d32SSunny Srivastava     populateInterfaces(singleFru["extraInterfaces"], interfaces, parsedVpdMap);
897fa5e4d32SSunny Srivastava     if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
898fa5e4d32SSunny Srivastava     {
899fa5e4d32SSunny Srivastava         if (singleFru["extraInterfaces"].contains(
900fa5e4d32SSunny Srivastava                 "xyz.openbmc_project.Inventory.Item.Cpu"))
901fa5e4d32SSunny Srivastava         {
902fa5e4d32SSunny Srivastava             auto itrToRec = (*ipzVpdMap).find("CP00");
903fa5e4d32SSunny Srivastava             if (itrToRec == (*ipzVpdMap).end())
904fa5e4d32SSunny Srivastava             {
905fa5e4d32SSunny Srivastava                 return;
906fa5e4d32SSunny Srivastava             }
907fa5e4d32SSunny Srivastava 
908a55fcca1SSouvik Roy             const std::string pgKeywordValue{
909a55fcca1SSouvik Roy                 vpdSpecificUtility::getKwVal(itrToRec->second, "PG")};
910a55fcca1SSouvik Roy 
911fa5e4d32SSunny Srivastava             if (!pgKeywordValue.empty())
912fa5e4d32SSunny Srivastava             {
913fa5e4d32SSunny Srivastava                 if (isCPUIOGoodOnly(pgKeywordValue))
914fa5e4d32SSunny Srivastava                 {
915fa5e4d32SSunny Srivastava                     interfaces["xyz.openbmc_project.Inventory.Item"]
916fa5e4d32SSunny Srivastava                               ["PrettyName"] = "IO Module";
917fa5e4d32SSunny Srivastava                 }
918fa5e4d32SSunny Srivastava             }
919a55fcca1SSouvik Roy             else
920a55fcca1SSouvik Roy             {
921a55fcca1SSouvik Roy                 throw std::runtime_error("Failed to get value for keyword PG");
922a55fcca1SSouvik Roy             }
923fa5e4d32SSunny Srivastava         }
924fa5e4d32SSunny Srivastava     }
925fa5e4d32SSunny Srivastava }
926fa5e4d32SSunny Srivastava 
processCopyRecordFlag(const nlohmann::json & singleFru,const types::VPDMapVariant & parsedVpdMap,types::InterfaceMap & interfaces)927fa5e4d32SSunny Srivastava void Worker::processCopyRecordFlag(const nlohmann::json& singleFru,
928fa5e4d32SSunny Srivastava                                    const types::VPDMapVariant& parsedVpdMap,
929fa5e4d32SSunny Srivastava                                    types::InterfaceMap& interfaces)
930fa5e4d32SSunny Srivastava {
931fa5e4d32SSunny Srivastava     if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
932fa5e4d32SSunny Srivastava     {
933fa5e4d32SSunny Srivastava         for (const auto& record : singleFru["copyRecords"])
934fa5e4d32SSunny Srivastava         {
935fa5e4d32SSunny Srivastava             const std::string& recordName = record;
936fa5e4d32SSunny Srivastava             if ((*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
937fa5e4d32SSunny Srivastava             {
938fa5e4d32SSunny Srivastava                 populateIPZVPDpropertyMap(interfaces,
939fa5e4d32SSunny Srivastava                                           (*ipzVpdMap).at(recordName),
940fa5e4d32SSunny Srivastava                                           constants::ipzVpdInf + recordName);
941fa5e4d32SSunny Srivastava             }
942fa5e4d32SSunny Srivastava         }
943fa5e4d32SSunny Srivastava     }
944fa5e4d32SSunny Srivastava }
945fa5e4d32SSunny Srivastava 
processInheritFlag(const types::VPDMapVariant & parsedVpdMap,types::InterfaceMap & interfaces)946fa5e4d32SSunny Srivastava void Worker::processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
947fa5e4d32SSunny Srivastava                                 types::InterfaceMap& interfaces)
948fa5e4d32SSunny Srivastava {
949fa5e4d32SSunny Srivastava     if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
950fa5e4d32SSunny Srivastava     {
951fa5e4d32SSunny Srivastava         for (const auto& [recordName, kwdValueMap] : *ipzVpdMap)
952fa5e4d32SSunny Srivastava         {
953fa5e4d32SSunny Srivastava             populateIPZVPDpropertyMap(interfaces, kwdValueMap,
954fa5e4d32SSunny Srivastava                                       constants::ipzVpdInf + recordName);
955fa5e4d32SSunny Srivastava         }
956fa5e4d32SSunny Srivastava     }
957fa5e4d32SSunny Srivastava     else if (auto kwdVpdMap = std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
958fa5e4d32SSunny Srivastava     {
959fa5e4d32SSunny Srivastava         populateKwdVPDpropertyMap(*kwdVpdMap, interfaces);
960fa5e4d32SSunny Srivastava     }
961fa5e4d32SSunny Srivastava 
962fa5e4d32SSunny Srivastava     if (m_parsedJson.contains("commonInterfaces"))
963fa5e4d32SSunny Srivastava     {
964fa5e4d32SSunny Srivastava         populateInterfaces(m_parsedJson["commonInterfaces"], interfaces,
965fa5e4d32SSunny Srivastava                            parsedVpdMap);
966fa5e4d32SSunny Srivastava     }
967fa5e4d32SSunny Srivastava }
968fa5e4d32SSunny Srivastava 
processFruWithCCIN(const nlohmann::json & singleFru,const types::VPDMapVariant & parsedVpdMap)969fa5e4d32SSunny Srivastava bool Worker::processFruWithCCIN(const nlohmann::json& singleFru,
970fa5e4d32SSunny Srivastava                                 const types::VPDMapVariant& parsedVpdMap)
971fa5e4d32SSunny Srivastava {
972fa5e4d32SSunny Srivastava     if (auto ipzVPDMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
973fa5e4d32SSunny Srivastava     {
974fa5e4d32SSunny Srivastava         auto itrToRec = (*ipzVPDMap).find("VINI");
975fa5e4d32SSunny Srivastava         if (itrToRec == (*ipzVPDMap).end())
976fa5e4d32SSunny Srivastava         {
977fa5e4d32SSunny Srivastava             return false;
978fa5e4d32SSunny Srivastava         }
979fa5e4d32SSunny Srivastava 
980a55fcca1SSouvik Roy         std::string ccinFromVpd{
981a55fcca1SSouvik Roy             vpdSpecificUtility::getKwVal(itrToRec->second, "CC")};
982a55fcca1SSouvik Roy 
983fa5e4d32SSunny Srivastava         if (ccinFromVpd.empty())
984fa5e4d32SSunny Srivastava         {
985fa5e4d32SSunny Srivastava             return false;
986fa5e4d32SSunny Srivastava         }
987fa5e4d32SSunny Srivastava 
988fa5e4d32SSunny Srivastava         transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
989fa5e4d32SSunny Srivastava                   ::toupper);
990fa5e4d32SSunny Srivastava 
991fa5e4d32SSunny Srivastava         std::vector<std::string> ccinList;
992fa5e4d32SSunny Srivastava         for (std::string ccin : singleFru["ccin"])
993fa5e4d32SSunny Srivastava         {
994fa5e4d32SSunny Srivastava             transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
995fa5e4d32SSunny Srivastava             ccinList.push_back(ccin);
996fa5e4d32SSunny Srivastava         }
997fa5e4d32SSunny Srivastava 
998fa5e4d32SSunny Srivastava         if (ccinList.empty())
999fa5e4d32SSunny Srivastava         {
1000fa5e4d32SSunny Srivastava             return false;
1001fa5e4d32SSunny Srivastava         }
1002fa5e4d32SSunny Srivastava 
1003fa5e4d32SSunny Srivastava         if (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
1004fa5e4d32SSunny Srivastava             ccinList.end())
1005fa5e4d32SSunny Srivastava         {
1006fa5e4d32SSunny Srivastava             return false;
1007fa5e4d32SSunny Srivastava         }
1008fa5e4d32SSunny Srivastava     }
1009fa5e4d32SSunny Srivastava     return true;
1010fa5e4d32SSunny Srivastava }
1011fa5e4d32SSunny Srivastava 
processFunctionalProperty(const std::string & i_inventoryObjPath,types::InterfaceMap & io_interfaces)1012fa5e4d32SSunny Srivastava void Worker::processFunctionalProperty(const std::string& i_inventoryObjPath,
1013fa5e4d32SSunny Srivastava                                        types::InterfaceMap& io_interfaces)
1014fa5e4d32SSunny Srivastava {
1015fa5e4d32SSunny Srivastava     if (!dbusUtility::isChassisPowerOn())
1016fa5e4d32SSunny Srivastava     {
1017fa5e4d32SSunny Srivastava         std::array<const char*, 1> l_operationalStatusInf = {
1018fa5e4d32SSunny Srivastava             constants::operationalStatusInf};
1019fa5e4d32SSunny Srivastava 
1020fa5e4d32SSunny Srivastava         auto mapperObjectMap = dbusUtility::getObjectMap(
1021fa5e4d32SSunny Srivastava             i_inventoryObjPath, l_operationalStatusInf);
1022fa5e4d32SSunny Srivastava 
1023fa5e4d32SSunny Srivastava         // If the object has been found. Check if it is under PIM.
1024fa5e4d32SSunny Srivastava         if (mapperObjectMap.size() != 0)
1025fa5e4d32SSunny Srivastava         {
1026fa5e4d32SSunny Srivastava             for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
1027fa5e4d32SSunny Srivastava             {
1028fa5e4d32SSunny Srivastava                 if (l_serviceName == constants::pimServiceName)
1029fa5e4d32SSunny Srivastava                 {
1030fa5e4d32SSunny Srivastava                     // The object is already under PIM. No need to process
1031fa5e4d32SSunny Srivastava                     // again. Retain the old value.
1032fa5e4d32SSunny Srivastava                     return;
1033fa5e4d32SSunny Srivastava                 }
1034fa5e4d32SSunny Srivastava             }
1035fa5e4d32SSunny Srivastava         }
1036fa5e4d32SSunny Srivastava 
1037fa5e4d32SSunny Srivastava         // Implies value is not there in D-Bus. Populate it with default
1038fa5e4d32SSunny Srivastava         // value "true".
1039fa5e4d32SSunny Srivastava         types::PropertyMap l_functionalProp;
1040fa5e4d32SSunny Srivastava         l_functionalProp.emplace("Functional", true);
1041fa5e4d32SSunny Srivastava         vpdSpecificUtility::insertOrMerge(io_interfaces,
1042fa5e4d32SSunny Srivastava                                           constants::operationalStatusInf,
1043fa5e4d32SSunny Srivastava                                           move(l_functionalProp));
1044fa5e4d32SSunny Srivastava     }
1045fa5e4d32SSunny Srivastava 
1046fa5e4d32SSunny Srivastava     // if chassis is power on. Functional property should be there on D-Bus.
1047fa5e4d32SSunny Srivastava     // Don't process.
1048fa5e4d32SSunny Srivastava     return;
1049fa5e4d32SSunny Srivastava }
1050fa5e4d32SSunny Srivastava 
processEnabledProperty(const std::string & i_inventoryObjPath,types::InterfaceMap & io_interfaces)1051fa5e4d32SSunny Srivastava void Worker::processEnabledProperty(const std::string& i_inventoryObjPath,
1052fa5e4d32SSunny Srivastava                                     types::InterfaceMap& io_interfaces)
1053fa5e4d32SSunny Srivastava {
1054fa5e4d32SSunny Srivastava     if (!dbusUtility::isChassisPowerOn())
1055fa5e4d32SSunny Srivastava     {
1056fa5e4d32SSunny Srivastava         std::array<const char*, 1> l_enableInf = {constants::enableInf};
1057fa5e4d32SSunny Srivastava 
1058fa5e4d32SSunny Srivastava         auto mapperObjectMap =
1059fa5e4d32SSunny Srivastava             dbusUtility::getObjectMap(i_inventoryObjPath, l_enableInf);
1060fa5e4d32SSunny Srivastava 
1061fa5e4d32SSunny Srivastava         // If the object has been found. Check if it is under PIM.
1062fa5e4d32SSunny Srivastava         if (mapperObjectMap.size() != 0)
1063fa5e4d32SSunny Srivastava         {
1064fa5e4d32SSunny Srivastava             for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
1065fa5e4d32SSunny Srivastava             {
1066fa5e4d32SSunny Srivastava                 if (l_serviceName == constants::pimServiceName)
1067fa5e4d32SSunny Srivastava                 {
1068fa5e4d32SSunny Srivastava                     // The object is already under PIM. No need to process
1069fa5e4d32SSunny Srivastava                     // again. Retain the old value.
1070fa5e4d32SSunny Srivastava                     return;
1071fa5e4d32SSunny Srivastava                 }
1072fa5e4d32SSunny Srivastava             }
1073fa5e4d32SSunny Srivastava         }
1074fa5e4d32SSunny Srivastava 
1075fa5e4d32SSunny Srivastava         // Implies value is not there in D-Bus. Populate it with default
1076fa5e4d32SSunny Srivastava         // value "true".
1077fa5e4d32SSunny Srivastava         types::PropertyMap l_enabledProp;
1078fa5e4d32SSunny Srivastava         l_enabledProp.emplace("Enabled", true);
1079fa5e4d32SSunny Srivastava         vpdSpecificUtility::insertOrMerge(io_interfaces, constants::enableInf,
1080fa5e4d32SSunny Srivastava                                           move(l_enabledProp));
1081fa5e4d32SSunny Srivastava     }
1082fa5e4d32SSunny Srivastava 
1083fa5e4d32SSunny Srivastava     // if chassis is power on. Enabled property should be there on D-Bus.
1084fa5e4d32SSunny Srivastava     // Don't process.
1085fa5e4d32SSunny Srivastava     return;
1086fa5e4d32SSunny Srivastava }
1087fa5e4d32SSunny Srivastava 
populateDbus(const types::VPDMapVariant & parsedVpdMap,types::ObjectMap & objectInterfaceMap,const std::string & vpdFilePath)1088fa5e4d32SSunny Srivastava void Worker::populateDbus(const types::VPDMapVariant& parsedVpdMap,
1089fa5e4d32SSunny Srivastava                           types::ObjectMap& objectInterfaceMap,
1090fa5e4d32SSunny Srivastava                           const std::string& vpdFilePath)
1091fa5e4d32SSunny Srivastava {
1092fa5e4d32SSunny Srivastava     if (vpdFilePath.empty())
1093fa5e4d32SSunny Srivastava     {
1094fa5e4d32SSunny Srivastava         throw std::runtime_error(
1095fa5e4d32SSunny Srivastava             "Invalid parameter passed to populateDbus API.");
1096fa5e4d32SSunny Srivastava     }
1097fa5e4d32SSunny Srivastava 
1098fa5e4d32SSunny Srivastava     // JSON config is mandatory for processing of "if". Add "else" for any
1099fa5e4d32SSunny Srivastava     // processing without config JSON.
1100fa5e4d32SSunny Srivastava     if (!m_parsedJson.empty())
1101fa5e4d32SSunny Srivastava     {
1102fa5e4d32SSunny Srivastava         types::InterfaceMap interfaces;
1103fa5e4d32SSunny Srivastava 
1104fa5e4d32SSunny Srivastava         for (const auto& aFru : m_parsedJson["frus"][vpdFilePath])
1105fa5e4d32SSunny Srivastava         {
1106fa5e4d32SSunny Srivastava             const auto& inventoryPath = aFru["inventoryPath"];
1107fa5e4d32SSunny Srivastava             sdbusplus::message::object_path fruObjectPath(inventoryPath);
1108fa5e4d32SSunny Srivastava             if (aFru.contains("ccin"))
1109fa5e4d32SSunny Srivastava             {
1110fa5e4d32SSunny Srivastava                 if (!processFruWithCCIN(aFru, parsedVpdMap))
1111fa5e4d32SSunny Srivastava                 {
1112fa5e4d32SSunny Srivastava                     continue;
1113fa5e4d32SSunny Srivastava                 }
1114fa5e4d32SSunny Srivastava             }
1115fa5e4d32SSunny Srivastava 
1116fa5e4d32SSunny Srivastava             if (aFru.value("inherit", true))
1117fa5e4d32SSunny Srivastava             {
1118fa5e4d32SSunny Srivastava                 processInheritFlag(parsedVpdMap, interfaces);
1119fa5e4d32SSunny Srivastava             }
1120fa5e4d32SSunny Srivastava 
1121fa5e4d32SSunny Srivastava             // If specific record needs to be copied.
1122fa5e4d32SSunny Srivastava             if (aFru.contains("copyRecords"))
1123fa5e4d32SSunny Srivastava             {
1124fa5e4d32SSunny Srivastava                 processCopyRecordFlag(aFru, parsedVpdMap, interfaces);
1125fa5e4d32SSunny Srivastava             }
1126fa5e4d32SSunny Srivastava 
1127fa5e4d32SSunny Srivastava             if (aFru.contains("extraInterfaces"))
1128fa5e4d32SSunny Srivastava             {
1129fa5e4d32SSunny Srivastava                 // Process extra interfaces w.r.t a FRU.
1130fa5e4d32SSunny Srivastava                 processExtraInterfaces(aFru, interfaces, parsedVpdMap);
1131fa5e4d32SSunny Srivastava             }
1132fa5e4d32SSunny Srivastava 
1133fa5e4d32SSunny Srivastava             // Process FRUS which are embedded in the parent FRU and whose VPD
1134fa5e4d32SSunny Srivastava             // will be synthesized.
1135fa5e4d32SSunny Srivastava             if ((aFru.value("embedded", true)) &&
1136fa5e4d32SSunny Srivastava                 (!aFru.value("synthesized", false)))
1137fa5e4d32SSunny Srivastava             {
1138fa5e4d32SSunny Srivastava                 processEmbeddedAndSynthesizedFrus(aFru, interfaces);
1139fa5e4d32SSunny Srivastava             }
1140fa5e4d32SSunny Srivastava 
1141fa5e4d32SSunny Srivastava             processFunctionalProperty(inventoryPath, interfaces);
1142fa5e4d32SSunny Srivastava             processEnabledProperty(inventoryPath, interfaces);
1143fa5e4d32SSunny Srivastava 
11441aad7834SPriyanga Ramasamy             // Update collection status as successful
11451aad7834SPriyanga Ramasamy             types::PropertyMap l_collectionProperty = {
11461aad7834SPriyanga Ramasamy                 {"CollectionStatus", constants::vpdCollectionSuccess}};
11471aad7834SPriyanga Ramasamy 
11481aad7834SPriyanga Ramasamy             vpdSpecificUtility::insertOrMerge(interfaces,
11491aad7834SPriyanga Ramasamy                                               constants::vpdCollectionInterface,
11501aad7834SPriyanga Ramasamy                                               std::move(l_collectionProperty));
11511aad7834SPriyanga Ramasamy 
1152fa5e4d32SSunny Srivastava             objectInterfaceMap.emplace(std::move(fruObjectPath),
1153fa5e4d32SSunny Srivastava                                        std::move(interfaces));
1154fa5e4d32SSunny Srivastava         }
1155fa5e4d32SSunny Srivastava     }
1156fa5e4d32SSunny Srivastava }
1157fa5e4d32SSunny Srivastava 
createAssetTagString(const types::VPDMapVariant & i_parsedVpdMap)115843fedabcSPatrick Williams std::string Worker::createAssetTagString(
115943fedabcSPatrick Williams     const types::VPDMapVariant& i_parsedVpdMap)
1160fa5e4d32SSunny Srivastava {
1161fa5e4d32SSunny Srivastava     std::string l_assetTag;
1162fa5e4d32SSunny Srivastava 
1163fa5e4d32SSunny Srivastava     // system VPD will be in IPZ format.
1164fa5e4d32SSunny Srivastava     if (auto l_parsedVpdMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
1165fa5e4d32SSunny Srivastava     {
1166fa5e4d32SSunny Srivastava         auto l_itrToVsys = (*l_parsedVpdMap).find(constants::recVSYS);
1167fa5e4d32SSunny Srivastava         if (l_itrToVsys != (*l_parsedVpdMap).end())
1168fa5e4d32SSunny Srivastava         {
1169a55fcca1SSouvik Roy             const std::string l_tmKwdValue{vpdSpecificUtility::getKwVal(
1170a55fcca1SSouvik Roy                 l_itrToVsys->second, constants::kwdTM)};
1171fa5e4d32SSunny Srivastava 
1172a55fcca1SSouvik Roy             if (l_tmKwdValue.empty())
1173a55fcca1SSouvik Roy             {
1174a55fcca1SSouvik Roy                 throw std::runtime_error(
1175a55fcca1SSouvik Roy                     std::string("Failed to get value for keyword [") +
1176a55fcca1SSouvik Roy                     constants::kwdTM +
1177a55fcca1SSouvik Roy                     std::string("] while creating Asset tag."));
1178a55fcca1SSouvik Roy             }
1179a55fcca1SSouvik Roy 
1180a55fcca1SSouvik Roy             const std::string l_seKwdValue{vpdSpecificUtility::getKwVal(
1181a55fcca1SSouvik Roy                 l_itrToVsys->second, constants::kwdSE)};
1182a55fcca1SSouvik Roy 
1183a55fcca1SSouvik Roy             if (l_seKwdValue.empty())
1184a55fcca1SSouvik Roy             {
1185a55fcca1SSouvik Roy                 throw std::runtime_error(
1186a55fcca1SSouvik Roy                     std::string("Failed to get value for keyword [") +
1187a55fcca1SSouvik Roy                     constants::kwdSE +
1188a55fcca1SSouvik Roy                     std::string("] while creating Asset tag."));
1189a55fcca1SSouvik Roy             }
1190fa5e4d32SSunny Srivastava 
1191fa5e4d32SSunny Srivastava             l_assetTag = std::string{"Server-"} + l_tmKwdValue +
1192fa5e4d32SSunny Srivastava                          std::string{"-"} + l_seKwdValue;
1193fa5e4d32SSunny Srivastava         }
1194fa5e4d32SSunny Srivastava         else
1195fa5e4d32SSunny Srivastava         {
1196fa5e4d32SSunny Srivastava             throw std::runtime_error(
1197fa5e4d32SSunny Srivastava                 "VSYS record not found in parsed VPD map to create Asset tag.");
1198fa5e4d32SSunny Srivastava         }
1199fa5e4d32SSunny Srivastava     }
1200fa5e4d32SSunny Srivastava     else
1201fa5e4d32SSunny Srivastava     {
1202fa5e4d32SSunny Srivastava         throw std::runtime_error(
1203fa5e4d32SSunny Srivastava             "Invalid VPD type recieved to create Asset tag.");
1204fa5e4d32SSunny Srivastava     }
1205fa5e4d32SSunny Srivastava 
1206fa5e4d32SSunny Srivastava     return l_assetTag;
1207fa5e4d32SSunny Srivastava }
1208fa5e4d32SSunny Srivastava 
publishSystemVPD(const types::VPDMapVariant & parsedVpdMap)1209fa5e4d32SSunny Srivastava void Worker::publishSystemVPD(const types::VPDMapVariant& parsedVpdMap)
1210fa5e4d32SSunny Srivastava {
1211fa5e4d32SSunny Srivastava     types::ObjectMap objectInterfaceMap;
1212fa5e4d32SSunny Srivastava 
1213fa5e4d32SSunny Srivastava     if (std::get_if<types::IPZVpdMap>(&parsedVpdMap))
1214fa5e4d32SSunny Srivastava     {
1215fa5e4d32SSunny Srivastava         populateDbus(parsedVpdMap, objectInterfaceMap, SYSTEM_VPD_FILE_PATH);
1216fa5e4d32SSunny Srivastava 
1217fa5e4d32SSunny Srivastava         try
1218fa5e4d32SSunny Srivastava         {
1219fa5e4d32SSunny Srivastava             if (m_isFactoryResetDone)
1220fa5e4d32SSunny Srivastava             {
1221fa5e4d32SSunny Srivastava                 const auto& l_assetTag = createAssetTagString(parsedVpdMap);
1222fa5e4d32SSunny Srivastava 
1223fa5e4d32SSunny Srivastava                 auto l_itrToSystemPath = objectInterfaceMap.find(
1224fa5e4d32SSunny Srivastava                     sdbusplus::message::object_path(constants::systemInvPath));
1225fa5e4d32SSunny Srivastava                 if (l_itrToSystemPath == objectInterfaceMap.end())
1226fa5e4d32SSunny Srivastava                 {
1227fa5e4d32SSunny Srivastava                     throw std::runtime_error(
1228*043955d2SSunny Srivastava                         "Asset tag update failed. System Path not found in object map.");
1229fa5e4d32SSunny Srivastava                 }
1230fa5e4d32SSunny Srivastava 
1231fa5e4d32SSunny Srivastava                 types::PropertyMap l_assetTagProperty;
1232fa5e4d32SSunny Srivastava                 l_assetTagProperty.emplace("AssetTag", l_assetTag);
1233fa5e4d32SSunny Srivastava 
1234fa5e4d32SSunny Srivastava                 (l_itrToSystemPath->second)
1235fa5e4d32SSunny Srivastava                     .emplace(constants::assetTagInf,
1236fa5e4d32SSunny Srivastava                              std::move(l_assetTagProperty));
1237fa5e4d32SSunny Srivastava             }
1238fa5e4d32SSunny Srivastava         }
1239fa5e4d32SSunny Srivastava         catch (const std::exception& l_ex)
1240fa5e4d32SSunny Srivastava         {
1241fa5e4d32SSunny Srivastava             EventLogger::createSyncPel(
1242*043955d2SSunny Srivastava                 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
1243*043955d2SSunny Srivastava                 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
1244fa5e4d32SSunny Srivastava                 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
1245fa5e4d32SSunny Srivastava         }
1246fa5e4d32SSunny Srivastava 
1247fa5e4d32SSunny Srivastava         // Notify PIM
1248fa5e4d32SSunny Srivastava         if (!dbusUtility::callPIM(move(objectInterfaceMap)))
1249fa5e4d32SSunny Srivastava         {
1250fa5e4d32SSunny Srivastava             throw std::runtime_error("Call to PIM failed for system VPD");
1251fa5e4d32SSunny Srivastava         }
1252fa5e4d32SSunny Srivastava     }
1253fa5e4d32SSunny Srivastava     else
1254fa5e4d32SSunny Srivastava     {
1255fa5e4d32SSunny Srivastava         throw DataException("Invalid format of parsed VPD map.");
1256fa5e4d32SSunny Srivastava     }
1257fa5e4d32SSunny Srivastava }
1258fa5e4d32SSunny Srivastava 
processPreAction(const std::string & i_vpdFilePath,const std::string & i_flagToProcess)1259fa5e4d32SSunny Srivastava bool Worker::processPreAction(const std::string& i_vpdFilePath,
1260fa5e4d32SSunny Srivastava                               const std::string& i_flagToProcess)
1261fa5e4d32SSunny Srivastava {
1262fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty() || i_flagToProcess.empty())
1263fa5e4d32SSunny Srivastava     {
1264fa5e4d32SSunny Srivastava         logging::logMessage(
1265fa5e4d32SSunny Srivastava             "Invalid input parameter. Abort processing pre action");
1266fa5e4d32SSunny Srivastava         return false;
1267fa5e4d32SSunny Srivastava     }
1268fa5e4d32SSunny Srivastava 
1269fa5e4d32SSunny Srivastava     if ((!jsonUtility::executeBaseAction(m_parsedJson, "preAction",
1270fa5e4d32SSunny Srivastava                                          i_vpdFilePath, i_flagToProcess)) &&
1271fa5e4d32SSunny Srivastava         (i_flagToProcess.compare("collection") == constants::STR_CMP_SUCCESS))
1272fa5e4d32SSunny Srivastava     {
1273fa5e4d32SSunny Srivastava         // TODO: Need a way to delete inventory object from Dbus and persisted
1274fa5e4d32SSunny Srivastava         // data section in case any FRU is not present or there is any
1275fa5e4d32SSunny Srivastava         // problem in collecting it. Once it has been deleted, it can be
1276fa5e4d32SSunny Srivastava         // re-created in the flow of priming the inventory. This needs to be
1277fa5e4d32SSunny Srivastava         // done either here or in the exception section of "parseAndPublishVPD"
1278fa5e4d32SSunny Srivastava         // API. Any failure in the process of collecting FRU will land up in the
1279fa5e4d32SSunny Srivastava         // excpetion of "parseAndPublishVPD".
1280fa5e4d32SSunny Srivastava 
1281fa5e4d32SSunny Srivastava         // If the FRU is not there, clear the VINI/CCIN data.
1282fa5e4d32SSunny Srivastava         // Enity manager probes for this keyword to look for this
1283fa5e4d32SSunny Srivastava         // FRU, now if the data is persistent on BMC and FRU is
1284fa5e4d32SSunny Srivastava         // removed this can lead to ambiguity. Hence clearing this
1285fa5e4d32SSunny Srivastava         // Keyword if FRU is absent.
1286fa5e4d32SSunny Srivastava         const auto& inventoryPath =
1287fa5e4d32SSunny Srivastava             m_parsedJson["frus"][i_vpdFilePath].at(0).value("inventoryPath",
1288fa5e4d32SSunny Srivastava                                                             "");
1289fa5e4d32SSunny Srivastava 
1290fa5e4d32SSunny Srivastava         if (!inventoryPath.empty())
1291fa5e4d32SSunny Srivastava         {
1292fa5e4d32SSunny Srivastava             types::ObjectMap l_pimObjMap{
1293fa5e4d32SSunny Srivastava                 {inventoryPath,
1294fa5e4d32SSunny Srivastava                  {{constants::kwdVpdInf,
1295fa5e4d32SSunny Srivastava                    {{constants::kwdCCIN, types::BinaryVector{}}}}}}};
1296fa5e4d32SSunny Srivastava 
1297fa5e4d32SSunny Srivastava             if (!dbusUtility::callPIM(std::move(l_pimObjMap)))
1298fa5e4d32SSunny Srivastava             {
1299fa5e4d32SSunny Srivastava                 logging::logMessage(
1300fa5e4d32SSunny Srivastava                     "Call to PIM failed for file " + i_vpdFilePath);
1301fa5e4d32SSunny Srivastava             }
1302fa5e4d32SSunny Srivastava         }
1303fa5e4d32SSunny Srivastava         else
1304fa5e4d32SSunny Srivastava         {
1305fa5e4d32SSunny Srivastava             logging::logMessage(
1306fa5e4d32SSunny Srivastava                 "Inventory path is empty in Json for file " + i_vpdFilePath);
1307fa5e4d32SSunny Srivastava         }
1308fa5e4d32SSunny Srivastava 
1309fa5e4d32SSunny Srivastava         return false;
1310fa5e4d32SSunny Srivastava     }
1311fa5e4d32SSunny Srivastava     return true;
1312fa5e4d32SSunny Srivastava }
1313fa5e4d32SSunny Srivastava 
processPostAction(const std::string & i_vpdFruPath,const std::string & i_flagToProcess,const std::optional<types::VPDMapVariant> i_parsedVpd)1314fa5e4d32SSunny Srivastava bool Worker::processPostAction(
1315fa5e4d32SSunny Srivastava     const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
1316fa5e4d32SSunny Srivastava     const std::optional<types::VPDMapVariant> i_parsedVpd)
1317fa5e4d32SSunny Srivastava {
1318fa5e4d32SSunny Srivastava     if (i_vpdFruPath.empty() || i_flagToProcess.empty())
1319fa5e4d32SSunny Srivastava     {
1320fa5e4d32SSunny Srivastava         logging::logMessage(
1321fa5e4d32SSunny Srivastava             "Invalid input parameter. Abort processing post action");
1322fa5e4d32SSunny Srivastava         return false;
1323fa5e4d32SSunny Srivastava     }
1324fa5e4d32SSunny Srivastava 
1325fa5e4d32SSunny Srivastava     // Check if post action tag is to be triggered in the flow of collection
1326fa5e4d32SSunny Srivastava     // based on some CCIN value?
1327fa5e4d32SSunny Srivastava     if (m_parsedJson["frus"][i_vpdFruPath]
1328fa5e4d32SSunny Srivastava             .at(0)["postAction"][i_flagToProcess]
1329fa5e4d32SSunny Srivastava             .contains("ccin"))
1330fa5e4d32SSunny Srivastava     {
1331fa5e4d32SSunny Srivastava         if (!i_parsedVpd.has_value())
1332fa5e4d32SSunny Srivastava         {
1333fa5e4d32SSunny Srivastava             logging::logMessage("Empty VPD Map");
1334fa5e4d32SSunny Srivastava             return false;
1335fa5e4d32SSunny Srivastava         }
1336fa5e4d32SSunny Srivastava 
1337fa5e4d32SSunny Srivastava         // CCIN match is required to process post action for this FRU as it
1338fa5e4d32SSunny Srivastava         // contains the flag.
1339fa5e4d32SSunny Srivastava         if (!vpdSpecificUtility::findCcinInVpd(
1340fa5e4d32SSunny Srivastava                 m_parsedJson["frus"][i_vpdFruPath].at(
1341fa5e4d32SSunny Srivastava                     0)["postAction"]["collection"],
1342fa5e4d32SSunny Srivastava                 i_parsedVpd.value()))
1343fa5e4d32SSunny Srivastava         {
1344fa5e4d32SSunny Srivastava             // If CCIN is not found, implies post action processing is not
1345fa5e4d32SSunny Srivastava             // required for this FRU. Let the flow continue.
1346fa5e4d32SSunny Srivastava             return true;
1347fa5e4d32SSunny Srivastava         }
1348fa5e4d32SSunny Srivastava     }
1349fa5e4d32SSunny Srivastava 
1350fa5e4d32SSunny Srivastava     if (!jsonUtility::executeBaseAction(m_parsedJson, "postAction",
1351fa5e4d32SSunny Srivastava                                         i_vpdFruPath, i_flagToProcess))
1352fa5e4d32SSunny Srivastava     {
1353fa5e4d32SSunny Srivastava         logging::logMessage(
1354fa5e4d32SSunny Srivastava             "Execution of post action failed for path: " + i_vpdFruPath);
1355fa5e4d32SSunny Srivastava 
1356fa5e4d32SSunny Srivastava         // If post action was required and failed only in that case return
1357fa5e4d32SSunny Srivastava         // false. In all other case post action is considered passed.
1358fa5e4d32SSunny Srivastava         return false;
1359fa5e4d32SSunny Srivastava     }
1360fa5e4d32SSunny Srivastava 
1361fa5e4d32SSunny Srivastava     return true;
1362fa5e4d32SSunny Srivastava }
1363fa5e4d32SSunny Srivastava 
parseVpdFile(const std::string & i_vpdFilePath)1364fa5e4d32SSunny Srivastava types::VPDMapVariant Worker::parseVpdFile(const std::string& i_vpdFilePath)
1365fa5e4d32SSunny Srivastava {
1366fa5e4d32SSunny Srivastava     if (i_vpdFilePath.empty())
1367fa5e4d32SSunny Srivastava     {
1368fa5e4d32SSunny Srivastava         throw std::runtime_error(
1369fa5e4d32SSunny Srivastava             "Empty VPD file path passed to Worker::parseVpdFile. Abort processing");
1370fa5e4d32SSunny Srivastava     }
1371fa5e4d32SSunny Srivastava 
1372fa5e4d32SSunny Srivastava     try
1373fa5e4d32SSunny Srivastava     {
1374fa5e4d32SSunny Srivastava         if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
1375fa5e4d32SSunny Srivastava                                           "preAction", "collection"))
1376fa5e4d32SSunny Srivastava         {
1377fa5e4d32SSunny Srivastava             if (!processPreAction(i_vpdFilePath, "collection"))
1378fa5e4d32SSunny Srivastava             {
1379fa5e4d32SSunny Srivastava                 throw std::runtime_error("Pre-Action failed");
1380fa5e4d32SSunny Srivastava             }
1381fa5e4d32SSunny Srivastava         }
1382fa5e4d32SSunny Srivastava 
1383fa5e4d32SSunny Srivastava         if (!std::filesystem::exists(i_vpdFilePath))
1384fa5e4d32SSunny Srivastava         {
1385fa5e4d32SSunny Srivastava             throw std::runtime_error(
1386fa5e4d32SSunny Srivastava                 "Could not find file path " + i_vpdFilePath +
1387fa5e4d32SSunny Srivastava                 "Skipping parser trigger for the EEPROM");
1388fa5e4d32SSunny Srivastava         }
1389fa5e4d32SSunny Srivastava 
1390fa5e4d32SSunny Srivastava         std::shared_ptr<Parser> vpdParser =
1391fa5e4d32SSunny Srivastava             std::make_shared<Parser>(i_vpdFilePath, m_parsedJson);
1392fa5e4d32SSunny Srivastava 
1393fa5e4d32SSunny Srivastava         types::VPDMapVariant l_parsedVpd = vpdParser->parse();
1394fa5e4d32SSunny Srivastava 
1395fa5e4d32SSunny Srivastava         // Before returning, as collection is over, check if FRU qualifies for
1396fa5e4d32SSunny Srivastava         // any post action in the flow of collection.
1397fa5e4d32SSunny Srivastava         // Note: Don't change the order, post action needs to be processed only
1398fa5e4d32SSunny Srivastava         // after collection for FRU is successfully done.
1399fa5e4d32SSunny Srivastava         if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
1400fa5e4d32SSunny Srivastava                                           "postAction", "collection"))
1401fa5e4d32SSunny Srivastava         {
1402fa5e4d32SSunny Srivastava             if (!processPostAction(i_vpdFilePath, "collection", l_parsedVpd))
1403fa5e4d32SSunny Srivastava             {
1404fa5e4d32SSunny Srivastava                 // TODO: Log PEL
1405fa5e4d32SSunny Srivastava                 logging::logMessage("Required post action failed for path [" +
1406fa5e4d32SSunny Srivastava                                     i_vpdFilePath + "]");
1407fa5e4d32SSunny Srivastava             }
1408fa5e4d32SSunny Srivastava         }
1409fa5e4d32SSunny Srivastava 
1410fa5e4d32SSunny Srivastava         return l_parsedVpd;
1411fa5e4d32SSunny Srivastava     }
1412fa5e4d32SSunny Srivastava     catch (std::exception& l_ex)
1413fa5e4d32SSunny Srivastava     {
1414fa5e4d32SSunny Srivastava         // If post fail action is required, execute it.
1415fa5e4d32SSunny Srivastava         if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
14164c164381SSunny Srivastava                                           "postFailAction", "collection"))
1417fa5e4d32SSunny Srivastava         {
1418fa5e4d32SSunny Srivastava             if (!jsonUtility::executePostFailAction(m_parsedJson, i_vpdFilePath,
1419fa5e4d32SSunny Srivastava                                                     "collection"))
1420fa5e4d32SSunny Srivastava             {
1421fa5e4d32SSunny Srivastava                 // TODO: Log PEL
1422fa5e4d32SSunny Srivastava                 throw std::runtime_error(
1423fa5e4d32SSunny Srivastava                     "VPD parsing failed for " + i_vpdFilePath +
1424fa5e4d32SSunny Srivastava                     " due to error: " + l_ex.what() +
1425fa5e4d32SSunny Srivastava                     ". Post Fail Action also failed, aborting collection for this FRU");
1426fa5e4d32SSunny Srivastava             }
1427fa5e4d32SSunny Srivastava         }
1428fa5e4d32SSunny Srivastava 
1429fa5e4d32SSunny Srivastava         // TODO: Log PEL
1430fa5e4d32SSunny Srivastava         throw std::runtime_error("VPD parsing failed for " + i_vpdFilePath +
1431fa5e4d32SSunny Srivastava                                  " due to error: " + l_ex.what());
1432fa5e4d32SSunny Srivastava     }
1433fa5e4d32SSunny Srivastava }
1434fa5e4d32SSunny Srivastava 
parseAndPublishVPD(const std::string & i_vpdFilePath)143543fedabcSPatrick Williams std::tuple<bool, std::string> Worker::parseAndPublishVPD(
143643fedabcSPatrick Williams     const std::string& i_vpdFilePath)
1437fa5e4d32SSunny Srivastava {
14381aad7834SPriyanga Ramasamy     std::string l_inventoryPath{};
14391aad7834SPriyanga Ramasamy 
1440fa5e4d32SSunny Srivastava     try
1441fa5e4d32SSunny Srivastava     {
1442fa5e4d32SSunny Srivastava         m_semaphore.acquire();
1443fa5e4d32SSunny Srivastava 
1444fa5e4d32SSunny Srivastava         // Thread launched.
1445fa5e4d32SSunny Srivastava         m_mutex.lock();
1446fa5e4d32SSunny Srivastava         m_activeCollectionThreadCount++;
1447fa5e4d32SSunny Srivastava         m_mutex.unlock();
1448fa5e4d32SSunny Srivastava 
14491aad7834SPriyanga Ramasamy         // Set CollectionStatus as InProgress. Since it's an intermediate state
14501aad7834SPriyanga Ramasamy         // D-bus set-property call is good enough to update the status.
14511aad7834SPriyanga Ramasamy         l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
14521aad7834SPriyanga Ramasamy             m_parsedJson, i_vpdFilePath);
14531aad7834SPriyanga Ramasamy 
14541ef21008SRekhaAparna01         if (!l_inventoryPath.empty())
14551ef21008SRekhaAparna01         {
1456c532b188SRekhaAparna01             if (!dbusUtility::writeDbusProperty(
14571aad7834SPriyanga Ramasamy                     jsonUtility::getServiceName(m_parsedJson, l_inventoryPath),
14581aad7834SPriyanga Ramasamy                     l_inventoryPath, constants::vpdCollectionInterface,
14591aad7834SPriyanga Ramasamy                     "CollectionStatus",
1460c532b188SRekhaAparna01                     types::DbusVariantType{constants::vpdCollectionInProgress}))
14611aad7834SPriyanga Ramasamy             {
14621aad7834SPriyanga Ramasamy                 logging::logMessage(
14631aad7834SPriyanga Ramasamy                     "Unable to set CollectionStatus as InProgress for " +
1464c532b188SRekhaAparna01                     i_vpdFilePath + ". Error : " + "DBus write failed");
14651aad7834SPriyanga Ramasamy             }
14661ef21008SRekhaAparna01         }
14671aad7834SPriyanga Ramasamy 
1468fa5e4d32SSunny Srivastava         const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
1469fa5e4d32SSunny Srivastava 
1470fa5e4d32SSunny Srivastava         types::ObjectMap objectInterfaceMap;
1471fa5e4d32SSunny Srivastava         populateDbus(parsedVpdMap, objectInterfaceMap, i_vpdFilePath);
1472fa5e4d32SSunny Srivastava 
1473fa5e4d32SSunny Srivastava         // logging::logMessage("Dbus sucessfully populated for FRU " +
1474fa5e4d32SSunny Srivastava         //                     i_vpdFilePath);
1475fa5e4d32SSunny Srivastava 
1476fa5e4d32SSunny Srivastava         // Notify PIM
1477fa5e4d32SSunny Srivastava         if (!dbusUtility::callPIM(move(objectInterfaceMap)))
1478fa5e4d32SSunny Srivastava         {
1479fa5e4d32SSunny Srivastava             throw std::runtime_error(
1480fa5e4d32SSunny Srivastava                 "Call to PIM failed while publishing VPD.");
1481fa5e4d32SSunny Srivastava         }
1482fa5e4d32SSunny Srivastava     }
1483fa5e4d32SSunny Srivastava     catch (const std::exception& ex)
1484fa5e4d32SSunny Srivastava     {
14851aad7834SPriyanga Ramasamy         // Notify FRU's VPD CollectionStatus as Failure
14861aad7834SPriyanga Ramasamy         if (!dbusUtility::notifyFRUCollectionStatus(
14871aad7834SPriyanga Ramasamy                 l_inventoryPath, constants::vpdCollectionFailure))
14881aad7834SPriyanga Ramasamy         {
14891aad7834SPriyanga Ramasamy             logging::logMessage(
14901aad7834SPriyanga Ramasamy                 "Call to PIM Notify method failed to update Collection status as Failure for " +
14911aad7834SPriyanga Ramasamy                 i_vpdFilePath);
14921aad7834SPriyanga Ramasamy         }
14931aad7834SPriyanga Ramasamy 
1494fa5e4d32SSunny Srivastava         // handle all the exceptions internally. Return only true/false
1495fa5e4d32SSunny Srivastava         // based on status of execution.
1496fa5e4d32SSunny Srivastava         if (typeid(ex) == std::type_index(typeid(DataException)))
1497fa5e4d32SSunny Srivastava         {
149878c91073SSunny Srivastava             // In case of pass1 planar, VPD can be corrupted on PCIe cards. Skip
149978c91073SSunny Srivastava             // logging error for these cases.
150078c91073SSunny Srivastava             if (vpdSpecificUtility::isPass1Planar())
150178c91073SSunny Srivastava             {
150278c91073SSunny Srivastava                 const std::string& l_invPathLeafValue =
150378c91073SSunny Srivastava                     sdbusplus::message::object_path(
15041ef21008SRekhaAparna01                         jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
15051ef21008SRekhaAparna01                                                                  i_vpdFilePath))
150678c91073SSunny Srivastava                         .filename();
150778c91073SSunny Srivastava 
150878c91073SSunny Srivastava                 if ((l_invPathLeafValue.find("pcie_card", 0) !=
150978c91073SSunny Srivastava                      std::string::npos))
151078c91073SSunny Srivastava                 {
151178c91073SSunny Srivastava                     // skip logging any PEL for PCIe cards on pass 1 planar.
151278c91073SSunny Srivastava                     return std::make_tuple(false, i_vpdFilePath);
151378c91073SSunny Srivastava                 }
151478c91073SSunny Srivastava             }
151578c91073SSunny Srivastava 
1516fa5e4d32SSunny Srivastava             // TODO: Add custom handling
1517fa5e4d32SSunny Srivastava             logging::logMessage(ex.what());
1518fa5e4d32SSunny Srivastava         }
1519fa5e4d32SSunny Srivastava         else if (typeid(ex) == std::type_index(typeid(EccException)))
1520fa5e4d32SSunny Srivastava         {
1521fa5e4d32SSunny Srivastava             // TODO: Add custom handling
1522fa5e4d32SSunny Srivastava             logging::logMessage(ex.what());
1523fa5e4d32SSunny Srivastava         }
1524fa5e4d32SSunny Srivastava         else if (typeid(ex) == std::type_index(typeid(JsonException)))
1525fa5e4d32SSunny Srivastava         {
1526fa5e4d32SSunny Srivastava             // TODO: Add custom handling
1527fa5e4d32SSunny Srivastava             logging::logMessage(ex.what());
1528fa5e4d32SSunny Srivastava         }
1529fa5e4d32SSunny Srivastava         else
1530fa5e4d32SSunny Srivastava         {
1531fa5e4d32SSunny Srivastava             logging::logMessage(ex.what());
1532fa5e4d32SSunny Srivastava         }
1533fa5e4d32SSunny Srivastava 
1534fa5e4d32SSunny Srivastava         // TODO: Figure out a way to clear data in case of any failure at
1535fa5e4d32SSunny Srivastava         // runtime.
1536d159bb49SSunny Srivastava 
1537d159bb49SSunny Srivastava         // set present property to false for any error case. In future this will
1538d159bb49SSunny Srivastava         // be replaced by presence logic.
15396a9553c8SSouvik Roy         // Update Present property for this FRU only if we handle Present
15406a9553c8SSouvik Roy         // property for the FRU.
15416a9553c8SSouvik Roy         if (isPresentPropertyHandlingRequired(
15426a9553c8SSouvik Roy                 m_parsedJson["frus"][i_vpdFilePath].at(0)))
15436a9553c8SSouvik Roy         {
1544d159bb49SSunny Srivastava             setPresentProperty(i_vpdFilePath, false);
15456a9553c8SSouvik Roy         }
1546d159bb49SSunny Srivastava 
1547fa5e4d32SSunny Srivastava         m_semaphore.release();
1548fa5e4d32SSunny Srivastava         return std::make_tuple(false, i_vpdFilePath);
1549fa5e4d32SSunny Srivastava     }
1550fa5e4d32SSunny Srivastava     m_semaphore.release();
1551fa5e4d32SSunny Srivastava     return std::make_tuple(true, i_vpdFilePath);
1552fa5e4d32SSunny Srivastava }
1553fa5e4d32SSunny Srivastava 
skipPathForCollection(const std::string & i_vpdFilePath)155461611751SSunny Srivastava bool Worker::skipPathForCollection(const std::string& i_vpdFilePath)
155561611751SSunny Srivastava {
155661611751SSunny Srivastava     if (i_vpdFilePath.empty())
155761611751SSunny Srivastava     {
155861611751SSunny Srivastava         return true;
155961611751SSunny Srivastava     }
156061611751SSunny Srivastava 
156161611751SSunny Srivastava     // skip processing of system VPD again as it has been already collected.
156261611751SSunny Srivastava     if (i_vpdFilePath == SYSTEM_VPD_FILE_PATH)
156361611751SSunny Srivastava     {
156461611751SSunny Srivastava         return true;
156561611751SSunny Srivastava     }
156661611751SSunny Srivastava 
156761611751SSunny Srivastava     if (dbusUtility::isChassisPowerOn())
156861611751SSunny Srivastava     {
156961611751SSunny Srivastava         // If chassis is powered on, skip collecting FRUs which are
157061611751SSunny Srivastava         // powerOffOnly.
157161611751SSunny Srivastava         if (jsonUtility::isFruPowerOffOnly(m_parsedJson, i_vpdFilePath))
157261611751SSunny Srivastava         {
157361611751SSunny Srivastava             return true;
157461611751SSunny Srivastava         }
157561611751SSunny Srivastava 
157661611751SSunny Srivastava         const std::string& l_invPathLeafValue =
157761611751SSunny Srivastava             sdbusplus::message::object_path(
157861611751SSunny Srivastava                 jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
157961611751SSunny Srivastava                                                          i_vpdFilePath))
158061611751SSunny Srivastava                 .filename();
158161611751SSunny Srivastava 
158261611751SSunny Srivastava         if ((l_invPathLeafValue.find("pcie_card", 0) != std::string::npos))
158361611751SSunny Srivastava         {
158461611751SSunny Srivastava             return true;
158561611751SSunny Srivastava         }
158661611751SSunny Srivastava     }
158761611751SSunny Srivastava 
158861611751SSunny Srivastava     return false;
158961611751SSunny Srivastava }
159061611751SSunny Srivastava 
collectFrusFromJson()1591fa5e4d32SSunny Srivastava void Worker::collectFrusFromJson()
1592fa5e4d32SSunny Srivastava {
1593fa5e4d32SSunny Srivastava     // A parsed JSON file should be present to pick FRUs EEPROM paths
1594fa5e4d32SSunny Srivastava     if (m_parsedJson.empty())
1595fa5e4d32SSunny Srivastava     {
1596fa5e4d32SSunny Srivastava         throw std::runtime_error(
1597fa5e4d32SSunny Srivastava             "A config JSON is required for processing of FRUs");
1598fa5e4d32SSunny Srivastava     }
1599fa5e4d32SSunny Srivastava 
1600fa5e4d32SSunny Srivastava     const nlohmann::json& listOfFrus =
1601fa5e4d32SSunny Srivastava         m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();
1602fa5e4d32SSunny Srivastava 
1603fa5e4d32SSunny Srivastava     for (const auto& itemFRUS : listOfFrus.items())
1604fa5e4d32SSunny Srivastava     {
1605fa5e4d32SSunny Srivastava         const std::string& vpdFilePath = itemFRUS.key();
1606fa5e4d32SSunny Srivastava 
160761611751SSunny Srivastava         if (skipPathForCollection(vpdFilePath))
1608fa5e4d32SSunny Srivastava         {
1609fa5e4d32SSunny Srivastava             continue;
1610fa5e4d32SSunny Srivastava         }
1611fa5e4d32SSunny Srivastava 
16121f4c8f81SSouvik Roy         try
16131f4c8f81SSouvik Roy         {
1614fa5e4d32SSunny Srivastava             std::thread{[vpdFilePath, this]() {
161561611751SSunny Srivastava                 const auto& l_parseResult = parseAndPublishVPD(vpdFilePath);
1616fa5e4d32SSunny Srivastava 
1617fa5e4d32SSunny Srivastava                 m_mutex.lock();
1618fa5e4d32SSunny Srivastava                 m_activeCollectionThreadCount--;
1619fa5e4d32SSunny Srivastava                 m_mutex.unlock();
1620fa5e4d32SSunny Srivastava 
1621fa5e4d32SSunny Srivastava                 if (!m_activeCollectionThreadCount)
1622fa5e4d32SSunny Srivastava                 {
1623fa5e4d32SSunny Srivastava                     m_isAllFruCollected = true;
1624fa5e4d32SSunny Srivastava                 }
1625fa5e4d32SSunny Srivastava             }}.detach();
1626fa5e4d32SSunny Srivastava         }
16271f4c8f81SSouvik Roy         catch (const std::exception& l_ex)
16281f4c8f81SSouvik Roy         {
16291f4c8f81SSouvik Roy             // add vpdFilePath(EEPROM path) to failed list
16301f4c8f81SSouvik Roy             m_failedEepromPaths.push_front(vpdFilePath);
16311f4c8f81SSouvik Roy         }
16321f4c8f81SSouvik Roy     }
1633fa5e4d32SSunny Srivastava }
1634fa5e4d32SSunny Srivastava 
1635fa5e4d32SSunny Srivastava // ToDo: Move the API under IBM_SYSTEM
performBackupAndRestore(types::VPDMapVariant & io_srcVpdMap)1636fa5e4d32SSunny Srivastava void Worker::performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap)
1637fa5e4d32SSunny Srivastava {
1638fa5e4d32SSunny Srivastava     try
1639fa5e4d32SSunny Srivastava     {
1640fa5e4d32SSunny Srivastava         std::string l_backupAndRestoreCfgFilePath =
1641fa5e4d32SSunny Srivastava             m_parsedJson.value("backupRestoreConfigPath", "");
1642fa5e4d32SSunny Srivastava 
1643fa5e4d32SSunny Srivastava         nlohmann::json l_backupAndRestoreCfgJsonObj =
1644fa5e4d32SSunny Srivastava             jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);
1645fa5e4d32SSunny Srivastava 
16461ef21008SRekhaAparna01         if (l_backupAndRestoreCfgJsonObj.empty())
16471ef21008SRekhaAparna01         {
16481ef21008SRekhaAparna01             throw JsonException("JSON parsing failed",
16491ef21008SRekhaAparna01                                 l_backupAndRestoreCfgFilePath);
16501ef21008SRekhaAparna01         }
16511ef21008SRekhaAparna01 
1652fa5e4d32SSunny Srivastava         // check if either of "source" or "destination" has inventory path.
1653fa5e4d32SSunny Srivastava         // this indicates that this sytem has System VPD on hardware
1654fa5e4d32SSunny Srivastava         // and other copy on D-Bus (BMC cache).
1655fa5e4d32SSunny Srivastava         if (!l_backupAndRestoreCfgJsonObj.empty() &&
1656fa5e4d32SSunny Srivastava             ((l_backupAndRestoreCfgJsonObj.contains("source") &&
1657fa5e4d32SSunny Srivastava               l_backupAndRestoreCfgJsonObj["source"].contains(
1658fa5e4d32SSunny Srivastava                   "inventoryPath")) ||
1659fa5e4d32SSunny Srivastava              (l_backupAndRestoreCfgJsonObj.contains("destination") &&
1660fa5e4d32SSunny Srivastava               l_backupAndRestoreCfgJsonObj["destination"].contains(
1661fa5e4d32SSunny Srivastava                   "inventoryPath"))))
1662fa5e4d32SSunny Srivastava         {
1663fa5e4d32SSunny Srivastava             BackupAndRestore l_backupAndRestoreObj(m_parsedJson);
1664fa5e4d32SSunny Srivastava             auto [l_srcVpdVariant,
1665fa5e4d32SSunny Srivastava                   l_dstVpdVariant] = l_backupAndRestoreObj.backupAndRestore();
1666fa5e4d32SSunny Srivastava 
1667fa5e4d32SSunny Srivastava             // ToDo: Revisit is this check is required or not.
1668fa5e4d32SSunny Srivastava             if (auto l_srcVpdMap =
1669fa5e4d32SSunny Srivastava                     std::get_if<types::IPZVpdMap>(&l_srcVpdVariant);
1670fa5e4d32SSunny Srivastava                 l_srcVpdMap && !(*l_srcVpdMap).empty())
1671fa5e4d32SSunny Srivastava             {
1672fa5e4d32SSunny Srivastava                 io_srcVpdMap = std::move(l_srcVpdVariant);
1673fa5e4d32SSunny Srivastava             }
1674fa5e4d32SSunny Srivastava         }
1675fa5e4d32SSunny Srivastava     }
1676fa5e4d32SSunny Srivastava     catch (const std::exception& l_ex)
1677fa5e4d32SSunny Srivastava     {
1678fa5e4d32SSunny Srivastava         EventLogger::createSyncPel(
1679*043955d2SSunny Srivastava             EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
168015a189a9SSunny Srivastava             __FILE__, __FUNCTION__, 0,
1681fa5e4d32SSunny Srivastava             std::string(
1682fa5e4d32SSunny Srivastava                 "Exception caught while backup and restore VPD keyword's.") +
168315a189a9SSunny Srivastava                 EventLogger::getErrorMsg(l_ex),
1684fa5e4d32SSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
1685fa5e4d32SSunny Srivastava     }
1686fa5e4d32SSunny Srivastava }
1687fa5e4d32SSunny Srivastava 
deleteFruVpd(const std::string & i_dbusObjPath)1688fa5e4d32SSunny Srivastava void Worker::deleteFruVpd(const std::string& i_dbusObjPath)
1689fa5e4d32SSunny Srivastava {
1690fa5e4d32SSunny Srivastava     if (i_dbusObjPath.empty())
1691fa5e4d32SSunny Srivastava     {
1692fa5e4d32SSunny Srivastava         throw std::runtime_error("Given DBus object path is empty.");
1693fa5e4d32SSunny Srivastava     }
1694fa5e4d32SSunny Srivastava 
1695fa5e4d32SSunny Srivastava     const std::string& l_fruPath =
1696fa5e4d32SSunny Srivastava         jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath);
1697fa5e4d32SSunny Srivastava 
1698fa5e4d32SSunny Srivastava     try
1699fa5e4d32SSunny Srivastava     {
1700fa5e4d32SSunny Srivastava         auto l_presentPropValue = dbusUtility::readDbusProperty(
1701fa5e4d32SSunny Srivastava             constants::pimServiceName, i_dbusObjPath,
1702fa5e4d32SSunny Srivastava             constants::inventoryItemInf, "Present");
1703fa5e4d32SSunny Srivastava 
1704fa5e4d32SSunny Srivastava         if (auto l_value = std::get_if<bool>(&l_presentPropValue))
1705fa5e4d32SSunny Srivastava         {
1706fa5e4d32SSunny Srivastava             if (!(*l_value))
1707fa5e4d32SSunny Srivastava             {
1708fa5e4d32SSunny Srivastava                 throw std::runtime_error("Given FRU is not present");
1709fa5e4d32SSunny Srivastava             }
1710fa5e4d32SSunny Srivastava             else
1711fa5e4d32SSunny Srivastava             {
1712fa5e4d32SSunny Srivastava                 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
1713fa5e4d32SSunny Srivastava                                                   "preAction", "deletion"))
1714fa5e4d32SSunny Srivastava                 {
1715fa5e4d32SSunny Srivastava                     if (!processPreAction(l_fruPath, "deletion"))
1716fa5e4d32SSunny Srivastava                     {
1717fa5e4d32SSunny Srivastava                         throw std::runtime_error("Pre action failed");
1718fa5e4d32SSunny Srivastava                     }
1719fa5e4d32SSunny Srivastava                 }
1720fa5e4d32SSunny Srivastava 
1721fa5e4d32SSunny Srivastava                 std::vector<std::string> l_interfaceList{
1722fa5e4d32SSunny Srivastava                     constants::operationalStatusInf};
1723fa5e4d32SSunny Srivastava 
1724fa5e4d32SSunny Srivastava                 types::MapperGetSubTree l_subTreeMap =
1725fa5e4d32SSunny Srivastava                     dbusUtility::getObjectSubTree(i_dbusObjPath, 0,
1726fa5e4d32SSunny Srivastava                                                   l_interfaceList);
1727fa5e4d32SSunny Srivastava 
1728fa5e4d32SSunny Srivastava                 types::ObjectMap l_objectMap;
1729fa5e4d32SSunny Srivastava 
1730fa5e4d32SSunny Srivastava                 // Updates VPD specific interfaces property value under PIM for
1731fa5e4d32SSunny Srivastava                 // sub FRUs.
1732fa5e4d32SSunny Srivastava                 for (const auto& [l_objectPath, l_serviceInterfaceMap] :
1733fa5e4d32SSunny Srivastava                      l_subTreeMap)
1734fa5e4d32SSunny Srivastava                 {
1735fa5e4d32SSunny Srivastava                     types::InterfaceMap l_interfaceMap;
1736fa5e4d32SSunny Srivastava                     vpdSpecificUtility::resetDataUnderPIM(l_objectPath,
1737fa5e4d32SSunny Srivastava                                                           l_interfaceMap);
1738fa5e4d32SSunny Srivastava                     l_objectMap.emplace(l_objectPath,
1739fa5e4d32SSunny Srivastava                                         std::move(l_interfaceMap));
1740fa5e4d32SSunny Srivastava                 }
1741fa5e4d32SSunny Srivastava 
1742fa5e4d32SSunny Srivastava                 types::InterfaceMap l_interfaceMap;
1743fa5e4d32SSunny Srivastava                 vpdSpecificUtility::resetDataUnderPIM(i_dbusObjPath,
1744fa5e4d32SSunny Srivastava                                                       l_interfaceMap);
1745fa5e4d32SSunny Srivastava 
1746fa5e4d32SSunny Srivastava                 l_objectMap.emplace(i_dbusObjPath, std::move(l_interfaceMap));
1747fa5e4d32SSunny Srivastava 
1748fa5e4d32SSunny Srivastava                 if (!dbusUtility::callPIM(std::move(l_objectMap)))
1749fa5e4d32SSunny Srivastava                 {
1750fa5e4d32SSunny Srivastava                     throw std::runtime_error("Call to PIM failed.");
1751fa5e4d32SSunny Srivastava                 }
1752fa5e4d32SSunny Srivastava 
1753fa5e4d32SSunny Srivastava                 if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
1754fa5e4d32SSunny Srivastava                                                   "postAction", "deletion"))
1755fa5e4d32SSunny Srivastava                 {
1756fa5e4d32SSunny Srivastava                     if (!processPostAction(l_fruPath, "deletion"))
1757fa5e4d32SSunny Srivastava                     {
1758fa5e4d32SSunny Srivastava                         throw std::runtime_error("Post action failed");
1759fa5e4d32SSunny Srivastava                     }
1760fa5e4d32SSunny Srivastava                 }
1761fa5e4d32SSunny Srivastava             }
1762fa5e4d32SSunny Srivastava         }
1763fa5e4d32SSunny Srivastava         else
1764fa5e4d32SSunny Srivastava         {
1765fa5e4d32SSunny Srivastava             logging::logMessage(
1766fa5e4d32SSunny Srivastava                 "Can't process delete VPD for FRU [" + i_dbusObjPath +
1767fa5e4d32SSunny Srivastava                 "] as unable to read present property");
1768fa5e4d32SSunny Srivastava             return;
1769fa5e4d32SSunny Srivastava         }
1770fa5e4d32SSunny Srivastava 
1771fa5e4d32SSunny Srivastava         logging::logMessage(
1772fa5e4d32SSunny Srivastava             "Successfully completed deletion of FRU VPD for " + i_dbusObjPath);
1773fa5e4d32SSunny Srivastava     }
1774fa5e4d32SSunny Srivastava     catch (const std::exception& l_ex)
1775fa5e4d32SSunny Srivastava     {
1776fa5e4d32SSunny Srivastava         if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
1777fa5e4d32SSunny Srivastava                                           "postFailAction", "deletion"))
1778fa5e4d32SSunny Srivastava         {
1779fa5e4d32SSunny Srivastava             if (!jsonUtility::executePostFailAction(m_parsedJson, l_fruPath,
1780fa5e4d32SSunny Srivastava                                                     "deletion"))
1781fa5e4d32SSunny Srivastava             {
1782fa5e4d32SSunny Srivastava                 logging::logMessage(
1783fa5e4d32SSunny Srivastava                     "Post fail action failed for: " + i_dbusObjPath);
1784fa5e4d32SSunny Srivastava             }
1785fa5e4d32SSunny Srivastava         }
1786fa5e4d32SSunny Srivastava 
1787fa5e4d32SSunny Srivastava         logging::logMessage("Failed to delete VPD for FRU : " + i_dbusObjPath +
1788fa5e4d32SSunny Srivastava                             " error: " + std::string(l_ex.what()));
1789fa5e4d32SSunny Srivastava     }
1790fa5e4d32SSunny Srivastava }
1791d159bb49SSunny Srivastava 
setPresentProperty(const std::string & i_vpdPath,const bool & i_value)1792d159bb49SSunny Srivastava void Worker::setPresentProperty(const std::string& i_vpdPath,
1793d159bb49SSunny Srivastava                                 const bool& i_value)
1794d159bb49SSunny Srivastava {
1795d159bb49SSunny Srivastava     try
1796d159bb49SSunny Srivastava     {
1797d159bb49SSunny Srivastava         if (i_vpdPath.empty())
1798d159bb49SSunny Srivastava         {
1799d159bb49SSunny Srivastava             throw std::runtime_error(
1800d159bb49SSunny Srivastava                 "Path is empty. Can't set present property");
1801d159bb49SSunny Srivastava         }
1802d159bb49SSunny Srivastava 
1803d159bb49SSunny Srivastava         types::ObjectMap l_objectInterfaceMap;
1804d159bb49SSunny Srivastava 
1805d159bb49SSunny Srivastava         // If the given path is EEPROM path.
1806d159bb49SSunny Srivastava         if (m_parsedJson["frus"].contains(i_vpdPath))
1807d159bb49SSunny Srivastava         {
1808d159bb49SSunny Srivastava             for (const auto& l_Fru : m_parsedJson["frus"][i_vpdPath])
1809d159bb49SSunny Srivastava             {
1810d159bb49SSunny Srivastava                 sdbusplus::message::object_path l_fruObjectPath(
1811d159bb49SSunny Srivastava                     l_Fru["inventoryPath"]);
1812d159bb49SSunny Srivastava 
1813d159bb49SSunny Srivastava                 types::PropertyMap l_propertyValueMap;
1814d159bb49SSunny Srivastava                 l_propertyValueMap.emplace("Present", i_value);
1815d159bb49SSunny Srivastava 
1816d159bb49SSunny Srivastava                 types::InterfaceMap l_interfaces;
1817d159bb49SSunny Srivastava                 vpdSpecificUtility::insertOrMerge(l_interfaces,
1818d159bb49SSunny Srivastava                                                   constants::inventoryItemInf,
1819d159bb49SSunny Srivastava                                                   move(l_propertyValueMap));
1820d159bb49SSunny Srivastava 
1821d159bb49SSunny Srivastava                 l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
1822d159bb49SSunny Srivastava                                              std::move(l_interfaces));
1823d159bb49SSunny Srivastava             }
1824d159bb49SSunny Srivastava         }
1825d159bb49SSunny Srivastava         else
1826d159bb49SSunny Srivastava         {
1827d159bb49SSunny Srivastava             // consider it as an inventory path.
1828d159bb49SSunny Srivastava             if (i_vpdPath.find(constants::pimPath) != constants::VALUE_0)
1829d159bb49SSunny Srivastava             {
1830d159bb49SSunny Srivastava                 throw std::runtime_error(
1831d159bb49SSunny Srivastava                     "Invalid inventory path: " + i_vpdPath);
1832d159bb49SSunny Srivastava             }
1833d159bb49SSunny Srivastava 
1834d159bb49SSunny Srivastava             types::PropertyMap l_propertyValueMap;
1835d159bb49SSunny Srivastava             l_propertyValueMap.emplace("Present", i_value);
1836d159bb49SSunny Srivastava 
1837d159bb49SSunny Srivastava             types::InterfaceMap l_interfaces;
1838d159bb49SSunny Srivastava             vpdSpecificUtility::insertOrMerge(l_interfaces,
1839d159bb49SSunny Srivastava                                               constants::inventoryItemInf,
1840d159bb49SSunny Srivastava                                               move(l_propertyValueMap));
1841d159bb49SSunny Srivastava 
1842d159bb49SSunny Srivastava             l_objectInterfaceMap.emplace(i_vpdPath, std::move(l_interfaces));
1843d159bb49SSunny Srivastava         }
1844d159bb49SSunny Srivastava 
1845d159bb49SSunny Srivastava         // Notify PIM
1846d159bb49SSunny Srivastava         if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
1847d159bb49SSunny Srivastava         {
1848d159bb49SSunny Srivastava             throw std::runtime_error(
1849d159bb49SSunny Srivastava                 "Call to PIM failed while setting present property for path " +
1850d159bb49SSunny Srivastava                 i_vpdPath);
1851d159bb49SSunny Srivastava         }
1852d159bb49SSunny Srivastava     }
1853d159bb49SSunny Srivastava     catch (const std::exception& l_ex)
1854d159bb49SSunny Srivastava     {
1855d159bb49SSunny Srivastava         logging::logMessage(l_ex.what());
1856d159bb49SSunny Srivastava     }
1857d159bb49SSunny Srivastava }
1858d159bb49SSunny Srivastava 
1859fa5e4d32SSunny Srivastava } // namespace vpd
1860