xref: /openbmc/openpower-vpd-parser/vpd-manager/oem-handler/ibm_handler.cpp (revision 56e4537c80d009d1d072d141b2d96f4368203a95)
1c74c8efeSSunny Srivastava #include "config.h"
2c74c8efeSSunny Srivastava 
3867ee75dSSunny Srivastava #include "ibm_handler.hpp"
4867ee75dSSunny Srivastava 
5*56e4537cSAnupama B R #include "listener.hpp"
6c74c8efeSSunny Srivastava #include "parser.hpp"
7c74c8efeSSunny Srivastava 
878a50427SSunny Srivastava #include <utility/common_utility.hpp>
9c74c8efeSSunny Srivastava #include <utility/dbus_utility.hpp>
10c74c8efeSSunny Srivastava #include <utility/json_utility.hpp>
11c74c8efeSSunny Srivastava #include <utility/vpd_specific_utility.hpp>
12c74c8efeSSunny Srivastava 
13867ee75dSSunny Srivastava namespace vpd
IbmHandler(std::shared_ptr<Worker> & o_worker,std::shared_ptr<BackupAndRestore> & o_backupAndRestoreObj,const std::shared_ptr<sdbusplus::asio::dbus_interface> & i_iFace,const std::shared_ptr<boost::asio::io_context> & i_ioCon,const std::shared_ptr<sdbusplus::asio::connection> & i_asioConnection)14867ee75dSSunny Srivastava {
15c74c8efeSSunny Srivastava IbmHandler::IbmHandler(
16c74c8efeSSunny Srivastava     std::shared_ptr<Worker>& o_worker,
17c74c8efeSSunny Srivastava     std::shared_ptr<BackupAndRestore>& o_backupAndRestoreObj,
18c74c8efeSSunny Srivastava     const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_iFace,
19c74c8efeSSunny Srivastava     const std::shared_ptr<boost::asio::io_context>& i_ioCon,
20c74c8efeSSunny Srivastava     const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection) :
21c74c8efeSSunny Srivastava     m_worker(o_worker), m_backupAndRestoreObj(o_backupAndRestoreObj),
22c74c8efeSSunny Srivastava     m_interface(i_iFace), m_ioContext(i_ioCon),
23c74c8efeSSunny Srivastava     m_asioConnection(i_asioConnection)
24c74c8efeSSunny Srivastava {
25c74c8efeSSunny Srivastava     if (dbusUtility::isChassisPowerOn())
26c74c8efeSSunny Srivastava     {
27c74c8efeSSunny Srivastava         // At power on, less number of FRU(s) needs collection. we can scale
28c74c8efeSSunny Srivastava         // down the threads to reduce CPU utilization.
29c74c8efeSSunny Srivastava         m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
30c74c8efeSSunny Srivastava                                             constants::VALUE_1);
31c74c8efeSSunny Srivastava     }
32c74c8efeSSunny Srivastava     else
33c74c8efeSSunny Srivastava     {
34c74c8efeSSunny Srivastava         // Initialize with default configuration
35c74c8efeSSunny Srivastava         m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
36c74c8efeSSunny Srivastava     }
37c74c8efeSSunny Srivastava 
38c74c8efeSSunny Srivastava     // Set up minimal things that is needed before bus name is claimed.
3978a50427SSunny Srivastava     performInitialSetup();
40c74c8efeSSunny Srivastava 
41c74c8efeSSunny Srivastava     if (!m_sysCfgJsonObj.empty() &&
42c74c8efeSSunny Srivastava         jsonUtility::isBackupAndRestoreRequired(m_sysCfgJsonObj))
43c74c8efeSSunny Srivastava     {
44c74c8efeSSunny Srivastava         try
45c74c8efeSSunny Srivastava         {
46c74c8efeSSunny Srivastava             m_backupAndRestoreObj =
47c74c8efeSSunny Srivastava                 std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
48c74c8efeSSunny Srivastava         }
49c74c8efeSSunny Srivastava         catch (const std::exception& l_ex)
50c74c8efeSSunny Srivastava         {
51c74c8efeSSunny Srivastava             logging::logMessage("Back up and restore instantiation failed. {" +
52c74c8efeSSunny Srivastava                                 std::string(l_ex.what()) + "}");
53c74c8efeSSunny Srivastava 
54c74c8efeSSunny Srivastava             EventLogger::createSyncPel(
55c74c8efeSSunny Srivastava                 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
56c74c8efeSSunny Srivastava                 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
57c74c8efeSSunny Srivastava                 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
58c74c8efeSSunny Srivastava         }
59c74c8efeSSunny Srivastava     }
60c74c8efeSSunny Srivastava 
61c7565ed6SAnupama B R     // Instantiate Listener object
62*56e4537cSAnupama B R     m_eventListener = std::make_shared<Listener>(m_worker, m_asioConnection);
63*56e4537cSAnupama B R     m_eventListener->registerAssetTagChangeCallback();
64*56e4537cSAnupama B R     m_eventListener->registerHostStateChangeCallback();
65c7565ed6SAnupama B R 
66c74c8efeSSunny Srivastava     // set async timer to detect if system VPD is published on D-Bus.
67c74c8efeSSunny Srivastava     SetTimerToDetectSVPDOnDbus();
68c74c8efeSSunny Srivastava 
69c74c8efeSSunny Srivastava     // set async timer to detect if VPD collection is done.
70c74c8efeSSunny Srivastava     SetTimerToDetectVpdCollectionStatus();
71c74c8efeSSunny Srivastava 
72c74c8efeSSunny Srivastava     // Instantiate GpioMonitor class
73c74c8efeSSunny Srivastava     m_gpioMonitor =
74c74c8efeSSunny Srivastava         std::make_shared<GpioMonitor>(m_sysCfgJsonObj, m_worker, m_ioContext);
75c74c8efeSSunny Srivastava }
76c74c8efeSSunny Srivastava 
77c74c8efeSSunny Srivastava void IbmHandler::SetTimerToDetectSVPDOnDbus()
78c74c8efeSSunny Srivastava {
79c74c8efeSSunny Srivastava     try
80c74c8efeSSunny Srivastava     {
81c74c8efeSSunny Srivastava         static boost::asio::steady_timer timer(*m_ioContext);
82c74c8efeSSunny Srivastava 
83c74c8efeSSunny Srivastava         // timer for 2 seconds
84c74c8efeSSunny Srivastava         auto asyncCancelled = timer.expires_after(std::chrono::seconds(2));
85c74c8efeSSunny Srivastava 
86c74c8efeSSunny Srivastava         (asyncCancelled == 0) ? logging::logMessage("Timer started")
87c74c8efeSSunny Srivastava                               : logging::logMessage("Timer re-started");
88c74c8efeSSunny Srivastava 
89c74c8efeSSunny Srivastava         timer.async_wait([this](const boost::system::error_code& ec) {
90c74c8efeSSunny Srivastava             if (ec == boost::asio::error::operation_aborted)
91c74c8efeSSunny Srivastava             {
92c74c8efeSSunny Srivastava                 throw std::runtime_error(
93c74c8efeSSunny Srivastava                     std::string(__FUNCTION__) +
94c74c8efeSSunny Srivastava                     ": Timer to detect system VPD collection status was aborted.");
95c74c8efeSSunny Srivastava             }
96c74c8efeSSunny Srivastava 
97c74c8efeSSunny Srivastava             if (ec)
98c74c8efeSSunny Srivastava             {
99c74c8efeSSunny Srivastava                 throw std::runtime_error(
100c74c8efeSSunny Srivastava                     std::string(__FUNCTION__) +
101c74c8efeSSunny Srivastava                     ": Timer to detect System VPD collection failed");
102c74c8efeSSunny Srivastava             }
103c74c8efeSSunny Srivastava 
104c74c8efeSSunny Srivastava             if (m_worker->isSystemVPDOnDBus())
105c74c8efeSSunny Srivastava             {
106c74c8efeSSunny Srivastava                 // cancel the timer
107c74c8efeSSunny Srivastava                 timer.cancel();
108c74c8efeSSunny Srivastava 
109c74c8efeSSunny Srivastava                 // Triggering FRU VPD collection. Setting status to "In
110c74c8efeSSunny Srivastava                 // Progress".
111c74c8efeSSunny Srivastava                 m_interface->set_property("CollectionStatus",
112c74c8efeSSunny Srivastava                                           std::string("InProgress"));
113c74c8efeSSunny Srivastava                 m_worker->collectFrusFromJson();
114c74c8efeSSunny Srivastava             }
115c74c8efeSSunny Srivastava         });
116c74c8efeSSunny Srivastava     }
117c74c8efeSSunny Srivastava     catch (const std::exception& l_ex)
118c74c8efeSSunny Srivastava     {
119c74c8efeSSunny Srivastava         EventLogger::createAsyncPel(
120c74c8efeSSunny Srivastava             EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
121c74c8efeSSunny Srivastava             __FILE__, __FUNCTION__, 0,
122c74c8efeSSunny Srivastava             std::string("Collection for FRUs failed with reason:") +
123c74c8efeSSunny Srivastava                 EventLogger::getErrorMsg(l_ex),
124c74c8efeSSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
125c74c8efeSSunny Srivastava     }
126c74c8efeSSunny Srivastava }
127c74c8efeSSunny Srivastava 
128c74c8efeSSunny Srivastava void IbmHandler::SetTimerToDetectVpdCollectionStatus()
129c74c8efeSSunny Srivastava {
130c74c8efeSSunny Srivastava     // Keeping max retry for 2 minutes. TODO: Make it configurable based on
131c74c8efeSSunny Srivastava     // system type.
132c74c8efeSSunny Srivastava     static constexpr auto MAX_RETRY = 12;
133c74c8efeSSunny Srivastava 
134c74c8efeSSunny Srivastava     static boost::asio::steady_timer l_timer(*m_ioContext);
135c74c8efeSSunny Srivastava     static uint8_t l_timerRetry = 0;
136c74c8efeSSunny Srivastava 
137c74c8efeSSunny Srivastava     auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
138c74c8efeSSunny Srivastava 
139c74c8efeSSunny Srivastava     (l_asyncCancelled == 0)
140c74c8efeSSunny Srivastava         ? logging::logMessage("Collection Timer started")
141c74c8efeSSunny Srivastava         : logging::logMessage("Collection Timer re-started");
142c74c8efeSSunny Srivastava 
143c74c8efeSSunny Srivastava     l_timer.async_wait([this](const boost::system::error_code& ec) {
144c74c8efeSSunny Srivastava         if (ec == boost::asio::error::operation_aborted)
145c74c8efeSSunny Srivastava         {
146c74c8efeSSunny Srivastava             throw std::runtime_error(
147c74c8efeSSunny Srivastava                 "Timer to detect thread collection status was aborted");
148c74c8efeSSunny Srivastava         }
149c74c8efeSSunny Srivastava 
150c74c8efeSSunny Srivastava         if (ec)
151c74c8efeSSunny Srivastava         {
152c74c8efeSSunny Srivastava             throw std::runtime_error(
153c74c8efeSSunny Srivastava                 "Timer to detect thread collection failed");
154c74c8efeSSunny Srivastava         }
155c74c8efeSSunny Srivastava 
156c74c8efeSSunny Srivastava         if (m_worker->isAllFruCollectionDone())
157c74c8efeSSunny Srivastava         {
158c74c8efeSSunny Srivastava             // cancel the timer
159c74c8efeSSunny Srivastava             l_timer.cancel();
160c74c8efeSSunny Srivastava             processFailedEeproms();
161c74c8efeSSunny Srivastava 
162c74c8efeSSunny Srivastava             // update VPD for powerVS system.
163c74c8efeSSunny Srivastava             ConfigurePowerVsSystem();
164c74c8efeSSunny Srivastava 
165c74c8efeSSunny Srivastava             std::cout << "m_worker->isSystemVPDOnDBus() completed" << std::endl;
166c74c8efeSSunny Srivastava             m_interface->set_property("CollectionStatus",
167c74c8efeSSunny Srivastava                                       std::string("Completed"));
168c74c8efeSSunny Srivastava 
169c74c8efeSSunny Srivastava             if (m_backupAndRestoreObj)
170c74c8efeSSunny Srivastava             {
171c74c8efeSSunny Srivastava                 m_backupAndRestoreObj->backupAndRestore();
172c74c8efeSSunny Srivastava             }
173c74c8efeSSunny Srivastava         }
174c74c8efeSSunny Srivastava         else
175c74c8efeSSunny Srivastava         {
176c74c8efeSSunny Srivastava             auto l_threadCount = m_worker->getActiveThreadCount();
177c74c8efeSSunny Srivastava             if (l_timerRetry == MAX_RETRY)
178c74c8efeSSunny Srivastava             {
179c74c8efeSSunny Srivastava                 l_timer.cancel();
180c74c8efeSSunny Srivastava                 logging::logMessage("Taking too long. Active thread = " +
181c74c8efeSSunny Srivastava                                     std::to_string(l_threadCount));
182c74c8efeSSunny Srivastava             }
183c74c8efeSSunny Srivastava             else
184c74c8efeSSunny Srivastava             {
185c74c8efeSSunny Srivastava                 l_timerRetry++;
186c74c8efeSSunny Srivastava                 logging::logMessage("Collection is in progress for [" +
187c74c8efeSSunny Srivastava                                     std::to_string(l_threadCount) + "] FRUs.");
188c74c8efeSSunny Srivastava 
189c74c8efeSSunny Srivastava                 SetTimerToDetectVpdCollectionStatus();
190c74c8efeSSunny Srivastava             }
191c74c8efeSSunny Srivastava         }
192c74c8efeSSunny Srivastava     });
193c74c8efeSSunny Srivastava }
194c74c8efeSSunny Srivastava 
195c74c8efeSSunny Srivastava void IbmHandler::checkAndUpdatePowerVsVpd(
196c74c8efeSSunny Srivastava     const nlohmann::json& i_powerVsJsonObj,
197c74c8efeSSunny Srivastava     std::vector<std::string>& o_failedPathList)
198c74c8efeSSunny Srivastava {
199c74c8efeSSunny Srivastava     for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
200c74c8efeSSunny Srivastava     {
201c74c8efeSSunny Srivastava         nlohmann::json l_sysCfgJsonObj{};
202c74c8efeSSunny Srivastava         if (m_worker.get() != nullptr)
203c74c8efeSSunny Srivastava         {
204c74c8efeSSunny Srivastava             l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
205c74c8efeSSunny Srivastava         }
206c74c8efeSSunny Srivastava 
207c74c8efeSSunny Srivastava         // The utility method will handle emty JSON case. No explicit
208c74c8efeSSunny Srivastava         // handling required here.
209c74c8efeSSunny Srivastava         auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
210c74c8efeSSunny Srivastava             l_sysCfgJsonObj, l_fruPath);
211c74c8efeSSunny Srivastava 
212c74c8efeSSunny Srivastava         // Mark it as failed if inventory path not found in JSON.
213c74c8efeSSunny Srivastava         if (l_inventoryPath.empty())
214c74c8efeSSunny Srivastava         {
215c74c8efeSSunny Srivastava             o_failedPathList.push_back(l_fruPath);
216c74c8efeSSunny Srivastava             continue;
217c74c8efeSSunny Srivastava         }
218c74c8efeSSunny Srivastava 
219c74c8efeSSunny Srivastava         // check if the FRU is present
220c74c8efeSSunny Srivastava         if (!dbusUtility::isInventoryPresent(l_inventoryPath))
221c74c8efeSSunny Srivastava         {
222c74c8efeSSunny Srivastava             logging::logMessage(
223c74c8efeSSunny Srivastava                 "Inventory not present, skip updating part number. Path: " +
224c74c8efeSSunny Srivastava                 l_inventoryPath);
225c74c8efeSSunny Srivastava             continue;
226c74c8efeSSunny Srivastava         }
227c74c8efeSSunny Srivastava 
228c74c8efeSSunny Srivastava         // check if the FRU needs CCIN check before updating PN.
229c74c8efeSSunny Srivastava         if (l_recJson.contains("CCIN"))
230c74c8efeSSunny Srivastava         {
231c74c8efeSSunny Srivastava             const auto& l_ccinFromDbus =
232c74c8efeSSunny Srivastava                 vpdSpecificUtility::getCcinFromDbus(l_inventoryPath);
233c74c8efeSSunny Srivastava 
234c74c8efeSSunny Srivastava             // Not an ideal situation as CCIN can't be empty.
235c74c8efeSSunny Srivastava             if (l_ccinFromDbus.empty())
236c74c8efeSSunny Srivastava             {
237c74c8efeSSunny Srivastava                 o_failedPathList.push_back(l_fruPath);
238c74c8efeSSunny Srivastava                 continue;
239c74c8efeSSunny Srivastava             }
240c74c8efeSSunny Srivastava 
241c74c8efeSSunny Srivastava             std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
242c74c8efeSSunny Srivastava 
243c74c8efeSSunny Srivastava             if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
244c74c8efeSSunny Srivastava                      l_ccinFromDbus) == l_ccinListFromJson.end())
245c74c8efeSSunny Srivastava             {
246c74c8efeSSunny Srivastava                 // Don't update PN in this case.
247c74c8efeSSunny Srivastava                 continue;
248c74c8efeSSunny Srivastava             }
249c74c8efeSSunny Srivastava         }
250c74c8efeSSunny Srivastava 
251c74c8efeSSunny Srivastava         for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
252c74c8efeSSunny Srivastava         {
253c74c8efeSSunny Srivastava             // Record name can't be CCIN, skip processing as it is there for PN
254c74c8efeSSunny Srivastava             // update based on CCIN check.
255c74c8efeSSunny Srivastava             if (l_recordName == constants::kwdCCIN)
256c74c8efeSSunny Srivastava             {
257c74c8efeSSunny Srivastava                 continue;
258c74c8efeSSunny Srivastava             }
259c74c8efeSSunny Srivastava 
260c74c8efeSSunny Srivastava             for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
261c74c8efeSSunny Srivastava             {
262c74c8efeSSunny Srivastava                 // Is value of type array.
263c74c8efeSSunny Srivastava                 if (!l_kwdValue.is_array())
264c74c8efeSSunny Srivastava                 {
265c74c8efeSSunny Srivastava                     o_failedPathList.push_back(l_fruPath);
266c74c8efeSSunny Srivastava                     continue;
267c74c8efeSSunny Srivastava                 }
268c74c8efeSSunny Srivastava 
269c74c8efeSSunny Srivastava                 // Get current FRU Part number.
270c74c8efeSSunny Srivastava                 auto l_retVal = dbusUtility::readDbusProperty(
271c74c8efeSSunny Srivastava                     constants::pimServiceName, l_inventoryPath,
272c74c8efeSSunny Srivastava                     constants::viniInf, constants::kwdFN);
273c74c8efeSSunny Srivastava 
274c74c8efeSSunny Srivastava                 auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
275c74c8efeSSunny Srivastava 
276c74c8efeSSunny Srivastava                 if (!l_ptrToFn)
277c74c8efeSSunny Srivastava                 {
278c74c8efeSSunny Srivastava                     o_failedPathList.push_back(l_fruPath);
279c74c8efeSSunny Srivastava                     continue;
280c74c8efeSSunny Srivastava                 }
281c74c8efeSSunny Srivastava 
282c74c8efeSSunny Srivastava                 types::BinaryVector l_binaryKwdValue =
283c74c8efeSSunny Srivastava                     l_kwdValue.get<types::BinaryVector>();
284c74c8efeSSunny Srivastava                 if (l_binaryKwdValue == (*l_ptrToFn))
285c74c8efeSSunny Srivastava                 {
286c74c8efeSSunny Srivastava                     continue;
287c74c8efeSSunny Srivastava                 }
288c74c8efeSSunny Srivastava 
289c74c8efeSSunny Srivastava                 // Update part number only if required.
290c74c8efeSSunny Srivastava                 std::shared_ptr<Parser> l_parserObj =
291c74c8efeSSunny Srivastava                     std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
292c74c8efeSSunny Srivastava                 if (l_parserObj->updateVpdKeyword(std::make_tuple(
293c74c8efeSSunny Srivastava                         l_recordName, l_kwdName, l_binaryKwdValue)) ==
294c74c8efeSSunny Srivastava                     constants::FAILURE)
295c74c8efeSSunny Srivastava                 {
296c74c8efeSSunny Srivastava                     o_failedPathList.push_back(l_fruPath);
297c74c8efeSSunny Srivastava                     continue;
298c74c8efeSSunny Srivastava                 }
299c74c8efeSSunny Srivastava 
300c74c8efeSSunny Srivastava                 // update the Asset interface Spare part number explicitly.
301c74c8efeSSunny Srivastava                 if (!dbusUtility::callPIM(types::ObjectMap{
302c74c8efeSSunny Srivastava                         {l_inventoryPath,
303c74c8efeSSunny Srivastava                          {{constants::assetInf,
304c74c8efeSSunny Srivastava                            {{"SparePartNumber",
305c74c8efeSSunny Srivastava                              std::string(l_binaryKwdValue.begin(),
306c74c8efeSSunny Srivastava                                          l_binaryKwdValue.end())}}}}}}))
307c74c8efeSSunny Srivastava                 {
308c74c8efeSSunny Srivastava                     logging::logMessage(
309c74c8efeSSunny Srivastava                         "Updating Spare Part Number under Asset interface failed for path [" +
310c74c8efeSSunny Srivastava                         l_inventoryPath + "]");
311c74c8efeSSunny Srivastava                 }
312c74c8efeSSunny Srivastava 
313c74c8efeSSunny Srivastava                 // Just needed for logging.
314c74c8efeSSunny Srivastava                 std::string l_initialPartNum((*l_ptrToFn).begin(),
315c74c8efeSSunny Srivastava                                              (*l_ptrToFn).end());
316c74c8efeSSunny Srivastava                 std::string l_finalPartNum(l_binaryKwdValue.begin(),
317c74c8efeSSunny Srivastava                                            l_binaryKwdValue.end());
318c74c8efeSSunny Srivastava                 logging::logMessage(
319c74c8efeSSunny Srivastava                     "FRU Part number updated for path [" + l_inventoryPath +
320c74c8efeSSunny Srivastava                     "]" + "From [" + l_initialPartNum + "]" + " to [" +
321c74c8efeSSunny Srivastava                     l_finalPartNum + "]");
322c74c8efeSSunny Srivastava             }
323c74c8efeSSunny Srivastava         }
324c74c8efeSSunny Srivastava     }
325c74c8efeSSunny Srivastava }
326c74c8efeSSunny Srivastava 
327c74c8efeSSunny Srivastava void IbmHandler::ConfigurePowerVsSystem()
328c74c8efeSSunny Srivastava {
329c74c8efeSSunny Srivastava     std::vector<std::string> l_failedPathList;
330c74c8efeSSunny Srivastava     try
331c74c8efeSSunny Srivastava     {
332c74c8efeSSunny Srivastava         types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
333c74c8efeSSunny Srivastava         if (l_imValue.empty())
334c74c8efeSSunny Srivastava         {
335c74c8efeSSunny Srivastava             throw DbusException("Invalid IM value read from Dbus");
336c74c8efeSSunny Srivastava         }
337c74c8efeSSunny Srivastava 
338c74c8efeSSunny Srivastava         if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue))
339c74c8efeSSunny Srivastava         {
340c74c8efeSSunny Srivastava             // TODO: Should booting be blocked in case of some
341c74c8efeSSunny Srivastava             // misconfigurations?
342c74c8efeSSunny Srivastava             return;
343c74c8efeSSunny Srivastava         }
344c74c8efeSSunny Srivastava 
345c74c8efeSSunny Srivastava         const nlohmann::json& l_powerVsJsonObj =
346c74c8efeSSunny Srivastava             jsonUtility::getPowerVsJson(l_imValue);
347c74c8efeSSunny Srivastava 
348c74c8efeSSunny Srivastava         if (l_powerVsJsonObj.empty())
349c74c8efeSSunny Srivastava         {
350c74c8efeSSunny Srivastava             throw std::runtime_error("PowerVS Json not found");
351c74c8efeSSunny Srivastava         }
352c74c8efeSSunny Srivastava 
353c74c8efeSSunny Srivastava         checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
354c74c8efeSSunny Srivastava 
355c74c8efeSSunny Srivastava         if (!l_failedPathList.empty())
356c74c8efeSSunny Srivastava         {
357c74c8efeSSunny Srivastava             throw std::runtime_error(
358c74c8efeSSunny Srivastava                 "Part number update failed for following paths: ");
359c74c8efeSSunny Srivastava         }
360c74c8efeSSunny Srivastava     }
361c74c8efeSSunny Srivastava     catch (const std::exception& l_ex)
362c74c8efeSSunny Srivastava     {
363c74c8efeSSunny Srivastava         // TODO log appropriate PEL
364c74c8efeSSunny Srivastava     }
365c74c8efeSSunny Srivastava }
366c74c8efeSSunny Srivastava 
367c74c8efeSSunny Srivastava void IbmHandler::processFailedEeproms()
368c74c8efeSSunny Srivastava {
369c74c8efeSSunny Srivastava     if (m_worker.get() != nullptr)
370c74c8efeSSunny Srivastava     {
371c74c8efeSSunny Srivastava         // TODO:
372c74c8efeSSunny Srivastava         // - iterate through list of EEPROMs for which thread creation has
373c74c8efeSSunny Srivastava         // failed
374c74c8efeSSunny Srivastava         // - For each failed EEPROM, trigger VPD collection
375c74c8efeSSunny Srivastava         m_worker->getFailedEepromPaths().clear();
376c74c8efeSSunny Srivastava     }
377c74c8efeSSunny Srivastava }
378380efbb5SSunny Srivastava 
37978a50427SSunny Srivastava void IbmHandler::primeSystemBlueprint()
38078a50427SSunny Srivastava {
38178a50427SSunny Srivastava     if (m_sysCfgJsonObj.empty())
38278a50427SSunny Srivastava     {
38378a50427SSunny Srivastava         return;
38478a50427SSunny Srivastava     }
38578a50427SSunny Srivastava 
38678a50427SSunny Srivastava     const nlohmann::json& l_listOfFrus =
38778a50427SSunny Srivastava         m_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
38878a50427SSunny Srivastava 
38978a50427SSunny Srivastava     for (const auto& l_itemFRUS : l_listOfFrus.items())
39078a50427SSunny Srivastava     {
39178a50427SSunny Srivastava         const std::string& l_vpdFilePath = l_itemFRUS.key();
39278a50427SSunny Srivastava 
39378a50427SSunny Srivastava         if (l_vpdFilePath == SYSTEM_VPD_FILE_PATH)
39478a50427SSunny Srivastava         {
39578a50427SSunny Srivastava             continue;
39678a50427SSunny Srivastava         }
39778a50427SSunny Srivastava 
39878a50427SSunny Srivastava         // Prime the inventry for FRUs which
39978a50427SSunny Srivastava         // are not present/processing had some error.
40078a50427SSunny Srivastava         if (m_worker.get() != nullptr &&
40178a50427SSunny Srivastava             !m_worker->primeInventory(l_vpdFilePath))
40278a50427SSunny Srivastava         {
40378a50427SSunny Srivastava             logging::logMessage(
40478a50427SSunny Srivastava                 "Priming of inventory failed for FRU " + l_vpdFilePath);
40578a50427SSunny Srivastava         }
40678a50427SSunny Srivastava     }
40778a50427SSunny Srivastava }
40878a50427SSunny Srivastava 
40978a50427SSunny Srivastava void IbmHandler::enableMuxChips()
41078a50427SSunny Srivastava {
41178a50427SSunny Srivastava     if (m_sysCfgJsonObj.empty())
41278a50427SSunny Srivastava     {
41378a50427SSunny Srivastava         // config JSON should not be empty at this point of execution.
41478a50427SSunny Srivastava         throw std::runtime_error("Config JSON is empty. Can't enable muxes");
41578a50427SSunny Srivastava         return;
41678a50427SSunny Srivastava     }
41778a50427SSunny Srivastava 
41878a50427SSunny Srivastava     if (!m_sysCfgJsonObj.contains("muxes"))
41978a50427SSunny Srivastava     {
42078a50427SSunny Srivastava         logging::logMessage("No mux defined for the system in config JSON");
42178a50427SSunny Srivastava         return;
42278a50427SSunny Srivastava     }
42378a50427SSunny Srivastava 
42478a50427SSunny Srivastava     // iterate over each MUX detail and enable them.
42578a50427SSunny Srivastava     for (const auto& item : m_sysCfgJsonObj["muxes"])
42678a50427SSunny Srivastava     {
42778a50427SSunny Srivastava         if (item.contains("holdidlepath"))
42878a50427SSunny Srivastava         {
42978a50427SSunny Srivastava             std::string cmd = "echo 0 > ";
43078a50427SSunny Srivastava             cmd += item["holdidlepath"];
43178a50427SSunny Srivastava 
43278a50427SSunny Srivastava             logging::logMessage("Enabling mux with command = " + cmd);
43378a50427SSunny Srivastava 
43478a50427SSunny Srivastava             commonUtility::executeCmd(cmd);
43578a50427SSunny Srivastava             continue;
43678a50427SSunny Srivastava         }
43778a50427SSunny Srivastava 
43878a50427SSunny Srivastava         logging::logMessage(
43978a50427SSunny Srivastava             "Mux Entry does not have hold idle path. Can't enable the mux");
44078a50427SSunny Srivastava     }
44178a50427SSunny Srivastava }
44278a50427SSunny Srivastava 
44378a50427SSunny Srivastava void IbmHandler::performInitialSetup()
44478a50427SSunny Srivastava {
44578a50427SSunny Srivastava     try
44678a50427SSunny Srivastava     {
447281e2d46SAnupama B R         if (m_worker.get() == nullptr)
44878a50427SSunny Srivastava         {
44978a50427SSunny Srivastava             throw std::runtime_error(
450281e2d46SAnupama B R                 "Worker object not found. Can't perform initial setup.");
45178a50427SSunny Srivastava         }
452281e2d46SAnupama B R 
45378a50427SSunny Srivastava         m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
454281e2d46SAnupama B R         if (!dbusUtility::isChassisPowerOn())
455281e2d46SAnupama B R         {
456281e2d46SAnupama B R             m_worker->setDeviceTreeAndJson();
457281e2d46SAnupama B R 
458281e2d46SAnupama B R             // Since the above function setDeviceTreeAndJson can change the json
459281e2d46SAnupama B R             // which is used, we would need to reacquire the json object again
460281e2d46SAnupama B R             // here.
461281e2d46SAnupama B R             m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
462281e2d46SAnupama B R 
463ec7f8869SAnupama B R             if (isPrimingRequired())
464ec7f8869SAnupama B R             {
465281e2d46SAnupama B R                 primeSystemBlueprint();
46678a50427SSunny Srivastava             }
467ec7f8869SAnupama B R         }
46878a50427SSunny Srivastava 
46978a50427SSunny Srivastava         // Enable all mux which are used for connecting to the i2c on the
47078a50427SSunny Srivastava         // pcie slots for pcie cards. These are not enabled by kernel due to
47178a50427SSunny Srivastava         // an issue seen with Castello cards, where the i2c line hangs on a
47278a50427SSunny Srivastava         // probe.
47378a50427SSunny Srivastava         enableMuxChips();
47478a50427SSunny Srivastava 
47578a50427SSunny Srivastava         // Nothing needs to be done. Service restarted or BMC re-booted for
47678a50427SSunny Srivastava         // some reason at system power on.
47778a50427SSunny Srivastava     }
47878a50427SSunny Srivastava     catch (const std::exception& l_ex)
47978a50427SSunny Srivastava     {
48078a50427SSunny Srivastava         // Any issue in system's inital set up is handled in this catch. Error
48178a50427SSunny Srivastava         // will not propogate to manager.
48278a50427SSunny Srivastava         EventLogger::createSyncPel(
48378a50427SSunny Srivastava             EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
48478a50427SSunny Srivastava             __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
48578a50427SSunny Srivastava             std::nullopt, std::nullopt, std::nullopt, std::nullopt);
48678a50427SSunny Srivastava     }
48778a50427SSunny Srivastava }
48878a50427SSunny Srivastava 
489ec7f8869SAnupama B R bool IbmHandler::isPrimingRequired() const noexcept
490ec7f8869SAnupama B R {
491ec7f8869SAnupama B R     try
492ec7f8869SAnupama B R     {
493ec7f8869SAnupama B R         // get all object paths under PIM
494ec7f8869SAnupama B R         const auto l_objectPaths = dbusUtility::GetSubTreePaths(
495ec7f8869SAnupama B R             constants::systemInvPath, 0,
496ec7f8869SAnupama B R             std::vector<std::string>{constants::vpdCollectionInterface});
497ec7f8869SAnupama B R 
498ec7f8869SAnupama B R         const nlohmann::json& l_listOfFrus =
499ec7f8869SAnupama B R             m_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
500ec7f8869SAnupama B R 
501ec7f8869SAnupama B R         size_t l_invPathCount = 0;
502ec7f8869SAnupama B R 
503ec7f8869SAnupama B R         for (const auto& l_itemFRUS : l_listOfFrus.items())
504ec7f8869SAnupama B R         {
505ec7f8869SAnupama B R             for (const auto& l_Fru : l_itemFRUS.value())
506ec7f8869SAnupama B R             {
507ec7f8869SAnupama B R                 if (l_Fru.contains("ccin") || (l_Fru.contains("noprime") &&
508ec7f8869SAnupama B R                                                l_Fru.value("noprime", false)))
509ec7f8869SAnupama B R                 {
510ec7f8869SAnupama B R                     continue;
511ec7f8869SAnupama B R                 }
512ec7f8869SAnupama B R 
513ec7f8869SAnupama B R                 l_invPathCount += 1;
514ec7f8869SAnupama B R             }
515ec7f8869SAnupama B R         }
516ec7f8869SAnupama B R         return ((l_objectPaths.size() >= l_invPathCount) ? false : true);
517ec7f8869SAnupama B R     }
518ec7f8869SAnupama B R     catch (const std::exception& l_ex)
519ec7f8869SAnupama B R     {
520ec7f8869SAnupama B R         logging::logMessage(
521ec7f8869SAnupama B R             "Error while checking is priming required or not, error: " +
522ec7f8869SAnupama B R             std::string(l_ex.what()));
523ec7f8869SAnupama B R     }
524ec7f8869SAnupama B R 
525ec7f8869SAnupama B R     // In case of any error, perform priming, as it's unclear whether priming is
526ec7f8869SAnupama B R     // required.
527ec7f8869SAnupama B R     return true;
528ec7f8869SAnupama B R }
529867ee75dSSunny Srivastava } // namespace vpd
530