xref: /openbmc/intel-ipmi-oem/include/sdrutils.hpp (revision 3f7c5e403c938154f83a52e14c3fdb21a5591dc9)
1*3f7c5e40SJason M. Bills /*
2*3f7c5e40SJason M. Bills // Copyright (c) 2018 Intel Corporation
3*3f7c5e40SJason M. Bills //
4*3f7c5e40SJason M. Bills // Licensed under the Apache License, Version 2.0 (the "License");
5*3f7c5e40SJason M. Bills // you may not use this file except in compliance with the License.
6*3f7c5e40SJason M. Bills // You may obtain a copy of the License at
7*3f7c5e40SJason M. Bills //
8*3f7c5e40SJason M. Bills //      http://www.apache.org/licenses/LICENSE-2.0
9*3f7c5e40SJason M. Bills //
10*3f7c5e40SJason M. Bills // Unless required by applicable law or agreed to in writing, software
11*3f7c5e40SJason M. Bills // distributed under the License is distributed on an "AS IS" BASIS,
12*3f7c5e40SJason M. Bills // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*3f7c5e40SJason M. Bills // See the License for the specific language governing permissions and
14*3f7c5e40SJason M. Bills // limitations under the License.
15*3f7c5e40SJason M. Bills */
16*3f7c5e40SJason M. Bills 
17*3f7c5e40SJason M. Bills #include <boost/algorithm/string.hpp>
18*3f7c5e40SJason M. Bills #include <boost/container/flat_map.hpp>
19*3f7c5e40SJason M. Bills #include <cstring>
20*3f7c5e40SJason M. Bills #include <phosphor-logging/log.hpp>
21*3f7c5e40SJason M. Bills #include <storagecommands.hpp>
22*3f7c5e40SJason M. Bills 
23*3f7c5e40SJason M. Bills #pragma once
24*3f7c5e40SJason M. Bills 
25*3f7c5e40SJason M. Bills struct CmpStrVersion
26*3f7c5e40SJason M. Bills {
27*3f7c5e40SJason M. Bills     bool operator()(std::string a, std::string b) const
28*3f7c5e40SJason M. Bills     {
29*3f7c5e40SJason M. Bills         return strverscmp(a.c_str(), b.c_str()) < 0;
30*3f7c5e40SJason M. Bills     }
31*3f7c5e40SJason M. Bills };
32*3f7c5e40SJason M. Bills 
33*3f7c5e40SJason M. Bills using SensorSubTree = boost::container::flat_map<
34*3f7c5e40SJason M. Bills     std::string,
35*3f7c5e40SJason M. Bills     boost::container::flat_map<std::string, std::vector<std::string>>,
36*3f7c5e40SJason M. Bills     CmpStrVersion>;
37*3f7c5e40SJason M. Bills 
38*3f7c5e40SJason M. Bills inline static bool getSensorSubtree(SensorSubTree& subtree)
39*3f7c5e40SJason M. Bills {
40*3f7c5e40SJason M. Bills     sd_bus* bus = NULL;
41*3f7c5e40SJason M. Bills     int ret = sd_bus_default_system(&bus);
42*3f7c5e40SJason M. Bills     if (ret < 0)
43*3f7c5e40SJason M. Bills     {
44*3f7c5e40SJason M. Bills         phosphor::logging::log<phosphor::logging::level::ERR>(
45*3f7c5e40SJason M. Bills             "Failed to connect to system bus",
46*3f7c5e40SJason M. Bills             phosphor::logging::entry("ERRNO=0x%X", -ret));
47*3f7c5e40SJason M. Bills         sd_bus_unref(bus);
48*3f7c5e40SJason M. Bills         return false;
49*3f7c5e40SJason M. Bills     }
50*3f7c5e40SJason M. Bills     sdbusplus::bus::bus dbus(bus);
51*3f7c5e40SJason M. Bills     auto mapperCall =
52*3f7c5e40SJason M. Bills         dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
53*3f7c5e40SJason M. Bills                              "/xyz/openbmc_project/object_mapper",
54*3f7c5e40SJason M. Bills                              "xyz.openbmc_project.ObjectMapper", "GetSubTree");
55*3f7c5e40SJason M. Bills     static const auto depth = 2;
56*3f7c5e40SJason M. Bills     static constexpr std::array<const char*, 3> interfaces = {
57*3f7c5e40SJason M. Bills         "xyz.openbmc_project.Sensor.Value",
58*3f7c5e40SJason M. Bills         "xyz.openbmc_project.Sensor.Threshold.Warning",
59*3f7c5e40SJason M. Bills         "xyz.openbmc_project.Sensor.Threshold.Critical"};
60*3f7c5e40SJason M. Bills     mapperCall.append("/xyz/openbmc_project/sensors", depth, interfaces);
61*3f7c5e40SJason M. Bills 
62*3f7c5e40SJason M. Bills     try
63*3f7c5e40SJason M. Bills     {
64*3f7c5e40SJason M. Bills         auto mapperReply = dbus.call(mapperCall);
65*3f7c5e40SJason M. Bills         subtree.clear();
66*3f7c5e40SJason M. Bills         mapperReply.read(subtree);
67*3f7c5e40SJason M. Bills     }
68*3f7c5e40SJason M. Bills     catch (sdbusplus::exception_t&)
69*3f7c5e40SJason M. Bills     {
70*3f7c5e40SJason M. Bills         phosphor::logging::log<phosphor::logging::level::ERR>(
71*3f7c5e40SJason M. Bills             "getSensorSubtree: Error calling mapper");
72*3f7c5e40SJason M. Bills         return false;
73*3f7c5e40SJason M. Bills     }
74*3f7c5e40SJason M. Bills     return true;
75*3f7c5e40SJason M. Bills }
76*3f7c5e40SJason M. Bills 
77*3f7c5e40SJason M. Bills struct CmpStr
78*3f7c5e40SJason M. Bills {
79*3f7c5e40SJason M. Bills     bool operator()(const char* a, const char* b) const
80*3f7c5e40SJason M. Bills     {
81*3f7c5e40SJason M. Bills         return std::strcmp(a, b) < 0;
82*3f7c5e40SJason M. Bills     }
83*3f7c5e40SJason M. Bills };
84*3f7c5e40SJason M. Bills 
85*3f7c5e40SJason M. Bills const static boost::container::flat_map<const char*, SensorTypeCodes, CmpStr>
86*3f7c5e40SJason M. Bills     sensorTypes{{{"temperature", SensorTypeCodes::temperature},
87*3f7c5e40SJason M. Bills                  {"voltage", SensorTypeCodes::voltage},
88*3f7c5e40SJason M. Bills                  {"current", SensorTypeCodes::current},
89*3f7c5e40SJason M. Bills                  {"fan_tach", SensorTypeCodes::fan},
90*3f7c5e40SJason M. Bills                  {"power", SensorTypeCodes::other}}};
91*3f7c5e40SJason M. Bills 
92*3f7c5e40SJason M. Bills inline static std::string getSensorTypeStringFromPath(const std::string& path)
93*3f7c5e40SJason M. Bills {
94*3f7c5e40SJason M. Bills     // get sensor type string from path, path is defined as
95*3f7c5e40SJason M. Bills     // /xyz/openbmc_project/sensors/<type>/label
96*3f7c5e40SJason M. Bills     size_t typeEnd = path.rfind("/");
97*3f7c5e40SJason M. Bills     size_t typeStart = path.rfind("/", typeEnd - 1);
98*3f7c5e40SJason M. Bills     if (typeEnd != std::string::npos && typeStart != std::string::npos)
99*3f7c5e40SJason M. Bills     {
100*3f7c5e40SJason M. Bills         return path.substr(typeStart + 1, typeEnd - typeStart);
101*3f7c5e40SJason M. Bills     }
102*3f7c5e40SJason M. Bills     return path;
103*3f7c5e40SJason M. Bills }
104*3f7c5e40SJason M. Bills 
105*3f7c5e40SJason M. Bills inline static uint8_t getSensorTypeFromPath(const std::string& path)
106*3f7c5e40SJason M. Bills {
107*3f7c5e40SJason M. Bills     uint8_t sensorType = 0;
108*3f7c5e40SJason M. Bills     std::string type = getSensorTypeStringFromPath(path);
109*3f7c5e40SJason M. Bills     auto findSensor = sensorTypes.find(type.c_str());
110*3f7c5e40SJason M. Bills     if (findSensor != sensorTypes.end())
111*3f7c5e40SJason M. Bills     {
112*3f7c5e40SJason M. Bills         sensorType = static_cast<uint8_t>(findSensor->second);
113*3f7c5e40SJason M. Bills     } // else default 0x0 RESERVED
114*3f7c5e40SJason M. Bills 
115*3f7c5e40SJason M. Bills     return sensorType;
116*3f7c5e40SJason M. Bills }
117*3f7c5e40SJason M. Bills 
118*3f7c5e40SJason M. Bills inline static uint8_t getSensorNumberFromPath(const std::string& path)
119*3f7c5e40SJason M. Bills {
120*3f7c5e40SJason M. Bills     SensorSubTree sensorTree;
121*3f7c5e40SJason M. Bills     if (!getSensorSubtree(sensorTree))
122*3f7c5e40SJason M. Bills         return 0xFF;
123*3f7c5e40SJason M. Bills     uint8_t sensorNum = 0xFF;
124*3f7c5e40SJason M. Bills 
125*3f7c5e40SJason M. Bills     for (const auto& sensor : sensorTree)
126*3f7c5e40SJason M. Bills     {
127*3f7c5e40SJason M. Bills         sensorNum++;
128*3f7c5e40SJason M. Bills         if (sensor.first == path)
129*3f7c5e40SJason M. Bills         {
130*3f7c5e40SJason M. Bills             break;
131*3f7c5e40SJason M. Bills         }
132*3f7c5e40SJason M. Bills     }
133*3f7c5e40SJason M. Bills     return sensorNum;
134*3f7c5e40SJason M. Bills }
135*3f7c5e40SJason M. Bills 
136*3f7c5e40SJason M. Bills inline static uint8_t getSensorEventTypeFromPath(const std::string& path)
137*3f7c5e40SJason M. Bills {
138*3f7c5e40SJason M. Bills     // TODO: Add support for additional reading types as needed
139*3f7c5e40SJason M. Bills     return 0x1; // reading type = threshold
140*3f7c5e40SJason M. Bills }
141*3f7c5e40SJason M. Bills 
142*3f7c5e40SJason M. Bills inline static std::string getPathFromSensorNumber(uint8_t sensorNum)
143*3f7c5e40SJason M. Bills {
144*3f7c5e40SJason M. Bills     SensorSubTree sensorTree;
145*3f7c5e40SJason M. Bills     std::string path;
146*3f7c5e40SJason M. Bills     if (!getSensorSubtree(sensorTree))
147*3f7c5e40SJason M. Bills         return path;
148*3f7c5e40SJason M. Bills 
149*3f7c5e40SJason M. Bills     if (sensorTree.size() < sensorNum)
150*3f7c5e40SJason M. Bills     {
151*3f7c5e40SJason M. Bills         return path;
152*3f7c5e40SJason M. Bills     }
153*3f7c5e40SJason M. Bills 
154*3f7c5e40SJason M. Bills     uint8_t sensorIndex = sensorNum;
155*3f7c5e40SJason M. Bills     for (const auto& sensor : sensorTree)
156*3f7c5e40SJason M. Bills     {
157*3f7c5e40SJason M. Bills         if (sensorIndex-- == 0)
158*3f7c5e40SJason M. Bills         {
159*3f7c5e40SJason M. Bills             path = sensor.first;
160*3f7c5e40SJason M. Bills             break;
161*3f7c5e40SJason M. Bills         }
162*3f7c5e40SJason M. Bills     }
163*3f7c5e40SJason M. Bills 
164*3f7c5e40SJason M. Bills     return path;
165*3f7c5e40SJason M. Bills }
166