xref: /openbmc/phosphor-power/phosphor-power-sequencer/src/services.cpp (revision 3a11d6328d0bfdbd74bde8ae6d70909560f66030)
1906cc3f3SShawn McCarney /**
2906cc3f3SShawn McCarney  * Copyright © 2024 IBM Corporation
3906cc3f3SShawn McCarney  *
4906cc3f3SShawn McCarney  * Licensed under the Apache License, Version 2.0 (the "License");
5906cc3f3SShawn McCarney  * you may not use this file except in compliance with the License.
6906cc3f3SShawn McCarney  * You may obtain a copy of the License at
7906cc3f3SShawn McCarney  *
8906cc3f3SShawn McCarney  *     http://www.apache.org/licenses/LICENSE-2.0
9906cc3f3SShawn McCarney  *
10906cc3f3SShawn McCarney  * Unless required by applicable law or agreed to in writing, software
11906cc3f3SShawn McCarney  * distributed under the License is distributed on an "AS IS" BASIS,
12906cc3f3SShawn McCarney  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13906cc3f3SShawn McCarney  * See the License for the specific language governing permissions and
14906cc3f3SShawn McCarney  * limitations under the License.
15906cc3f3SShawn McCarney  */
16906cc3f3SShawn McCarney 
17906cc3f3SShawn McCarney #include "services.hpp"
18906cc3f3SShawn McCarney 
19906cc3f3SShawn McCarney #include "types.hpp"
20906cc3f3SShawn McCarney #include "utility.hpp"
21906cc3f3SShawn McCarney 
22906cc3f3SShawn McCarney #include <sys/types.h> // for getpid()
23906cc3f3SShawn McCarney #include <unistd.h>    // for getpid()
24906cc3f3SShawn McCarney 
25906cc3f3SShawn McCarney #include <gpiod.hpp>
26906cc3f3SShawn McCarney 
27906cc3f3SShawn McCarney #include <exception>
28*3a11d632SShawn McCarney #include <variant>
29906cc3f3SShawn McCarney 
30906cc3f3SShawn McCarney namespace phosphor::power::sequencer
31906cc3f3SShawn McCarney {
32906cc3f3SShawn McCarney 
logError(const std::string & message,Entry::Level severity,std::map<std::string,std::string> & additionalData)33906cc3f3SShawn McCarney void BMCServices::logError(const std::string& message, Entry::Level severity,
34906cc3f3SShawn McCarney                            std::map<std::string, std::string>& additionalData)
35906cc3f3SShawn McCarney {
36906cc3f3SShawn McCarney     try
37906cc3f3SShawn McCarney     {
38906cc3f3SShawn McCarney         // Add PID to AdditionalData
39906cc3f3SShawn McCarney         additionalData.emplace("_PID", std::to_string(getpid()));
40906cc3f3SShawn McCarney 
41906cc3f3SShawn McCarney         // If severity is critical, set error as system terminating
42906cc3f3SShawn McCarney         if (severity == Entry::Level::Critical)
43906cc3f3SShawn McCarney         {
44906cc3f3SShawn McCarney             additionalData.emplace("SEVERITY_DETAIL", "SYSTEM_TERM");
45906cc3f3SShawn McCarney         }
46906cc3f3SShawn McCarney 
47906cc3f3SShawn McCarney         auto method = bus.new_method_call(
48906cc3f3SShawn McCarney             "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
49906cc3f3SShawn McCarney             "xyz.openbmc_project.Logging.Create", "Create");
50906cc3f3SShawn McCarney         method.append(message, severity, additionalData);
51906cc3f3SShawn McCarney         bus.call_noreply(method);
52906cc3f3SShawn McCarney     }
53906cc3f3SShawn McCarney     catch (const std::exception& e)
54906cc3f3SShawn McCarney     {
55906cc3f3SShawn McCarney         lg2::error("Unable to log error {ERROR}: {EXCEPTION}", "ERROR", message,
56906cc3f3SShawn McCarney                    "EXCEPTION", e);
57906cc3f3SShawn McCarney     }
58906cc3f3SShawn McCarney }
59906cc3f3SShawn McCarney 
isPresent(const std::string & inventoryPath)60906cc3f3SShawn McCarney bool BMCServices::isPresent(const std::string& inventoryPath)
61906cc3f3SShawn McCarney {
62906cc3f3SShawn McCarney     // Initially assume hardware is not present
63906cc3f3SShawn McCarney     bool present{false};
64906cc3f3SShawn McCarney 
65e4fef0fcSShawn McCarney     // Try to find cached presence value
66e4fef0fcSShawn McCarney     auto it = presenceCache.find(inventoryPath);
67e4fef0fcSShawn McCarney     if (it != presenceCache.end())
68e4fef0fcSShawn McCarney     {
69e4fef0fcSShawn McCarney         present = it->second;
70e4fef0fcSShawn McCarney     }
71e4fef0fcSShawn McCarney     else
72e4fef0fcSShawn McCarney     {
73906cc3f3SShawn McCarney         // Get presence from D-Bus interface/property
74906cc3f3SShawn McCarney         try
75906cc3f3SShawn McCarney         {
76906cc3f3SShawn McCarney             util::getProperty(INVENTORY_IFACE, PRESENT_PROP, inventoryPath,
77906cc3f3SShawn McCarney                               INVENTORY_MGR_IFACE, bus, present);
78906cc3f3SShawn McCarney         }
79906cc3f3SShawn McCarney         catch (const sdbusplus::exception_t& e)
80906cc3f3SShawn McCarney         {
81906cc3f3SShawn McCarney             // If exception type is expected and indicates hardware not present
82906cc3f3SShawn McCarney             if (isExpectedException(e))
83906cc3f3SShawn McCarney             {
84906cc3f3SShawn McCarney                 present = false;
85906cc3f3SShawn McCarney             }
86906cc3f3SShawn McCarney             else
87906cc3f3SShawn McCarney             {
88906cc3f3SShawn McCarney                 // Re-throw unexpected exception
89906cc3f3SShawn McCarney                 throw;
90906cc3f3SShawn McCarney             }
91906cc3f3SShawn McCarney         }
92906cc3f3SShawn McCarney 
93e4fef0fcSShawn McCarney         // Cache presence value
94e4fef0fcSShawn McCarney         presenceCache[inventoryPath] = present;
95e4fef0fcSShawn McCarney     }
96e4fef0fcSShawn McCarney 
97906cc3f3SShawn McCarney     return present;
98906cc3f3SShawn McCarney }
99906cc3f3SShawn McCarney 
getGPIOValues(const std::string & chipLabel)100906cc3f3SShawn McCarney std::vector<int> BMCServices::getGPIOValues(const std::string& chipLabel)
101906cc3f3SShawn McCarney {
102906cc3f3SShawn McCarney     // Set up the chip object
103906cc3f3SShawn McCarney     gpiod::chip chip{chipLabel, gpiod::chip::OPEN_BY_LABEL};
104906cc3f3SShawn McCarney     unsigned int numLines = chip.num_lines();
105906cc3f3SShawn McCarney     lg2::info(
106906cc3f3SShawn McCarney         "Reading GPIO values from chip {NAME} with label {LABEL} and {NUM_LINES} lines",
107906cc3f3SShawn McCarney         "NAME", chip.name(), "LABEL", chipLabel, "NUM_LINES", numLines);
108906cc3f3SShawn McCarney 
109906cc3f3SShawn McCarney     // Read GPIO values.  Work around libgpiod bulk line maximum by getting
110906cc3f3SShawn McCarney     // values from individual lines.
111906cc3f3SShawn McCarney     std::vector<int> values;
112906cc3f3SShawn McCarney     for (unsigned int offset = 0; offset < numLines; ++offset)
113906cc3f3SShawn McCarney     {
114906cc3f3SShawn McCarney         gpiod::line line = chip.get_line(offset);
115906cc3f3SShawn McCarney         line.request({"phosphor-power-control",
116906cc3f3SShawn McCarney                       gpiod::line_request::DIRECTION_INPUT, 0});
117906cc3f3SShawn McCarney         values.push_back(line.get_value());
118906cc3f3SShawn McCarney         line.release();
119906cc3f3SShawn McCarney     }
120906cc3f3SShawn McCarney     return values;
121906cc3f3SShawn McCarney }
122906cc3f3SShawn McCarney 
isExpectedException(const sdbusplus::exception_t & e)123906cc3f3SShawn McCarney bool BMCServices::isExpectedException(const sdbusplus::exception_t& e)
124906cc3f3SShawn McCarney {
125906cc3f3SShawn McCarney     // Initially assume exception is not one of the expected types
126906cc3f3SShawn McCarney     bool isExpected{false};
127906cc3f3SShawn McCarney 
128906cc3f3SShawn McCarney     // If the D-Bus error name is set within the exception
129906cc3f3SShawn McCarney     if (e.name() != nullptr)
130906cc3f3SShawn McCarney     {
131906cc3f3SShawn McCarney         // Check if the error name is one of the expected values when hardware
132906cc3f3SShawn McCarney         // is not present.
133906cc3f3SShawn McCarney         //
134906cc3f3SShawn McCarney         // Sometimes the object path does not exist.  Sometimes the object path
135906cc3f3SShawn McCarney         // exists, but it does not implement the D-Bus interface that contains
136906cc3f3SShawn McCarney         // the present property.  Both of these cases result in exceptions.
137906cc3f3SShawn McCarney         //
138906cc3f3SShawn McCarney         // In the case where the interface is not implemented, the systemd
139906cc3f3SShawn McCarney         // documentation seems to indicate that the error name should be
140906cc3f3SShawn McCarney         // SD_BUS_ERROR_UNKNOWN_INTERFACE.  However, in OpenBMC the
141906cc3f3SShawn McCarney         // SD_BUS_ERROR_UNKNOWN_PROPERTY error name can occur.
142906cc3f3SShawn McCarney         std::string name = e.name();
143906cc3f3SShawn McCarney         if ((name == SD_BUS_ERROR_UNKNOWN_OBJECT) ||
144906cc3f3SShawn McCarney             (name == SD_BUS_ERROR_UNKNOWN_INTERFACE) ||
145906cc3f3SShawn McCarney             (name == SD_BUS_ERROR_UNKNOWN_PROPERTY))
146906cc3f3SShawn McCarney         {
147906cc3f3SShawn McCarney             isExpected = true;
148906cc3f3SShawn McCarney         }
149906cc3f3SShawn McCarney     }
150906cc3f3SShawn McCarney 
151906cc3f3SShawn McCarney     return isExpected;
152906cc3f3SShawn McCarney }
153906cc3f3SShawn McCarney 
createBMCDump()154*3a11d632SShawn McCarney void BMCServices::createBMCDump()
155*3a11d632SShawn McCarney {
156*3a11d632SShawn McCarney     try
157*3a11d632SShawn McCarney     {
158*3a11d632SShawn McCarney         auto method = bus.new_method_call(
159*3a11d632SShawn McCarney             "xyz.openbmc_project.Dump.Manager", "/xyz/openbmc_project/dump/bmc",
160*3a11d632SShawn McCarney             "xyz.openbmc_project.Dump.Create", "CreateDump");
161*3a11d632SShawn McCarney         method.append(
162*3a11d632SShawn McCarney             std::vector<
163*3a11d632SShawn McCarney                 std::pair<std::string, std::variant<std::string, uint64_t>>>());
164*3a11d632SShawn McCarney         bus.call_noreply(method);
165*3a11d632SShawn McCarney     }
166*3a11d632SShawn McCarney     catch (const std::exception& e)
167*3a11d632SShawn McCarney     {
168*3a11d632SShawn McCarney         lg2::error("Unable to create BMC dump: {ERROR}", "ERROR", e);
169*3a11d632SShawn McCarney     }
170*3a11d632SShawn McCarney }
171*3a11d632SShawn McCarney 
172906cc3f3SShawn McCarney } // namespace phosphor::power::sequencer
173