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