1 /**
2  * Copyright © 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include <sdbusplus/bus.hpp>
19 #include <sdbusplus/exception.hpp>
20 
21 #include <cstdint>
22 #include <map>
23 #include <string>
24 #include <vector>
25 
26 namespace phosphor::power::regulators
27 {
28 
29 /**
30  * @class VPD
31  *
32  * Abstract base class that provides an interface to hardware VPD (Vital Product
33  * Data).
34  *
35  * The interface is used to obtain VPD keyword values.
36  */
37 class VPD
38 {
39   public:
40     // Specify which compiler-generated methods we want
41     VPD() = default;
42     VPD(const VPD&) = delete;
43     VPD(VPD&&) = delete;
44     VPD& operator=(const VPD&) = delete;
45     VPD& operator=(VPD&&) = delete;
46     virtual ~VPD() = default;
47 
48     /**
49      * Clears any cached hardware VPD values.
50      */
51     virtual void clearCache(void) = 0;
52 
53     /**
54      * Returns the value of the specified VPD keyword for the specified
55      * inventory path.
56      *
57      * May return a cached value if one is available to improve performance.
58      *
59      * Throws an exception if an error occurs while obtaining the VPD
60      * value.
61      *
62      * @param inventoryPath D-Bus inventory path of the hardware
63      * @param keyword VPD keyword
64      * @return VPD keyword value
65      */
66     virtual std::vector<uint8_t> getValue(const std::string& inventoryPath,
67                                           const std::string& keyword) = 0;
68 };
69 
70 /**
71  * @class DBusVPD
72  *
73  * Implementation of the VPD interface using D-Bus method calls.
74  */
75 class DBusVPD : public VPD
76 {
77   public:
78     // Specify which compiler-generated methods we want
79     DBusVPD() = delete;
80     DBusVPD(const DBusVPD&) = delete;
81     DBusVPD(DBusVPD&&) = delete;
82     DBusVPD& operator=(const DBusVPD&) = delete;
83     DBusVPD& operator=(DBusVPD&&) = delete;
84     virtual ~DBusVPD() = default;
85 
86     /**
87      * Constructor.
88      *
89      * @param bus D-Bus bus object
90      */
91     explicit DBusVPD(sdbusplus::bus_t& bus) : bus{bus} {}
92 
93     /** @copydoc VPD::clearCache() */
94     virtual void clearCache(void) override
95     {
96         cache.clear();
97     }
98 
99     /** @copydoc VPD::getValue() */
100     virtual std::vector<uint8_t> getValue(const std::string& inventoryPath,
101                                           const std::string& keyword) override;
102 
103   private:
104     /**
105      * Gets the value of the specified VPD keyword from a D-Bus interface and
106      * property.
107      *
108      * Throws an exception if an error occurs while obtaining the VPD
109      * value.
110      *
111      * @param inventoryPath D-Bus inventory path of the hardware
112      * @param keyword VPD keyword
113      * @param value the resulting keyword value
114      */
115     void getDBusProperty(const std::string& inventoryPath,
116                          const std::string& keyword,
117                          std::vector<uint8_t>& value);
118 
119     /**
120      * Returns whether the specified D-Bus exception indicates the VPD interface
121      * or property does not exist for the specified inventory path.
122      *
123      * This is treated as an "empty" keyword value rather than an error
124      * condition.
125      *
126      * @return true if exception indicates interface/property does not exist
127      */
128     bool isUnknownPropertyException(const sdbusplus::exception_t& e);
129 
130     /**
131      * Type alias for map from keyword names to values.
132      */
133     using KeywordMap = std::map<std::string, std::vector<uint8_t>>;
134 
135     /**
136      * D-Bus bus object.
137      */
138     sdbusplus::bus_t& bus;
139 
140     /**
141      * Cached VPD keyword values.
142      *
143      * Map from inventory paths to VPD keywords.
144      */
145     std::map<std::string, KeywordMap> cache{};
146 };
147 
148 } // namespace phosphor::power::regulators
149