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 
94     /** @copydoc VPD::clearCache() */
95     virtual void clearCache(void) override
96     {
97         cache.clear();
98     }
99 
100     /** @copydoc VPD::getValue() */
101     virtual std::vector<uint8_t> getValue(const std::string& inventoryPath,
102                                           const std::string& keyword) override;
103 
104   private:
105     /**
106      * Gets the value of the specified VPD keyword from a D-Bus interface and
107      * property.
108      *
109      * Throws an exception if an error occurs while obtaining the VPD
110      * value.
111      *
112      * @param inventoryPath D-Bus inventory path of the hardware
113      * @param keyword VPD keyword
114      * @param value the resulting keyword value
115      */
116     void getDBusProperty(const std::string& inventoryPath,
117                          const std::string& keyword,
118                          std::vector<uint8_t>& value);
119 
120     /**
121      * Returns whether the specified D-Bus exception indicates the VPD interface
122      * or property does not exist for the specified inventory path.
123      *
124      * This is treated as an "empty" keyword value rather than an error
125      * condition.
126      *
127      * @return true if exception indicates interface/property does not exist
128      */
129     bool isUnknownPropertyException(const sdbusplus::exception_t& e);
130 
131     /**
132      * Type alias for map from keyword names to values.
133      */
134     using KeywordMap = std::map<std::string, std::vector<uint8_t>>;
135 
136     /**
137      * D-Bus bus object.
138      */
139     sdbusplus::bus_t& bus;
140 
141     /**
142      * Cached VPD keyword values.
143      *
144      * Map from inventory paths to VPD keywords.
145      */
146     std::map<std::string, KeywordMap> cache{};
147 };
148 
149 } // namespace phosphor::power::regulators
150