1 #pragma once
2 
3 #include "dbus_types.hpp"
4 #include "dbus_watcher.hpp"
5 
6 #include <phosphor-logging/lg2.hpp>
7 #include <sdbusplus/bus.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 
10 #include <expected>
11 #include <filesystem>
12 #include <fstream>
13 #include <unordered_map>
14 
15 namespace openpower
16 {
17 namespace pels
18 {
19 
20 /**
21  * @class DataInterface
22  *
23  * A base class for gathering data about the system for use
24  * in PELs. Implemented this way to facilitate mocking.
25  */
26 class DataInterfaceBase
27 {
28   public:
29     DataInterfaceBase() = default;
30     virtual ~DataInterfaceBase() = default;
31     DataInterfaceBase(const DataInterfaceBase&) = default;
32     DataInterfaceBase& operator=(const DataInterfaceBase&) = default;
33     DataInterfaceBase(DataInterfaceBase&&) = default;
34     DataInterfaceBase& operator=(DataInterfaceBase&&) = default;
35 
36     /**
37      * @brief Returns the machine Type/Model
38      *
39      * @return string - The machine Type/Model string
40      */
41     virtual std::string getMachineTypeModel() const = 0;
42 
43     /**
44      * @brief Returns the machine serial number
45      *
46      * @return string - The machine serial number
47      */
48     virtual std::string getMachineSerialNumber() const = 0;
49 
50     /**
51      * @brief Says if the system is managed by a hardware
52      *        management console.
53      * @return bool - If the system is HMC managed
54      */
55     virtual bool isHMCManaged() const
56     {
57         return _hmcManaged;
58     }
59 
60     /**
61      * @brief Says if the host is up and running
62      *
63      * @return bool - If the host is running
64      */
65     virtual bool isHostUp() const
66     {
67         return _hostUp;
68     }
69 
70     using HostStateChangeFunc = std::function<void(bool)>;
71 
72     /**
73      * @brief Register a callback function that will get
74      *        called on all host on/off transitions.
75      *
76      * The void(bool) function will get passed the new
77      * value of the host state.
78      *
79      * @param[in] name - The subscription name
80      * @param[in] func - The function to run
81      */
82     void subscribeToHostStateChange(const std::string& name,
83                                     HostStateChangeFunc func)
84     {
85         _hostChangeCallbacks[name] = func;
86     }
87 
88     /**
89      * @brief Unsubscribe from host state changes.
90      *
91      * @param[in] name - The subscription name
92      */
93     void unsubscribeFromHostStateChange(const std::string& name)
94     {
95         _hostChangeCallbacks.erase(name);
96     }
97 
98     using FRUPresentFunc =
99         std::function<void(const std::string& /* locationCode */)>;
100 
101     /**
102      * @brief Register a callback function that will get
103      *        called when certain FRUs become present.
104      *
105      * The void(std::string) function will get passed the
106      * location code of the FRU.
107      *
108      * @param[in] name - The subscription name
109      * @param[in] func - The function to run
110      */
111     void subscribeToFruPresent(const std::string& name, FRUPresentFunc func)
112     {
113         _fruPresentCallbacks[name] = std::move(func);
114     }
115 
116     /**
117      * @brief Returns the BMC firmware version
118      *
119      * @return std::string - The BMC version
120      */
121     virtual std::string getBMCFWVersion() const
122     {
123         return _bmcFWVersion;
124     }
125 
126     /**
127      * @brief Returns the server firmware version
128      *
129      * @return std::string - The server firmware version
130      */
131     virtual std::string getServerFWVersion() const
132     {
133         return _serverFWVersion;
134     }
135 
136     /**
137      * @brief Returns the BMC FW version ID
138      *
139      * @return std::string - The BMC FW version ID
140      */
141     virtual std::string getBMCFWVersionID() const
142     {
143         return _bmcFWVersionID;
144     }
145 
146     /**
147      * @brief Returns the process name given its PID.
148      *
149      * @param[in] pid - The PID value as a string
150      *
151      * @return std::optional<std::string> - The name, or std::nullopt
152      */
153     std::optional<std::string> getProcessName(const std::string& pid) const
154     {
155         namespace fs = std::filesystem;
156 
157         fs::path path{"/proc"};
158         path /= fs::path{pid} / "exe";
159 
160         if (fs::exists(path))
161         {
162             return fs::read_symlink(path);
163         }
164 
165         return std::nullopt;
166     }
167 
168     /**
169      * @brief Returns the time the system was running.
170      *
171      * @return std::optional<uint64_t> - The System uptime or std::nullopt
172      */
173     std::optional<uint64_t> getUptimeInSeconds() const
174     {
175         std::ifstream versionFile{"/proc/uptime"};
176         std::string line{};
177 
178         std::getline(versionFile, line);
179         auto pos = line.find(" ");
180         if (pos == std::string::npos)
181         {
182             return std::nullopt;
183         }
184 
185         uint64_t seconds = atol(line.substr(0, pos).c_str());
186         if (seconds == 0)
187         {
188             return std::nullopt;
189         }
190 
191         return seconds;
192     }
193 
194     /**
195      * @brief Returns the time the system was running.
196      *
197      * @param[in] seconds - The number of seconds the system has been running
198      *
199      * @return std::string - days/hours/minutes/seconds
200      */
201     std::string getBMCUptime(uint64_t seconds) const
202     {
203         time_t t(seconds);
204         tm* p = gmtime(&t);
205 
206         std::string uptime =
207             std::to_string(p->tm_year - 70) + "y " +
208             std::to_string(p->tm_yday) + "d " + std::to_string(p->tm_hour) +
209             "h " + std::to_string(p->tm_min) + "m " +
210             std::to_string(p->tm_sec) + "s";
211 
212         return uptime;
213     }
214 
215     /**
216      * @brief Returns the system load average over the past 1 minute, 5 minutes
217      *        and 15 minutes.
218      *
219      * @return std::string - The system load average
220      */
221     std::string getBMCLoadAvg() const
222     {
223         std::string loadavg{};
224 
225         std::ifstream loadavgFile{"/proc/loadavg"};
226         std::string line;
227         std::getline(loadavgFile, line);
228 
229         size_t count = 3;
230         for (size_t i = 0; i < count; i++)
231         {
232             auto pos = line.find(" ");
233             if (pos == std::string::npos)
234             {
235                 return {};
236             }
237 
238             if (i != count - 1)
239             {
240                 loadavg.append(line.substr(0, pos + 1));
241             }
242             else
243             {
244                 loadavg.append(line.substr(0, pos));
245             }
246 
247             line = line.substr(pos + 1);
248         }
249 
250         return loadavg;
251     }
252 
253     /**
254      * @brief Returns the 'send event logs to host' setting.
255      *
256      * @return bool - If sending PELs to the host is enabled.
257      */
258     virtual bool getHostPELEnablement() const
259     {
260         return _sendPELsToHost;
261     }
262 
263     /**
264      * @brief Returns the BMC state
265      *
266      * @return std::string - The BMC state property value
267      */
268     virtual std::string getBMCState() const
269     {
270         return _bmcState;
271     }
272 
273     /**
274      * @brief Returns the Chassis state
275      *
276      * @return std::string - The chassis state property value
277      */
278     virtual std::string getChassisState() const
279     {
280         return _chassisState;
281     }
282 
283     /**
284      * @brief Returns the chassis requested power
285      *        transition value.
286      *
287      * @return std::string - The chassis transition property
288      */
289     virtual std::string getChassisTransition() const
290     {
291         return _chassisTransition;
292     }
293 
294     /**
295      * @brief Returns the Host state
296      *
297      * @return std::string - The Host state property value
298      */
299     virtual std::string getHostState() const
300     {
301         return _hostState;
302     }
303 
304     /**
305      * @brief Returns the Boot state
306      *
307      * @return std::string - The Boot state property value
308      */
309     virtual std::string getBootState() const
310     {
311         return _bootState;
312     }
313 
314     /**
315      * @brief Returns the motherboard CCIN
316      *
317      * @return std::string The motherboard CCIN
318      */
319     virtual std::string getMotherboardCCIN() const = 0;
320 
321     /**
322      * @brief Returns the system IM
323      *
324      * @return std::string The system IM
325      */
326     virtual std::vector<uint8_t> getSystemIMKeyword() const = 0;
327 
328     /**
329      * @brief Get the fields from the inventory necessary for doing
330      *        a callout on an inventory path.
331      *
332      * @param[in] inventoryPath - The item to get the data for
333      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
334      * @param[out] ccin - Filled in with the VINI/CC keyword
335      * @param[out] serialNumber - Filled in with the VINI/SN keyword
336      */
337     virtual void getHWCalloutFields(
338         const std::string& inventoryPath, std::string& fruPartNumber,
339         std::string& ccin, std::string& serialNumber) const = 0;
340 
341     /**
342      * @brief Get the location code for an inventory item.
343      *
344      * @param[in] inventoryPath - The item to get the data for
345      *
346      * @return std::string - The location code
347      */
348     virtual std::string
349         getLocationCode(const std::string& inventoryPath) const = 0;
350 
351     /**
352      * @brief Get the list of system type names the system is called.
353      *
354      * @return std::vector<std::string> - The list of names
355      */
356     virtual std::vector<std::string> getSystemNames() const = 0;
357 
358     /**
359      * @brief Fills in the placeholder 'Ufcs' in the passed in location
360      *        code with the machine feature code and serial number, which
361      *        is needed to create a valid location code.
362      *
363      * @param[in] locationCode - Location code value starting with Ufcs-, and
364      *                           if that isn't present it will be added first.
365      *
366      * @param[in] node - The node number the location is on.
367      *
368      * @return std::string - The expanded location code
369      */
370     virtual std::string expandLocationCode(const std::string& locationCode,
371                                            uint16_t node) const = 0;
372 
373     /**
374      * @brief Returns the inventory paths for the FRU that the location
375      *        code represents.
376      *
377      * @param[in] locationCode - If an expanded location code, then the
378      *                           full location code.
379      *                           If not expanded, a location code value
380      *                           starting with Ufcs-, and if that isn't
381      *                           present it will be added first.
382      *
383      * @param[in] node - The node number the location is on.  Ignored if the
384      *                   expanded location code is passed in.
385      *
386      * @param[in] expanded - If the location code already has the relevent
387      *                       VPD fields embedded in it.
388      *
389      * @return std::vector<std::string> - The inventory D-Bus objects
390      */
391     virtual std::vector<std::string>
392         getInventoryFromLocCode(const std::string& LocationCode, uint16_t node,
393                                 bool expanded) const = 0;
394 
395     /**
396      * @brief Sets the Asserted property on the LED group passed in.
397      *
398      * @param[in] ledGroup - The LED group D-Bus path
399      * @param[in] value - The value to set it to
400      */
401     virtual void assertLEDGroup(const std::string& ledGroup,
402                                 bool value) const = 0;
403 
404     /**
405      * @brief Sets the Functional property on the OperationalStatus
406      *        interface on a D-Bus object.
407      *
408      * @param[in] objectPath - The D-Bus object path
409      * @param[in] functional - The value
410      */
411     virtual void setFunctional(const std::string& objectPath,
412                                bool functional) const = 0;
413 
414     /**
415      * @brief Sets the critical association on the D-Bus object.
416      *
417      * @param[in] objectPath - The D-Bus object path
418      */
419     virtual void
420         setCriticalAssociation(const std::string& objectPath) const = 0;
421 
422     /**
423      * @brief Returns the manufacturing QuiesceOnError property
424      *
425      * @return bool - Manufacturing QuiesceOnError property
426      */
427     virtual bool getQuiesceOnError() const = 0;
428 
429     /**
430      * @brief Split location code into base and connector segments
431      *
432      * A location code that ends in '-Tx', where 'x' is a number,
433      * represents a connector, such as a USB cable connector.
434      *
435      * This function splits the passed in location code into a
436      * base and connector segment.  e.g.:
437      *   P0-T1 -> ['P0', '-T1']
438      *   P0 -> ['P0', '']
439      *
440      * @param[in] locationCode - location code to split
441      * @return pair<string, string> - The base and connector segments
442      */
443     static std::pair<std::string, std::string>
444         extractConnectorFromLocCode(const std::string& locationCode);
445 
446     /**
447      * @brief Returns the dump status
448      *
449      * @return bool dump status
450      */
451     virtual std::vector<bool>
452         checkDumpStatus(const std::vector<std::string>& type) const = 0;
453 
454     /**
455      * @brief Create guard record
456      *
457      *  @param[in] binPath: phal devtree binary path used as key
458      *  @param[in] type: Guard type
459      *  @param[in] logPath: error log entry object path
460      */
461     virtual void createGuardRecord(const std::vector<uint8_t>& binPath,
462                                    const std::string& type,
463                                    const std::string& logPath) const = 0;
464 
465     /**
466      * @brief Create Progress SRC property on the boot progress
467      *        interface on a D-Bus object.
468      *
469      * @param[in] priSRC - Primary SRC value (e.g. BD8D1001)
470      * @param[in] srcStruct - Full SRC base structure
471      */
472     virtual void
473         createProgressSRC(const uint64_t& priSRC,
474                           const std::vector<uint8_t>& srcStruct) const = 0;
475 
476     /**
477      * @brief Get the list of unresolved OpenBMC event log ids that have an
478      * associated hardware isolation entry.
479      *
480      * @return std::vector<uint32_t> - The list of log ids
481      */
482     virtual std::vector<uint32_t> getLogIDWithHwIsolation() const = 0;
483 
484     /**
485      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
486      *        D-Bus interface.
487      *
488      * @return std::vector<uint8_t> - The progress SRC bytes
489      */
490     virtual std::vector<uint8_t> getRawProgressSRC() const = 0;
491 
492     /**
493      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
494      * the given location code.
495      *
496      * @param[in] locationCode - The location code of the FRU
497      *
498      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
499      * std::nullopt
500      */
501     virtual std::optional<std::vector<uint8_t>>
502         getDIProperty(const std::string& locationCode) const = 0;
503 
504     /**
505      * @brief Wrpper API to call pHAL API 'getFRUType()' and check whether the
506      * given location code is DIMM or not
507      *
508      * @param[in] locCode - The location code of the FRU
509      *
510      * @return std::expected<bool, std::string>
511      *       - Returns bool value if FRU type is able to determine successfully.
512      *              - true , if the given locCode is DIMM
513      *              - false, if the given locCode is not a DIMM
514      *       - Returns an error message in string format if an error occurs.
515      */
516     std::expected<bool, std::string> isDIMM(const std::string& locCode);
517 
518     /**
519      * @brief Check whether the given location code present in the cache
520      * memory
521      *
522      * @param[in] locCode - The location code of the FRU
523      *
524      * @return true, if the given location code present in cache and is a DIMM
525      *         false, if the given location code present in cache, but a non
526      *         DIMM FRU
527      *         std::nullopt, if the given location code is not present in the
528      *         cache.
529      */
530     std::optional<bool> isDIMMLocCode(const std::string& locCode) const;
531 
532     /**
533      * @brief add the given location code to the cache memory
534      *
535      * @param[in] locCode - The location code of the FRU
536      * @param[in] isFRUDIMM - true indicates the FRU is a DIMM
537      *                        false indicates the FRU is a non DIMM
538      *
539      */
540     void addDIMMLocCode(const std::string& locCode, bool isFRUDIMM);
541 
542   protected:
543     /**
544      * @brief Sets the host on/off state and runs any
545      *        callback functions (if there was a change).
546      */
547     void setHostUp(bool hostUp)
548     {
549         if (_hostUp != hostUp)
550         {
551             _hostUp = hostUp;
552 
553             for (auto& [name, func] : _hostChangeCallbacks)
554             {
555                 try
556                 {
557                     func(_hostUp);
558                 }
559                 catch (const std::exception& e)
560                 {
561                     lg2::error(
562                         "A host state change callback threw an exception");
563                 }
564             }
565         }
566     }
567 
568     /**
569      * @brief Runs the callback functions registered when
570      *        FRUs become present.
571      */
572     void setFruPresent(const std::string& locationCode)
573     {
574         for (const auto& [_, func] : _fruPresentCallbacks)
575         {
576             try
577             {
578                 func(locationCode);
579             }
580             catch (const std::exception& e)
581             {
582                 lg2::error("A FRU present callback threw an exception");
583             }
584         }
585     }
586 
587     /**
588      * @brief The hardware management console status.  Always kept
589      *        up to date.
590      */
591     bool _hmcManaged = false;
592 
593     /**
594      * @brief The host up status.  Always kept up to date.
595      */
596     bool _hostUp = false;
597 
598     /**
599      * @brief The map of host state change subscriber
600      *        names to callback functions.
601      */
602     std::map<std::string, HostStateChangeFunc> _hostChangeCallbacks;
603 
604     /**
605      * @brief The map of FRU present subscriber
606      *        names to callback functions.
607      */
608     std::map<std::string, FRUPresentFunc> _fruPresentCallbacks;
609 
610     /**
611      * @brief The BMC firmware version string
612      */
613     std::string _bmcFWVersion;
614 
615     /**
616      * @brief The server firmware version string
617      */
618     std::string _serverFWVersion;
619 
620     /**
621      * @brief The BMC firmware version ID string
622      */
623     std::string _bmcFWVersionID;
624 
625     /**
626      * @brief If sending PELs is enabled.
627      *
628      * This is usually set to false in manufacturing test.
629      */
630     bool _sendPELsToHost = true;
631 
632     /**
633      * @brief The BMC state property
634      */
635     std::string _bmcState;
636 
637     /**
638      * @brief The Chassis current power state property
639      */
640     std::string _chassisState;
641 
642     /**
643      * @brief The Chassis requested power transition property
644      */
645     std::string _chassisTransition;
646 
647     /**
648      * @brief The host state property
649      */
650     std::string _hostState;
651 
652     /**
653      * @brief The boot state property
654      */
655     std::string _bootState;
656 
657     /**
658      * @brief A cache storage for location code and its FRU Type
659      *  - The key 'std::string' represents the locationCode of the FRU
660      *  - The bool value - true indicates the FRU is a DIMM
661      *                     false indicates the FRU is a non DIMM.
662      */
663     std::unordered_map<std::string, bool> _locationCache;
664 };
665 
666 /**
667  * @class DataInterface
668  *
669  * Concrete implementation of DataInterfaceBase.
670  */
671 class DataInterface : public DataInterfaceBase
672 {
673   public:
674     DataInterface() = delete;
675     ~DataInterface() = default;
676     DataInterface(const DataInterface&) = default;
677     DataInterface& operator=(const DataInterface&) = default;
678     DataInterface(DataInterface&&) = default;
679     DataInterface& operator=(DataInterface&&) = default;
680 
681     /**
682      * @brief Constructor
683      *
684      * @param[in] bus - The sdbusplus bus object
685      */
686     explicit DataInterface(sdbusplus::bus_t& bus);
687 
688     /**
689      * @brief Finds the D-Bus service name that hosts the
690      *        passed in path and interface.
691      *
692      * @param[in] objectPath - The D-Bus object path
693      * @param[in] interface - The D-Bus interface
694      */
695     DBusService getService(const std::string& objectPath,
696                            const std::string& interface) const;
697 
698     /**
699      * @brief Wrapper for the 'GetAll' properties method call
700      *
701      * @param[in] service - The D-Bus service to call it on
702      * @param[in] objectPath - The D-Bus object path
703      * @param[in] interface - The interface to get the props on
704      *
705      * @return DBusPropertyMap - The property results
706      */
707     DBusPropertyMap getAllProperties(const std::string& service,
708                                      const std::string& objectPath,
709                                      const std::string& interface) const;
710     /**
711      * @brief Wrapper for the 'Get' properties method call
712      *
713      * @param[in] service - The D-Bus service to call it on
714      * @param[in] objectPath - The D-Bus object path
715      * @param[in] interface - The interface to get the property on
716      * @param[in] property - The property name
717      * @param[out] value - Filled in with the property value.
718      */
719     void getProperty(const std::string& service, const std::string& objectPath,
720                      const std::string& interface, const std::string& property,
721                      DBusValue& value) const;
722     /**
723      * @brief Returns the machine Type/Model
724      *
725      * @return string - The machine Type/Model string
726      */
727     std::string getMachineTypeModel() const override;
728 
729     /**
730      * @brief Returns the machine serial number
731      *
732      * @return string - The machine serial number
733      */
734     std::string getMachineSerialNumber() const override;
735 
736     /**
737      * @brief Returns the motherboard CCIN
738      *
739      * @return std::string The motherboard CCIN
740      */
741     std::string getMotherboardCCIN() const override;
742 
743     /**
744      * @brief Returns the system IM
745      *
746      * @return std::vector The system IM keyword in 4 byte vector
747      */
748     std::vector<uint8_t> getSystemIMKeyword() const override;
749 
750     /**
751      * @brief Get the fields from the inventory necessary for doing
752      *        a callout on an inventory path.
753      *
754      * @param[in] inventoryPath - The item to get the data for
755      * @param[out] fruPartNumber - Filled in with the VINI/FN keyword
756      * @param[out] ccin - Filled in with the VINI/CC keyword
757      * @param[out] serialNumber - Filled in with the VINI/SN keyword
758      */
759     void getHWCalloutFields(const std::string& inventoryPath,
760                             std::string& fruPartNumber, std::string& ccin,
761                             std::string& serialNumber) const override;
762 
763     /**
764      * @brief Get the location code for an inventory item.
765      *
766      * Throws an exception if the inventory item doesn't have the
767      * location code interface.
768      *
769      * @param[in] inventoryPath - The item to get the data for
770      *
771      * @return std::string - The location code
772      */
773     std::string
774         getLocationCode(const std::string& inventoryPath) const override;
775 
776     /**
777      * @brief Get the list of system type names the system is called.
778      *
779      * @return std::vector<std::string> - The list of names
780      */
781     std::vector<std::string> getSystemNames() const override;
782 
783     /**
784      * @brief Fills in the placeholder 'Ufcs' in the passed in location
785      *        code with the machine feature code and serial number, which
786      *        is needed to create a valid location code.
787      *
788      * @param[in] locationCode - Location code value starting with Ufcs-, and
789      *                           if that isn't present it will be added first.
790      *
791      * @param[in] node - The node number the location is one.
792      *
793      * @return std::string - The expanded location code
794      */
795     std::string expandLocationCode(const std::string& locationCode,
796                                    uint16_t node) const override;
797 
798     /**
799      * @brief Returns the inventory paths for the FRU that the location
800      *        code represents.
801      *
802      * @param[in] locationCode - If an expanded location code, then the
803      *                           full location code.
804      *                           If not expanded, a location code value
805      *                           starting with Ufcs-, and if that isn't
806      *                           present it will be added first.
807      *
808      * @param[in] node - The node number the location is on.  Ignored if the
809      *                   expanded location code is passed in.
810      *
811      * @param[in] expanded - If the location code already has the relevent
812      *                       VPD fields embedded in it.
813      *
814      * @return std::vector<std::string> - The inventory D-Bus objects
815      */
816     std::vector<std::string>
817         getInventoryFromLocCode(const std::string& locationCode, uint16_t node,
818                                 bool expanded) const override;
819 
820     /**
821      * @brief Sets the Asserted property on the LED group passed in.
822      *
823      * @param[in] ledGroup - The LED group D-Bus path
824      * @param[in] value - The value to set it to
825      */
826     void assertLEDGroup(const std::string& ledGroup, bool value) const override;
827 
828     /**
829      * @brief Sets the Functional property on the OperationalStatus
830      *        interface on a D-Bus object.
831      *
832      * @param[in] objectPath - The D-Bus object path
833      * @param[in] functional - The value
834      */
835     void setFunctional(const std::string& objectPath,
836                        bool functional) const override;
837 
838     /**
839      * @brief Sets the critical association on the D-Bus object.
840      *
841      * @param[in] objectPath - The D-Bus object path
842      */
843     void setCriticalAssociation(const std::string& objectPath) const override;
844 
845     /**
846      * @brief Returns the manufacturing QuiesceOnError property
847      *
848      * @return bool - Manufacturing QuiesceOnError property
849      */
850     bool getQuiesceOnError() const override;
851 
852     /**
853      * @brief Returns the dump status
854      *
855      * @param[in] type - The dump type to check for
856      *
857      * @return bool dump status
858      */
859     std::vector<bool>
860         checkDumpStatus(const std::vector<std::string>& type) const override;
861 
862     /**
863      * @brief Create guard record
864      *
865      *  @param[in] binPath: phal devtree binary path used as key
866      *  @param[in] type: Guard type
867      *  @param[in] logPath: error log entry object path
868      */
869     void createGuardRecord(const std::vector<uint8_t>& binPath,
870                            const std::string& type,
871                            const std::string& logPath) const override;
872 
873     /**
874      * @brief Create Progress SRC property on the boot progress
875      *        interface on a D-Bus object.
876      *
877      * @param[in] priSRC - Primary SRC value
878      * @param[in] srcStruct - Full SRC base structure
879      */
880     void
881         createProgressSRC(const uint64_t& priSRC,
882                           const std::vector<uint8_t>& srcStruct) const override;
883 
884     /**
885      * @brief Get the list of unresolved OpenBMC event log ids that have an
886      * associated hardware isolation entry.
887      *
888      * @return std::vector<uint32_t> - The list of log ids
889      */
890     std::vector<uint32_t> getLogIDWithHwIsolation() const override;
891 
892     /**
893      * @brief Returns the latest raw progress SRC from the State.Boot.Raw
894      *        D-Bus interface.
895      *
896      * @return std::vector<uint8_t>: The progress SRC bytes
897      */
898     std::vector<uint8_t> getRawProgressSRC() const override;
899 
900     /**
901      * @brief Returns the FRUs DI property value hosted on the VINI iterface for
902      * the given location code.
903      *
904      * @param[in] locationCode - The location code of the FRU
905      *
906      * @return std::optional<std::vector<uint8_t>> -  The FRUs DI or
907      * std::nullopt
908      */
909     std::optional<std::vector<uint8_t>>
910         getDIProperty(const std::string& locationCode) const override;
911 
912   private:
913     /**
914      * @brief Reads the BMC firmware version string and puts it into
915      *        _bmcFWVersion.
916      */
917     void readBMCFWVersion();
918 
919     /**
920      * @brief Reads the server firmware version string and puts it into
921      *        _serverFWVersion.
922      */
923     void readServerFWVersion();
924 
925     /**
926      * @brief Reads the BMC firmware version ID and puts it into
927      *        _bmcFWVersionID.
928      */
929     void readBMCFWVersionID();
930 
931     /**
932      * @brief Finds all D-Bus paths that contain any of the interfaces
933      *        passed in, by using GetSubTreePaths.
934      *
935      * @param[in] interfaces - The desired interfaces
936      *
937      * @return The D-Bus paths.
938      */
939     DBusPathList getPaths(const DBusInterfaceList& interfaces) const;
940 
941     /**
942      * @brief The interfacesAdded callback used on the inventory to
943      *        find the D-Bus object that has the motherboard interface.
944      *        When the motherboard is found, it then adds a PropertyWatcher
945      *        for the motherboard CCIN.
946      */
947     void motherboardIfaceAdded(sdbusplus::message_t& msg);
948 
949     /**
950      * @brief Start watching for the hotpluggable FRUs to become
951      *        present.
952      */
953     void startFruPlugWatch();
954 
955     /**
956      * @brief Create a D-Bus match object for the Present property
957      *        to change on the path passed in.
958      * @param[in] path - The path to watch.
959      */
960     void addHotplugWatch(const std::string& path);
961 
962     /**
963      * @brief Callback when an inventory interface was added.
964      *
965      * Only does something if it's one of the hotpluggable FRUs,
966      * in which case it will treat it as a hotplug if the
967      * Present property is true.
968      *
969      * @param[in] msg - The InterfacesAdded signal contents.
970      */
971     void inventoryIfaceAdded(sdbusplus::message_t& msg);
972 
973     /**
974      * @brief Callback when the Present property changes.
975      *
976      * If present, will run the registered callbacks.
977      *
978      * @param[in] msg - The PropertiesChanged signal contents.
979      */
980     void presenceChanged(sdbusplus::message_t& msg);
981 
982     /**
983      * @brief If the Present property is in the properties map
984      *        passed in and it is true, notify the subscribers.
985      *
986      * @param[in] path - The object path of the inventory item.
987      * @param[in] properties - The properties map
988      */
989     void notifyPresenceSubsribers(const std::string& path,
990                                   const DBusPropertyMap& properties);
991 
992     /**
993      * @brief Adds the Ufcs- prefix to the location code passed in
994      *        if necessary.
995      *
996      * Needed because the location codes that come back from the
997      * message registry and device callout JSON don't have it.
998      *
999      * @param[in] - The location code without a prefix, like P1-C1
1000      *
1001      * @return std::string - The location code with the prefix
1002      */
1003     static std::string addLocationCodePrefix(const std::string& locationCode);
1004 
1005 #ifdef PEL_ENABLE_PHAL
1006     /**
1007      * @brief A helper API to check whether the PHAL device tree is exists,
1008      *        ensuring the PHAL init API can be invoked.
1009      *
1010      * @return true if the PHAL device tree is exists, otherwise false
1011      */
1012     bool isPHALDevTreeExist() const;
1013 
1014     /**
1015      * @brief A helper API to init PHAL libraries
1016      *
1017      * @return None
1018      */
1019     void initPHAL();
1020 
1021     /**
1022      * @brief A helper API to subscribe to systemd signals
1023      *
1024      * @return None
1025      */
1026     void subscribeToSystemdSignals();
1027 
1028     /**
1029      * @brief A helper API to unsubscribe to systemd signals
1030      *
1031      * @return None
1032      */
1033     void unsubscribeFromSystemdSignals();
1034 #endif // PEL_ENABLE_PHAL
1035 
1036     /**
1037      * @brief The D-Bus property or interface watchers that have callbacks
1038      *        registered that will set members in this class when
1039      *        they change.
1040      */
1041     std::vector<std::unique_ptr<DBusWatcher>> _properties;
1042 
1043     std::unique_ptr<sdbusplus::bus::match_t> _invIaMatch;
1044 
1045     /**
1046      * @brief The matches for watching for hotplugs.
1047      *
1048      * A map so we can check that we never get duplicates.
1049      */
1050     std::map<std::string, std::unique_ptr<sdbusplus::bus::match_t>>
1051         _invPresentMatches;
1052 
1053     /**
1054      * @brief The sdbusplus bus object for making D-Bus calls.
1055      */
1056     sdbusplus::bus_t& _bus;
1057 
1058 #ifdef PEL_ENABLE_PHAL
1059     /**
1060      * @brief Watcher to check "openpower-update-bios-attr-table" service
1061      *        is "done" to init PHAL libraires
1062      */
1063     std::unique_ptr<sdbusplus::bus::match_t> _systemdMatch;
1064 #endif // PEL_ENABLE_PHAL
1065 
1066     /**
1067      * @brief A slot object for async dbus call
1068      */
1069     sdbusplus::slot_t _systemdSlot;
1070 };
1071 
1072 } // namespace pels
1073 } // namespace openpower
1074