blob: fb3d64417670ad1b53c2df301e8824db3f870330 [file] [log] [blame]
Patrick Venture46470a32018-09-07 19:26:25 -07001#include "config.h"
2
3#include "chassishandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07004
Patrick Venture0b02be92018-08-31 11:55:55 -07005#include <arpa/inet.h>
6#include <endian.h>
7#include <limits.h>
8#include <mapper.h>
9#include <netinet/in.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070010
Ratan Guptafd28dd72016-08-01 04:58:01 -050011#include <array>
Patrick Venture0b02be92018-08-31 11:55:55 -070012#include <chrono>
Patrick Ventureb51bf9c2018-09-10 15:53:14 -070013#include <cstring>
Vernon Mauerybdda8002019-02-26 10:18:51 -080014#include <filesystem>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050015#include <fstream>
Tom Joseph5110c122018-03-23 17:55:40 +053016#include <future>
Vernon Mauerye08fbff2019-04-03 09:19:34 -070017#include <ipmid/api.hpp>
Vernon Mauery33250242019-03-12 16:49:26 -070018#include <ipmid/types.hpp>
Vernon Mauery6a98fe72019-03-11 15:57:48 -070019#include <ipmid/utils.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070020#include <map>
21#include <phosphor-logging/elog-errors.hpp>
22#include <phosphor-logging/log.hpp>
23#include <sdbusplus/bus.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070024#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070025#include <sdbusplus/server/object.hpp>
Vernon Mauery1181af72018-10-08 12:05:00 -070026#include <sdbusplus/timer.hpp>
Vernon Mauerye278ead2018-10-09 09:23:43 -070027#include <settings.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070028#include <sstream>
Patrick Venture3a5071a2018-09-12 13:27:42 -070029#include <string>
30#include <xyz/openbmc_project/Common/error.hpp>
31#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
32#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +030033#include <xyz/openbmc_project/Control/Boot/Type/server.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070034#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
35#include <xyz/openbmc_project/State/Host/server.hpp>
36#include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
37
Lei YU4b0ddb62019-01-25 16:43:50 +080038std::unique_ptr<phosphor::Timer> identifyTimer
39 __attribute__((init_priority(101)));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050040
Yong Lif4e38512019-05-21 14:46:55 +080041static ChassisIDState chassisIDState = ChassisIDState::reserved;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000042static constexpr uint8_t setParmVersion = 0x01;
Yong Lif4e38512019-05-21 14:46:55 +080043
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000044constexpr size_t sizeVersion = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053045constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053046
Patrick Venture0b02be92018-08-31 11:55:55 -070047// PetiBoot-Specific
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000048static constexpr uint8_t netConfInitialBytes[] = {0x80, 0x21, 0x70, 0x62,
49 0x21, 0x00, 0x01, 0x06};
50static constexpr uint8_t oemParmStart = 96;
51static constexpr uint8_t oemParmEnd = 127;
Ratan Guptafd28dd72016-08-01 04:58:01 -050052
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000053static constexpr size_t cookieOffset = 1;
54static constexpr size_t versionOffset = 5;
55static constexpr size_t addrSizeOffset = 8;
56static constexpr size_t macOffset = 9;
57static constexpr size_t addrTypeOffset = 16;
58static constexpr size_t ipAddrOffset = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050059
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050060static constexpr size_t encIdentifyObjectsSize = 1;
61static constexpr size_t chassisIdentifyReqLength = 2;
62static constexpr size_t identifyIntervalPos = 0;
63static constexpr size_t forceIdentifyPos = 1;
shgoupfd84fbbf2015-12-17 10:05:51 +080064
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000065namespace ipmi
66{
67constexpr Cc ccParmNotSupported = 0x80;
68
69static inline auto responseParmNotSupported()
70{
71 return response(ccParmNotSupported);
72}
73} // namespace ipmi
74
Adriana Kobylak40814c62015-10-27 15:58:44 -050075void register_netfn_chassis_functions() __attribute__((constructor));
76
shgoupfd84fbbf2015-12-17 10:05:51 +080077// Host settings in dbus
78// Service name should be referenced by connection name got via object mapper
Patrick Venture0b02be92018-08-31 11:55:55 -070079const char* settings_object_name = "/org/openbmc/settings/host0";
80const char* settings_intf_name = "org.freedesktop.DBus.Properties";
Patrick Venture0b02be92018-08-31 11:55:55 -070081const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053082 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080083
Ratan Guptadcb10672017-07-10 10:33:50 +053084constexpr auto SETTINGS_ROOT = "/";
85constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053086
87constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
88constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
89
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050090static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
91static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -070092 "xyz.openbmc_project.State.PowerOnHours";
Patrick Williams7345ac42021-04-30 20:57:39 -050093static constexpr auto pohCounterProperty = "POHCounter";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050094static constexpr auto match = "chassis0";
Yong Liae4b0402018-11-02 11:12:14 +080095const static constexpr char chassisCapIntf[] =
96 "xyz.openbmc_project.Control.ChassisCapabilities";
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -080097const static constexpr char chassisIntrusionProp[] = "ChassisIntrusionEnabled";
98const static constexpr char chassisFrontPanelLockoutProp[] =
99 "ChassisFrontPanelLockoutEnabled";
100const static constexpr char chassisNMIProp[] = "ChassisNMIEnabled";
101const static constexpr char chassisPowerInterlockProp[] =
102 "ChassisPowerInterlockEnabled";
Yong Liae4b0402018-11-02 11:12:14 +0800103const static constexpr char chassisFRUDevAddrProp[] = "FRUDeviceAddress";
104const static constexpr char chassisSDRDevAddrProp[] = "SDRDeviceAddress";
105const static constexpr char chassisSELDevAddrProp[] = "SELDeviceAddress";
106const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress";
107const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress";
108static constexpr uint8_t chassisCapFlagMask = 0x0f;
109static constexpr uint8_t chassisCapAddrMask = 0xfe;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700110static constexpr const char* powerButtonIntf =
111 "xyz.openbmc_project.Chassis.Buttons.Power";
112static constexpr const char* powerButtonPath =
113 "/xyz/openbmc_project/Chassis/Buttons/Power0";
114static constexpr const char* resetButtonIntf =
115 "xyz.openbmc_project.Chassis.Buttons.Reset";
116static constexpr const char* resetButtonPath =
117 "/xyz/openbmc_project/Chassis/Buttons/Reset0";
Ratan Guptadcb10672017-07-10 10:33:50 +0530118
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530119// Phosphor Host State manager
120namespace State = sdbusplus::xyz::openbmc_project::State::server;
121
Vernon Mauery185b9f82018-07-20 10:52:36 -0700122namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500123
Ratan Guptadcb10672017-07-10 10:33:50 +0530124using namespace phosphor::logging;
125using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500126using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
William A. Kennington III4c008022018-10-12 17:18:14 -0700127
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500128namespace chassis
129{
130namespace internal
131{
132
133constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +0300134constexpr auto bootTypeIntf = "xyz.openbmc_project.Control.Boot.Type";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500135constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500136constexpr auto powerRestoreIntf =
137 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500138sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
139
140namespace cache
141{
142
James Feist225dec82019-11-26 16:25:06 -0800143std::unique_ptr<settings::Objects> objectsPtr = nullptr;
144
145settings::Objects& getObjects()
146{
147 if (objectsPtr == nullptr)
148 {
149 objectsPtr = std::make_unique<settings::Objects>(
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +0300150 dbus, std::vector<std::string>{bootModeIntf, bootTypeIntf,
151 bootSourceIntf, powerRestoreIntf});
James Feist225dec82019-11-26 16:25:06 -0800152 }
153 return *objectsPtr;
154}
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500155
156} // namespace cache
157} // namespace internal
158} // namespace chassis
159
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500160namespace poh
161{
162
163constexpr auto minutesPerCount = 60;
164
165} // namespace poh
166
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000167int getHostNetworkData(ipmi::message::Payload& payload)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500168{
Ratan Guptadcb10672017-07-10 10:33:50 +0530169 ipmi::PropertyMap properties;
170 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530171 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500172
Ratan Guptadcb10672017-07-10 10:33:50 +0530173 try
174 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700175 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530176 // objects,to handle such cases we are interested on that object
177 // which are on interested busname.
178 // Currenlty mapper doesn't give the readable busname(gives busid)
179 // so we can't match with bus name so giving some object specific info
180 // as SETTINGS_MATCH.
181 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500182
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530183 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530184
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530185 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
186 SETTINGS_ROOT, SETTINGS_MATCH);
187
188 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
189 SETTINGS_ROOT, SETTINGS_MATCH);
190
Patrick Venture0b02be92018-08-31 11:55:55 -0700191 properties = ipmi::getAllDbusProperties(
192 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
193 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
194 macObjectInfo.first, MAC_INTERFACE,
195 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530196
Vernon Maueryf442e112019-04-09 11:44:36 -0700197 auto ipAddress = std::get<std::string>(properties["Address"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530198
Vernon Maueryf442e112019-04-09 11:44:36 -0700199 auto gateway = std::get<std::string>(properties["Gateway"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530200
Vernon Maueryf442e112019-04-09 11:44:36 -0700201 auto prefix = std::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530202
Patrick Venture0b02be92018-08-31 11:55:55 -0700203 uint8_t isStatic =
Vernon Maueryf442e112019-04-09 11:44:36 -0700204 (std::get<std::string>(properties["Origin"]) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700205 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
206 ? 1
207 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530208
Vernon Maueryf442e112019-04-09 11:44:36 -0700209 auto MACAddress = std::get<std::string>(variant);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530210
Ratan Guptad70f4532017-08-04 02:07:31 +0530211 // it is expected here that we should get the valid data
212 // but we may also get the default values.
213 // Validation of the data is done by settings.
214 //
215 // if mac address is default mac address then
216 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530217 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530218 {
Ratan Guptad70f4532017-08-04 02:07:31 +0530219 rc = -1;
220 return rc;
221 }
222 // if addr is static then ipaddress,gateway,prefix
223 // should not be default one,don't send blank override.
224 if (isStatic)
225 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700226 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
227 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530228 {
Ratan Guptad70f4532017-08-04 02:07:31 +0530229 rc = -1;
230 return rc;
231 }
232 }
233
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000234 std::string token;
235 std::stringstream ss(MACAddress);
Ratan Guptadcb10672017-07-10 10:33:50 +0530236
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000237 // First pack macOffset no of bytes in payload.
238 // Latter this PetiBoot-Specific data will be populated.
239 std::vector<uint8_t> payloadInitialBytes(macOffset);
240 payload.pack(payloadInitialBytes);
Ratan Guptadcb10672017-07-10 10:33:50 +0530241
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000242 while (std::getline(ss, token, ':'))
243 {
244 payload.pack(stoi(token, nullptr, 16));
245 }
246
247 payload.pack(0x00);
248
249 payload.pack(isStatic);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530250
Vernon Maueryf442e112019-04-09 11:44:36 -0700251 uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
252 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
253 ? AF_INET
254 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530255
Patrick Venture0b02be92018-08-31 11:55:55 -0700256 addrSize = (addressFamily == AF_INET)
257 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
258 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530259
260 // ipaddress and gateway would be in IPv4 format
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000261 std::vector<uint8_t> addrInBinary(addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530262 inet_pton(addressFamily, ipAddress.c_str(),
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000263 reinterpret_cast<void*>(addrInBinary.data()));
Ratan Guptadcb10672017-07-10 10:33:50 +0530264
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000265 payload.pack(addrInBinary);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530266
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000267 payload.pack(prefix);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530268
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000269 std::vector<uint8_t> gatewayDetails(addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530270 inet_pton(addressFamily, gateway.c_str(),
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000271 reinterpret_cast<void*>(gatewayDetails.data()));
272 payload.pack(gatewayDetails);
Ratan Guptadcb10672017-07-10 10:33:50 +0530273 }
274 catch (InternalFailure& e)
275 {
276 commit<InternalFailure>();
Ratan Guptadcb10672017-07-10 10:33:50 +0530277 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500278 return rc;
279 }
280
Patrick Venture0b02be92018-08-31 11:55:55 -0700281 // PetiBoot-Specific
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000282 // If success then copy the first 9 bytes to the payload message
283 // payload first 2 bytes contain the parameter values. Skip that 2 bytes.
284 uint8_t skipFirstTwoBytes = 2;
285 size_t payloadSize = payload.size();
286 uint8_t* configDataStartingAddress = payload.data() + skipFirstTwoBytes;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500287
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000288 if (payloadSize < skipFirstTwoBytes + sizeof(netConfInitialBytes))
289 {
290 log<level::ERR>("Invalid net config ");
291 rc = -1;
292 return rc;
293 }
294 std::copy(netConfInitialBytes,
295 netConfInitialBytes + sizeof(netConfInitialBytes),
296 configDataStartingAddress);
297
298 if (payloadSize < skipFirstTwoBytes + addrSizeOffset + sizeof(addrSize))
299 {
300 log<level::ERR>("Invalid length of address size");
301 rc = -1;
302 return rc;
303 }
304 std::copy(&addrSize, &(addrSize) + sizeof(addrSize),
305 configDataStartingAddress + addrSizeOffset);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530306
Ratan Guptafd28dd72016-08-01 04:58:01 -0500307#ifdef _IPMI_DEBUG_
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700308 std::printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500309
Ratan Guptadcb10672017-07-10 10:33:50 +0530310 for (uint8_t pos = 0; pos < index; pos++)
311 {
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +0000312 std::printf("%02x ", payloadStartingAddress[pos]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530313 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500314#endif
315
Ratan Guptafd28dd72016-08-01 04:58:01 -0500316 return rc;
317}
318
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530319/** @brief convert IPv4 and IPv6 addresses from binary to text form.
320 * @param[in] family - IPv4/Ipv6
321 * @param[in] data - req data pointer.
322 * @param[in] offset - offset in the data.
323 * @param[in] addrSize - size of the data which needs to be read from offset.
324 * @returns address in text form.
325 */
326
Patrick Venture0b02be92018-08-31 11:55:55 -0700327std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
328 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530329{
330 char ipAddr[INET6_ADDRSTRLEN] = {};
331
Patrick Venture0b02be92018-08-31 11:55:55 -0700332 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530333 {
334 case AF_INET:
335 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700336 struct sockaddr_in addr4
337 {
338 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700339 std::memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530340
Patrick Venture0b02be92018-08-31 11:55:55 -0700341 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530342
343 break;
344 }
345 case AF_INET6:
346 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700347 struct sockaddr_in6 addr6
348 {
349 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700350 std::memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530351
Patrick Venture0b02be92018-08-31 11:55:55 -0700352 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530353
354 break;
355 }
356 default:
357 {
358 return {};
359 }
360 }
361
362 return ipAddr;
363}
364
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000365ipmi::Cc setHostNetworkData(ipmi::message::Payload& data)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500366{
Ratan Guptadcb10672017-07-10 10:33:50 +0530367 using namespace std::string_literals;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000368 std::string hostNetworkConfig;
369 std::string mac("00:00:00:00:00:00");
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530370 std::string ipAddress, gateway;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000371 std::string addrOrigin{0};
Patrick Venture0b02be92018-08-31 11:55:55 -0700372 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530373 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530374 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700375 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
376 uint8_t prefix{0};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530377 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500378
Patrick Venture0b02be92018-08-31 11:55:55 -0700379 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500380 // version starts from sixth byte
381
Ratan Guptadcb10672017-07-10 10:33:50 +0530382 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500383 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530384 do
385 {
386 // cookie == 0x21 0x70 0x62 0x21
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000387 data.trailingOk = true;
388 auto msgLen = data.size();
389 std::vector<uint8_t> msgPayloadBytes(msgLen);
390 if (data.unpack(msgPayloadBytes) != 0 || !data.fullyUnpacked())
Ratan Guptadcb10672017-07-10 10:33:50 +0530391 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000392 log<level::ERR>(
393 "Error in unpacking message of setHostNetworkData");
394 return ipmi::ccReqDataLenInvalid;
395 }
396
397 uint8_t* msgPayloadStartingPos = msgPayloadBytes.data();
398 constexpr size_t cookieSize = 4;
399 if (msgLen < cookieOffset + cookieSize)
400 {
401 log<level::ERR>(
402 "Error in cookie getting of setHostNetworkData");
403 return ipmi::ccReqDataLenInvalid;
404 }
405 if (std::equal(msgPayloadStartingPos + cookieOffset,
406 msgPayloadStartingPos + cookieOffset + cookieSize,
407 (netConfInitialBytes + cookieOffset)) != 0)
408 {
409 // all cookie == 0
410 if (std::all_of(msgPayloadStartingPos + cookieOffset,
411 msgPayloadStartingPos + cookieOffset +
412 cookieSize,
413 [](int i) { return i == 0; }) == true)
Ratan Guptadcb10672017-07-10 10:33:50 +0530414 {
415 // need to zero out the network settings.
416 break;
417 }
418
419 log<level::ERR>("Invalid Cookie");
420 elog<InternalFailure>();
421 }
422
423 // vesion == 0x00 0x01
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000424 if (msgLen < versionOffset + sizeVersion)
Ratan Guptadcb10672017-07-10 10:33:50 +0530425 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000426 log<level::ERR>(
427 "Error in version getting of setHostNetworkData");
428 return ipmi::ccReqDataLenInvalid;
429 }
430 if (std::equal(msgPayloadStartingPos + versionOffset,
431 msgPayloadStartingPos + versionOffset + sizeVersion,
432 (netConfInitialBytes + versionOffset)) != 0)
433 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530434 log<level::ERR>("Invalid Version");
435 elog<InternalFailure>();
436 }
437
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000438 if (msgLen < macOffset + 6)
439 {
440 log<level::ERR>(
441 "Error in mac address getting of setHostNetworkData");
442 return ipmi::ccReqDataLenInvalid;
443 }
444 std::stringstream result;
445 std::copy((msgPayloadStartingPos + macOffset),
446 (msgPayloadStartingPos + macOffset + 5),
447 std::ostream_iterator<int>(result, ":"));
448 mac = result.str();
Ratan Guptadcb10672017-07-10 10:33:50 +0530449
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000450 if (msgLen < addrTypeOffset + sizeof(decltype(addrOrigin)))
451 {
452 log<level::ERR>(
453 "Error in original address getting of setHostNetworkData");
454 return ipmi::ccReqDataLenInvalid;
455 }
456 std::copy(msgPayloadStartingPos + addrTypeOffset,
457 msgPayloadStartingPos + addrTypeOffset +
458 sizeof(decltype(addrOrigin)),
459 std::ostream_iterator<int>(result, ""));
460 addrOrigin = result.str();
Ratan Guptadcb10672017-07-10 10:33:50 +0530461
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000462 if (!addrOrigin.empty())
Ratan Guptadcb10672017-07-10 10:33:50 +0530463 {
464 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530465 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530466 }
467
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000468 if (msgLen < addrSizeOffset + sizeof(decltype(addrSize)))
469 {
470 log<level::ERR>(
471 "Error in address size getting of setHostNetworkData");
472 return ipmi::ccReqDataLenInvalid;
473 }
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530474 // Get the address size
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000475 std::copy(msgPayloadStartingPos + addrSizeOffset,
476 (msgPayloadStartingPos + addrSizeOffset +
477 sizeof(decltype(addrSize))),
478 &addrSize);
Ratan Guptadcb10672017-07-10 10:33:50 +0530479
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000480 uint8_t prefixOffset = ipAddrOffset + addrSize;
481 if (msgLen < prefixOffset + sizeof(decltype(prefix)))
482 {
483 log<level::ERR>(
484 "Error in prefix getting of setHostNetworkData");
485 return ipmi::ccReqDataLenInvalid;
486 }
487 std::copy(msgPayloadStartingPos + prefixOffset,
488 (msgPayloadStartingPos + prefixOffset +
489 sizeof(decltype(prefix))),
490 &prefix);
Ratan Guptadcb10672017-07-10 10:33:50 +0530491
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530492 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
Ratan Gupta8c31d232017-08-13 05:49:43 +0530493 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530494 {
495 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
496 family = AF_INET6;
497 }
498
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000499 if (msgLen < ipAddrOffset + addrSize)
500 {
501 log<level::ERR>(
502 "Error in IP address getting of setHostNetworkData");
503 return ipmi::ccReqDataLenInvalid;
504 }
505 ipAddress = getAddrStr(family, msgPayloadStartingPos, ipAddrOffset,
506 addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530507
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000508 if (msgLen < gatewayOffset + addrSize)
509 {
510 log<level::ERR>(
511 "Error in gateway address getting of setHostNetworkData");
512 return ipmi::ccReqDataLenInvalid;
513 }
514 gateway = getAddrStr(family, msgPayloadStartingPos, gatewayOffset,
515 addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530516
Patrick Venture0b02be92018-08-31 11:55:55 -0700517 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530518
Patrick Venture0b02be92018-08-31 11:55:55 -0700519 // Cookie == 0 or it is a valid cookie
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000520 hostNetworkConfig += "ipaddress="s + ipAddress + ",prefix="s +
521 std::to_string(prefix) + ",gateway="s + gateway +
522 ",mac="s + mac + ",addressOrigin="s +
523 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500524
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530525 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
526
527 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
528 SETTINGS_ROOT, SETTINGS_MATCH);
529 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
530 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530531 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530532 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700533 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530534 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700535 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530536 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700537 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530538 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700539 IP_INTERFACE, "Gateway", std::string(gateway));
540 ipmi::setDbusProperty(
541 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
542 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530543 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700544 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500545
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000546 log<level::DEBUG>("Network configuration changed",
547 entry("NETWORKCONFIG=%s", hostNetworkConfig.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500548 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000549 catch (sdbusplus::exception_t& e)
Ratan Guptadcb10672017-07-10 10:33:50 +0530550 {
551 commit<InternalFailure>();
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000552 log<level::ERR>("Error in ipmiChassisSetSysBootOptions call");
553 return ipmi::ccUnspecifiedError;
Ratan Guptadcb10672017-07-10 10:33:50 +0530554 }
555
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000556 return ipmi::ccSuccess;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500557}
558
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500559uint32_t getPOHCounter()
560{
561 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
562
Patrick Venture0b02be92018-08-31 11:55:55 -0700563 auto chassisStateObj =
564 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500565
Patrick Venture0b02be92018-08-31 11:55:55 -0700566 auto service =
567 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500568
Patrick Venture0b02be92018-08-31 11:55:55 -0700569 auto propValue =
570 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
Patrick Williams7345ac42021-04-30 20:57:39 -0500571 chassisPOHStateIntf, pohCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500572
Vernon Maueryf442e112019-04-09 11:44:36 -0700573 return std::get<uint32_t>(propValue);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500574}
575
anil kumar appana43263c62019-05-27 12:45:04 +0000576/** @brief Implements the get chassis capabilities command
577 *
578 * @returns IPMI completion code plus response data
579 * chassisCapFlags - chassis capability flag
580 * chassisFRUInfoDevAddr - chassis FRU info Device Address
581 * chassisSDRDevAddr - chassis SDR device address
582 * chassisSELDevAddr - chassis SEL device address
583 * chassisSMDevAddr - chassis system management device address
584 * chassisBridgeDevAddr - chassis bridge device address
585 */
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800586ipmi::RspType<bool, // chassis intrusion sensor
587 bool, // chassis Front panel lockout
588 bool, // chassis NMI
589 bool, // chassis power interlock
590 uint4_t, // reserved
anil kumar appana43263c62019-05-27 12:45:04 +0000591 uint8_t, // chassis FRU info Device Address
592 uint8_t, // chassis SDR device address
593 uint8_t, // chassis SEL device address
594 uint8_t, // chassis system management device address
595 uint8_t // chassis bridge device address
596 >
597 ipmiGetChassisCap()
Nan Li8d15fb42016-08-16 22:29:40 +0800598{
anil kumar appana43263c62019-05-27 12:45:04 +0000599 ipmi::PropertyMap properties;
Yong Liae4b0402018-11-02 11:12:14 +0800600 try
601 {
602 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Nan Li8d15fb42016-08-16 22:29:40 +0800603
Yong Liae4b0402018-11-02 11:12:14 +0800604 ipmi::DbusObjectInfo chassisCapObject =
605 ipmi::getDbusObject(bus, chassisCapIntf);
Nan Li8d15fb42016-08-16 22:29:40 +0800606
Yong Liae4b0402018-11-02 11:12:14 +0800607 // capabilities flags
608 // [7..4] - reserved
609 // [3] – 1b = provides power interlock (IPM 1.5)
610 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
611 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis
612 // has capabilities
613 // to lock out external power control and reset button or
614 // front panel interfaces and/or detect tampering with those
615 // interfaces).
616 // [0] -1b = Chassis provides intrusion (physical security) sensor.
617 // set to default value 0x0.
Nan Li8d15fb42016-08-16 22:29:40 +0800618
anil kumar appana43263c62019-05-27 12:45:04 +0000619 properties =
620 ipmi::getAllDbusProperties(bus, chassisCapObject.second,
621 chassisCapObject.first, chassisCapIntf);
Yong Liae4b0402018-11-02 11:12:14 +0800622 }
623 catch (std::exception& e)
624 {
anil kumar appana43263c62019-05-27 12:45:04 +0000625 log<level::ERR>("Failed to fetch Chassis Capability properties",
626 entry("ERROR=%s", e.what()));
627 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800628 }
629
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800630 bool* chassisIntrusionFlag =
631 std::get_if<bool>(&properties[chassisIntrusionProp]);
632 if (chassisIntrusionFlag == nullptr)
anil kumar appana43263c62019-05-27 12:45:04 +0000633 {
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800634 log<level::ERR>("Error to get chassis Intrusion flags");
635 return ipmi::responseUnspecifiedError();
636 }
637 bool* chassisFrontPanelFlag =
638 std::get_if<bool>(&properties[chassisFrontPanelLockoutProp]);
639 if (chassisFrontPanelFlag == nullptr)
640 {
641 log<level::ERR>("Error to get chassis intrusion flags");
642 return ipmi::responseUnspecifiedError();
643 }
644 bool* chassisNMIFlag = std::get_if<bool>(&properties[chassisNMIProp]);
645 if (chassisNMIFlag == nullptr)
646 {
647 log<level::ERR>("Error to get chassis NMI flags");
648 return ipmi::responseUnspecifiedError();
649 }
650 bool* chassisPowerInterlockFlag =
651 std::get_if<bool>(&properties[chassisPowerInterlockProp]);
652 if (chassisPowerInterlockFlag == nullptr)
653 {
654 log<level::ERR>("Error to get chassis power interlock flags");
anil kumar appana43263c62019-05-27 12:45:04 +0000655 return ipmi::responseUnspecifiedError();
656 }
657 uint8_t* chassisFRUInfoDevAddr =
658 std::get_if<uint8_t>(&properties[chassisFRUDevAddrProp]);
659 if (chassisFRUInfoDevAddr == nullptr)
660 {
661 log<level::ERR>("Error to get chassis FRU info device address");
662 return ipmi::responseUnspecifiedError();
663 }
664 uint8_t* chassisSDRDevAddr =
665 std::get_if<uint8_t>(&properties[chassisSDRDevAddrProp]);
666 if (chassisSDRDevAddr == nullptr)
667 {
668 log<level::ERR>("Error to get chassis SDR device address");
669 return ipmi::responseUnspecifiedError();
670 }
671 uint8_t* chassisSELDevAddr =
672 std::get_if<uint8_t>(&properties[chassisSELDevAddrProp]);
673 if (chassisSELDevAddr == nullptr)
674 {
675 log<level::ERR>("Error to get chassis SEL device address");
676 return ipmi::responseUnspecifiedError();
677 }
678 uint8_t* chassisSMDevAddr =
679 std::get_if<uint8_t>(&properties[chassisSMDevAddrProp]);
680 if (chassisSMDevAddr == nullptr)
681 {
682 log<level::ERR>("Error to get chassis SM device address");
683 return ipmi::responseUnspecifiedError();
684 }
685 uint8_t* chassisBridgeDevAddr =
686 std::get_if<uint8_t>(&properties[chassisBridgeDevAddrProp]);
687 if (chassisBridgeDevAddr == nullptr)
688 {
689 log<level::ERR>("Error to get chassis bridge device address");
690 return ipmi::responseUnspecifiedError();
691 }
692
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800693 return ipmi::responseSuccess(*chassisIntrusionFlag, *chassisFrontPanelFlag,
694 *chassisNMIFlag, *chassisPowerInterlockFlag, 0,
695 *chassisFRUInfoDevAddr, *chassisSDRDevAddr,
696 *chassisSELDevAddr, *chassisSMDevAddr,
697 *chassisBridgeDevAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800698}
699
anil kumar appana894d0222019-05-27 16:32:14 +0000700/** @brief implements set chassis capalibities command
701 * @param intrusion - chassis intrusion
702 * @param fpLockout - frontpannel lockout
703 * @param reserved1 - skip one bit
704 * @param fruDeviceAddr - chassis FRU info Device Address
705 * @param sdrDeviceAddr - chassis SDR device address
706 * @param selDeviceAddr - chassis SEL device address
707 * @param smDeviceAddr - chassis system management device address
708 * @param bridgeDeviceAddr - chassis bridge device address
709 *
710 * @returns IPMI completion code
711 */
712ipmi::RspType<> ipmiSetChassisCap(bool intrusion, bool fpLockout,
713 uint6_t reserved1,
714
715 uint8_t fruDeviceAddr,
716
717 uint8_t sdrDeviceAddr,
718
719 uint8_t selDeviceAddr,
720
721 uint8_t smDeviceAddr,
722
723 uint8_t bridgeDeviceAddr)
Yong Liae4b0402018-11-02 11:12:14 +0800724{
Yong Liae4b0402018-11-02 11:12:14 +0800725
726 // check input data
anil kumar appana894d0222019-05-27 16:32:14 +0000727 if (reserved1 != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800728 {
anil kumar appana894d0222019-05-27 16:32:14 +0000729 log<level::ERR>("Unsupported request parameter");
730 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800731 }
732
anil kumar appana894d0222019-05-27 16:32:14 +0000733 if ((fruDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800734 {
735 log<level::ERR>("Unsupported request parameter(FRU Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000736 entry("REQ=0x%x", fruDeviceAddr));
737 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800738 }
anil kumar appana894d0222019-05-27 16:32:14 +0000739 if ((sdrDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800740 {
741 log<level::ERR>("Unsupported request parameter(SDR Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000742 entry("REQ=0x%x", sdrDeviceAddr));
743 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800744 }
745
anil kumar appana894d0222019-05-27 16:32:14 +0000746 if ((selDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800747 {
748 log<level::ERR>("Unsupported request parameter(SEL Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000749 entry("REQ=0x%x", selDeviceAddr));
750 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800751 }
752
anil kumar appana894d0222019-05-27 16:32:14 +0000753 if ((smDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800754 {
anil kumar appana894d0222019-05-27 16:32:14 +0000755 log<level::ERR>("Unsupported request parameter(SM Addr)",
756 entry("REQ=0x%x", smDeviceAddr));
757 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800758 }
759
anil kumar appana894d0222019-05-27 16:32:14 +0000760 if ((bridgeDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800761 {
762 log<level::ERR>("Unsupported request parameter(Bridge Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000763 entry("REQ=0x%x", bridgeDeviceAddr));
764 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800765 }
766
767 try
768 {
769 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
770 ipmi::DbusObjectInfo chassisCapObject =
771 ipmi::getDbusObject(bus, chassisCapIntf);
772
773 ipmi::setDbusProperty(bus, chassisCapObject.second,
774 chassisCapObject.first, chassisCapIntf,
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800775 chassisIntrusionProp, intrusion);
776
777 ipmi::setDbusProperty(bus, chassisCapObject.second,
778 chassisCapObject.first, chassisCapIntf,
779 chassisFrontPanelLockoutProp, fpLockout);
Yong Liae4b0402018-11-02 11:12:14 +0800780
781 ipmi::setDbusProperty(bus, chassisCapObject.second,
782 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000783 chassisFRUDevAddrProp, fruDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800784
785 ipmi::setDbusProperty(bus, chassisCapObject.second,
786 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000787 chassisSDRDevAddrProp, sdrDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800788
789 ipmi::setDbusProperty(bus, chassisCapObject.second,
790 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000791 chassisSELDevAddrProp, selDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800792
793 ipmi::setDbusProperty(bus, chassisCapObject.second,
794 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000795 chassisSMDevAddrProp, smDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800796
797 ipmi::setDbusProperty(bus, chassisCapObject.second,
798 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000799 chassisBridgeDevAddrProp, bridgeDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800800 }
801 catch (std::exception& e)
802 {
803 log<level::ERR>(e.what());
anil kumar appana894d0222019-05-27 16:32:14 +0000804 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800805 }
anil kumar appana894d0222019-05-27 16:32:14 +0000806 return ipmi::responseSuccess();
Nan Li8d15fb42016-08-16 22:29:40 +0800807}
808
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530809//------------------------------------------
810// Calls into Host State Manager Dbus object
811//------------------------------------------
812int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600813{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500814 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700815 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500816 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700817 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
818 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530819
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500820 // sd_bus error
821 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700822 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600823
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500824 // SD Bus error report mechanism.
825 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600826
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500827 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700828 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500829 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
830 if (rc < 0)
831 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700832 log<level::ERR>(
833 "Failed to get bus name",
834 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500835 return rc;
836 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530837
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500838 // Convert to string equivalent of the passed in transition enum.
839 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530840
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500841 rc = sd_bus_call_method(bus_type, // On the system bus
842 busname, // Service to contact
843 HOST_STATE_MANAGER_ROOT, // Object path
844 DBUS_PROPERTY_IFACE, // Interface name
845 "Set", // Method to be called
846 &bus_error, // object to return error
847 nullptr, // Response buffer if any
848 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700849 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
850 request.c_str());
851 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500852 {
853 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530854 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500855 }
856 else
857 {
858 log<level::INFO>("Transition request initiated successfully");
859 }
vishwa36993272015-11-20 12:43:49 -0600860
861 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500862 free(busname);
vishwa36993272015-11-20 12:43:49 -0600863
Sergey Solomineb9b8142016-08-23 09:07:28 -0500864 return rc;
vishwa36993272015-11-20 12:43:49 -0600865}
866
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +0800867//------------------------------------------
868// Set Enabled property to inform NMI source
869// handling to trigger a NMI_OUT BSOD.
870//------------------------------------------
871int setNmiProperty(const bool value)
872{
873 constexpr const char* nmiSourceObjPath =
874 "/xyz/openbmc_project/Chassis/Control/NMISource";
875 constexpr const char* nmiSourceIntf =
876 "xyz.openbmc_project.Chassis.Control.NMISource";
877 std::string bmcSourceSignal = "xyz.openbmc_project.Chassis.Control."
878 "NMISource.BMCSourceSignal.ChassisCmd";
879 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
880
881 try
882 {
883 auto service = ipmi::getService(*busp, nmiSourceIntf, nmiSourceObjPath);
884 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
885 "BMCSource", bmcSourceSignal);
886 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
887 "Enabled", value);
888 }
889 catch (std::exception& e)
890 {
891 log<level::ERR>("Failed to trigger NMI_OUT",
892 entry("EXCEPTION=%s", e.what()));
893 return -1;
894 }
895
896 return 0;
897}
898
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500899namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500900{
Nan Lifdd8ec52016-08-28 03:57:40 +0800901
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500902using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
903using IpmiValue = uint8_t;
904using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800905
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700906const std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500907 {RestorePolicy::Policy::AlwaysOff, 0x00},
908 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700909 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800910
Yong Lic6713cf2018-09-12 12:35:13 +0800911static constexpr uint8_t noChange = 0x03;
912static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700913
914/* helper function for Get Chassis Status Command
915 */
916std::optional<uint2_t> getPowerRestorePolicy()
917{
918 uint2_t restorePolicy = 0;
919 using namespace chassis::internal;
920
James Feist225dec82019-11-26 16:25:06 -0800921 settings::Objects& objects = cache::getObjects();
922
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700923 try
924 {
925 const auto& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -0800926 objects.map.at(powerRestoreIntf).front();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700927 ipmi::Value result = ipmi::getDbusProperty(
928 *getSdBus(),
James Feist225dec82019-11-26 16:25:06 -0800929 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700930 powerRestoreSetting.c_str(), powerRestoreIntf,
931 "PowerRestorePolicy");
932 auto powerRestore = RestorePolicy::convertPolicyFromString(
933 std::get<std::string>(result));
934 restorePolicy = dbusToIpmi.at(powerRestore);
935 }
936 catch (const std::exception& e)
937 {
938 log<level::ERR>(
939 "Failed to fetch pgood property", entry("ERROR=%s", e.what()),
James Feist225dec82019-11-26 16:25:06 -0800940 entry("PATH=%s", objects.map.at(powerRestoreIntf).front().c_str()),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700941 entry("INTERFACE=%s", powerRestoreIntf));
James Feist225dec82019-11-26 16:25:06 -0800942 cache::objectsPtr.reset();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700943 return std::nullopt;
944 }
945 return std::make_optional(restorePolicy);
946}
947
948/*
949 * getPowerStatus
950 * helper function for Get Chassis Status Command
951 * return - optional value for pgood (no value on error)
952 */
953std::optional<bool> getPowerStatus()
954{
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700955 bool powerGood = false;
956 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
957 try
958 {
Jason M. Bills3de424c2019-05-21 09:57:16 -0700959 constexpr const char* chassisStatePath =
960 "/xyz/openbmc_project/state/chassis0";
961 constexpr const char* chassisStateIntf =
962 "xyz.openbmc_project.State.Chassis";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700963 auto service =
Jason M. Bills3de424c2019-05-21 09:57:16 -0700964 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700965
Jason M. Bills3de424c2019-05-21 09:57:16 -0700966 ipmi::Value powerState =
967 ipmi::getDbusProperty(*busp, service, chassisStatePath,
968 chassisStateIntf, "CurrentPowerState");
969 powerGood = std::get<std::string>(powerState) ==
970 "xyz.openbmc_project.State.Chassis.PowerState.On";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700971 }
972 catch (const std::exception& e)
973 {
974 try
975 {
976 // FIXME: some legacy modules use the older path; try that next
977 constexpr const char* legacyPwrCtrlObj =
978 "/org/openbmc/control/power0";
979 constexpr const char* legacyPwrCtrlIntf =
980 "org.openbmc.control.Power";
981 auto service =
982 ipmi::getService(*busp, legacyPwrCtrlIntf, legacyPwrCtrlObj);
983
984 ipmi::Value variant = ipmi::getDbusProperty(
985 *busp, service, legacyPwrCtrlObj, legacyPwrCtrlIntf, "pgood");
986 powerGood = static_cast<bool>(std::get<int>(variant));
987 }
988 catch (const std::exception& e)
989 {
990 log<level::ERR>("Failed to fetch pgood property",
Jason M. Bills3de424c2019-05-21 09:57:16 -0700991 entry("ERROR=%s", e.what()));
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700992 return std::nullopt;
993 }
994 }
995 return std::make_optional(powerGood);
996}
997
Yong Li70ce7352019-05-16 21:15:27 +0800998/*
999 * getACFailStatus
1000 * helper function for Get Chassis Status Command
1001 * return - bool value for ACFail (false on error)
1002 */
1003bool getACFailStatus()
1004{
1005 constexpr const char* powerControlObj =
1006 "/xyz/openbmc_project/Chassis/Control/Power0";
1007 constexpr const char* powerControlIntf =
1008 "xyz.openbmc_project.Chassis.Control.Power";
1009 bool acFail = false;
1010 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1011 try
1012 {
1013 auto service =
1014 ipmi::getService(*bus, powerControlIntf, powerControlObj);
1015
1016 ipmi::Value variant = ipmi::getDbusProperty(
1017 *bus, service, powerControlObj, powerControlIntf, "PFail");
1018 acFail = std::get<bool>(variant);
1019 }
1020 catch (const std::exception& e)
1021 {
1022 log<level::ERR>("Failed to fetch PFail property",
1023 entry("ERROR=%s", e.what()),
1024 entry("PATH=%s", powerControlObj),
1025 entry("INTERFACE=%s", powerControlIntf));
1026 }
1027 return acFail;
1028}
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001029} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +08001030
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001031static std::optional<bool> getButtonEnabled(const std::string& buttonPath,
1032 const std::string& buttonIntf)
1033{
1034 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
1035 bool buttonDisabled = false;
1036 try
1037 {
1038 auto service = ipmi::getService(*busp, buttonIntf, buttonPath);
1039 ipmi::Value enabled = ipmi::getDbusProperty(*busp, service, buttonPath,
1040 buttonIntf, "Enabled");
1041 buttonDisabled = !std::get<bool>(enabled);
1042 }
1043 catch (sdbusplus::exception::SdBusError& e)
1044 {
1045 log<level::ERR>("Fail to get button Enabled property",
1046 entry("PATH=%s", buttonPath.c_str()),
1047 entry("ERROR=%s", e.what()));
1048 return std::nullopt;
1049 }
1050 return std::make_optional(buttonDisabled);
1051}
1052
Kuiying Wang21addc52019-01-04 10:50:21 +08001053static bool setButtonEnabled(ipmi::Context::ptr& ctx,
1054 const std::string& buttonPath,
1055 const std::string& buttonIntf, bool enable)
1056{
1057 std::string service;
1058 boost::system::error_code ec;
1059 ec = ipmi::getService(ctx, buttonIntf, buttonPath, service);
1060 if (!ec)
1061 {
1062 ec = ipmi::setDbusProperty(ctx, service, buttonPath, buttonIntf,
1063 "Enabled", enable);
1064 }
1065 if (ec)
1066 {
1067 log<level::ERR>("Fail to set button Enabled property",
1068 entry("SERVICE=%s", service.c_str()),
1069 entry("PATH=%s", buttonPath.c_str()),
1070 entry("ERROR=%s", ec.message().c_str()));
1071 return false;
1072 }
1073 return true;
1074}
1075
Nan Lifdd8ec52016-08-28 03:57:40 +08001076//----------------------------------------------------------------------
1077// Get Chassis Status commands
1078//----------------------------------------------------------------------
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001079ipmi::RspType<bool, // Power is on
1080 bool, // Power overload
1081 bool, // Interlock
1082 bool, // power fault
1083 bool, // power control fault
1084 uint2_t, // power restore policy
1085 bool, // reserved
1086
1087 bool, // AC failed
1088 bool, // last power down caused by a Power overload
1089 bool, // last power down caused by a power interlock
1090 bool, // last power down caused by power fault
1091 bool, // last ‘Power is on’ state was entered via IPMI command
1092 uint3_t, // reserved
1093
1094 bool, // Chassis intrusion active
1095 bool, // Front Panel Lockout active
1096 bool, // Drive Fault
1097 bool, // Cooling/fan fault detected
1098 uint2_t, // Chassis Identify State
1099 bool, // Chassis Identify command and state info supported
1100 bool, // reserved
1101
1102 bool, // Power off button disabled
1103 bool, // Reset button disabled
1104 bool, // Diagnostic Interrupt button disabled
1105 bool, // Standby (sleep) button disabled
1106 bool, // Power off button disable allowed
1107 bool, // Reset button disable allowed
1108 bool, // Diagnostic Interrupt button disable allowed
1109 bool // Standby (sleep) button disable allowed
1110 >
1111 ipmiGetChassisStatus()
Nan Lifdd8ec52016-08-28 03:57:40 +08001112{
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001113 using namespace chassis::internal;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001114 std::optional<uint2_t> restorePolicy =
1115 power_policy::getPowerRestorePolicy();
1116 std::optional<bool> powerGood = power_policy::getPowerStatus();
1117 if (!restorePolicy || !powerGood)
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001118 {
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001119 return ipmi::responseUnspecifiedError();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001120 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001121
1122 // Front Panel Button Capabilities and disable/enable status(Optional)
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001123 std::optional<bool> powerButtonReading =
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001124 getButtonEnabled(powerButtonPath, powerButtonIntf);
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001125 // allow disable if the interface is present
1126 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
1127 // default return the button is enabled (not disabled)
1128 bool powerButtonDisabled = false;
1129 if (powerButtonDisableAllow)
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001130 {
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001131 // return the real value of the button status, if present
1132 powerButtonDisabled = *powerButtonReading;
1133 }
1134
1135 std::optional<bool> resetButtonReading =
1136 getButtonEnabled(resetButtonPath, resetButtonIntf);
1137 // allow disable if the interface is present
1138 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
1139 // default return the button is enabled (not disabled)
1140 bool resetButtonDisabled = false;
1141 if (resetButtonDisableAllow)
1142 {
1143 // return the real value of the button status, if present
1144 resetButtonDisabled = *resetButtonReading;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001145 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001146
Yong Li70ce7352019-05-16 21:15:27 +08001147 bool powerDownAcFailed = power_policy::getACFailStatus();
1148
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001149 // This response has a lot of hard-coded, unsupported fields
1150 // They are set to false or 0
1151 constexpr bool powerOverload = false;
1152 constexpr bool chassisInterlock = false;
1153 constexpr bool powerFault = false;
1154 constexpr bool powerControlFault = false;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001155 constexpr bool powerDownOverload = false;
1156 constexpr bool powerDownInterlock = false;
1157 constexpr bool powerDownPowerFault = false;
1158 constexpr bool powerStatusIPMI = false;
1159 constexpr bool chassisIntrusionActive = false;
1160 constexpr bool frontPanelLockoutActive = false;
1161 constexpr bool driveFault = false;
1162 constexpr bool coolingFanFault = false;
1163 // chassisIdentifySupport set because this command is implemented
1164 constexpr bool chassisIdentifySupport = true;
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001165 uint2_t chassisIdentifyState = types::enum_cast<uint2_t>(chassisIDState);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001166 constexpr bool diagButtonDisabled = false;
1167 constexpr bool sleepButtonDisabled = false;
1168 constexpr bool diagButtonDisableAllow = false;
1169 constexpr bool sleepButtonDisableAllow = false;
1170
1171 return ipmi::responseSuccess(
1172 *powerGood, powerOverload, chassisInterlock, powerFault,
1173 powerControlFault, *restorePolicy,
1174 false, // reserved
1175
1176 powerDownAcFailed, powerDownOverload, powerDownInterlock,
1177 powerDownPowerFault, powerStatusIPMI,
1178 uint3_t(0), // reserved
1179
1180 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
1181 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
1182 false, // reserved
1183
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001184 powerButtonDisabled, resetButtonDisabled, diagButtonDisabled,
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001185 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
1186 diagButtonDisableAllow, sleepButtonDisableAllow);
Nan Lifdd8ec52016-08-28 03:57:40 +08001187}
Chris Austen7888c4d2015-12-03 15:26:20 -06001188
Vijay Khemka074f64d2020-03-03 15:08:43 -08001189enum class IpmiRestartCause
1190{
1191 Unknown = 0x0,
1192 RemoteCommand = 0x1,
1193 ResetButton = 0x2,
1194 PowerButton = 0x3,
1195 WatchdogTimer = 0x4,
1196 PowerPolicyAlwaysOn = 0x6,
1197 PowerPolicyPreviousState = 0x7,
1198 SoftReset = 0xa,
1199};
1200
1201static IpmiRestartCause
1202 restartCauseToIpmiRestartCause(State::Host::RestartCause cause)
1203{
1204 switch (cause)
1205 {
1206 case State::Host::RestartCause::Unknown:
1207 {
1208 return IpmiRestartCause::Unknown;
1209 }
1210 case State::Host::RestartCause::RemoteCommand:
1211 {
1212 return IpmiRestartCause::RemoteCommand;
1213 }
1214 case State::Host::RestartCause::ResetButton:
1215 {
1216 return IpmiRestartCause::ResetButton;
1217 }
1218 case State::Host::RestartCause::PowerButton:
1219 {
1220 return IpmiRestartCause::PowerButton;
1221 }
1222 case State::Host::RestartCause::WatchdogTimer:
1223 {
1224 return IpmiRestartCause::WatchdogTimer;
1225 }
1226 case State::Host::RestartCause::PowerPolicyAlwaysOn:
1227 {
1228 return IpmiRestartCause::PowerPolicyAlwaysOn;
1229 }
1230 case State::Host::RestartCause::PowerPolicyPreviousState:
1231 {
1232 return IpmiRestartCause::PowerPolicyPreviousState;
1233 }
1234 case State::Host::RestartCause::SoftReset:
1235 {
1236 return IpmiRestartCause::SoftReset;
1237 }
1238 default:
1239 {
1240 return IpmiRestartCause::Unknown;
1241 }
1242 }
1243}
1244
1245/*
1246 * getRestartCause
1247 * helper function for Get Host restart cause Command
1248 * return - optional value for RestartCause (no value on error)
1249 */
1250static std::optional<uint4_t> getRestartCause(ipmi::Context::ptr ctx)
1251{
1252 constexpr const char* restartCausePath =
1253 "/xyz/openbmc_project/control/host0/restart_cause";
1254 constexpr const char* restartCauseIntf =
1255 "xyz.openbmc_project.Control.Host.RestartCause";
1256
1257 std::string service;
1258 boost::system::error_code ec =
1259 ipmi::getService(ctx, restartCauseIntf, restartCausePath, service);
1260 if (!ec)
1261 {
1262 std::string restartCauseStr;
1263 ec = ipmi::getDbusProperty<std::string>(
1264 ctx, service, restartCausePath, restartCauseIntf, "RestartCause",
1265 restartCauseStr);
1266 if (!ec)
1267 {
1268 auto cause =
1269 State::Host::convertRestartCauseFromString(restartCauseStr);
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001270 return types::enum_cast<uint4_t>(
1271 restartCauseToIpmiRestartCause(cause));
Vijay Khemka074f64d2020-03-03 15:08:43 -08001272 }
1273 }
1274
1275 log<level::ERR>("Failed to fetch RestartCause property",
1276 entry("ERROR=%s", ec.message().c_str()),
1277 entry("PATH=%s", restartCausePath),
1278 entry("INTERFACE=%s", restartCauseIntf));
1279 return std::nullopt;
1280}
1281
1282ipmi::RspType<uint4_t, // Restart Cause
1283 uint4_t, // reserved
1284 uint8_t // channel number (not supported)
1285 >
1286 ipmiGetSystemRestartCause(ipmi::Context::ptr ctx)
1287{
1288 std::optional<uint4_t> cause = getRestartCause(ctx);
1289 if (!cause)
1290 {
1291 return ipmi::responseUnspecifiedError();
1292 }
1293
Vernon Mauery916d4232021-03-29 13:42:16 -07001294 constexpr uint4_t reserved = 0;
1295 auto channel = static_cast<uint8_t>(ctx->channel);
1296 return ipmi::responseSuccess(cause.value(), reserved, channel);
Vijay Khemka074f64d2020-03-03 15:08:43 -08001297}
1298
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301299//-------------------------------------------------------------
1300// Send a command to SoftPowerOff application to stop any timer
1301//-------------------------------------------------------------
1302int stop_soft_off_timer()
1303{
Patrick Venture0b02be92018-08-31 11:55:55 -07001304 constexpr auto iface = "org.freedesktop.DBus.Properties";
1305 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
1306 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301307
Patrick Venture0b02be92018-08-31 11:55:55 -07001308 constexpr auto property = "ResponseReceived";
1309 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
1310 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301311
1312 // Get the system bus where most system services are provided.
1313 auto bus = ipmid_get_sd_bus_connection();
1314
1315 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001316 // TODO openbmc/openbmc#1661 - Mapper refactor
1317 //
1318 // See openbmc/openbmc#1743 for some details but high level summary is that
1319 // for now the code will directly call the soft off interface due to a
1320 // race condition with mapper usage
1321 //
Patrick Venture0b02be92018-08-31 11:55:55 -07001322 // char *busname = nullptr;
1323 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
1324 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001325 //{
1326 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301327 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001328 // return r;
1329 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301330
1331 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001332 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -07001333 "Set", nullptr, nullptr, "ssv", soft_off_iface,
1334 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301335 if (rc < 0)
1336 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301337 log<level::ERR>("Failed to set property in SoftPowerOff object",
1338 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301339 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001340
Patrick Venture0b02be92018-08-31 11:55:55 -07001341 // TODO openbmc/openbmc#1661 - Mapper refactor
1342 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301343 return rc;
1344}
1345
vishwa36993272015-11-20 12:43:49 -06001346//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001347// Create file to indicate there is no need for softoff notification to host
1348//----------------------------------------------------------------------
1349void indicate_no_softoff_needed()
1350{
1351 fs::path path{HOST_INBAND_REQUEST_DIR};
1352 if (!fs::is_directory(path))
1353 {
1354 fs::create_directory(path);
1355 }
1356
1357 // Add the host instance (default 0 for now) to the file name
1358 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001359 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001360 size++; // null
1361 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001362 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001363
1364 // Append file name to directory and create it
1365 path /= buf.get();
1366 std::ofstream(path.c_str());
1367}
1368
anil kumar appanadafff5f2019-04-27 18:06:00 +00001369/** @brief Implementation of chassis control command
1370 *
1371 * @param - chassisControl command byte
1372 *
1373 * @return Success or InvalidFieldRequest.
1374 */
1375ipmi::RspType<> ipmiChassisControl(uint8_t chassisControl)
vishwa36993272015-11-20 12:43:49 -06001376{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001377 int rc = 0;
anil kumar appanadafff5f2019-04-27 18:06:00 +00001378 switch (chassisControl)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001379 {
1380 case CMD_POWER_ON:
1381 rc = initiate_state_transition(State::Host::Transition::On);
1382 break;
1383 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301384 // This path would be hit in 2 conditions.
1385 // 1: When user asks for power off using ipmi chassis command 0x04
1386 // 2: Host asking for power off post shutting down.
1387
1388 // If it's a host requested power off, then need to nudge Softoff
1389 // application that it needs to stop the watchdog timer if running.
1390 // If it is a user requested power off, then this is not really
1391 // needed. But then we need to differentiate between user and host
1392 // calling this same command
1393
1394 // For now, we are going ahead with trying to nudge the soft off and
1395 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001396 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301397
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001398 // Only request the Off transition if the soft power off
1399 // application is not running
1400 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001401 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001402 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301403 // that it should not run. Not doing this will result in State
1404 // manager doing a default soft power off when asked for power
1405 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001406 indicate_no_softoff_needed();
1407
1408 // Now request the shutdown
1409 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001410 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001411 else
1412 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301413 log<level::INFO>("Soft off is running, so let shutdown target "
1414 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001415 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001416 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301417
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001418 case CMD_HARD_RESET:
1419 case CMD_POWER_CYCLE:
1420 // SPEC has a section that says certain implementations can trigger
1421 // PowerOn if power is Off when a command to power cycle is
1422 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001423
1424 // First create a file to indicate to the soft off application
1425 // that it should not run since this is a direct user initiated
1426 // power reboot request (i.e. a reboot request that is not
1427 // originating via a soft power off SMS request)
1428 indicate_no_softoff_needed();
1429
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001430 rc = initiate_state_transition(State::Host::Transition::Reboot);
1431 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301432
1433 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1434 // Request Host State Manager to do a soft power off
1435 rc = initiate_state_transition(State::Host::Transition::Off);
1436 break;
1437
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +08001438 case CMD_PULSE_DIAGNOSTIC_INTR:
1439 rc = setNmiProperty(true);
1440 break;
1441
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001442 default:
1443 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301444 log<level::ERR>("Invalid Chassis Control command",
anil kumar appanadafff5f2019-04-27 18:06:00 +00001445 entry("CMD=0x%X", chassisControl));
1446 return ipmi::responseInvalidFieldRequest();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001447 }
1448 }
vishwa36993272015-11-20 12:43:49 -06001449
anil kumar appanadafff5f2019-04-27 18:06:00 +00001450 return ((rc < 0) ? ipmi::responseUnspecifiedError()
1451 : ipmi::responseSuccess());
vishwa36993272015-11-20 12:43:49 -06001452}
1453
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001454/** @brief Return D-Bus connection string to enclosure identify LED object
1455 *
1456 * @param[in, out] connection - connection to D-Bus object
1457 * @return a IPMI return code
1458 */
1459std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301460{
Tom Joseph5110c122018-03-23 17:55:40 +05301461 // lookup enclosure_identify group owner(s) in mapper
1462 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001463 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1464 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301465
1466 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001467 static const std::vector<std::string> interfaces = {
1468 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301469 mapperCall.append(interfaces);
1470 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1471 if (mapperReply.is_method_error())
1472 {
1473 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001474 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301475 }
1476 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1477 mapperReply.read(mapperResp);
1478
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001479 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301480 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001481 log<level::ERR>(
1482 "Invalid number of enclosure identify objects.",
1483 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001484 elog<InternalFailure>();
1485 }
1486 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1487 return pair.first;
1488}
Tom Joseph5110c122018-03-23 17:55:40 +05301489
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001490/** @brief Turn On/Off enclosure identify LED
1491 *
1492 * @param[in] flag - true to turn on LED, false to turn off
1493 * @return a IPMI return code
1494 */
1495void enclosureIdentifyLed(bool flag)
1496{
1497 using namespace chassis::internal;
1498 std::string connection = std::move(getEnclosureIdentifyConnection());
Vernon Mauery400cc782018-10-09 13:49:53 -07001499 auto msg = std::string("enclosureIdentifyLed(") +
1500 boost::lexical_cast<std::string>(flag) + ")";
1501 log<level::DEBUG>(msg.c_str());
Patrick Venture0b02be92018-08-31 11:55:55 -07001502 auto led =
1503 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1504 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001505 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Vernon Mauery16b86932019-05-01 08:36:11 -07001506 std::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001507 auto ledReply = dbus.call(led);
1508 if (ledReply.is_method_error())
1509 {
1510 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001511 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001512 elog<InternalFailure>();
1513 }
1514}
1515
1516/** @brief Callback method to turn off LED
1517 */
1518void enclosureIdentifyLedOff()
1519{
1520 try
1521 {
Yong Lif4e38512019-05-21 14:46:55 +08001522 chassisIDState = ChassisIDState::off;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001523 enclosureIdentifyLed(false);
1524 }
1525 catch (const InternalFailure& e)
1526 {
1527 report<InternalFailure>();
1528 }
1529}
1530
1531/** @brief Create timer to turn on and off the enclosure LED
1532 */
1533void createIdentifyTimer()
1534{
1535 if (!identifyTimer)
1536 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001537 identifyTimer =
1538 std::make_unique<phosphor::Timer>(enclosureIdentifyLedOff);
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001539 }
1540}
1541
Vernon Mauery400cc782018-10-09 13:49:53 -07001542ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
1543 std::optional<uint8_t> force)
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001544{
Vernon Mauery400cc782018-10-09 13:49:53 -07001545 uint8_t identifyInterval = interval.value_or(DEFAULT_IDENTIFY_TIME_OUT);
1546 bool forceIdentify = force.value_or(0) & 0x01;
Tom Josephbed26992018-07-31 23:00:24 +05301547
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001548 if (identifyInterval || forceIdentify)
1549 {
Vernon Mauery400cc782018-10-09 13:49:53 -07001550 // stop the timer if already started;
1551 // for force identify we should not turn off LED
Vernon Mauery1181af72018-10-08 12:05:00 -07001552 identifyTimer->stop();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001553 try
Tom Joseph5110c122018-03-23 17:55:40 +05301554 {
Yong Lif4e38512019-05-21 14:46:55 +08001555 chassisIDState = ChassisIDState::temporaryOn;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001556 enclosureIdentifyLed(true);
1557 }
1558 catch (const InternalFailure& e)
1559 {
1560 report<InternalFailure>();
Vernon Mauery400cc782018-10-09 13:49:53 -07001561 return ipmi::responseResponseError();
Tom Joseph5110c122018-03-23 17:55:40 +05301562 }
1563
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001564 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301565 {
Yong Lif4e38512019-05-21 14:46:55 +08001566 chassisIDState = ChassisIDState::indefiniteOn;
Vernon Mauery400cc782018-10-09 13:49:53 -07001567 return ipmi::responseSuccess();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001568 }
1569 // start the timer
1570 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001571 std::chrono::seconds(identifyInterval));
Vernon Mauery1181af72018-10-08 12:05:00 -07001572 identifyTimer->start(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301573 }
Tom Josephbed26992018-07-31 23:00:24 +05301574 else if (!identifyInterval)
1575 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001576 identifyTimer->stop();
Tom Josephbed26992018-07-31 23:00:24 +05301577 enclosureIdentifyLedOff();
1578 }
Vernon Mauery400cc782018-10-09 13:49:53 -07001579 return ipmi::responseSuccess();
Tom Joseph5110c122018-03-23 17:55:40 +05301580}
1581
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001582namespace boot_options
1583{
1584
1585using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1586using IpmiValue = uint8_t;
1587constexpr auto ipmiDefault = 0;
1588
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001589std::map<IpmiValue, Type::Types> typeIpmiToDbus = {{0x00, Type::Types::Legacy},
1590 {0x01, Type::Types::EFI}};
1591
Patrick Venture0b02be92018-08-31 11:55:55 -07001592std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001593 {0x01, Source::Sources::Network},
1594 {0x02, Source::Sources::Disk},
1595 {0x05, Source::Sources::ExternalMedia},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001596 {0x0f, Source::Sources::RemovableMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001597 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001598
Patrick Venture0b02be92018-08-31 11:55:55 -07001599std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Yong Li5833cb62019-10-30 13:27:12 +08001600#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001601 {0x03, Mode::Modes::Safe},
Yong Li5833cb62019-10-30 13:27:12 +08001602#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001603 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001604 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001605
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001606std::map<Type::Types, IpmiValue> typeDbusToIpmi = {{Type::Types::Legacy, 0x00},
1607 {Type::Types::EFI, 0x01}};
1608
Patrick Venture0b02be92018-08-31 11:55:55 -07001609std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001610 {Source::Sources::Network, 0x01},
1611 {Source::Sources::Disk, 0x02},
1612 {Source::Sources::ExternalMedia, 0x05},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001613 {Source::Sources::RemovableMedia, 0x0f},
Patrick Venture0b02be92018-08-31 11:55:55 -07001614 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001615
Patrick Venture0b02be92018-08-31 11:55:55 -07001616std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Yong Li5833cb62019-10-30 13:27:12 +08001617#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001618 {Mode::Modes::Safe, 0x03},
Yong Li5833cb62019-10-30 13:27:12 +08001619#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001620 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001621 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001622
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001623} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001624
Marri Devender Rao81719702018-05-07 00:53:48 -05001625/** @brief Set the property value for boot source
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001626 * @param[in] ctx - context pointer
Marri Devender Rao81719702018-05-07 00:53:48 -05001627 * @param[in] source - boot source value
1628 * @return On failure return IPMI error.
1629 */
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001630static ipmi_ret_t setBootSource(ipmi::Context::ptr& ctx,
1631 const Source::Sources& source)
Marri Devender Rao81719702018-05-07 00:53:48 -05001632{
1633 using namespace chassis::internal;
1634 using namespace chassis::internal::cache;
James Feist225dec82019-11-26 16:25:06 -08001635 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001636 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1637 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001638 boost::system::error_code ec = ipmi::setDbusProperty(
1639 ctx, objects.service(bootSourceSetting, bootSourceIntf),
1640 bootSourceSetting, bootSourceIntf, "BootSource",
1641 convertForMessage(source));
1642 if (ec)
Marri Devender Rao81719702018-05-07 00:53:48 -05001643 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001644 log<level::ERR>("Error in BootSource Set",
1645 entry("ERROR=%s", ec.message().c_str()));
1646 return ipmi::ccUnspecifiedError;
Marri Devender Rao81719702018-05-07 00:53:48 -05001647 }
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001648 return ipmi::ccSuccess;
Marri Devender Rao81719702018-05-07 00:53:48 -05001649}
1650
Patrick Venture0b02be92018-08-31 11:55:55 -07001651/** @brief Set the property value for boot mode
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001652 * @param[in] ctx - context pointer
Marri Devender Rao81719702018-05-07 00:53:48 -05001653 * @param[in] mode - boot mode value
1654 * @return On failure return IPMI error.
1655 */
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001656static ipmi::Cc setBootMode(ipmi::Context::ptr& ctx, const Mode::Modes& mode)
Marri Devender Rao81719702018-05-07 00:53:48 -05001657{
1658 using namespace chassis::internal;
1659 using namespace chassis::internal::cache;
James Feist225dec82019-11-26 16:25:06 -08001660 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001661 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1662 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001663 boost::system::error_code ec = ipmi::setDbusProperty(
1664 ctx, objects.service(bootModeSetting, bootModeIntf), bootModeSetting,
1665 bootModeIntf, "BootMode", convertForMessage(mode));
1666 if (ec)
Marri Devender Rao81719702018-05-07 00:53:48 -05001667 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001668 log<level::ERR>("Error in BootMode Set",
1669 entry("ERROR=%s", ec.message().c_str()));
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001670 return ipmi::ccUnspecifiedError;
Marri Devender Rao81719702018-05-07 00:53:48 -05001671 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001672 return ipmi::ccSuccess;
Marri Devender Rao81719702018-05-07 00:53:48 -05001673}
1674
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001675/** @brief Set the property value for boot type
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001676 * @param[in] ctx - context pointer
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001677 * @param[in] type - boot type value
1678 * @return On failure return IPMI error.
1679 */
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001680static ipmi::Cc setBootType(ipmi::Context::ptr& ctx, const Type::Types& type)
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001681{
1682 using namespace chassis::internal;
1683 using namespace chassis::internal::cache;
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001684 settings::Objects& objects = getObjects();
1685 std::tuple<settings::Path, settings::boot::OneTimeEnabled> bootSetting;
1686 try
1687 {
1688 bootSetting = settings::boot::setting(objects, bootTypeIntf);
1689 }
1690 catch (const std::exception& e)
1691 {
1692 // Return immediately if BootType interface is not present.
1693 // This interface is not relevant for some Host architectures
1694 // (for example POWER). In this case we don't won't IPMI to
1695 // return an error, but want to just skip this function.
1696 return ipmi::ccSuccess;
1697 }
1698 const auto& bootTypeSetting = std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001699 boost::system::error_code ec = ipmi::setDbusProperty(
1700 ctx, objects.service(bootTypeSetting, bootTypeIntf), bootTypeSetting,
1701 bootTypeIntf, "BootType", convertForMessage(type));
1702 if (ec)
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001703 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001704 log<level::ERR>("Error in BootType Set",
1705 entry("ERROR=%s", ec.message().c_str()));
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001706 return ipmi::ccUnspecifiedError;
1707 }
1708 return ipmi::ccSuccess;
1709}
1710
huangheab369282020-10-10 14:40:00 +08001711static constexpr uint8_t setComplete = 0x0;
1712static constexpr uint8_t setInProgress = 0x1;
1713static uint8_t transferStatus = setComplete;
Chen Yugang86ac4992021-06-25 08:14:52 +08001714static uint8_t bootFlagValidBitClr = 0;
huangheab369282020-10-10 14:40:00 +08001715
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001716/** @brief implements the Get Chassis system boot option
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001717 * @param ctx - context pointer
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001718 * @param bootOptionParameter - boot option parameter selector
1719 * @param reserved1 - reserved bit
1720 * @param setSelector - selects a particular block or set of parameters
1721 * under the given parameter selector
1722 * write as 00h if parameter doesn't use a setSelector
1723 * @param blockSelector- selects a particular block within a set of
1724 * parameters write as 00h if parameter doesn't use a
1725 * blockSelector
1726 *
1727 * @return IPMI completion code plus response data
1728 * @return Payload contains below parameters:
1729 * version - parameter version
1730 * bootOptionParameter - boot option parameter selector
Patrick Venture8b1c3032020-09-15 09:43:03 -07001731 * parmIndicator - parameter valid/invalid indicator
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001732 * data - configuration parameter data
1733 */
1734ipmi::RspType<ipmi::message::Payload>
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001735 ipmiChassisGetSysBootOptions(ipmi::Context::ptr ctx,
1736 uint7_t bootOptionParameter, bool reserved1,
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001737
1738 uint8_t setSelector, uint8_t blockSelector)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001739{
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001740 if (reserved1)
1741 {
1742 return ipmi::responseInvalidFieldRequest();
1743 }
1744
1745 constexpr uint4_t version = 0x01;
1746 ipmi::message::Payload response;
1747 response.pack(version, uint4_t{});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001748 using namespace boot_options;
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001749
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001750 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001751
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001752 if (types::enum_cast<BootOptionParameter>(bootOptionParameter) ==
1753 BootOptionParameter::setInProgress)
huangheab369282020-10-10 14:40:00 +08001754 {
1755 response.pack(bootOptionParameter, reserved1, transferStatus);
1756 return ipmi::responseSuccess(std::move(response));
1757 }
1758
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001759 if (types::enum_cast<BootOptionParameter>(bootOptionParameter) ==
1760 BootOptionParameter::bootInfo)
John Wang0213f902020-12-28 14:49:57 +08001761 {
1762 constexpr uint8_t writeMask = 0;
1763 constexpr uint8_t bootInfoAck = 0;
1764 response.pack(bootOptionParameter, writeMask, bootInfoAck);
1765 return ipmi::responseSuccess(std::move(response));
1766 }
1767
Chen Yugang86ac4992021-06-25 08:14:52 +08001768 if (types::enum_cast<BootOptionParameter>(bootOptionParameter) ==
1769 BootOptionParameter::bootFlagValidClr)
1770 {
1771 response.pack(bootOptionParameter, reserved1,
1772 uint5_t{bootFlagValidBitClr}, uint3_t{});
1773 return ipmi::responseSuccess(std::move(response));
1774 }
1775
shgoupfd84fbbf2015-12-17 10:05:51 +08001776 /*
1777 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1778 * This is the only parameter used by petitboot.
1779 */
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001780 if (types::enum_cast<BootOptionParameter>(bootOptionParameter) ==
1781 BootOptionParameter::bootFlags)
Patrick Venture0b02be92018-08-31 11:55:55 -07001782 {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001783 using namespace chassis::internal;
1784 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001785
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001786 try
ratagupta6f6bff2016-04-04 06:20:11 -05001787 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001788 std::string result;
1789 boost::system::error_code ec;
James Feist225dec82019-11-26 16:25:06 -08001790 settings::Objects& objects = getObjects();
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001791
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001792 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1793 const auto& bootSourceSetting =
1794 std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001795 ec = ipmi::getDbusProperty(
1796 ctx, objects.service(bootSourceSetting, bootSourceIntf),
1797 bootSourceSetting, bootSourceIntf, "BootSource", result);
1798 if (ec)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001799 {
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001800 log<level::ERR>(
1801 "ipmiChassisGetSysBootOptions: Error in BootSource Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001802 report<InternalFailure>();
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001803 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001804 }
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001805 auto bootSource = Source::convertSourcesFromString(result);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001806
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001807 Type::Types bootType;
1808 bool bootTypeIntfPresent = true;
1809 try
1810 {
1811 bootSetting = settings::boot::setting(objects, bootTypeIntf);
1812 }
1813 catch (const std::exception& e)
1814 {
1815 bootTypeIntfPresent = false;
1816 }
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001817 if (bootTypeIntfPresent)
1818 {
1819 const auto& bootTypeSetting =
1820 std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001821 ec = ipmi::getDbusProperty(
1822 ctx, objects.service(bootTypeSetting, bootTypeIntf),
1823 bootTypeSetting, bootTypeIntf, "BootType", result);
1824 if (ec)
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001825 {
1826 log<level::ERR>(
1827 "ipmiChassisGetSysBootOptions: Error in BootType Get");
1828 report<InternalFailure>();
1829 return ipmi::responseUnspecifiedError();
1830 }
1831 else
1832 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001833 bootType = Type::convertTypesFromString(result);
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001834 }
1835 }
1836 else
1837 {
1838 bootType = Type::Types::EFI;
1839 }
1840
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001841 bootSetting = settings::boot::setting(objects, bootModeIntf);
1842 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001843 ec = ipmi::getDbusProperty(
1844 ctx, objects.service(bootModeSetting, bootModeIntf),
1845 bootModeSetting, bootModeIntf, "BootMode", result);
1846 if (ec)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001847 {
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001848 log<level::ERR>(
1849 "ipmiChassisGetSysBootOptions: Error in BootMode Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001850 report<InternalFailure>();
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001851 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001852 }
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001853 auto bootMode = Mode::convertModesFromString(result);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001854
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001855 bootOption = sourceDbusToIpmi.at(bootSource);
1856 if ((Mode::Modes::Regular == bootMode) &&
1857 (Source::Sources::Default == bootSource))
1858 {
1859 bootOption = ipmiDefault;
1860 }
1861 else if (Source::Sources::Default == bootSource)
1862 {
1863 bootOption = modeDbusToIpmi.at(bootMode);
1864 }
ratagupta6f6bff2016-04-04 06:20:11 -05001865
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001866 IpmiValue biosBootType = typeDbusToIpmi.at(bootType);
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03001867 auto oneTimeEnabled =
1868 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03001869 uint1_t permanent = oneTimeEnabled ? 0 : 1;
1870 uint1_t validFlag = 1;
1871
1872 response.pack(bootOptionParameter, reserved1, uint5_t{},
1873 uint1_t{biosBootType}, uint1_t{permanent},
1874 uint1_t{validFlag}, uint2_t{}, uint4_t{bootOption},
1875 uint2_t{}, uint8_t{}, uint8_t{}, uint8_t{});
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001876 return ipmi::responseSuccess(std::move(response));
ratagupta6f6bff2016-04-04 06:20:11 -05001877 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001878 catch (InternalFailure& e)
1879 {
James Feist225dec82019-11-26 16:25:06 -08001880 cache::objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001881 report<InternalFailure>();
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001882 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001883 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001884 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001885 else
1886 {
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001887 if ((bootOptionParameter >= oemParmStart) &&
1888 (bootOptionParameter <= oemParmEnd))
1889 {
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001890 if (types::enum_cast<BootOptionParameter>(bootOptionParameter) ==
1891 BootOptionParameter::opalNetworkSettings)
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001892 {
1893 response.pack(bootOptionParameter, reserved1);
1894 int ret = getHostNetworkData(response);
1895 if (ret < 0)
1896 {
1897 response.trailingOk = true;
1898 log<level::ERR>(
1899 "getHostNetworkData failed for GetSysBootOptions.");
1900 return ipmi::responseUnspecifiedError();
1901 }
1902 else
1903 {
1904 return ipmi::responseSuccess(std::move(response));
1905 }
1906 }
1907 }
1908 else
1909 {
1910 log<level::ERR>(
1911 "ipmiChassisGetSysBootOptions: Unsupported parameter",
1912 entry("PARAM=0x%x", static_cast<uint8_t>(bootOptionParameter)));
1913 return ipmi::responseUnspecifiedError();
1914 }
shgoupfd84fbbf2015-12-17 10:05:51 +08001915 }
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00001916 return ipmi::responseUnspecifiedError();
shgoupfd84fbbf2015-12-17 10:05:51 +08001917}
1918
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001919ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
1920 uint7_t parameterSelector,
1921 bool parameterIsValid,
1922 ipmi::message::Payload& data)
shgoupfd84fbbf2015-12-17 10:05:51 +08001923{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001924 using namespace boot_options;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001925 ipmi::Cc rc;
shgoupfd84fbbf2015-12-17 10:05:51 +08001926
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001927 if (types::enum_cast<BootOptionParameter>(parameterSelector) ==
1928 BootOptionParameter::setInProgress)
huangheab369282020-10-10 14:40:00 +08001929 {
1930 uint2_t setInProgressFlag;
1931 uint6_t rsvd;
1932 if (data.unpack(setInProgressFlag, rsvd) != 0 || !data.fullyUnpacked())
1933 {
1934 return ipmi::responseReqDataLenInvalid();
1935 }
1936 if (rsvd)
1937 {
1938 return ipmi::responseInvalidFieldRequest();
1939 }
1940 if ((transferStatus == setInProgress) &&
1941 (static_cast<uint8_t>(setInProgressFlag) != setComplete))
1942 {
1943 return ipmi::response(IPMI_CC_FAIL_SET_IN_PROGRESS);
1944 }
1945 transferStatus = static_cast<uint8_t>(setInProgressFlag);
1946 return ipmi::responseSuccess();
1947 }
1948
shgoupfd84fbbf2015-12-17 10:05:51 +08001949 /* 000101
1950 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1951 * This is the only parameter used by petitboot.
1952 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001953
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07001954 if (types::enum_cast<BootOptionParameter>(parameterSelector) ==
1955 BootOptionParameter::bootFlags)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001956 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001957 uint5_t rsvd;
1958 bool validFlag;
1959 bool permanent;
1960 bool biosBootType;
1961 bool lockOutResetButton;
1962 bool screenBlank;
1963 uint4_t bootDeviceSelector;
1964 bool lockKeyboard;
1965 bool cmosClear;
1966 uint8_t data3;
1967 uint4_t biosInfo;
1968 uint4_t rsvd1;
1969 uint5_t deviceInstance;
1970 uint3_t rsvd2;
1971
1972 if (data.unpack(rsvd, biosBootType, permanent, validFlag,
1973 lockOutResetButton, screenBlank, bootDeviceSelector,
1974 lockKeyboard, cmosClear, data3, biosInfo, rsvd1,
1975 deviceInstance, rsvd2) != 0 ||
1976 !data.fullyUnpacked())
1977 {
1978 return ipmi::responseReqDataLenInvalid();
1979 }
1980 if (rsvd || rsvd1 || rsvd2)
1981 {
1982 return ipmi::responseInvalidFieldRequest();
1983 }
1984
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001985 using namespace chassis::internal;
1986 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001987 auto oneTimeEnabled = false;
1988 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301989 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001990 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001991
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001992 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001993 {
James Feist225dec82019-11-26 16:25:06 -08001994 settings::Objects& objects = getObjects();
1995
Patrick Venture0b02be92018-08-31 11:55:55 -07001996 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301997
1998 oneTimeEnabled =
1999 std::get<settings::boot::OneTimeEnabled>(bootSetting);
2000
2001 /*
2002 * Check if the current boot setting is onetime or permanent, if the
2003 * request in the command is otherwise, then set the "Enabled"
2004 * property in one_time object path to 'True' to indicate onetime
2005 * and 'False' to indicate permanent.
2006 *
2007 * Once the onetime/permanent setting is applied, then the bootMode
2008 * and bootSource is updated for the corresponding object.
2009 */
2010 if ((permanent && oneTimeEnabled) ||
2011 (!permanent && !oneTimeEnabled))
2012 {
2013 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
2014
Patrick Venture0b02be92018-08-31 11:55:55 -07002015 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
2016 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05302017 }
2018
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002019 auto modeItr =
2020 modeIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03002021 auto typeItr =
2022 typeIpmiToDbus.find(static_cast<uint8_t>(biosBootType));
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002023 auto sourceItr =
2024 sourceIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002025 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05002026 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03002027 rc = setBootSource(ctx, sourceItr->second);
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002028 if (rc != ipmi::ccSuccess)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002029 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002030 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002031 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002032 // If a set boot device is mapping to a boot source, then reset
2033 // the boot mode D-Bus property to default.
2034 // This way the ipmid code can determine which property is not
2035 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07002036 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002037 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03002038 setBootMode(ctx, Mode::Modes::Regular);
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002039 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002040 }
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03002041
2042 if (typeIpmiToDbus.end() != typeItr)
2043 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03002044 rc = setBootType(ctx, typeItr->second);
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03002045 if (rc != ipmi::ccSuccess)
2046 {
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03002047 return ipmi::responseUnspecifiedError();
2048 }
2049 }
2050
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002051 if (modeIpmiToDbus.end() != modeItr)
2052 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03002053 rc = setBootMode(ctx, modeItr->second);
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002054 if (rc != ipmi::ccSuccess)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002055 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002056 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002057 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002058 // If a set boot device is mapping to a boot mode, then reset
2059 // the boot source D-Bus property to default.
2060 // This way the ipmid code can determine which property is not
2061 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07002062 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002063 {
Konstantin Aladysheve76a61a2021-03-18 22:19:13 +03002064 setBootSource(ctx, Source::Sources::Default);
Marri Devender Rao54fa1302018-05-07 01:06:23 -05002065 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05002066 }
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08002067 if ((modeIpmiToDbus.end() == modeItr) &&
Konstantin Aladyshev96ef0282021-02-09 13:57:10 +03002068 (typeIpmiToDbus.end() == typeItr) &&
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08002069 (sourceIpmiToDbus.end() == sourceItr))
2070 {
2071 // return error if boot option is not supported
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002072 log<level::ERR>(
2073 "ipmiChassisSetSysBootOptions: Boot option not supported");
2074 return ipmi::responseInvalidFieldRequest();
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08002075 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05002076 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002077 catch (sdbusplus::exception_t& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05002078 {
James Feist225dec82019-11-26 16:25:06 -08002079 objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05002080 report<InternalFailure>();
Aditya Saripalli5fb14602017-11-09 14:46:27 +05302081 log<level::ERR>(
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002082 "ipmiChassisSetSysBootOptions: Error in setting Boot "
2083 "flag parameters");
2084 return ipmi::responseUnspecifiedError();
Ratan Guptafd28dd72016-08-01 04:58:01 -05002085 }
Patrick Venture0b02be92018-08-31 11:55:55 -07002086 }
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07002087 else if (types::enum_cast<BootOptionParameter>(parameterSelector) ==
2088 BootOptionParameter::bootInfo)
Patrick Venture0b02be92018-08-31 11:55:55 -07002089 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002090 uint8_t writeMak;
2091 uint5_t bootInitiatorAckData;
2092 uint3_t rsvd;
2093
2094 if (data.unpack(writeMak, bootInitiatorAckData, rsvd) != 0 ||
2095 !data.fullyUnpacked())
2096 {
2097 return ipmi::responseReqDataLenInvalid();
2098 }
2099 if (rsvd)
2100 {
2101 return ipmi::responseInvalidFieldRequest();
2102 }
2103 // (ccSuccess). There is no implementation in OpenBMC for this
Tom Josephf536c902017-09-25 18:08:15 +05302104 // parameter. This is added to support the ipmitool command `chassis
2105 // bootdev` which sends set on parameter #4, before setting the boot
2106 // flags.
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002107 log<level::INFO>("ipmiChassisSetSysBootOptions: bootInfo parameter set "
2108 "successfully");
2109 data.trailingOk = true;
2110 return ipmi::responseSuccess();
Patrick Venture0b02be92018-08-31 11:55:55 -07002111 }
Chen Yugang86ac4992021-06-25 08:14:52 +08002112 else if (types::enum_cast<BootOptionParameter>(parameterSelector) ==
2113 BootOptionParameter::bootFlagValidClr)
2114 {
2115 uint5_t bootFlagValidClr;
2116 uint3_t rsvd;
2117
2118 if (data.unpack(bootFlagValidClr, rsvd) != 0 || !data.fullyUnpacked())
2119 {
2120 return ipmi::responseReqDataLenInvalid();
2121 }
2122 if (rsvd)
2123 {
2124 return ipmi::responseInvalidFieldRequest();
2125 }
2126 // store boot flag valid bits clear value
2127 bootFlagValidBitClr = static_cast<uint8_t>(bootFlagValidClr);
2128 log<level::INFO>(
2129 "ipmiChassisSetSysBootOptions: bootFlagValidBits parameter set "
2130 "successfully",
2131 entry("value=0x%x", bootFlagValidBitClr));
2132 return ipmi::responseSuccess();
2133 }
Patrick Venture0b02be92018-08-31 11:55:55 -07002134 else
2135 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002136 if ((parameterSelector >= static_cast<uint7_t>(oemParmStart)) &&
2137 (parameterSelector <= static_cast<uint7_t>(oemParmEnd)))
2138 {
William A. Kennington III7a0e5df2021-05-19 13:31:29 -07002139 if (types::enum_cast<BootOptionParameter>(parameterSelector) ==
2140 BootOptionParameter::opalNetworkSettings)
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002141 {
2142 ipmi::Cc ret = setHostNetworkData(data);
2143 if (ret != ipmi::ccSuccess)
2144 {
2145 log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
2146 "setHostNetworkData");
2147 data.trailingOk = true;
2148 return ipmi::response(ret);
2149 }
2150 data.trailingOk = true;
2151 return ipmi::responseSuccess();
2152 }
2153 else
2154 {
2155 log<level::ERR>(
2156 "ipmiChassisSetSysBootOptions: Unsupported parameters",
2157 entry("PARAM=0x%x",
2158 static_cast<uint8_t>(parameterSelector)));
2159 data.trailingOk = true;
2160 return ipmi::responseParmNotSupported();
2161 }
2162 }
2163 data.trailingOk = true;
2164 return ipmi::responseParmNotSupported();
Adriana Kobylak40814c62015-10-27 15:58:44 -05002165 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002166 return ipmi::responseSuccess();
Adriana Kobylak40814c62015-10-27 15:58:44 -05002167}
2168
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002169/** @brief implements Get POH counter command
2170 * @parameter
2171 * - none
2172 * @returns IPMI completion code plus response data
2173 * - minPerCount - Minutes per count
2174 * - counterReading - counter reading
2175 */
2176ipmi::RspType<uint8_t, // Minutes per count
2177 uint32_t // Counter reading
2178 >
2179 ipmiGetPOHCounter()
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002180{
2181 // sd_bus error
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002182 try
2183 {
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002184 return ipmi::responseSuccess(static_cast<uint8_t>(poh::minutesPerCount),
2185 getPOHCounter());
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002186 }
2187 catch (std::exception& e)
2188 {
2189 log<level::ERR>(e.what());
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002190 return ipmi::responseUnspecifiedError();
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002191 }
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002192}
2193
Jason M. Billsbc996a32019-06-17 15:46:37 -07002194ipmi::RspType<uint3_t, // policy support
2195 uint5_t // reserved
2196 >
Vernon Mauerye278ead2018-10-09 09:23:43 -07002197 ipmiChassisSetPowerRestorePolicy(boost::asio::yield_context yield,
Jason M. Billsbc996a32019-06-17 15:46:37 -07002198 uint3_t policy, uint5_t reserved)
Yong Lic6713cf2018-09-12 12:35:13 +08002199{
Yong Lic6713cf2018-09-12 12:35:13 +08002200 power_policy::DbusValue value =
2201 power_policy::RestorePolicy::Policy::AlwaysOff;
2202
Jason M. Billsbc996a32019-06-17 15:46:37 -07002203 if (reserved || (policy > power_policy::noChange))
Yong Lic6713cf2018-09-12 12:35:13 +08002204 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07002205 phosphor::logging::log<level::ERR>(
2206 "Reserved request parameter",
2207 entry("REQ=0x%x", static_cast<int>(policy)));
Jason M. Billsbc996a32019-06-17 15:46:37 -07002208 return ipmi::responseInvalidFieldRequest();
Yong Lic6713cf2018-09-12 12:35:13 +08002209 }
2210
Vernon Mauerye278ead2018-10-09 09:23:43 -07002211 if (policy == power_policy::noChange)
Yong Lic6713cf2018-09-12 12:35:13 +08002212 {
2213 // just return the supported policy
Jason M. Billsbc996a32019-06-17 15:46:37 -07002214 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08002215 }
2216
2217 for (auto const& it : power_policy::dbusToIpmi)
2218 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07002219 if (it.second == policy)
Yong Lic6713cf2018-09-12 12:35:13 +08002220 {
2221 value = it.first;
2222 break;
2223 }
2224 }
2225
2226 try
2227 {
James Feist225dec82019-11-26 16:25:06 -08002228 settings::Objects& objects = chassis::internal::cache::getObjects();
Yong Lic6713cf2018-09-12 12:35:13 +08002229 const settings::Path& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -08002230 objects.map.at(chassis::internal::powerRestoreIntf).front();
Vernon Mauery16b86932019-05-01 08:36:11 -07002231 std::variant<std::string> property = convertForMessage(value);
Yong Lic6713cf2018-09-12 12:35:13 +08002232
Vernon Mauerye278ead2018-10-09 09:23:43 -07002233 auto sdbusp = getSdBus();
2234 boost::system::error_code ec;
2235 sdbusp->yield_method_call<void>(
2236 yield, ec,
James Feist225dec82019-11-26 16:25:06 -08002237 objects
Yong Lic6713cf2018-09-12 12:35:13 +08002238 .service(powerRestoreSetting,
2239 chassis::internal::powerRestoreIntf)
2240 .c_str(),
Vernon Mauerye278ead2018-10-09 09:23:43 -07002241 powerRestoreSetting, ipmi::PROP_INTF, "Set",
2242 chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
2243 property);
2244 if (ec)
Yong Lic6713cf2018-09-12 12:35:13 +08002245 {
2246 phosphor::logging::log<level::ERR>("Unspecified Error");
Vernon Mauerye278ead2018-10-09 09:23:43 -07002247 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08002248 }
2249 }
2250 catch (InternalFailure& e)
2251 {
James Feist225dec82019-11-26 16:25:06 -08002252 chassis::internal::cache::objectsPtr.reset();
Yong Lic6713cf2018-09-12 12:35:13 +08002253 report<InternalFailure>();
Vernon Mauerye278ead2018-10-09 09:23:43 -07002254 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08002255 }
2256
Jason M. Billsbc996a32019-06-17 15:46:37 -07002257 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08002258}
2259
Kuiying Wang21addc52019-01-04 10:50:21 +08002260ipmi::RspType<> ipmiSetFrontPanelButtonEnables(
2261 ipmi::Context::ptr ctx, bool disablePowerButton, bool disableResetButton,
2262 bool disableDiagButton, bool disableSleepButton, uint4_t reserved)
2263{
2264 using namespace chassis::internal;
2265
2266 // set power button Enabled property
2267 bool success = setButtonEnabled(ctx, powerButtonPath, powerButtonIntf,
2268 !disablePowerButton);
2269
2270 // set reset button Enabled property
2271 success &= setButtonEnabled(ctx, resetButtonPath, resetButtonIntf,
2272 !disableResetButton);
2273
2274 if (!success)
2275 {
2276 // not all buttons were successfully set
2277 return ipmi::responseUnspecifiedError();
2278 }
2279 return ipmi::responseSuccess();
2280}
2281
Adriana Kobylak40814c62015-10-27 15:58:44 -05002282void register_netfn_chassis_functions()
2283{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05002284 createIdentifyTimer();
2285
Tom05732372016-09-06 17:21:23 +05302286 // Get Chassis Capabilities
anil kumar appana43263c62019-05-27 12:45:04 +00002287 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2288 ipmi::chassis::cmdGetChassisCapabilities,
2289 ipmi::Privilege::User, ipmiGetChassisCap);
Nan Li8d15fb42016-08-16 22:29:40 +08002290
Kuiying Wang21addc52019-01-04 10:50:21 +08002291 // Set Front Panel Button Enables
2292 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2293 ipmi::chassis::cmdSetFrontPanelButtonEnables,
2294 ipmi::Privilege::Admin,
2295 ipmiSetFrontPanelButtonEnables);
2296
Yong Liae4b0402018-11-02 11:12:14 +08002297 // Set Chassis Capabilities
anil kumar appana894d0222019-05-27 16:32:14 +00002298 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2299 ipmi::chassis::cmdSetChassisCapabilities,
2300 ipmi::Privilege::User, ipmiSetChassisCap);
Yong Liae4b0402018-11-02 11:12:14 +08002301
Tom05732372016-09-06 17:21:23 +05302302 // <Get System Boot Options>
Jayaprakash Mutyalad1ef8772020-08-25 10:32:58 +00002303 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2304 ipmi::chassis::cmdGetSystemBootOptions,
2305 ipmi::Privilege::Operator,
2306 ipmiChassisGetSysBootOptions);
Adriana Kobylak40814c62015-10-27 15:58:44 -05002307
Tom05732372016-09-06 17:21:23 +05302308 // <Get Chassis Status>
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07002309 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2310 ipmi::chassis::cmdGetChassisStatus,
2311 ipmi::Privilege::User, ipmiGetChassisStatus);
Nan Lifdd8ec52016-08-28 03:57:40 +08002312
Vijay Khemka074f64d2020-03-03 15:08:43 -08002313 // <Chassis Get System Restart Cause>
2314 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2315 ipmi::chassis::cmdGetSystemRestartCause,
2316 ipmi::Privilege::User, ipmiGetSystemRestartCause);
2317
Tom05732372016-09-06 17:21:23 +05302318 // <Chassis Control>
anil kumar appanadafff5f2019-04-27 18:06:00 +00002319 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2320 ipmi::chassis::cmdChassisControl,
2321 ipmi::Privilege::Operator, ipmiChassisControl);
shgoupfd84fbbf2015-12-17 10:05:51 +08002322
Tom Joseph5110c122018-03-23 17:55:40 +05302323 // <Chassis Identify>
Vernon Mauery400cc782018-10-09 13:49:53 -07002324 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2325 ipmi::chassis::cmdChassisIdentify,
2326 ipmi::Privilege::Operator, ipmiChassisIdentify);
Tom Joseph5110c122018-03-23 17:55:40 +05302327
Tom05732372016-09-06 17:21:23 +05302328 // <Set System Boot Options>
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002329 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2330 ipmi::chassis::cmdSetSystemBootOptions,
2331 ipmi::Privilege::Operator,
2332 ipmiChassisSetSysBootOptions);
2333
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002334 // <Get POH Counter>
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002335 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2336 ipmi::chassis::cmdGetPohCounter,
2337 ipmi::Privilege::User, ipmiGetPOHCounter);
Yong Lic6713cf2018-09-12 12:35:13 +08002338
2339 // <Set Power Restore Policy>
Vernon Mauerye278ead2018-10-09 09:23:43 -07002340 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2341 ipmi::chassis::cmdSetPowerRestorePolicy,
2342 ipmi::Privilege::Operator,
2343 ipmiChassisSetPowerRestorePolicy);
vishwa36993272015-11-20 12:43:49 -06002344}