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