1fa5e4d32SSunny Srivastava #include "config.h"
2fa5e4d32SSunny Srivastava
3fa5e4d32SSunny Srivastava #include "manager.hpp"
4fa5e4d32SSunny Srivastava
5fa5e4d32SSunny Srivastava #include "backup_restore.hpp"
6fa5e4d32SSunny Srivastava #include "constants.hpp"
7fa5e4d32SSunny Srivastava #include "exceptions.hpp"
8fa5e4d32SSunny Srivastava #include "logger.hpp"
9fa5e4d32SSunny Srivastava #include "parser.hpp"
10fa5e4d32SSunny Srivastava #include "parser_factory.hpp"
11fa5e4d32SSunny Srivastava #include "parser_interface.hpp"
12*ffdff313SRekha Aparna #include "single_fab.hpp"
13fa5e4d32SSunny Srivastava #include "types.hpp"
14fa5e4d32SSunny Srivastava #include "utility/dbus_utility.hpp"
15fa5e4d32SSunny Srivastava #include "utility/json_utility.hpp"
16fa5e4d32SSunny Srivastava #include "utility/vpd_specific_utility.hpp"
17fa5e4d32SSunny Srivastava
18fa5e4d32SSunny Srivastava #include <boost/asio/steady_timer.hpp>
19fa5e4d32SSunny Srivastava #include <sdbusplus/bus/match.hpp>
20fa5e4d32SSunny Srivastava #include <sdbusplus/message.hpp>
21fa5e4d32SSunny Srivastava
22fa5e4d32SSunny Srivastava namespace vpd
Manager(const std::shared_ptr<boost::asio::io_context> & ioCon,const std::shared_ptr<sdbusplus::asio::dbus_interface> & iFace,const std::shared_ptr<sdbusplus::asio::connection> & asioConnection)23fa5e4d32SSunny Srivastava {
24fa5e4d32SSunny Srivastava Manager::Manager(
25fa5e4d32SSunny Srivastava const std::shared_ptr<boost::asio::io_context>& ioCon,
26fa5e4d32SSunny Srivastava const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
27fa5e4d32SSunny Srivastava const std::shared_ptr<sdbusplus::asio::connection>& asioConnection) :
28fa5e4d32SSunny Srivastava m_ioContext(ioCon), m_interface(iFace), m_asioConnection(asioConnection)
29fa5e4d32SSunny Srivastava {
30*ffdff313SRekha Aparna #ifdef IBM_SYSTEM
31*ffdff313SRekha Aparna if (!dbusUtility::isChassisPowerOn())
32*ffdff313SRekha Aparna {
33*ffdff313SRekha Aparna SingleFab l_singleFab;
34*ffdff313SRekha Aparna const int& l_rc = l_singleFab.singleFabImOverride();
35*ffdff313SRekha Aparna
36*ffdff313SRekha Aparna if (l_rc == constants::FAILURE)
37*ffdff313SRekha Aparna {
38*ffdff313SRekha Aparna throw std::runtime_error(
39*ffdff313SRekha Aparna std::string(__FUNCTION__) +
40*ffdff313SRekha Aparna " : Found an invalid system configuration. Needs manual intervention. BMC is being quiesced.");
41*ffdff313SRekha Aparna }
42*ffdff313SRekha Aparna }
43*ffdff313SRekha Aparna #endif
44*ffdff313SRekha Aparna
45fa5e4d32SSunny Srivastava try
46fa5e4d32SSunny Srivastava {
47fa5e4d32SSunny Srivastava #ifdef IBM_SYSTEM
48765cf7b8SSunny Srivastava if (dbusUtility::isChassisPowerOn())
49765cf7b8SSunny Srivastava {
50765cf7b8SSunny Srivastava // At power on, less number of FRU(s) needs collection. we can scale
51765cf7b8SSunny Srivastava // down the threads to reduce CPU utilization.
52765cf7b8SSunny Srivastava m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
53765cf7b8SSunny Srivastava constants::VALUE_1);
54765cf7b8SSunny Srivastava }
55765cf7b8SSunny Srivastava else
56765cf7b8SSunny Srivastava {
57765cf7b8SSunny Srivastava // Initialize with default configuration
58fa5e4d32SSunny Srivastava m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
59765cf7b8SSunny Srivastava }
60fa5e4d32SSunny Srivastava
61fa5e4d32SSunny Srivastava // Set up minimal things that is needed before bus name is claimed.
62fa5e4d32SSunny Srivastava m_worker->performInitialSetup();
63fa5e4d32SSunny Srivastava
64fa5e4d32SSunny Srivastava // set callback to detect any asset tag change
65fa5e4d32SSunny Srivastava registerAssetTagChangeCallback();
66fa5e4d32SSunny Srivastava
67fa5e4d32SSunny Srivastava // set async timer to detect if system VPD is published on D-Bus.
68fa5e4d32SSunny Srivastava SetTimerToDetectSVPDOnDbus();
69fa5e4d32SSunny Srivastava
70fa5e4d32SSunny Srivastava // set async timer to detect if VPD collection is done.
71fa5e4d32SSunny Srivastava SetTimerToDetectVpdCollectionStatus();
72fa5e4d32SSunny Srivastava
73fa5e4d32SSunny Srivastava // Instantiate GpioMonitor class
74fa5e4d32SSunny Srivastava m_gpioMonitor = std::make_shared<GpioMonitor>(
75fa5e4d32SSunny Srivastava m_worker->getSysCfgJsonObj(), m_worker, m_ioContext);
76fa5e4d32SSunny Srivastava
77fa5e4d32SSunny Srivastava #endif
78fa5e4d32SSunny Srivastava // set callback to detect host state change.
79fa5e4d32SSunny Srivastava registerHostStateChangeCallback();
80fa5e4d32SSunny Srivastava
81fa5e4d32SSunny Srivastava // For backward compatibility. Should be depricated.
82fa5e4d32SSunny Srivastava iFace->register_method(
83fa5e4d32SSunny Srivastava "WriteKeyword",
84fa5e4d32SSunny Srivastava [this](const sdbusplus::message::object_path i_path,
85fa5e4d32SSunny Srivastava const std::string i_recordName, const std::string i_keyword,
86fa5e4d32SSunny Srivastava const types::BinaryVector i_value) -> int {
87fa5e4d32SSunny Srivastava return this->updateKeyword(
88fa5e4d32SSunny Srivastava i_path, std::make_tuple(i_recordName, i_keyword, i_value));
89fa5e4d32SSunny Srivastava });
90fa5e4d32SSunny Srivastava
91fa5e4d32SSunny Srivastava // Register methods under com.ibm.VPD.Manager interface
92fa5e4d32SSunny Srivastava iFace->register_method(
93fa5e4d32SSunny Srivastava "UpdateKeyword",
94fa5e4d32SSunny Srivastava [this](const types::Path i_vpdPath,
95fa5e4d32SSunny Srivastava const types::WriteVpdParams i_paramsToWriteData) -> int {
96fa5e4d32SSunny Srivastava return this->updateKeyword(i_vpdPath, i_paramsToWriteData);
97fa5e4d32SSunny Srivastava });
98fa5e4d32SSunny Srivastava
99fa5e4d32SSunny Srivastava iFace->register_method(
100fa5e4d32SSunny Srivastava "WriteKeywordOnHardware",
101fa5e4d32SSunny Srivastava [this](const types::Path i_fruPath,
102fa5e4d32SSunny Srivastava const types::WriteVpdParams i_paramsToWriteData) -> int {
103fa5e4d32SSunny Srivastava return this->updateKeywordOnHardware(i_fruPath,
104fa5e4d32SSunny Srivastava i_paramsToWriteData);
105fa5e4d32SSunny Srivastava });
106fa5e4d32SSunny Srivastava
107fa5e4d32SSunny Srivastava iFace->register_method(
108fa5e4d32SSunny Srivastava "ReadKeyword",
109fa5e4d32SSunny Srivastava [this](const types::Path i_fruPath,
110fa5e4d32SSunny Srivastava const types::ReadVpdParams i_paramsToReadData)
111fa5e4d32SSunny Srivastava -> types::DbusVariantType {
112fa5e4d32SSunny Srivastava return this->readKeyword(i_fruPath, i_paramsToReadData);
113fa5e4d32SSunny Srivastava });
114fa5e4d32SSunny Srivastava
115fa5e4d32SSunny Srivastava iFace->register_method(
116fa5e4d32SSunny Srivastava "CollectFRUVPD",
117fa5e4d32SSunny Srivastava [this](const sdbusplus::message::object_path& i_dbusObjPath) {
118fa5e4d32SSunny Srivastava this->collectSingleFruVpd(i_dbusObjPath);
119fa5e4d32SSunny Srivastava });
120fa5e4d32SSunny Srivastava
121fa5e4d32SSunny Srivastava iFace->register_method(
122fa5e4d32SSunny Srivastava "deleteFRUVPD",
123fa5e4d32SSunny Srivastava [this](const sdbusplus::message::object_path& i_dbusObjPath) {
124fa5e4d32SSunny Srivastava this->deleteSingleFruVpd(i_dbusObjPath);
125fa5e4d32SSunny Srivastava });
126fa5e4d32SSunny Srivastava
127fa5e4d32SSunny Srivastava iFace->register_method(
128fa5e4d32SSunny Srivastava "GetExpandedLocationCode",
129fa5e4d32SSunny Srivastava [this](const std::string& i_unexpandedLocationCode,
130fa5e4d32SSunny Srivastava uint16_t& i_nodeNumber) -> std::string {
131fa5e4d32SSunny Srivastava return this->getExpandedLocationCode(i_unexpandedLocationCode,
132fa5e4d32SSunny Srivastava i_nodeNumber);
133fa5e4d32SSunny Srivastava });
134fa5e4d32SSunny Srivastava
135fa5e4d32SSunny Srivastava iFace->register_method("GetFRUsByExpandedLocationCode",
136fa5e4d32SSunny Srivastava [this](const std::string& i_expandedLocationCode)
137fa5e4d32SSunny Srivastava -> types::ListOfPaths {
138fa5e4d32SSunny Srivastava return this->getFrusByExpandedLocationCode(
139fa5e4d32SSunny Srivastava i_expandedLocationCode);
140fa5e4d32SSunny Srivastava });
141fa5e4d32SSunny Srivastava
142fa5e4d32SSunny Srivastava iFace->register_method(
143fa5e4d32SSunny Srivastava "GetFRUsByUnexpandedLocationCode",
144fa5e4d32SSunny Srivastava [this](const std::string& i_unexpandedLocationCode,
145fa5e4d32SSunny Srivastava uint16_t& i_nodeNumber) -> types::ListOfPaths {
146fa5e4d32SSunny Srivastava return this->getFrusByUnexpandedLocationCode(
147fa5e4d32SSunny Srivastava i_unexpandedLocationCode, i_nodeNumber);
148fa5e4d32SSunny Srivastava });
149fa5e4d32SSunny Srivastava
150fa5e4d32SSunny Srivastava iFace->register_method(
151fa5e4d32SSunny Srivastava "GetHardwarePath",
152fa5e4d32SSunny Srivastava [this](const sdbusplus::message::object_path& i_dbusObjPath)
153fa5e4d32SSunny Srivastava -> std::string { return this->getHwPath(i_dbusObjPath); });
154fa5e4d32SSunny Srivastava
155fa5e4d32SSunny Srivastava iFace->register_method("PerformVPDRecollection", [this]() {
156fa5e4d32SSunny Srivastava this->performVpdRecollection();
157fa5e4d32SSunny Srivastava });
158fa5e4d32SSunny Srivastava
159fa5e4d32SSunny Srivastava // Indicates FRU VPD collection for the system has not started.
160fa5e4d32SSunny Srivastava iFace->register_property_rw<std::string>(
161fa5e4d32SSunny Srivastava "CollectionStatus", sdbusplus::vtable::property_::emits_change,
162fa5e4d32SSunny Srivastava [this](const std::string l_currStatus, const auto&) {
163fa5e4d32SSunny Srivastava m_vpdCollectionStatus = l_currStatus;
164fa5e4d32SSunny Srivastava return 0;
165fa5e4d32SSunny Srivastava },
166fa5e4d32SSunny Srivastava [this](const auto&) { return m_vpdCollectionStatus; });
167fa5e4d32SSunny Srivastava }
168fa5e4d32SSunny Srivastava catch (const std::exception& e)
169fa5e4d32SSunny Srivastava {
170fa5e4d32SSunny Srivastava logging::logMessage(
171fa5e4d32SSunny Srivastava "VPD-Manager service failed. " + std::string(e.what()));
172fa5e4d32SSunny Srivastava throw;
173fa5e4d32SSunny Srivastava }
174fa5e4d32SSunny Srivastava }
175fa5e4d32SSunny Srivastava
176fa5e4d32SSunny Srivastava #ifdef IBM_SYSTEM
177fa5e4d32SSunny Srivastava void Manager::registerAssetTagChangeCallback()
178fa5e4d32SSunny Srivastava {
179fa5e4d32SSunny Srivastava static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
180fa5e4d32SSunny Srivastava std::make_shared<sdbusplus::bus::match_t>(
181fa5e4d32SSunny Srivastava *m_asioConnection,
182fa5e4d32SSunny Srivastava sdbusplus::bus::match::rules::propertiesChanged(
183fa5e4d32SSunny Srivastava constants::systemInvPath, constants::assetTagInf),
184fa5e4d32SSunny Srivastava [this](sdbusplus::message_t& l_msg) {
185fa5e4d32SSunny Srivastava processAssetTagChangeCallback(l_msg);
186fa5e4d32SSunny Srivastava });
187fa5e4d32SSunny Srivastava }
188fa5e4d32SSunny Srivastava
189fa5e4d32SSunny Srivastava void Manager::processAssetTagChangeCallback(sdbusplus::message_t& i_msg)
190fa5e4d32SSunny Srivastava {
191fa5e4d32SSunny Srivastava try
192fa5e4d32SSunny Srivastava {
193fa5e4d32SSunny Srivastava if (i_msg.is_method_error())
194fa5e4d32SSunny Srivastava {
195fa5e4d32SSunny Srivastava throw std::runtime_error(
196fa5e4d32SSunny Srivastava "Error reading callback msg for asset tag.");
197fa5e4d32SSunny Srivastava }
198fa5e4d32SSunny Srivastava
199fa5e4d32SSunny Srivastava std::string l_objectPath;
200fa5e4d32SSunny Srivastava types::PropertyMap l_propMap;
201fa5e4d32SSunny Srivastava i_msg.read(l_objectPath, l_propMap);
202fa5e4d32SSunny Srivastava
203fa5e4d32SSunny Srivastava const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
204fa5e4d32SSunny Srivastava if (l_itrToAssetTag != l_propMap.end())
205fa5e4d32SSunny Srivastava {
206fa5e4d32SSunny Srivastava if (auto l_assetTag =
207fa5e4d32SSunny Srivastava std::get_if<std::string>(&(l_itrToAssetTag->second)))
208fa5e4d32SSunny Srivastava {
209fa5e4d32SSunny Srivastava // Call Notify to persist the AssetTag
210fa5e4d32SSunny Srivastava types::ObjectMap l_objectMap = {
211fa5e4d32SSunny Srivastava {sdbusplus::message::object_path(constants::systemInvPath),
212fa5e4d32SSunny Srivastava {{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};
213fa5e4d32SSunny Srivastava
214fa5e4d32SSunny Srivastava // Notify PIM
215fa5e4d32SSunny Srivastava if (!dbusUtility::callPIM(move(l_objectMap)))
216fa5e4d32SSunny Srivastava {
217fa5e4d32SSunny Srivastava throw std::runtime_error(
218fa5e4d32SSunny Srivastava "Call to PIM failed for asset tag update.");
219fa5e4d32SSunny Srivastava }
220fa5e4d32SSunny Srivastava }
221fa5e4d32SSunny Srivastava }
222fa5e4d32SSunny Srivastava else
223fa5e4d32SSunny Srivastava {
224fa5e4d32SSunny Srivastava throw std::runtime_error(
225fa5e4d32SSunny Srivastava "Could not find asset tag in callback message.");
226fa5e4d32SSunny Srivastava }
227fa5e4d32SSunny Srivastava }
228fa5e4d32SSunny Srivastava catch (const std::exception& l_ex)
229fa5e4d32SSunny Srivastava {
230fa5e4d32SSunny Srivastava // TODO: Log PEL with below description.
231fa5e4d32SSunny Srivastava logging::logMessage("Asset tag callback update failed with error: " +
232fa5e4d32SSunny Srivastava std::string(l_ex.what()));
233fa5e4d32SSunny Srivastava }
234fa5e4d32SSunny Srivastava }
235fa5e4d32SSunny Srivastava
236fa5e4d32SSunny Srivastava void Manager::SetTimerToDetectSVPDOnDbus()
237fa5e4d32SSunny Srivastava {
23858057c18SSunny Srivastava try
23958057c18SSunny Srivastava {
240fa5e4d32SSunny Srivastava static boost::asio::steady_timer timer(*m_ioContext);
241fa5e4d32SSunny Srivastava
242fa5e4d32SSunny Srivastava // timer for 2 seconds
243fa5e4d32SSunny Srivastava auto asyncCancelled = timer.expires_after(std::chrono::seconds(2));
244fa5e4d32SSunny Srivastava
245fa5e4d32SSunny Srivastava (asyncCancelled == 0) ? logging::logMessage("Timer started")
246fa5e4d32SSunny Srivastava : logging::logMessage("Timer re-started");
247fa5e4d32SSunny Srivastava
248fa5e4d32SSunny Srivastava timer.async_wait([this](const boost::system::error_code& ec) {
249fa5e4d32SSunny Srivastava if (ec == boost::asio::error::operation_aborted)
250fa5e4d32SSunny Srivastava {
251fa5e4d32SSunny Srivastava throw std::runtime_error(
25258057c18SSunny Srivastava std::string(__FUNCTION__) +
25358057c18SSunny Srivastava ": Timer to detect system VPD collection status was aborted.");
254fa5e4d32SSunny Srivastava }
255fa5e4d32SSunny Srivastava
256fa5e4d32SSunny Srivastava if (ec)
257fa5e4d32SSunny Srivastava {
258fa5e4d32SSunny Srivastava throw std::runtime_error(
25958057c18SSunny Srivastava std::string(__FUNCTION__) +
26058057c18SSunny Srivastava ": Timer to detect System VPD collection failed");
261fa5e4d32SSunny Srivastava }
262fa5e4d32SSunny Srivastava
263fa5e4d32SSunny Srivastava if (m_worker->isSystemVPDOnDBus())
264fa5e4d32SSunny Srivastava {
265fa5e4d32SSunny Srivastava // cancel the timer
266fa5e4d32SSunny Srivastava timer.cancel();
267fa5e4d32SSunny Srivastava
268fa5e4d32SSunny Srivastava // Triggering FRU VPD collection. Setting status to "In
269fa5e4d32SSunny Srivastava // Progress".
270fa5e4d32SSunny Srivastava m_interface->set_property("CollectionStatus",
271fa5e4d32SSunny Srivastava std::string("InProgress"));
272fa5e4d32SSunny Srivastava m_worker->collectFrusFromJson();
273fa5e4d32SSunny Srivastava }
274fa5e4d32SSunny Srivastava });
275fa5e4d32SSunny Srivastava }
27658057c18SSunny Srivastava catch (const std::exception& l_ex)
27758057c18SSunny Srivastava {
27858057c18SSunny Srivastava EventLogger::createAsyncPel(
27958057c18SSunny Srivastava EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
28058057c18SSunny Srivastava __FILE__, __FUNCTION__, 0,
28158057c18SSunny Srivastava std::string("Collection for FRUs failed with reason:") +
28258057c18SSunny Srivastava EventLogger::getErrorMsg(l_ex),
28358057c18SSunny Srivastava std::nullopt, std::nullopt, std::nullopt, std::nullopt);
28458057c18SSunny Srivastava }
28558057c18SSunny Srivastava }
286fa5e4d32SSunny Srivastava
287fa5e4d32SSunny Srivastava void Manager::SetTimerToDetectVpdCollectionStatus()
288fa5e4d32SSunny Srivastava {
28959f91a84SSunny Srivastava // Keeping max retry for 2 minutes. TODO: Make it configurable based on
290fa5e4d32SSunny Srivastava // system type.
29159f91a84SSunny Srivastava static constexpr auto MAX_RETRY = 12;
292fa5e4d32SSunny Srivastava
293fa5e4d32SSunny Srivastava static boost::asio::steady_timer l_timer(*m_ioContext);
294fa5e4d32SSunny Srivastava static uint8_t l_timerRetry = 0;
295fa5e4d32SSunny Srivastava
29659f91a84SSunny Srivastava auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
297fa5e4d32SSunny Srivastava
298fa5e4d32SSunny Srivastava (l_asyncCancelled == 0)
299fa5e4d32SSunny Srivastava ? logging::logMessage("Collection Timer started")
300fa5e4d32SSunny Srivastava : logging::logMessage("Collection Timer re-started");
301fa5e4d32SSunny Srivastava
302fa5e4d32SSunny Srivastava l_timer.async_wait([this](const boost::system::error_code& ec) {
303fa5e4d32SSunny Srivastava if (ec == boost::asio::error::operation_aborted)
304fa5e4d32SSunny Srivastava {
305fa5e4d32SSunny Srivastava throw std::runtime_error(
306fa5e4d32SSunny Srivastava "Timer to detect thread collection status was aborted");
307fa5e4d32SSunny Srivastava }
308fa5e4d32SSunny Srivastava
309fa5e4d32SSunny Srivastava if (ec)
310fa5e4d32SSunny Srivastava {
311fa5e4d32SSunny Srivastava throw std::runtime_error(
312fa5e4d32SSunny Srivastava "Timer to detect thread collection failed");
313fa5e4d32SSunny Srivastava }
314fa5e4d32SSunny Srivastava
315fa5e4d32SSunny Srivastava if (m_worker->isAllFruCollectionDone())
316fa5e4d32SSunny Srivastava {
317fa5e4d32SSunny Srivastava // cancel the timer
318fa5e4d32SSunny Srivastava l_timer.cancel();
3191f4c8f81SSouvik Roy processFailedEeproms();
3204c7798aaSSunny Srivastava
3214c7798aaSSunny Srivastava // update VPD for powerVS system.
3224c7798aaSSunny Srivastava ConfigurePowerVsSystem();
3234c7798aaSSunny Srivastava
324fa5e4d32SSunny Srivastava m_interface->set_property("CollectionStatus",
325fa5e4d32SSunny Srivastava std::string("Completed"));
326fa5e4d32SSunny Srivastava
327fa5e4d32SSunny Srivastava const nlohmann::json& l_sysCfgJsonObj =
328fa5e4d32SSunny Srivastava m_worker->getSysCfgJsonObj();
329fa5e4d32SSunny Srivastava if (jsonUtility::isBackupAndRestoreRequired(l_sysCfgJsonObj))
330fa5e4d32SSunny Srivastava {
331fa5e4d32SSunny Srivastava BackupAndRestore l_backupAndRestoreObj(l_sysCfgJsonObj);
332fa5e4d32SSunny Srivastava l_backupAndRestoreObj.backupAndRestore();
333fa5e4d32SSunny Srivastava }
334fa5e4d32SSunny Srivastava }
335fa5e4d32SSunny Srivastava else
336fa5e4d32SSunny Srivastava {
337fa5e4d32SSunny Srivastava auto l_threadCount = m_worker->getActiveThreadCount();
338fa5e4d32SSunny Srivastava if (l_timerRetry == MAX_RETRY)
339fa5e4d32SSunny Srivastava {
340fa5e4d32SSunny Srivastava l_timer.cancel();
341fa5e4d32SSunny Srivastava logging::logMessage("Taking too long. Active thread = " +
342fa5e4d32SSunny Srivastava std::to_string(l_threadCount));
343fa5e4d32SSunny Srivastava }
344fa5e4d32SSunny Srivastava else
345fa5e4d32SSunny Srivastava {
346fa5e4d32SSunny Srivastava l_timerRetry++;
34759f91a84SSunny Srivastava logging::logMessage("Collection is in progress for [" +
34859f91a84SSunny Srivastava std::to_string(l_threadCount) + "] FRUs.");
349fa5e4d32SSunny Srivastava
350fa5e4d32SSunny Srivastava SetTimerToDetectVpdCollectionStatus();
351fa5e4d32SSunny Srivastava }
352fa5e4d32SSunny Srivastava }
353fa5e4d32SSunny Srivastava });
354fa5e4d32SSunny Srivastava }
3554c7798aaSSunny Srivastava
356022112bcSSunny Srivastava void Manager::checkAndUpdatePowerVsVpd(
357022112bcSSunny Srivastava const nlohmann::json& i_powerVsJsonObj,
358022112bcSSunny Srivastava std::vector<std::string>& o_failedPathList)
359022112bcSSunny Srivastava {
3600cd15e1eSSunny Srivastava for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
3610cd15e1eSSunny Srivastava {
3620cd15e1eSSunny Srivastava nlohmann::json l_sysCfgJsonObj{};
3630cd15e1eSSunny Srivastava if (m_worker.get() != nullptr)
3640cd15e1eSSunny Srivastava {
3650cd15e1eSSunny Srivastava l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
3660cd15e1eSSunny Srivastava }
3670cd15e1eSSunny Srivastava
368f1dda767SSunny Srivastava // The utility method will handle emty JSON case. No explicit
3690cd15e1eSSunny Srivastava // handling required here.
3700cd15e1eSSunny Srivastava auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
3710cd15e1eSSunny Srivastava l_sysCfgJsonObj, l_fruPath);
3720cd15e1eSSunny Srivastava
3730cd15e1eSSunny Srivastava // Mark it as failed if inventory path not found in JSON.
3740cd15e1eSSunny Srivastava if (l_inventoryPath.empty())
3750cd15e1eSSunny Srivastava {
3760cd15e1eSSunny Srivastava o_failedPathList.push_back(l_fruPath);
3770cd15e1eSSunny Srivastava continue;
3780cd15e1eSSunny Srivastava }
3790cd15e1eSSunny Srivastava
380f1dda767SSunny Srivastava // check if the FRU is present
381f1dda767SSunny Srivastava if (!dbusUtility::isInventoryPresent(l_inventoryPath))
382f1dda767SSunny Srivastava {
383f1dda767SSunny Srivastava logging::logMessage(
384f1dda767SSunny Srivastava "Inventory not present, skip updating part number. Path: " +
385f1dda767SSunny Srivastava l_inventoryPath);
386f1dda767SSunny Srivastava continue;
387f1dda767SSunny Srivastava }
388f1dda767SSunny Srivastava
389f1dda767SSunny Srivastava // check if the FRU needs CCIN check before updating PN.
390f1dda767SSunny Srivastava if (l_recJson.contains("CCIN"))
391f1dda767SSunny Srivastava {
392f1dda767SSunny Srivastava const auto& l_ccinFromDbus =
393f1dda767SSunny Srivastava vpdSpecificUtility::getCcinFromDbus(l_inventoryPath);
394f1dda767SSunny Srivastava
395f1dda767SSunny Srivastava // Not an ideal situation as CCIN can't be empty.
396f1dda767SSunny Srivastava if (l_ccinFromDbus.empty())
397f1dda767SSunny Srivastava {
398f1dda767SSunny Srivastava o_failedPathList.push_back(l_fruPath);
399f1dda767SSunny Srivastava continue;
400f1dda767SSunny Srivastava }
401f1dda767SSunny Srivastava
402f1dda767SSunny Srivastava std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
403f1dda767SSunny Srivastava
404f1dda767SSunny Srivastava if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
405f1dda767SSunny Srivastava l_ccinFromDbus) == l_ccinListFromJson.end())
406f1dda767SSunny Srivastava {
407f1dda767SSunny Srivastava // Don't update PN in this case.
408f1dda767SSunny Srivastava continue;
409f1dda767SSunny Srivastava }
410f1dda767SSunny Srivastava }
411f1dda767SSunny Srivastava
412f1dda767SSunny Srivastava for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
413f1dda767SSunny Srivastava {
414f1dda767SSunny Srivastava // Record name can't be CCIN, skip processing as it is there for PN
415f1dda767SSunny Srivastava // update based on CCIN check.
416f1dda767SSunny Srivastava if (l_recordName == constants::kwdCCIN)
417f1dda767SSunny Srivastava {
418f1dda767SSunny Srivastava continue;
419f1dda767SSunny Srivastava }
420f1dda767SSunny Srivastava
421f1dda767SSunny Srivastava for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
422f1dda767SSunny Srivastava {
423f1dda767SSunny Srivastava // Is value of type array.
424f1dda767SSunny Srivastava if (!l_kwdValue.is_array())
425f1dda767SSunny Srivastava {
426f1dda767SSunny Srivastava o_failedPathList.push_back(l_fruPath);
427f1dda767SSunny Srivastava continue;
428f1dda767SSunny Srivastava }
429f1dda767SSunny Srivastava
43022793834SSunny Srivastava // Get current FRU Part number.
4310cd15e1eSSunny Srivastava auto l_retVal = dbusUtility::readDbusProperty(
4320cd15e1eSSunny Srivastava constants::pimServiceName, l_inventoryPath,
43322793834SSunny Srivastava constants::viniInf, constants::kwdFN);
4340cd15e1eSSunny Srivastava
43522793834SSunny Srivastava auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
4360cd15e1eSSunny Srivastava
43722793834SSunny Srivastava if (!l_ptrToFn)
4380cd15e1eSSunny Srivastava {
4390cd15e1eSSunny Srivastava o_failedPathList.push_back(l_fruPath);
4400cd15e1eSSunny Srivastava continue;
4410cd15e1eSSunny Srivastava }
4420cd15e1eSSunny Srivastava
4430cd15e1eSSunny Srivastava types::BinaryVector l_binaryKwdValue =
4440cd15e1eSSunny Srivastava l_kwdValue.get<types::BinaryVector>();
44522793834SSunny Srivastava if (l_binaryKwdValue == (*l_ptrToFn))
4460cd15e1eSSunny Srivastava {
4470cd15e1eSSunny Srivastava continue;
4480cd15e1eSSunny Srivastava }
4490cd15e1eSSunny Srivastava
4500cd15e1eSSunny Srivastava // Update part number only if required.
4510cd15e1eSSunny Srivastava if (updateKeyword(
4520cd15e1eSSunny Srivastava l_fruPath,
4530cd15e1eSSunny Srivastava std::make_tuple(l_recordName, l_kwdName, l_kwdValue)) ==
4540cd15e1eSSunny Srivastava constants::FAILURE)
4550cd15e1eSSunny Srivastava {
4560cd15e1eSSunny Srivastava o_failedPathList.push_back(l_fruPath);
4570cd15e1eSSunny Srivastava continue;
4580cd15e1eSSunny Srivastava }
4590cd15e1eSSunny Srivastava
46022793834SSunny Srivastava // update the Asset interface Spare part number explicitly.
461b83cb35fSSunny Srivastava if (!dbusUtility::callPIM(types::ObjectMap{
462b83cb35fSSunny Srivastava {l_inventoryPath,
46322793834SSunny Srivastava {{constants::assetInf,
46422793834SSunny Srivastava {{"SparePartNumber",
465b83cb35fSSunny Srivastava std::string(l_binaryKwdValue.begin(),
466b83cb35fSSunny Srivastava l_binaryKwdValue.end())}}}}}}))
467b83cb35fSSunny Srivastava {
468b83cb35fSSunny Srivastava logging::logMessage(
46922793834SSunny Srivastava "Updating Spare Part Number under Asset interface failed for path [" +
470b83cb35fSSunny Srivastava l_inventoryPath + "]");
471b83cb35fSSunny Srivastava }
472b83cb35fSSunny Srivastava
4730cd15e1eSSunny Srivastava // Just needed for logging.
47422793834SSunny Srivastava std::string l_initialPartNum((*l_ptrToFn).begin(),
47522793834SSunny Srivastava (*l_ptrToFn).end());
4760cd15e1eSSunny Srivastava std::string l_finalPartNum(l_binaryKwdValue.begin(),
4770cd15e1eSSunny Srivastava l_binaryKwdValue.end());
4780cd15e1eSSunny Srivastava logging::logMessage(
47922793834SSunny Srivastava "FRU Part number updated for path [" + l_inventoryPath +
48022793834SSunny Srivastava "]" + "From [" + l_initialPartNum + "]" + " to [" +
4810cd15e1eSSunny Srivastava l_finalPartNum + "]");
4820cd15e1eSSunny Srivastava }
4830cd15e1eSSunny Srivastava }
4840cd15e1eSSunny Srivastava }
485022112bcSSunny Srivastava }
486022112bcSSunny Srivastava
4874c7798aaSSunny Srivastava void Manager::ConfigurePowerVsSystem()
4884c7798aaSSunny Srivastava {
489022112bcSSunny Srivastava std::vector<std::string> l_failedPathList;
4901a48f0ceSSunny Srivastava try
4911a48f0ceSSunny Srivastava {
4921a48f0ceSSunny Srivastava types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
4931a48f0ceSSunny Srivastava if (l_imValue.empty())
4941a48f0ceSSunny Srivastava {
4951a48f0ceSSunny Srivastava throw DbusException("Invalid IM value read from Dbus");
4961a48f0ceSSunny Srivastava }
497c6ef42d6SSunny Srivastava
498c6ef42d6SSunny Srivastava if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue))
499c6ef42d6SSunny Srivastava {
500c6ef42d6SSunny Srivastava // TODO: Should booting be blocked in case of some
501c6ef42d6SSunny Srivastava // misconfigurations?
502c6ef42d6SSunny Srivastava return;
503c6ef42d6SSunny Srivastava }
504022112bcSSunny Srivastava
505022112bcSSunny Srivastava const nlohmann::json& l_powerVsJsonObj =
506022112bcSSunny Srivastava jsonUtility::getPowerVsJson(l_imValue);
507022112bcSSunny Srivastava
508022112bcSSunny Srivastava if (l_powerVsJsonObj.empty())
509022112bcSSunny Srivastava {
510022112bcSSunny Srivastava throw std::runtime_error("PowerVS Json not found");
511022112bcSSunny Srivastava }
512022112bcSSunny Srivastava
513022112bcSSunny Srivastava checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
514022112bcSSunny Srivastava
515022112bcSSunny Srivastava if (!l_failedPathList.empty())
516022112bcSSunny Srivastava {
517022112bcSSunny Srivastava throw std::runtime_error(
518022112bcSSunny Srivastava "Part number update failed for following paths: ");
519022112bcSSunny Srivastava }
5201a48f0ceSSunny Srivastava }
5211a48f0ceSSunny Srivastava catch (const std::exception& l_ex)
5221a48f0ceSSunny Srivastava {
5231a48f0ceSSunny Srivastava // TODO log appropriate PEL
5241a48f0ceSSunny Srivastava }
5254c7798aaSSunny Srivastava }
52646f2981aSSunny Srivastava
52746f2981aSSunny Srivastava void Manager::processFailedEeproms()
52846f2981aSSunny Srivastava {
52946f2981aSSunny Srivastava if (m_worker.get() != nullptr)
53046f2981aSSunny Srivastava {
53146f2981aSSunny Srivastava // TODO:
53246f2981aSSunny Srivastava // - iterate through list of EEPROMs for which thread creation has
53346f2981aSSunny Srivastava // failed
53446f2981aSSunny Srivastava // - For each failed EEPROM, trigger VPD collection
53546f2981aSSunny Srivastava m_worker->getFailedEepromPaths().clear();
53646f2981aSSunny Srivastava }
53746f2981aSSunny Srivastava }
538fa5e4d32SSunny Srivastava #endif
539fa5e4d32SSunny Srivastava
540fa5e4d32SSunny Srivastava int Manager::updateKeyword(const types::Path i_vpdPath,
541fa5e4d32SSunny Srivastava const types::WriteVpdParams i_paramsToWriteData)
542fa5e4d32SSunny Srivastava {
543fa5e4d32SSunny Srivastava if (i_vpdPath.empty())
544fa5e4d32SSunny Srivastava {
545fa5e4d32SSunny Srivastava logging::logMessage("Given VPD path is empty.");
546fa5e4d32SSunny Srivastava return -1;
547fa5e4d32SSunny Srivastava }
548fa5e4d32SSunny Srivastava
549fa5e4d32SSunny Srivastava types::Path l_fruPath;
550fa5e4d32SSunny Srivastava nlohmann::json l_sysCfgJsonObj{};
551fa5e4d32SSunny Srivastava
552fa5e4d32SSunny Srivastava if (m_worker.get() != nullptr)
553fa5e4d32SSunny Srivastava {
554fa5e4d32SSunny Srivastava l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
555fa5e4d32SSunny Srivastava
556fa5e4d32SSunny Srivastava // Get the EEPROM path
557fa5e4d32SSunny Srivastava if (!l_sysCfgJsonObj.empty())
558fa5e4d32SSunny Srivastava {
559fa5e4d32SSunny Srivastava l_fruPath =
560fa5e4d32SSunny Srivastava jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_vpdPath);
561fa5e4d32SSunny Srivastava }
562fa5e4d32SSunny Srivastava }
563fa5e4d32SSunny Srivastava
564fa5e4d32SSunny Srivastava if (l_fruPath.empty())
565fa5e4d32SSunny Srivastava {
566fa5e4d32SSunny Srivastava l_fruPath = i_vpdPath;
567fa5e4d32SSunny Srivastava }
568fa5e4d32SSunny Srivastava
569fa5e4d32SSunny Srivastava try
570fa5e4d32SSunny Srivastava {
571fa5e4d32SSunny Srivastava std::shared_ptr<Parser> l_parserObj =
572fa5e4d32SSunny Srivastava std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
573fa5e4d32SSunny Srivastava return l_parserObj->updateVpdKeyword(i_paramsToWriteData);
574fa5e4d32SSunny Srivastava }
575fa5e4d32SSunny Srivastava catch (const std::exception& l_exception)
576fa5e4d32SSunny Srivastava {
577fa5e4d32SSunny Srivastava // TODO:: error log needed
578fa5e4d32SSunny Srivastava logging::logMessage("Update keyword failed for file[" + i_vpdPath +
579fa5e4d32SSunny Srivastava "], reason: " + std::string(l_exception.what()));
580fa5e4d32SSunny Srivastava return -1;
581fa5e4d32SSunny Srivastava }
582fa5e4d32SSunny Srivastava }
583fa5e4d32SSunny Srivastava
584fa5e4d32SSunny Srivastava int Manager::updateKeywordOnHardware(
585fa5e4d32SSunny Srivastava const types::Path i_fruPath,
586fa5e4d32SSunny Srivastava const types::WriteVpdParams i_paramsToWriteData) noexcept
587fa5e4d32SSunny Srivastava {
588fa5e4d32SSunny Srivastava try
589fa5e4d32SSunny Srivastava {
590fa5e4d32SSunny Srivastava if (i_fruPath.empty())
591fa5e4d32SSunny Srivastava {
592fa5e4d32SSunny Srivastava throw std::runtime_error("Given FRU path is empty");
593fa5e4d32SSunny Srivastava }
594fa5e4d32SSunny Srivastava
595fa5e4d32SSunny Srivastava nlohmann::json l_sysCfgJsonObj{};
596fa5e4d32SSunny Srivastava
597fa5e4d32SSunny Srivastava if (m_worker.get() != nullptr)
598fa5e4d32SSunny Srivastava {
599fa5e4d32SSunny Srivastava l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
600fa5e4d32SSunny Srivastava }
601fa5e4d32SSunny Srivastava
602fa5e4d32SSunny Srivastava std::shared_ptr<Parser> l_parserObj =
603fa5e4d32SSunny Srivastava std::make_shared<Parser>(i_fruPath, l_sysCfgJsonObj);
604fa5e4d32SSunny Srivastava return l_parserObj->updateVpdKeywordOnHardware(i_paramsToWriteData);
605fa5e4d32SSunny Srivastava }
606fa5e4d32SSunny Srivastava catch (const std::exception& l_exception)
607fa5e4d32SSunny Srivastava {
608fa5e4d32SSunny Srivastava EventLogger::createAsyncPel(
609fa5e4d32SSunny Srivastava types::ErrorType::InvalidEeprom, types::SeverityType::Informational,
610fa5e4d32SSunny Srivastava __FILE__, __FUNCTION__, 0,
611fa5e4d32SSunny Srivastava "Update keyword on hardware failed for file[" + i_fruPath +
612fa5e4d32SSunny Srivastava "], reason: " + std::string(l_exception.what()),
613fa5e4d32SSunny Srivastava std::nullopt, std::nullopt, std::nullopt, std::nullopt);
614fa5e4d32SSunny Srivastava
615fa5e4d32SSunny Srivastava return constants::FAILURE;
616fa5e4d32SSunny Srivastava }
617fa5e4d32SSunny Srivastava }
618fa5e4d32SSunny Srivastava
619fa5e4d32SSunny Srivastava types::DbusVariantType Manager::readKeyword(
620fa5e4d32SSunny Srivastava const types::Path i_fruPath, const types::ReadVpdParams i_paramsToReadData)
621fa5e4d32SSunny Srivastava {
622fa5e4d32SSunny Srivastava try
623fa5e4d32SSunny Srivastava {
624fa5e4d32SSunny Srivastava nlohmann::json l_jsonObj{};
625fa5e4d32SSunny Srivastava
626fa5e4d32SSunny Srivastava if (m_worker.get() != nullptr)
627fa5e4d32SSunny Srivastava {
628fa5e4d32SSunny Srivastava l_jsonObj = m_worker->getSysCfgJsonObj();
629fa5e4d32SSunny Srivastava }
630fa5e4d32SSunny Srivastava
631fa5e4d32SSunny Srivastava std::error_code ec;
632fa5e4d32SSunny Srivastava
633fa5e4d32SSunny Srivastava // Check if given path is filesystem path
634fa5e4d32SSunny Srivastava if (!std::filesystem::exists(i_fruPath, ec) && (ec))
635fa5e4d32SSunny Srivastava {
636fa5e4d32SSunny Srivastava throw std::runtime_error(
637fa5e4d32SSunny Srivastava "Given file path " + i_fruPath + " not found.");
638fa5e4d32SSunny Srivastava }
639fa5e4d32SSunny Srivastava
640fa5e4d32SSunny Srivastava logging::logMessage("Performing VPD read on " + i_fruPath);
641fa5e4d32SSunny Srivastava
642fa5e4d32SSunny Srivastava std::shared_ptr<vpd::Parser> l_parserObj =
643fa5e4d32SSunny Srivastava std::make_shared<vpd::Parser>(i_fruPath, l_jsonObj);
644fa5e4d32SSunny Srivastava
645fa5e4d32SSunny Srivastava std::shared_ptr<vpd::ParserInterface> l_vpdParserInstance =
646fa5e4d32SSunny Srivastava l_parserObj->getVpdParserInstance();
647fa5e4d32SSunny Srivastava
648fa5e4d32SSunny Srivastava return (
649fa5e4d32SSunny Srivastava l_vpdParserInstance->readKeywordFromHardware(i_paramsToReadData));
650fa5e4d32SSunny Srivastava }
651fa5e4d32SSunny Srivastava catch (const std::exception& e)
652fa5e4d32SSunny Srivastava {
653fa5e4d32SSunny Srivastava logging::logMessage(
654fa5e4d32SSunny Srivastava e.what() + std::string(". VPD manager read operation failed for ") +
655fa5e4d32SSunny Srivastava i_fruPath);
656fa5e4d32SSunny Srivastava throw types::DeviceError::ReadFailure();
657fa5e4d32SSunny Srivastava }
658fa5e4d32SSunny Srivastava }
659fa5e4d32SSunny Srivastava
660fa5e4d32SSunny Srivastava void Manager::collectSingleFruVpd(
661fa5e4d32SSunny Srivastava const sdbusplus::message::object_path& i_dbusObjPath)
662fa5e4d32SSunny Srivastava {
663fa5e4d32SSunny Srivastava try
664fa5e4d32SSunny Srivastava {
665fa5e4d32SSunny Srivastava if (m_vpdCollectionStatus != "Completed")
666fa5e4d32SSunny Srivastava {
66746b73d9fSPriyanga Ramasamy logging::logMessage(
668fa5e4d32SSunny Srivastava "Currently VPD CollectionStatus is not completed. Cannot perform single FRU VPD collection for " +
669fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
67046b73d9fSPriyanga Ramasamy return;
671fa5e4d32SSunny Srivastava }
672fa5e4d32SSunny Srivastava
673fa5e4d32SSunny Srivastava // Get system config JSON object from worker class
674fa5e4d32SSunny Srivastava nlohmann::json l_sysCfgJsonObj{};
675fa5e4d32SSunny Srivastava
676fa5e4d32SSunny Srivastava if (m_worker.get() != nullptr)
677fa5e4d32SSunny Srivastava {
678fa5e4d32SSunny Srivastava l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
679fa5e4d32SSunny Srivastava }
680fa5e4d32SSunny Srivastava
681fa5e4d32SSunny Srivastava // Check if system config JSON is present
682fa5e4d32SSunny Srivastava if (l_sysCfgJsonObj.empty())
683fa5e4d32SSunny Srivastava {
68446b73d9fSPriyanga Ramasamy logging::logMessage(
68546b73d9fSPriyanga Ramasamy "System config JSON object not present. Single FRU VPD collection is not performed for " +
686fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
68746b73d9fSPriyanga Ramasamy return;
688fa5e4d32SSunny Srivastava }
689fa5e4d32SSunny Srivastava
690fa5e4d32SSunny Srivastava // Get FRU path for the given D-bus object path from JSON
691fa5e4d32SSunny Srivastava const std::string& l_fruPath =
692fa5e4d32SSunny Srivastava jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_dbusObjPath);
693fa5e4d32SSunny Srivastava
694fa5e4d32SSunny Srivastava if (l_fruPath.empty())
695fa5e4d32SSunny Srivastava {
69646b73d9fSPriyanga Ramasamy logging::logMessage(
69746b73d9fSPriyanga Ramasamy "D-bus object path not present in JSON. Single FRU VPD collection is not performed for " +
698fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
69946b73d9fSPriyanga Ramasamy return;
700fa5e4d32SSunny Srivastava }
701fa5e4d32SSunny Srivastava
702fa5e4d32SSunny Srivastava // Check if host is up and running
703fa5e4d32SSunny Srivastava if (dbusUtility::isHostRunning())
704fa5e4d32SSunny Srivastava {
705fa5e4d32SSunny Srivastava if (!jsonUtility::isFruReplaceableAtRuntime(l_sysCfgJsonObj,
706fa5e4d32SSunny Srivastava l_fruPath))
707fa5e4d32SSunny Srivastava {
70846b73d9fSPriyanga Ramasamy logging::logMessage(
70946b73d9fSPriyanga Ramasamy "Given FRU is not replaceable at host runtime. Single FRU VPD collection is not performed for " +
710fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
71146b73d9fSPriyanga Ramasamy return;
712fa5e4d32SSunny Srivastava }
713fa5e4d32SSunny Srivastava }
714fa5e4d32SSunny Srivastava else if (dbusUtility::isBMCReady())
715fa5e4d32SSunny Srivastava {
716fa5e4d32SSunny Srivastava if (!jsonUtility::isFruReplaceableAtStandby(l_sysCfgJsonObj,
717fa5e4d32SSunny Srivastava l_fruPath) &&
718fa5e4d32SSunny Srivastava (!jsonUtility::isFruReplaceableAtRuntime(l_sysCfgJsonObj,
719fa5e4d32SSunny Srivastava l_fruPath)))
720fa5e4d32SSunny Srivastava {
72146b73d9fSPriyanga Ramasamy logging::logMessage(
72246b73d9fSPriyanga Ramasamy "Given FRU is neither replaceable at standby nor replaceable at runtime. Single FRU VPD collection is not performed for " +
723fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
72446b73d9fSPriyanga Ramasamy return;
725fa5e4d32SSunny Srivastava }
726fa5e4d32SSunny Srivastava }
727fa5e4d32SSunny Srivastava
72846b73d9fSPriyanga Ramasamy // Set CollectionStatus as InProgress. Since it's an intermediate state
72946b73d9fSPriyanga Ramasamy // D-bus set-property call is good enough to update the status.
73046b73d9fSPriyanga Ramasamy const std::string& l_collStatusProp = "CollectionStatus";
731c532b188SRekhaAparna01
732c532b188SRekhaAparna01 if (!dbusUtility::writeDbusProperty(
73346b73d9fSPriyanga Ramasamy jsonUtility::getServiceName(l_sysCfgJsonObj,
73446b73d9fSPriyanga Ramasamy std::string(i_dbusObjPath)),
73546b73d9fSPriyanga Ramasamy std::string(i_dbusObjPath), constants::vpdCollectionInterface,
73646b73d9fSPriyanga Ramasamy l_collStatusProp,
737c532b188SRekhaAparna01 types::DbusVariantType{constants::vpdCollectionInProgress}))
73846b73d9fSPriyanga Ramasamy {
73946b73d9fSPriyanga Ramasamy logging::logMessage(
74046b73d9fSPriyanga Ramasamy "Unable to set CollectionStatus as InProgress for " +
74146b73d9fSPriyanga Ramasamy std::string(i_dbusObjPath) +
74246b73d9fSPriyanga Ramasamy ". Continue single FRU VPD collection.");
74346b73d9fSPriyanga Ramasamy }
74446b73d9fSPriyanga Ramasamy
745fa5e4d32SSunny Srivastava // Parse VPD
746fa5e4d32SSunny Srivastava types::VPDMapVariant l_parsedVpd = m_worker->parseVpdFile(l_fruPath);
747fa5e4d32SSunny Srivastava
748fa5e4d32SSunny Srivastava // If l_parsedVpd is pointing to std::monostate
749fa5e4d32SSunny Srivastava if (l_parsedVpd.index() == 0)
750fa5e4d32SSunny Srivastava {
751fa5e4d32SSunny Srivastava throw std::runtime_error(
752fa5e4d32SSunny Srivastava "VPD parsing failed for " + std::string(i_dbusObjPath));
753fa5e4d32SSunny Srivastava }
754fa5e4d32SSunny Srivastava
755fa5e4d32SSunny Srivastava // Get D-bus object map from worker class
756fa5e4d32SSunny Srivastava types::ObjectMap l_dbusObjectMap;
757fa5e4d32SSunny Srivastava m_worker->populateDbus(l_parsedVpd, l_dbusObjectMap, l_fruPath);
758fa5e4d32SSunny Srivastava
759fa5e4d32SSunny Srivastava if (l_dbusObjectMap.empty())
760fa5e4d32SSunny Srivastava {
761fa5e4d32SSunny Srivastava throw std::runtime_error(
762fa5e4d32SSunny Srivastava "Failed to create D-bus object map. Single FRU VPD collection failed for " +
763fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
764fa5e4d32SSunny Srivastava }
765fa5e4d32SSunny Srivastava
766fa5e4d32SSunny Srivastava // Call PIM's Notify method
767fa5e4d32SSunny Srivastava if (!dbusUtility::callPIM(move(l_dbusObjectMap)))
768fa5e4d32SSunny Srivastava {
769fa5e4d32SSunny Srivastava throw std::runtime_error(
770fa5e4d32SSunny Srivastava "Notify PIM failed. Single FRU VPD collection failed for " +
771fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
772fa5e4d32SSunny Srivastava }
773fa5e4d32SSunny Srivastava }
774fa5e4d32SSunny Srivastava catch (const std::exception& l_error)
775fa5e4d32SSunny Srivastava {
77646b73d9fSPriyanga Ramasamy // Notify FRU's VPD CollectionStatus as Failure
77746b73d9fSPriyanga Ramasamy if (!dbusUtility::notifyFRUCollectionStatus(
77846b73d9fSPriyanga Ramasamy std::string(i_dbusObjPath), constants::vpdCollectionFailure))
77946b73d9fSPriyanga Ramasamy {
78046b73d9fSPriyanga Ramasamy logging::logMessage(
78146b73d9fSPriyanga Ramasamy "Call to PIM Notify method failed to update Collection status as Failure for " +
78246b73d9fSPriyanga Ramasamy std::string(i_dbusObjPath));
78346b73d9fSPriyanga Ramasamy }
78446b73d9fSPriyanga Ramasamy
785fa5e4d32SSunny Srivastava // TODO: Log PEL
786fa5e4d32SSunny Srivastava logging::logMessage(std::string(l_error.what()));
787fa5e4d32SSunny Srivastava }
788fa5e4d32SSunny Srivastava }
789fa5e4d32SSunny Srivastava
790fa5e4d32SSunny Srivastava void Manager::deleteSingleFruVpd(
791fa5e4d32SSunny Srivastava const sdbusplus::message::object_path& i_dbusObjPath)
792fa5e4d32SSunny Srivastava {
793fa5e4d32SSunny Srivastava try
794fa5e4d32SSunny Srivastava {
795fa5e4d32SSunny Srivastava if (std::string(i_dbusObjPath).empty())
796fa5e4d32SSunny Srivastava {
797fa5e4d32SSunny Srivastava throw std::runtime_error(
798fa5e4d32SSunny Srivastava "Given DBus object path is empty. Aborting FRU VPD deletion.");
799fa5e4d32SSunny Srivastava }
800fa5e4d32SSunny Srivastava
801fa5e4d32SSunny Srivastava if (m_worker.get() == nullptr)
802fa5e4d32SSunny Srivastava {
803fa5e4d32SSunny Srivastava throw std::runtime_error(
804fa5e4d32SSunny Srivastava "Worker object not found, can't perform FRU VPD deletion for: " +
805fa5e4d32SSunny Srivastava std::string(i_dbusObjPath));
806fa5e4d32SSunny Srivastava }
807fa5e4d32SSunny Srivastava
808fa5e4d32SSunny Srivastava m_worker->deleteFruVpd(std::string(i_dbusObjPath));
809fa5e4d32SSunny Srivastava }
810fa5e4d32SSunny Srivastava catch (const std::exception& l_ex)
811fa5e4d32SSunny Srivastava {
812fa5e4d32SSunny Srivastava // TODO: Log PEL
813fa5e4d32SSunny Srivastava logging::logMessage(l_ex.what());
814fa5e4d32SSunny Srivastava }
815fa5e4d32SSunny Srivastava }
816fa5e4d32SSunny Srivastava
817fa5e4d32SSunny Srivastava bool Manager::isValidUnexpandedLocationCode(
818fa5e4d32SSunny Srivastava const std::string& i_unexpandedLocationCode)
819fa5e4d32SSunny Srivastava {
820fa5e4d32SSunny Srivastava if ((i_unexpandedLocationCode.length() <
821fa5e4d32SSunny Srivastava constants::UNEXP_LOCATION_CODE_MIN_LENGTH) ||
822fa5e4d32SSunny Srivastava ((i_unexpandedLocationCode.compare(0, 4, "Ufcs") !=
823fa5e4d32SSunny Srivastava constants::STR_CMP_SUCCESS) &&
824fa5e4d32SSunny Srivastava (i_unexpandedLocationCode.compare(0, 4, "Umts") !=
825fa5e4d32SSunny Srivastava constants::STR_CMP_SUCCESS)) ||
826fa5e4d32SSunny Srivastava ((i_unexpandedLocationCode.length() >
827fa5e4d32SSunny Srivastava constants::UNEXP_LOCATION_CODE_MIN_LENGTH) &&
828fa5e4d32SSunny Srivastava (i_unexpandedLocationCode.find("-") != 4)))
829fa5e4d32SSunny Srivastava {
830fa5e4d32SSunny Srivastava return false;
831fa5e4d32SSunny Srivastava }
832fa5e4d32SSunny Srivastava
833fa5e4d32SSunny Srivastava return true;
834fa5e4d32SSunny Srivastava }
835fa5e4d32SSunny Srivastava
836fa5e4d32SSunny Srivastava std::string Manager::getExpandedLocationCode(
837fa5e4d32SSunny Srivastava const std::string& i_unexpandedLocationCode,
838fa5e4d32SSunny Srivastava [[maybe_unused]] const uint16_t i_nodeNumber)
839fa5e4d32SSunny Srivastava {
840fa5e4d32SSunny Srivastava if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
841fa5e4d32SSunny Srivastava {
842fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
843fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
844fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
845fa5e4d32SSunny Srivastava i_unexpandedLocationCode.c_str()));
846fa5e4d32SSunny Srivastava }
847fa5e4d32SSunny Srivastava
848fa5e4d32SSunny Srivastava const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
849fa5e4d32SSunny Srivastava if (!l_sysCfgJsonObj.contains("frus"))
850fa5e4d32SSunny Srivastava {
851fa5e4d32SSunny Srivastava logging::logMessage("Missing frus tag in system config JSON");
852fa5e4d32SSunny Srivastava }
853fa5e4d32SSunny Srivastava
854fa5e4d32SSunny Srivastava const nlohmann::json& l_listOfFrus =
855fa5e4d32SSunny Srivastava l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
856fa5e4d32SSunny Srivastava
857fa5e4d32SSunny Srivastava for (const auto& l_frus : l_listOfFrus.items())
858fa5e4d32SSunny Srivastava {
859fa5e4d32SSunny Srivastava for (const auto& l_aFru : l_frus.value())
860fa5e4d32SSunny Srivastava {
861fa5e4d32SSunny Srivastava if (l_aFru["extraInterfaces"].contains(
862fa5e4d32SSunny Srivastava constants::locationCodeInf) &&
863fa5e4d32SSunny Srivastava l_aFru["extraInterfaces"][constants::locationCodeInf].value(
864fa5e4d32SSunny Srivastava "LocationCode", "") == i_unexpandedLocationCode)
865fa5e4d32SSunny Srivastava {
866fa5e4d32SSunny Srivastava return std::get<std::string>(dbusUtility::readDbusProperty(
867fa5e4d32SSunny Srivastava l_aFru["serviceName"], l_aFru["inventoryPath"],
868fa5e4d32SSunny Srivastava constants::locationCodeInf, "LocationCode"));
869fa5e4d32SSunny Srivastava }
870fa5e4d32SSunny Srivastava }
871fa5e4d32SSunny Srivastava }
872fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
873fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
874fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
875fa5e4d32SSunny Srivastava i_unexpandedLocationCode.c_str()));
876fa5e4d32SSunny Srivastava }
877fa5e4d32SSunny Srivastava
878fa5e4d32SSunny Srivastava types::ListOfPaths Manager::getFrusByUnexpandedLocationCode(
879fa5e4d32SSunny Srivastava const std::string& i_unexpandedLocationCode,
880fa5e4d32SSunny Srivastava [[maybe_unused]] const uint16_t i_nodeNumber)
881fa5e4d32SSunny Srivastava {
882fa5e4d32SSunny Srivastava types::ListOfPaths l_inventoryPaths;
883fa5e4d32SSunny Srivastava
884fa5e4d32SSunny Srivastava if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
885fa5e4d32SSunny Srivastava {
886fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
887fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
888fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
889fa5e4d32SSunny Srivastava i_unexpandedLocationCode.c_str()));
890fa5e4d32SSunny Srivastava }
891fa5e4d32SSunny Srivastava
892fa5e4d32SSunny Srivastava const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
893fa5e4d32SSunny Srivastava if (!l_sysCfgJsonObj.contains("frus"))
894fa5e4d32SSunny Srivastava {
895fa5e4d32SSunny Srivastava logging::logMessage("Missing frus tag in system config JSON");
896fa5e4d32SSunny Srivastava }
897fa5e4d32SSunny Srivastava
898fa5e4d32SSunny Srivastava const nlohmann::json& l_listOfFrus =
899fa5e4d32SSunny Srivastava l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
900fa5e4d32SSunny Srivastava
901fa5e4d32SSunny Srivastava for (const auto& l_frus : l_listOfFrus.items())
902fa5e4d32SSunny Srivastava {
903fa5e4d32SSunny Srivastava for (const auto& l_aFru : l_frus.value())
904fa5e4d32SSunny Srivastava {
905fa5e4d32SSunny Srivastava if (l_aFru["extraInterfaces"].contains(
906fa5e4d32SSunny Srivastava constants::locationCodeInf) &&
907fa5e4d32SSunny Srivastava l_aFru["extraInterfaces"][constants::locationCodeInf].value(
908fa5e4d32SSunny Srivastava "LocationCode", "") == i_unexpandedLocationCode)
909fa5e4d32SSunny Srivastava {
910fa5e4d32SSunny Srivastava l_inventoryPaths.push_back(
911fa5e4d32SSunny Srivastava l_aFru.at("inventoryPath")
912fa5e4d32SSunny Srivastava .get_ref<const nlohmann::json::string_t&>());
913fa5e4d32SSunny Srivastava }
914fa5e4d32SSunny Srivastava }
915fa5e4d32SSunny Srivastava }
916fa5e4d32SSunny Srivastava
917fa5e4d32SSunny Srivastava if (l_inventoryPaths.empty())
918fa5e4d32SSunny Srivastava {
919fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
920fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
921fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
922fa5e4d32SSunny Srivastava i_unexpandedLocationCode.c_str()));
923fa5e4d32SSunny Srivastava }
924fa5e4d32SSunny Srivastava
925fa5e4d32SSunny Srivastava return l_inventoryPaths;
926fa5e4d32SSunny Srivastava }
927fa5e4d32SSunny Srivastava
92843fedabcSPatrick Williams std::string Manager::getHwPath(
92943fedabcSPatrick Williams const sdbusplus::message::object_path& i_dbusObjPath)
930fa5e4d32SSunny Srivastava {
931fa5e4d32SSunny Srivastava // Dummy code to supress unused variable warning. To be removed.
932fa5e4d32SSunny Srivastava logging::logMessage(std::string(i_dbusObjPath));
933fa5e4d32SSunny Srivastava
934fa5e4d32SSunny Srivastava return std::string{};
935fa5e4d32SSunny Srivastava }
936fa5e4d32SSunny Srivastava
937fa5e4d32SSunny Srivastava std::tuple<std::string, uint16_t> Manager::getUnexpandedLocationCode(
938fa5e4d32SSunny Srivastava const std::string& i_expandedLocationCode)
939fa5e4d32SSunny Srivastava {
940fa5e4d32SSunny Srivastava /**
941fa5e4d32SSunny Srivastava * Location code should always start with U and fulfil minimum length
942fa5e4d32SSunny Srivastava * criteria.
943fa5e4d32SSunny Srivastava */
944fa5e4d32SSunny Srivastava if (i_expandedLocationCode[0] != 'U' ||
945fa5e4d32SSunny Srivastava i_expandedLocationCode.length() <
946fa5e4d32SSunny Srivastava constants::EXP_LOCATION_CODE_MIN_LENGTH)
947fa5e4d32SSunny Srivastava {
948fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
949fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
950fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
951fa5e4d32SSunny Srivastava i_expandedLocationCode.c_str()));
952fa5e4d32SSunny Srivastava }
953fa5e4d32SSunny Srivastava
954fa5e4d32SSunny Srivastava std::string l_fcKwd;
955fa5e4d32SSunny Srivastava
956fa5e4d32SSunny Srivastava auto l_fcKwdValue = dbusUtility::readDbusProperty(
957fa5e4d32SSunny Srivastava "xyz.openbmc_project.Inventory.Manager",
958fa5e4d32SSunny Srivastava "/xyz/openbmc_project/inventory/system/chassis/motherboard",
959fa5e4d32SSunny Srivastava "com.ibm.ipzvpd.VCEN", "FC");
960fa5e4d32SSunny Srivastava
961fa5e4d32SSunny Srivastava if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_fcKwdValue))
962fa5e4d32SSunny Srivastava {
963fa5e4d32SSunny Srivastava l_fcKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
964fa5e4d32SSunny Srivastava }
965fa5e4d32SSunny Srivastava
966fa5e4d32SSunny Srivastava // Get the first part of expanded location code to check for FC or TM.
967fa5e4d32SSunny Srivastava std::string l_firstKwd = i_expandedLocationCode.substr(1, 4);
968fa5e4d32SSunny Srivastava
969fa5e4d32SSunny Srivastava std::string l_unexpandedLocationCode{};
970fa5e4d32SSunny Srivastava uint16_t l_nodeNummber = constants::INVALID_NODE_NUMBER;
971fa5e4d32SSunny Srivastava
972fa5e4d32SSunny Srivastava // Check if this value matches the value of FC keyword.
973fa5e4d32SSunny Srivastava if (l_fcKwd.substr(0, 4) == l_firstKwd)
974fa5e4d32SSunny Srivastava {
975fa5e4d32SSunny Srivastava /**
976fa5e4d32SSunny Srivastava * Period(.) should be there in expanded location code to seggregate
977fa5e4d32SSunny Srivastava * FC, node number and SE values.
978fa5e4d32SSunny Srivastava */
979fa5e4d32SSunny Srivastava size_t l_nodeStartPos = i_expandedLocationCode.find('.');
980fa5e4d32SSunny Srivastava if (l_nodeStartPos == std::string::npos)
981fa5e4d32SSunny Srivastava {
982fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
983fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
984fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
985fa5e4d32SSunny Srivastava i_expandedLocationCode.c_str()));
986fa5e4d32SSunny Srivastava }
987fa5e4d32SSunny Srivastava
988fa5e4d32SSunny Srivastava size_t l_nodeEndPos =
989fa5e4d32SSunny Srivastava i_expandedLocationCode.find('.', l_nodeStartPos + 1);
990fa5e4d32SSunny Srivastava if (l_nodeEndPos == std::string::npos)
991fa5e4d32SSunny Srivastava {
992fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
993fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
994fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
995fa5e4d32SSunny Srivastava i_expandedLocationCode.c_str()));
996fa5e4d32SSunny Srivastava }
997fa5e4d32SSunny Srivastava
998fa5e4d32SSunny Srivastava // Skip 3 bytes for '.ND'
999fa5e4d32SSunny Srivastava l_nodeNummber = std::stoi(i_expandedLocationCode.substr(
1000fa5e4d32SSunny Srivastava l_nodeStartPos + 3, (l_nodeEndPos - l_nodeStartPos - 3)));
1001fa5e4d32SSunny Srivastava
1002fa5e4d32SSunny Srivastava /**
1003fa5e4d32SSunny Srivastava * Confirm if there are other details apart FC, node number and SE
1004fa5e4d32SSunny Srivastava * in location code
1005fa5e4d32SSunny Srivastava */
1006fa5e4d32SSunny Srivastava if (i_expandedLocationCode.length() >
1007fa5e4d32SSunny Srivastava constants::EXP_LOCATION_CODE_MIN_LENGTH)
1008fa5e4d32SSunny Srivastava {
1009fa5e4d32SSunny Srivastava l_unexpandedLocationCode =
1010fa5e4d32SSunny Srivastava i_expandedLocationCode[0] + std::string("fcs") +
1011fa5e4d32SSunny Srivastava i_expandedLocationCode.substr(
1012fa5e4d32SSunny Srivastava l_nodeEndPos + 1 + constants::SE_KWD_LENGTH,
1013fa5e4d32SSunny Srivastava std::string::npos);
1014fa5e4d32SSunny Srivastava }
1015fa5e4d32SSunny Srivastava else
1016fa5e4d32SSunny Srivastava {
1017fa5e4d32SSunny Srivastava l_unexpandedLocationCode = "Ufcs";
1018fa5e4d32SSunny Srivastava }
1019fa5e4d32SSunny Srivastava }
1020fa5e4d32SSunny Srivastava else
1021fa5e4d32SSunny Srivastava {
1022fa5e4d32SSunny Srivastava std::string l_tmKwd;
1023fa5e4d32SSunny Srivastava // Read TM keyword value.
1024fa5e4d32SSunny Srivastava auto l_tmKwdValue = dbusUtility::readDbusProperty(
1025fa5e4d32SSunny Srivastava "xyz.openbmc_project.Inventory.Manager",
1026fa5e4d32SSunny Srivastava "/xyz/openbmc_project/inventory/system/chassis/motherboard",
1027fa5e4d32SSunny Srivastava "com.ibm.ipzvpd.VSYS", "TM");
1028fa5e4d32SSunny Srivastava
1029fa5e4d32SSunny Srivastava if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_tmKwdValue))
1030fa5e4d32SSunny Srivastava {
1031fa5e4d32SSunny Srivastava l_tmKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
1032fa5e4d32SSunny Srivastava }
1033fa5e4d32SSunny Srivastava
1034fa5e4d32SSunny Srivastava // Check if the substr matches to TM keyword value.
1035fa5e4d32SSunny Srivastava if (l_tmKwd.substr(0, 4) == l_firstKwd)
1036fa5e4d32SSunny Srivastava {
1037fa5e4d32SSunny Srivastava /**
1038fa5e4d32SSunny Srivastava * System location code will not have node number and any other
1039fa5e4d32SSunny Srivastava * details.
1040fa5e4d32SSunny Srivastava */
1041fa5e4d32SSunny Srivastava l_unexpandedLocationCode = "Umts";
1042fa5e4d32SSunny Srivastava }
1043fa5e4d32SSunny Srivastava // The given location code is neither "fcs" or "mts".
1044fa5e4d32SSunny Srivastava else
1045fa5e4d32SSunny Srivastava {
1046fa5e4d32SSunny Srivastava phosphor::logging::elog<types::DbusInvalidArgument>(
1047fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
1048fa5e4d32SSunny Srivastava types::InvalidArgument::ARGUMENT_VALUE(
1049fa5e4d32SSunny Srivastava i_expandedLocationCode.c_str()));
1050fa5e4d32SSunny Srivastava }
1051fa5e4d32SSunny Srivastava }
1052fa5e4d32SSunny Srivastava
1053fa5e4d32SSunny Srivastava return std::make_tuple(l_unexpandedLocationCode, l_nodeNummber);
1054fa5e4d32SSunny Srivastava }
1055fa5e4d32SSunny Srivastava
1056fa5e4d32SSunny Srivastava types::ListOfPaths Manager::getFrusByExpandedLocationCode(
1057fa5e4d32SSunny Srivastava const std::string& i_expandedLocationCode)
1058fa5e4d32SSunny Srivastava {
1059fa5e4d32SSunny Srivastava std::tuple<std::string, uint16_t> l_locationAndNodePair =
1060fa5e4d32SSunny Srivastava getUnexpandedLocationCode(i_expandedLocationCode);
1061fa5e4d32SSunny Srivastava
1062fa5e4d32SSunny Srivastava return getFrusByUnexpandedLocationCode(std::get<0>(l_locationAndNodePair),
1063fa5e4d32SSunny Srivastava std::get<1>(l_locationAndNodePair));
1064fa5e4d32SSunny Srivastava }
1065fa5e4d32SSunny Srivastava
1066fa5e4d32SSunny Srivastava void Manager::registerHostStateChangeCallback()
1067fa5e4d32SSunny Srivastava {
1068fa5e4d32SSunny Srivastava static std::shared_ptr<sdbusplus::bus::match_t> l_hostState =
1069fa5e4d32SSunny Srivastava std::make_shared<sdbusplus::bus::match_t>(
1070fa5e4d32SSunny Srivastava *m_asioConnection,
1071fa5e4d32SSunny Srivastava sdbusplus::bus::match::rules::propertiesChanged(
1072fa5e4d32SSunny Srivastava constants::hostObjectPath, constants::hostInterface),
1073fa5e4d32SSunny Srivastava [this](sdbusplus::message_t& i_msg) {
1074fa5e4d32SSunny Srivastava hostStateChangeCallBack(i_msg);
1075fa5e4d32SSunny Srivastava });
1076fa5e4d32SSunny Srivastava }
1077fa5e4d32SSunny Srivastava
1078fa5e4d32SSunny Srivastava void Manager::hostStateChangeCallBack(sdbusplus::message_t& i_msg)
1079fa5e4d32SSunny Srivastava {
1080fa5e4d32SSunny Srivastava try
1081fa5e4d32SSunny Srivastava {
1082fa5e4d32SSunny Srivastava if (i_msg.is_method_error())
1083fa5e4d32SSunny Srivastava {
1084fa5e4d32SSunny Srivastava throw std::runtime_error(
1085fa5e4d32SSunny Srivastava "Error reading callback message for host state");
1086fa5e4d32SSunny Srivastava }
1087fa5e4d32SSunny Srivastava
1088fa5e4d32SSunny Srivastava std::string l_objectPath;
1089fa5e4d32SSunny Srivastava types::PropertyMap l_propMap;
1090fa5e4d32SSunny Srivastava i_msg.read(l_objectPath, l_propMap);
1091fa5e4d32SSunny Srivastava
1092fa5e4d32SSunny Srivastava const auto l_itr = l_propMap.find("CurrentHostState");
1093fa5e4d32SSunny Srivastava
1094fa5e4d32SSunny Srivastava if (l_itr == l_propMap.end())
1095fa5e4d32SSunny Srivastava {
1096fa5e4d32SSunny Srivastava throw std::runtime_error(
1097fa5e4d32SSunny Srivastava "CurrentHostState field is missing in callback message");
1098fa5e4d32SSunny Srivastava }
1099fa5e4d32SSunny Srivastava
1100fa5e4d32SSunny Srivastava if (auto l_hostState = std::get_if<std::string>(&(l_itr->second)))
1101fa5e4d32SSunny Srivastava {
1102fa5e4d32SSunny Srivastava // implies system is moving from standby to power on state
1103fa5e4d32SSunny Srivastava if (*l_hostState == "xyz.openbmc_project.State.Host.HostState."
1104fa5e4d32SSunny Srivastava "TransitioningToRunning")
1105fa5e4d32SSunny Srivastava {
1106fa5e4d32SSunny Srivastava // TODO: check for all the essential FRUs in the system.
1107fa5e4d32SSunny Srivastava
1108fa5e4d32SSunny Srivastava // Perform recollection.
1109fa5e4d32SSunny Srivastava performVpdRecollection();
1110fa5e4d32SSunny Srivastava return;
1111fa5e4d32SSunny Srivastava }
1112fa5e4d32SSunny Srivastava }
1113fa5e4d32SSunny Srivastava else
1114fa5e4d32SSunny Srivastava {
1115fa5e4d32SSunny Srivastava throw std::runtime_error(
1116fa5e4d32SSunny Srivastava "Invalid type recieved in variant for host state.");
1117fa5e4d32SSunny Srivastava }
1118fa5e4d32SSunny Srivastava }
1119fa5e4d32SSunny Srivastava catch (const std::exception& l_ex)
1120fa5e4d32SSunny Srivastava {
1121fa5e4d32SSunny Srivastava // TODO: Log PEL.
1122fa5e4d32SSunny Srivastava logging::logMessage(l_ex.what());
1123fa5e4d32SSunny Srivastava }
1124fa5e4d32SSunny Srivastava }
1125fa5e4d32SSunny Srivastava
1126fa5e4d32SSunny Srivastava void Manager::performVpdRecollection()
1127fa5e4d32SSunny Srivastava {
1128fa5e4d32SSunny Srivastava try
1129fa5e4d32SSunny Srivastava {
1130fa5e4d32SSunny Srivastava if (m_worker.get() != nullptr)
1131fa5e4d32SSunny Srivastava {
1132fa5e4d32SSunny Srivastava nlohmann::json l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
1133fa5e4d32SSunny Srivastava
1134fa5e4d32SSunny Srivastava // Check if system config JSON is present
1135fa5e4d32SSunny Srivastava if (l_sysCfgJsonObj.empty())
1136fa5e4d32SSunny Srivastava {
1137fa5e4d32SSunny Srivastava throw std::runtime_error(
1138fa5e4d32SSunny Srivastava "System config json object is empty, can't process recollection.");
1139fa5e4d32SSunny Srivastava }
1140fa5e4d32SSunny Srivastava
1141fa5e4d32SSunny Srivastava const auto& l_frusReplaceableAtStandby =
1142fa5e4d32SSunny Srivastava jsonUtility::getListOfFrusReplaceableAtStandby(l_sysCfgJsonObj);
1143fa5e4d32SSunny Srivastava
1144fa5e4d32SSunny Srivastava for (const auto& l_fruInventoryPath : l_frusReplaceableAtStandby)
1145fa5e4d32SSunny Srivastava {
1146fa5e4d32SSunny Srivastava // ToDo: Add some logic/trace to know the flow to
1147fa5e4d32SSunny Srivastava // collectSingleFruVpd has been directed via
1148fa5e4d32SSunny Srivastava // performVpdRecollection.
1149fa5e4d32SSunny Srivastava collectSingleFruVpd(l_fruInventoryPath);
1150fa5e4d32SSunny Srivastava }
1151fa5e4d32SSunny Srivastava return;
1152fa5e4d32SSunny Srivastava }
1153fa5e4d32SSunny Srivastava
1154fa5e4d32SSunny Srivastava throw std::runtime_error(
1155fa5e4d32SSunny Srivastava "Worker object not found can't process recollection");
1156fa5e4d32SSunny Srivastava }
1157fa5e4d32SSunny Srivastava catch (const std::exception& l_ex)
1158fa5e4d32SSunny Srivastava {
1159fa5e4d32SSunny Srivastava // TODO Log PEL
1160fa5e4d32SSunny Srivastava logging::logMessage(
1161fa5e4d32SSunny Srivastava "VPD recollection failed with error: " + std::string(l_ex.what()));
1162fa5e4d32SSunny Srivastava }
1163fa5e4d32SSunny Srivastava }
1164fa5e4d32SSunny Srivastava } // namespace vpd
1165