blob: 28cb756f28735af9e83ea3dd7ef7abbb610b5a8e [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>
33#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
34#include <xyz/openbmc_project/State/Host/server.hpp>
35#include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
36
Lei YU4b0ddb62019-01-25 16:43:50 +080037std::unique_ptr<phosphor::Timer> identifyTimer
38 __attribute__((init_priority(101)));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050039
Yong Lif4e38512019-05-21 14:46:55 +080040static ChassisIDState chassisIDState = ChassisIDState::reserved;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000041static constexpr uint8_t setParmVersion = 0x01;
42static constexpr uint8_t setParmBootFlagsPermanent = 0x40;
43static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80;
44static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0;
Yong Lif4e38512019-05-21 14:46:55 +080045
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000046constexpr size_t SIZE_BOOT_OPTION = static_cast<size_t>(
47 BootOptionResponseSize::opalNetworkSettings); // Maximum size of the boot
48 // option parameters
49constexpr size_t sizeVersion = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053050constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053051
Patrick Venture0b02be92018-08-31 11:55:55 -070052// PetiBoot-Specific
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000053static constexpr uint8_t netConfInitialBytes[] = {0x80, 0x21, 0x70, 0x62,
54 0x21, 0x00, 0x01, 0x06};
55static constexpr uint8_t oemParmStart = 96;
56static constexpr uint8_t oemParmEnd = 127;
Ratan Guptafd28dd72016-08-01 04:58:01 -050057
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000058static constexpr size_t cookieOffset = 1;
59static constexpr size_t versionOffset = 5;
60static constexpr size_t addrSizeOffset = 8;
61static constexpr size_t macOffset = 9;
62static constexpr size_t addrTypeOffset = 16;
63static constexpr size_t ipAddrOffset = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050064
Vijay Khemka074f64d2020-03-03 15:08:43 -080065static constexpr uint4_t RESERVED = 0;
66static constexpr uint8_t CHANNEL_NOT_SUPPORTED = 0;
67
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050068static constexpr size_t encIdentifyObjectsSize = 1;
69static constexpr size_t chassisIdentifyReqLength = 2;
70static constexpr size_t identifyIntervalPos = 0;
71static constexpr size_t forceIdentifyPos = 1;
shgoupfd84fbbf2015-12-17 10:05:51 +080072
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +000073namespace ipmi
74{
75constexpr Cc ccParmNotSupported = 0x80;
76
77static inline auto responseParmNotSupported()
78{
79 return response(ccParmNotSupported);
80}
81} // namespace ipmi
82
Adriana Kobylak40814c62015-10-27 15:58:44 -050083void register_netfn_chassis_functions() __attribute__((constructor));
84
shgoupfd84fbbf2015-12-17 10:05:51 +080085// Host settings in dbus
86// Service name should be referenced by connection name got via object mapper
Patrick Venture0b02be92018-08-31 11:55:55 -070087const char* settings_object_name = "/org/openbmc/settings/host0";
88const char* settings_intf_name = "org.freedesktop.DBus.Properties";
Patrick Venture0b02be92018-08-31 11:55:55 -070089const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053090 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080091
Ratan Guptadcb10672017-07-10 10:33:50 +053092constexpr auto SETTINGS_ROOT = "/";
93constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053094
95constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
96constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
97
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050098static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
99static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -0700100 "xyz.openbmc_project.State.PowerOnHours";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500101static constexpr auto pOHCounterProperty = "POHCounter";
102static constexpr auto match = "chassis0";
Yong Liae4b0402018-11-02 11:12:14 +0800103const static constexpr char chassisCapIntf[] =
104 "xyz.openbmc_project.Control.ChassisCapabilities";
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800105const static constexpr char chassisIntrusionProp[] = "ChassisIntrusionEnabled";
106const static constexpr char chassisFrontPanelLockoutProp[] =
107 "ChassisFrontPanelLockoutEnabled";
108const static constexpr char chassisNMIProp[] = "ChassisNMIEnabled";
109const static constexpr char chassisPowerInterlockProp[] =
110 "ChassisPowerInterlockEnabled";
Yong Liae4b0402018-11-02 11:12:14 +0800111const static constexpr char chassisFRUDevAddrProp[] = "FRUDeviceAddress";
112const static constexpr char chassisSDRDevAddrProp[] = "SDRDeviceAddress";
113const static constexpr char chassisSELDevAddrProp[] = "SELDeviceAddress";
114const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress";
115const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress";
116static constexpr uint8_t chassisCapFlagMask = 0x0f;
117static constexpr uint8_t chassisCapAddrMask = 0xfe;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700118static constexpr const char* powerButtonIntf =
119 "xyz.openbmc_project.Chassis.Buttons.Power";
120static constexpr const char* powerButtonPath =
121 "/xyz/openbmc_project/Chassis/Buttons/Power0";
122static constexpr const char* resetButtonIntf =
123 "xyz.openbmc_project.Chassis.Buttons.Reset";
124static constexpr const char* resetButtonPath =
125 "/xyz/openbmc_project/Chassis/Buttons/Reset0";
Ratan Guptadcb10672017-07-10 10:33:50 +0530126
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530127// Phosphor Host State manager
128namespace State = sdbusplus::xyz::openbmc_project::State::server;
129
Vernon Mauery185b9f82018-07-20 10:52:36 -0700130namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500131
Ratan Guptadcb10672017-07-10 10:33:50 +0530132using namespace phosphor::logging;
133using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500134using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
William A. Kennington III4c008022018-10-12 17:18:14 -0700135
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500136namespace chassis
137{
138namespace internal
139{
140
141constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
142constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500143constexpr auto powerRestoreIntf =
144 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500145sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
146
147namespace cache
148{
149
James Feist225dec82019-11-26 16:25:06 -0800150std::unique_ptr<settings::Objects> objectsPtr = nullptr;
151
152settings::Objects& getObjects()
153{
154 if (objectsPtr == nullptr)
155 {
156 objectsPtr = std::make_unique<settings::Objects>(
157 dbus, std::vector<std::string>{bootModeIntf, bootSourceIntf,
158 powerRestoreIntf});
159 }
160 return *objectsPtr;
161}
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500162
163} // namespace cache
164} // namespace internal
165} // namespace chassis
166
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500167namespace poh
168{
169
170constexpr auto minutesPerCount = 60;
171
172} // namespace poh
173
Patrick Venture0b02be92018-08-31 11:55:55 -0700174struct get_sys_boot_options_t
175{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500176 uint8_t parameter;
177 uint8_t set;
178 uint8_t block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700179} __attribute__((packed));
Adriana Kobylak40814c62015-10-27 15:58:44 -0500180
Patrick Venture0b02be92018-08-31 11:55:55 -0700181struct get_sys_boot_options_response_t
182{
shgoupfd84fbbf2015-12-17 10:05:51 +0800183 uint8_t version;
184 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500185 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700186} __attribute__((packed));
shgoupfd84fbbf2015-12-17 10:05:51 +0800187
Ratan Guptadcb10672017-07-10 10:33:50 +0530188int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500189{
Ratan Guptadcb10672017-07-10 10:33:50 +0530190 ipmi::PropertyMap properties;
191 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530192 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500193
Ratan Guptadcb10672017-07-10 10:33:50 +0530194 try
195 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700196 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530197 // objects,to handle such cases we are interested on that object
198 // which are on interested busname.
199 // Currenlty mapper doesn't give the readable busname(gives busid)
200 // so we can't match with bus name so giving some object specific info
201 // as SETTINGS_MATCH.
202 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500203
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530204 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530205
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530206 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
207 SETTINGS_ROOT, SETTINGS_MATCH);
208
209 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
210 SETTINGS_ROOT, SETTINGS_MATCH);
211
Patrick Venture0b02be92018-08-31 11:55:55 -0700212 properties = ipmi::getAllDbusProperties(
213 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
214 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
215 macObjectInfo.first, MAC_INTERFACE,
216 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530217
Vernon Maueryf442e112019-04-09 11:44:36 -0700218 auto ipAddress = std::get<std::string>(properties["Address"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530219
Vernon Maueryf442e112019-04-09 11:44:36 -0700220 auto gateway = std::get<std::string>(properties["Gateway"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530221
Vernon Maueryf442e112019-04-09 11:44:36 -0700222 auto prefix = std::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530223
Patrick Venture0b02be92018-08-31 11:55:55 -0700224 uint8_t isStatic =
Vernon Maueryf442e112019-04-09 11:44:36 -0700225 (std::get<std::string>(properties["Origin"]) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700226 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
227 ? 1
228 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530229
Vernon Maueryf442e112019-04-09 11:44:36 -0700230 auto MACAddress = std::get<std::string>(variant);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530231
Ratan Guptad70f4532017-08-04 02:07:31 +0530232 // it is expected here that we should get the valid data
233 // but we may also get the default values.
234 // Validation of the data is done by settings.
235 //
236 // if mac address is default mac address then
237 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530238 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530239 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700240 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530241 rc = -1;
242 return rc;
243 }
244 // if addr is static then ipaddress,gateway,prefix
245 // should not be default one,don't send blank override.
246 if (isStatic)
247 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700248 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
249 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530250 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700251 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530252 rc = -1;
253 return rc;
254 }
255 }
256
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000257 sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
258 (respptr->data + macOffset), (respptr->data + macOffset + 1),
259 (respptr->data + macOffset + 2), (respptr->data + macOffset + 3),
260 (respptr->data + macOffset + 4),
261 (respptr->data + macOffset + 5));
Ratan Guptadcb10672017-07-10 10:33:50 +0530262
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000263 respptr->data[macOffset + 6] = 0x00;
Ratan Guptadcb10672017-07-10 10:33:50 +0530264
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000265 std::memcpy(respptr->data + addrTypeOffset, &isStatic,
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700266 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530267
Vernon Maueryf442e112019-04-09 11:44:36 -0700268 uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
269 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
270 ? AF_INET
271 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530272
Patrick Venture0b02be92018-08-31 11:55:55 -0700273 addrSize = (addressFamily == AF_INET)
274 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
275 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530276
277 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530278 inet_pton(addressFamily, ipAddress.c_str(),
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000279 (respptr->data + ipAddrOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530280
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000281 uint8_t prefixOffset = ipAddrOffset + addrSize;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530282
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700283 std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530284
285 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
286
Ratan Guptad70f4532017-08-04 02:07:31 +0530287 inet_pton(addressFamily, gateway.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700288 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530289 }
290 catch (InternalFailure& e)
291 {
292 commit<InternalFailure>();
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700293 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptadcb10672017-07-10 10:33:50 +0530294 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500295 return rc;
296 }
297
Patrick Venture0b02be92018-08-31 11:55:55 -0700298 // PetiBoot-Specific
299 // If success then copy the first 9 bytes to the data
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000300 std::memcpy(respptr->data, netConfInitialBytes,
301 sizeof(netConfInitialBytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500302
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000303 std::memcpy(respptr->data + addrSizeOffset, &addrSize, sizeof(addrSize));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530304
Ratan Guptafd28dd72016-08-01 04:58:01 -0500305#ifdef _IPMI_DEBUG_
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700306 std::printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500307
Ratan Guptadcb10672017-07-10 10:33:50 +0530308 for (uint8_t pos = 0; pos < index; pos++)
309 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700310 std::printf("%02x ", respptr->data[pos]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530311 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500312#endif
313
Ratan Guptafd28dd72016-08-01 04:58:01 -0500314 return rc;
315}
316
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530317/** @brief convert IPv4 and IPv6 addresses from binary to text form.
318 * @param[in] family - IPv4/Ipv6
319 * @param[in] data - req data pointer.
320 * @param[in] offset - offset in the data.
321 * @param[in] addrSize - size of the data which needs to be read from offset.
322 * @returns address in text form.
323 */
324
Patrick Venture0b02be92018-08-31 11:55:55 -0700325std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
326 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530327{
328 char ipAddr[INET6_ADDRSTRLEN] = {};
329
Patrick Venture0b02be92018-08-31 11:55:55 -0700330 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530331 {
332 case AF_INET:
333 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700334 struct sockaddr_in addr4
335 {
336 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700337 std::memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530338
Patrick Venture0b02be92018-08-31 11:55:55 -0700339 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530340
341 break;
342 }
343 case AF_INET6:
344 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700345 struct sockaddr_in6 addr6
346 {
347 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700348 std::memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530349
Patrick Venture0b02be92018-08-31 11:55:55 -0700350 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530351
352 break;
353 }
354 default:
355 {
356 return {};
357 }
358 }
359
360 return ipAddr;
361}
362
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000363ipmi::Cc setHostNetworkData(ipmi::message::Payload& data)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500364{
Ratan Guptadcb10672017-07-10 10:33:50 +0530365 using namespace std::string_literals;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000366 std::string hostNetworkConfig;
367 std::string mac("00:00:00:00:00:00");
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530368 std::string ipAddress, gateway;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000369 std::string addrOrigin{0};
Patrick Venture0b02be92018-08-31 11:55:55 -0700370 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530371 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530372 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700373 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
374 uint8_t prefix{0};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530375 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500376
Patrick Venture0b02be92018-08-31 11:55:55 -0700377 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500378 // version starts from sixth byte
379
Ratan Guptadcb10672017-07-10 10:33:50 +0530380 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500381 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530382 do
383 {
384 // cookie == 0x21 0x70 0x62 0x21
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000385 data.trailingOk = true;
386 auto msgLen = data.size();
387 std::vector<uint8_t> msgPayloadBytes(msgLen);
388 if (data.unpack(msgPayloadBytes) != 0 || !data.fullyUnpacked())
Ratan Guptadcb10672017-07-10 10:33:50 +0530389 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000390 log<level::ERR>(
391 "Error in unpacking message of setHostNetworkData");
392 return ipmi::ccReqDataLenInvalid;
393 }
394
395 uint8_t* msgPayloadStartingPos = msgPayloadBytes.data();
396 constexpr size_t cookieSize = 4;
397 if (msgLen < cookieOffset + cookieSize)
398 {
399 log<level::ERR>(
400 "Error in cookie getting of setHostNetworkData");
401 return ipmi::ccReqDataLenInvalid;
402 }
403 if (std::equal(msgPayloadStartingPos + cookieOffset,
404 msgPayloadStartingPos + cookieOffset + cookieSize,
405 (netConfInitialBytes + cookieOffset)) != 0)
406 {
407 // all cookie == 0
408 if (std::all_of(msgPayloadStartingPos + cookieOffset,
409 msgPayloadStartingPos + cookieOffset +
410 cookieSize,
411 [](int i) { return i == 0; }) == true)
Ratan Guptadcb10672017-07-10 10:33:50 +0530412 {
413 // need to zero out the network settings.
414 break;
415 }
416
417 log<level::ERR>("Invalid Cookie");
418 elog<InternalFailure>();
419 }
420
421 // vesion == 0x00 0x01
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000422 if (msgLen < versionOffset + sizeVersion)
Ratan Guptadcb10672017-07-10 10:33:50 +0530423 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000424 log<level::ERR>(
425 "Error in version getting of setHostNetworkData");
426 return ipmi::ccReqDataLenInvalid;
427 }
428 if (std::equal(msgPayloadStartingPos + versionOffset,
429 msgPayloadStartingPos + versionOffset + sizeVersion,
430 (netConfInitialBytes + versionOffset)) != 0)
431 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530432 log<level::ERR>("Invalid Version");
433 elog<InternalFailure>();
434 }
435
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000436 if (msgLen < macOffset + 6)
437 {
438 log<level::ERR>(
439 "Error in mac address getting of setHostNetworkData");
440 return ipmi::ccReqDataLenInvalid;
441 }
442 std::stringstream result;
443 std::copy((msgPayloadStartingPos + macOffset),
444 (msgPayloadStartingPos + macOffset + 5),
445 std::ostream_iterator<int>(result, ":"));
446 mac = result.str();
Ratan Guptadcb10672017-07-10 10:33:50 +0530447
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000448 if (msgLen < addrTypeOffset + sizeof(decltype(addrOrigin)))
449 {
450 log<level::ERR>(
451 "Error in original address getting of setHostNetworkData");
452 return ipmi::ccReqDataLenInvalid;
453 }
454 std::copy(msgPayloadStartingPos + addrTypeOffset,
455 msgPayloadStartingPos + addrTypeOffset +
456 sizeof(decltype(addrOrigin)),
457 std::ostream_iterator<int>(result, ""));
458 addrOrigin = result.str();
Ratan Guptadcb10672017-07-10 10:33:50 +0530459
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000460 if (!addrOrigin.empty())
Ratan Guptadcb10672017-07-10 10:33:50 +0530461 {
462 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530463 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530464 }
465
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000466 if (msgLen < addrSizeOffset + sizeof(decltype(addrSize)))
467 {
468 log<level::ERR>(
469 "Error in address size getting of setHostNetworkData");
470 return ipmi::ccReqDataLenInvalid;
471 }
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530472 // Get the address size
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000473 std::copy(msgPayloadStartingPos + addrSizeOffset,
474 (msgPayloadStartingPos + addrSizeOffset +
475 sizeof(decltype(addrSize))),
476 &addrSize);
Ratan Guptadcb10672017-07-10 10:33:50 +0530477
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000478 uint8_t prefixOffset = ipAddrOffset + addrSize;
479 if (msgLen < prefixOffset + sizeof(decltype(prefix)))
480 {
481 log<level::ERR>(
482 "Error in prefix getting of setHostNetworkData");
483 return ipmi::ccReqDataLenInvalid;
484 }
485 std::copy(msgPayloadStartingPos + prefixOffset,
486 (msgPayloadStartingPos + prefixOffset +
487 sizeof(decltype(prefix))),
488 &prefix);
Ratan Guptadcb10672017-07-10 10:33:50 +0530489
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530490 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
Ratan Gupta8c31d232017-08-13 05:49:43 +0530491 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530492 {
493 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
494 family = AF_INET6;
495 }
496
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000497 if (msgLen < ipAddrOffset + addrSize)
498 {
499 log<level::ERR>(
500 "Error in IP address getting of setHostNetworkData");
501 return ipmi::ccReqDataLenInvalid;
502 }
503 ipAddress = getAddrStr(family, msgPayloadStartingPos, ipAddrOffset,
504 addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530505
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000506 if (msgLen < gatewayOffset + addrSize)
507 {
508 log<level::ERR>(
509 "Error in gateway address getting of setHostNetworkData");
510 return ipmi::ccReqDataLenInvalid;
511 }
512 gateway = getAddrStr(family, msgPayloadStartingPos, gatewayOffset,
513 addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530514
Patrick Venture0b02be92018-08-31 11:55:55 -0700515 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530516
Patrick Venture0b02be92018-08-31 11:55:55 -0700517 // Cookie == 0 or it is a valid cookie
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000518 hostNetworkConfig += "ipaddress="s + ipAddress + ",prefix="s +
519 std::to_string(prefix) + ",gateway="s + gateway +
520 ",mac="s + mac + ",addressOrigin="s +
521 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500522
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530523 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
524
525 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
526 SETTINGS_ROOT, SETTINGS_MATCH);
527 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
528 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530529 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530530 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700531 IP_INTERFACE, "Address", std::string(ipAddress));
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, "PrefixLength", prefix);
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, "Origin", addressOrigin);
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, "Gateway", std::string(gateway));
538 ipmi::setDbusProperty(
539 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
540 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530541 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700542 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500543
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000544 log<level::DEBUG>("Network configuration changed",
545 entry("NETWORKCONFIG=%s", hostNetworkConfig.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500546 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000547 catch (sdbusplus::exception_t& e)
Ratan Guptadcb10672017-07-10 10:33:50 +0530548 {
549 commit<InternalFailure>();
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000550 log<level::ERR>("Error in ipmiChassisSetSysBootOptions call");
551 return ipmi::ccUnspecifiedError;
Ratan Guptadcb10672017-07-10 10:33:50 +0530552 }
553
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +0000554 return ipmi::ccSuccess;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500555}
556
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500557uint32_t getPOHCounter()
558{
559 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
560
Patrick Venture0b02be92018-08-31 11:55:55 -0700561 auto chassisStateObj =
562 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500563
Patrick Venture0b02be92018-08-31 11:55:55 -0700564 auto service =
565 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500566
Patrick Venture0b02be92018-08-31 11:55:55 -0700567 auto propValue =
568 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
569 chassisPOHStateIntf, pOHCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500570
Vernon Maueryf442e112019-04-09 11:44:36 -0700571 return std::get<uint32_t>(propValue);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500572}
573
anil kumar appana43263c62019-05-27 12:45:04 +0000574/** @brief Implements the get chassis capabilities command
575 *
576 * @returns IPMI completion code plus response data
577 * chassisCapFlags - chassis capability flag
578 * chassisFRUInfoDevAddr - chassis FRU info Device Address
579 * chassisSDRDevAddr - chassis SDR device address
580 * chassisSELDevAddr - chassis SEL device address
581 * chassisSMDevAddr - chassis system management device address
582 * chassisBridgeDevAddr - chassis bridge device address
583 */
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800584ipmi::RspType<bool, // chassis intrusion sensor
585 bool, // chassis Front panel lockout
586 bool, // chassis NMI
587 bool, // chassis power interlock
588 uint4_t, // reserved
anil kumar appana43263c62019-05-27 12:45:04 +0000589 uint8_t, // chassis FRU info Device Address
590 uint8_t, // chassis SDR device address
591 uint8_t, // chassis SEL device address
592 uint8_t, // chassis system management device address
593 uint8_t // chassis bridge device address
594 >
595 ipmiGetChassisCap()
Nan Li8d15fb42016-08-16 22:29:40 +0800596{
anil kumar appana43263c62019-05-27 12:45:04 +0000597 ipmi::PropertyMap properties;
Yong Liae4b0402018-11-02 11:12:14 +0800598 try
599 {
600 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Nan Li8d15fb42016-08-16 22:29:40 +0800601
Yong Liae4b0402018-11-02 11:12:14 +0800602 ipmi::DbusObjectInfo chassisCapObject =
603 ipmi::getDbusObject(bus, chassisCapIntf);
Nan Li8d15fb42016-08-16 22:29:40 +0800604
Yong Liae4b0402018-11-02 11:12:14 +0800605 // capabilities flags
606 // [7..4] - reserved
607 // [3] – 1b = provides power interlock (IPM 1.5)
608 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
609 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis
610 // has capabilities
611 // to lock out external power control and reset button or
612 // front panel interfaces and/or detect tampering with those
613 // interfaces).
614 // [0] -1b = Chassis provides intrusion (physical security) sensor.
615 // set to default value 0x0.
Nan Li8d15fb42016-08-16 22:29:40 +0800616
anil kumar appana43263c62019-05-27 12:45:04 +0000617 properties =
618 ipmi::getAllDbusProperties(bus, chassisCapObject.second,
619 chassisCapObject.first, chassisCapIntf);
Yong Liae4b0402018-11-02 11:12:14 +0800620 }
621 catch (std::exception& e)
622 {
anil kumar appana43263c62019-05-27 12:45:04 +0000623 log<level::ERR>("Failed to fetch Chassis Capability properties",
624 entry("ERROR=%s", e.what()));
625 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800626 }
627
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800628 bool* chassisIntrusionFlag =
629 std::get_if<bool>(&properties[chassisIntrusionProp]);
630 if (chassisIntrusionFlag == nullptr)
anil kumar appana43263c62019-05-27 12:45:04 +0000631 {
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800632 log<level::ERR>("Error to get chassis Intrusion flags");
633 return ipmi::responseUnspecifiedError();
634 }
635 bool* chassisFrontPanelFlag =
636 std::get_if<bool>(&properties[chassisFrontPanelLockoutProp]);
637 if (chassisFrontPanelFlag == nullptr)
638 {
639 log<level::ERR>("Error to get chassis intrusion flags");
640 return ipmi::responseUnspecifiedError();
641 }
642 bool* chassisNMIFlag = std::get_if<bool>(&properties[chassisNMIProp]);
643 if (chassisNMIFlag == nullptr)
644 {
645 log<level::ERR>("Error to get chassis NMI flags");
646 return ipmi::responseUnspecifiedError();
647 }
648 bool* chassisPowerInterlockFlag =
649 std::get_if<bool>(&properties[chassisPowerInterlockProp]);
650 if (chassisPowerInterlockFlag == nullptr)
651 {
652 log<level::ERR>("Error to get chassis power interlock flags");
anil kumar appana43263c62019-05-27 12:45:04 +0000653 return ipmi::responseUnspecifiedError();
654 }
655 uint8_t* chassisFRUInfoDevAddr =
656 std::get_if<uint8_t>(&properties[chassisFRUDevAddrProp]);
657 if (chassisFRUInfoDevAddr == nullptr)
658 {
659 log<level::ERR>("Error to get chassis FRU info device address");
660 return ipmi::responseUnspecifiedError();
661 }
662 uint8_t* chassisSDRDevAddr =
663 std::get_if<uint8_t>(&properties[chassisSDRDevAddrProp]);
664 if (chassisSDRDevAddr == nullptr)
665 {
666 log<level::ERR>("Error to get chassis SDR device address");
667 return ipmi::responseUnspecifiedError();
668 }
669 uint8_t* chassisSELDevAddr =
670 std::get_if<uint8_t>(&properties[chassisSELDevAddrProp]);
671 if (chassisSELDevAddr == nullptr)
672 {
673 log<level::ERR>("Error to get chassis SEL device address");
674 return ipmi::responseUnspecifiedError();
675 }
676 uint8_t* chassisSMDevAddr =
677 std::get_if<uint8_t>(&properties[chassisSMDevAddrProp]);
678 if (chassisSMDevAddr == nullptr)
679 {
680 log<level::ERR>("Error to get chassis SM device address");
681 return ipmi::responseUnspecifiedError();
682 }
683 uint8_t* chassisBridgeDevAddr =
684 std::get_if<uint8_t>(&properties[chassisBridgeDevAddrProp]);
685 if (chassisBridgeDevAddr == nullptr)
686 {
687 log<level::ERR>("Error to get chassis bridge device address");
688 return ipmi::responseUnspecifiedError();
689 }
690
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800691 return ipmi::responseSuccess(*chassisIntrusionFlag, *chassisFrontPanelFlag,
692 *chassisNMIFlag, *chassisPowerInterlockFlag, 0,
693 *chassisFRUInfoDevAddr, *chassisSDRDevAddr,
694 *chassisSELDevAddr, *chassisSMDevAddr,
695 *chassisBridgeDevAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800696}
697
anil kumar appana894d0222019-05-27 16:32:14 +0000698/** @brief implements set chassis capalibities command
699 * @param intrusion - chassis intrusion
700 * @param fpLockout - frontpannel lockout
701 * @param reserved1 - skip one bit
702 * @param fruDeviceAddr - chassis FRU info Device Address
703 * @param sdrDeviceAddr - chassis SDR device address
704 * @param selDeviceAddr - chassis SEL device address
705 * @param smDeviceAddr - chassis system management device address
706 * @param bridgeDeviceAddr - chassis bridge device address
707 *
708 * @returns IPMI completion code
709 */
710ipmi::RspType<> ipmiSetChassisCap(bool intrusion, bool fpLockout,
711 uint6_t reserved1,
712
713 uint8_t fruDeviceAddr,
714
715 uint8_t sdrDeviceAddr,
716
717 uint8_t selDeviceAddr,
718
719 uint8_t smDeviceAddr,
720
721 uint8_t bridgeDeviceAddr)
Yong Liae4b0402018-11-02 11:12:14 +0800722{
Yong Liae4b0402018-11-02 11:12:14 +0800723
724 // check input data
anil kumar appana894d0222019-05-27 16:32:14 +0000725 if (reserved1 != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800726 {
anil kumar appana894d0222019-05-27 16:32:14 +0000727 log<level::ERR>("Unsupported request parameter");
728 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800729 }
730
anil kumar appana894d0222019-05-27 16:32:14 +0000731 if ((fruDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800732 {
733 log<level::ERR>("Unsupported request parameter(FRU Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000734 entry("REQ=0x%x", fruDeviceAddr));
735 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800736 }
anil kumar appana894d0222019-05-27 16:32:14 +0000737 if ((sdrDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800738 {
739 log<level::ERR>("Unsupported request parameter(SDR Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000740 entry("REQ=0x%x", sdrDeviceAddr));
741 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800742 }
743
anil kumar appana894d0222019-05-27 16:32:14 +0000744 if ((selDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800745 {
746 log<level::ERR>("Unsupported request parameter(SEL Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000747 entry("REQ=0x%x", selDeviceAddr));
748 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800749 }
750
anil kumar appana894d0222019-05-27 16:32:14 +0000751 if ((smDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800752 {
anil kumar appana894d0222019-05-27 16:32:14 +0000753 log<level::ERR>("Unsupported request parameter(SM Addr)",
754 entry("REQ=0x%x", smDeviceAddr));
755 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800756 }
757
anil kumar appana894d0222019-05-27 16:32:14 +0000758 if ((bridgeDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800759 {
760 log<level::ERR>("Unsupported request parameter(Bridge Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000761 entry("REQ=0x%x", bridgeDeviceAddr));
762 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800763 }
764
765 try
766 {
767 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
768 ipmi::DbusObjectInfo chassisCapObject =
769 ipmi::getDbusObject(bus, chassisCapIntf);
770
771 ipmi::setDbusProperty(bus, chassisCapObject.second,
772 chassisCapObject.first, chassisCapIntf,
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800773 chassisIntrusionProp, intrusion);
774
775 ipmi::setDbusProperty(bus, chassisCapObject.second,
776 chassisCapObject.first, chassisCapIntf,
777 chassisFrontPanelLockoutProp, fpLockout);
Yong Liae4b0402018-11-02 11:12:14 +0800778
779 ipmi::setDbusProperty(bus, chassisCapObject.second,
780 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000781 chassisFRUDevAddrProp, fruDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800782
783 ipmi::setDbusProperty(bus, chassisCapObject.second,
784 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000785 chassisSDRDevAddrProp, sdrDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800786
787 ipmi::setDbusProperty(bus, chassisCapObject.second,
788 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000789 chassisSELDevAddrProp, selDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800790
791 ipmi::setDbusProperty(bus, chassisCapObject.second,
792 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000793 chassisSMDevAddrProp, smDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800794
795 ipmi::setDbusProperty(bus, chassisCapObject.second,
796 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000797 chassisBridgeDevAddrProp, bridgeDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800798 }
799 catch (std::exception& e)
800 {
801 log<level::ERR>(e.what());
anil kumar appana894d0222019-05-27 16:32:14 +0000802 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800803 }
anil kumar appana894d0222019-05-27 16:32:14 +0000804 return ipmi::responseSuccess();
Nan Li8d15fb42016-08-16 22:29:40 +0800805}
806
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530807//------------------------------------------
808// Calls into Host State Manager Dbus object
809//------------------------------------------
810int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600811{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500812 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700813 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500814 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700815 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
816 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530817
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500818 // sd_bus error
819 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700820 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600821
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500822 // SD Bus error report mechanism.
823 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600824
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500825 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700826 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500827 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
828 if (rc < 0)
829 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700830 log<level::ERR>(
831 "Failed to get bus name",
832 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500833 return rc;
834 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530835
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500836 // Convert to string equivalent of the passed in transition enum.
837 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530838
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500839 rc = sd_bus_call_method(bus_type, // On the system bus
840 busname, // Service to contact
841 HOST_STATE_MANAGER_ROOT, // Object path
842 DBUS_PROPERTY_IFACE, // Interface name
843 "Set", // Method to be called
844 &bus_error, // object to return error
845 nullptr, // Response buffer if any
846 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700847 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
848 request.c_str());
849 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500850 {
851 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530852 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500853 }
854 else
855 {
856 log<level::INFO>("Transition request initiated successfully");
857 }
vishwa36993272015-11-20 12:43:49 -0600858
859 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500860 free(busname);
vishwa36993272015-11-20 12:43:49 -0600861
Sergey Solomineb9b8142016-08-23 09:07:28 -0500862 return rc;
vishwa36993272015-11-20 12:43:49 -0600863}
864
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +0800865//------------------------------------------
866// Set Enabled property to inform NMI source
867// handling to trigger a NMI_OUT BSOD.
868//------------------------------------------
869int setNmiProperty(const bool value)
870{
871 constexpr const char* nmiSourceObjPath =
872 "/xyz/openbmc_project/Chassis/Control/NMISource";
873 constexpr const char* nmiSourceIntf =
874 "xyz.openbmc_project.Chassis.Control.NMISource";
875 std::string bmcSourceSignal = "xyz.openbmc_project.Chassis.Control."
876 "NMISource.BMCSourceSignal.ChassisCmd";
877 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
878
879 try
880 {
881 auto service = ipmi::getService(*busp, nmiSourceIntf, nmiSourceObjPath);
882 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
883 "BMCSource", bmcSourceSignal);
884 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
885 "Enabled", value);
886 }
887 catch (std::exception& e)
888 {
889 log<level::ERR>("Failed to trigger NMI_OUT",
890 entry("EXCEPTION=%s", e.what()));
891 return -1;
892 }
893
894 return 0;
895}
896
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500897namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500898{
Nan Lifdd8ec52016-08-28 03:57:40 +0800899
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500900using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
901using IpmiValue = uint8_t;
902using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800903
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700904const std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500905 {RestorePolicy::Policy::AlwaysOff, 0x00},
906 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700907 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800908
Yong Lic6713cf2018-09-12 12:35:13 +0800909static constexpr uint8_t noChange = 0x03;
910static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700911
912/* helper function for Get Chassis Status Command
913 */
914std::optional<uint2_t> getPowerRestorePolicy()
915{
916 uint2_t restorePolicy = 0;
917 using namespace chassis::internal;
918
James Feist225dec82019-11-26 16:25:06 -0800919 settings::Objects& objects = cache::getObjects();
920
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700921 try
922 {
923 const auto& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -0800924 objects.map.at(powerRestoreIntf).front();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700925 ipmi::Value result = ipmi::getDbusProperty(
926 *getSdBus(),
James Feist225dec82019-11-26 16:25:06 -0800927 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700928 powerRestoreSetting.c_str(), powerRestoreIntf,
929 "PowerRestorePolicy");
930 auto powerRestore = RestorePolicy::convertPolicyFromString(
931 std::get<std::string>(result));
932 restorePolicy = dbusToIpmi.at(powerRestore);
933 }
934 catch (const std::exception& e)
935 {
936 log<level::ERR>(
937 "Failed to fetch pgood property", entry("ERROR=%s", e.what()),
James Feist225dec82019-11-26 16:25:06 -0800938 entry("PATH=%s", objects.map.at(powerRestoreIntf).front().c_str()),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700939 entry("INTERFACE=%s", powerRestoreIntf));
James Feist225dec82019-11-26 16:25:06 -0800940 cache::objectsPtr.reset();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700941 return std::nullopt;
942 }
943 return std::make_optional(restorePolicy);
944}
945
946/*
947 * getPowerStatus
948 * helper function for Get Chassis Status Command
949 * return - optional value for pgood (no value on error)
950 */
951std::optional<bool> getPowerStatus()
952{
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700953 bool powerGood = false;
954 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
955 try
956 {
Jason M. Bills3de424c2019-05-21 09:57:16 -0700957 constexpr const char* chassisStatePath =
958 "/xyz/openbmc_project/state/chassis0";
959 constexpr const char* chassisStateIntf =
960 "xyz.openbmc_project.State.Chassis";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700961 auto service =
Jason M. Bills3de424c2019-05-21 09:57:16 -0700962 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700963
Jason M. Bills3de424c2019-05-21 09:57:16 -0700964 ipmi::Value powerState =
965 ipmi::getDbusProperty(*busp, service, chassisStatePath,
966 chassisStateIntf, "CurrentPowerState");
967 powerGood = std::get<std::string>(powerState) ==
968 "xyz.openbmc_project.State.Chassis.PowerState.On";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700969 }
970 catch (const std::exception& e)
971 {
972 try
973 {
974 // FIXME: some legacy modules use the older path; try that next
975 constexpr const char* legacyPwrCtrlObj =
976 "/org/openbmc/control/power0";
977 constexpr const char* legacyPwrCtrlIntf =
978 "org.openbmc.control.Power";
979 auto service =
980 ipmi::getService(*busp, legacyPwrCtrlIntf, legacyPwrCtrlObj);
981
982 ipmi::Value variant = ipmi::getDbusProperty(
983 *busp, service, legacyPwrCtrlObj, legacyPwrCtrlIntf, "pgood");
984 powerGood = static_cast<bool>(std::get<int>(variant));
985 }
986 catch (const std::exception& e)
987 {
988 log<level::ERR>("Failed to fetch pgood property",
Jason M. Bills3de424c2019-05-21 09:57:16 -0700989 entry("ERROR=%s", e.what()));
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700990 return std::nullopt;
991 }
992 }
993 return std::make_optional(powerGood);
994}
995
Yong Li70ce7352019-05-16 21:15:27 +0800996/*
997 * getACFailStatus
998 * helper function for Get Chassis Status Command
999 * return - bool value for ACFail (false on error)
1000 */
1001bool getACFailStatus()
1002{
1003 constexpr const char* powerControlObj =
1004 "/xyz/openbmc_project/Chassis/Control/Power0";
1005 constexpr const char* powerControlIntf =
1006 "xyz.openbmc_project.Chassis.Control.Power";
1007 bool acFail = false;
1008 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
1009 try
1010 {
1011 auto service =
1012 ipmi::getService(*bus, powerControlIntf, powerControlObj);
1013
1014 ipmi::Value variant = ipmi::getDbusProperty(
1015 *bus, service, powerControlObj, powerControlIntf, "PFail");
1016 acFail = std::get<bool>(variant);
1017 }
1018 catch (const std::exception& e)
1019 {
1020 log<level::ERR>("Failed to fetch PFail property",
1021 entry("ERROR=%s", e.what()),
1022 entry("PATH=%s", powerControlObj),
1023 entry("INTERFACE=%s", powerControlIntf));
1024 }
1025 return acFail;
1026}
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001027} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +08001028
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001029static std::optional<bool> getButtonEnabled(const std::string& buttonPath,
1030 const std::string& buttonIntf)
1031{
1032 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
1033 bool buttonDisabled = false;
1034 try
1035 {
1036 auto service = ipmi::getService(*busp, buttonIntf, buttonPath);
1037 ipmi::Value enabled = ipmi::getDbusProperty(*busp, service, buttonPath,
1038 buttonIntf, "Enabled");
1039 buttonDisabled = !std::get<bool>(enabled);
1040 }
1041 catch (sdbusplus::exception::SdBusError& e)
1042 {
1043 log<level::ERR>("Fail to get button Enabled property",
1044 entry("PATH=%s", buttonPath.c_str()),
1045 entry("ERROR=%s", e.what()));
1046 return std::nullopt;
1047 }
1048 return std::make_optional(buttonDisabled);
1049}
1050
Kuiying Wang21addc52019-01-04 10:50:21 +08001051static bool setButtonEnabled(ipmi::Context::ptr& ctx,
1052 const std::string& buttonPath,
1053 const std::string& buttonIntf, bool enable)
1054{
1055 std::string service;
1056 boost::system::error_code ec;
1057 ec = ipmi::getService(ctx, buttonIntf, buttonPath, service);
1058 if (!ec)
1059 {
1060 ec = ipmi::setDbusProperty(ctx, service, buttonPath, buttonIntf,
1061 "Enabled", enable);
1062 }
1063 if (ec)
1064 {
1065 log<level::ERR>("Fail to set button Enabled property",
1066 entry("SERVICE=%s", service.c_str()),
1067 entry("PATH=%s", buttonPath.c_str()),
1068 entry("ERROR=%s", ec.message().c_str()));
1069 return false;
1070 }
1071 return true;
1072}
1073
Nan Lifdd8ec52016-08-28 03:57:40 +08001074//----------------------------------------------------------------------
1075// Get Chassis Status commands
1076//----------------------------------------------------------------------
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001077ipmi::RspType<bool, // Power is on
1078 bool, // Power overload
1079 bool, // Interlock
1080 bool, // power fault
1081 bool, // power control fault
1082 uint2_t, // power restore policy
1083 bool, // reserved
1084
1085 bool, // AC failed
1086 bool, // last power down caused by a Power overload
1087 bool, // last power down caused by a power interlock
1088 bool, // last power down caused by power fault
1089 bool, // last ‘Power is on’ state was entered via IPMI command
1090 uint3_t, // reserved
1091
1092 bool, // Chassis intrusion active
1093 bool, // Front Panel Lockout active
1094 bool, // Drive Fault
1095 bool, // Cooling/fan fault detected
1096 uint2_t, // Chassis Identify State
1097 bool, // Chassis Identify command and state info supported
1098 bool, // reserved
1099
1100 bool, // Power off button disabled
1101 bool, // Reset button disabled
1102 bool, // Diagnostic Interrupt button disabled
1103 bool, // Standby (sleep) button disabled
1104 bool, // Power off button disable allowed
1105 bool, // Reset button disable allowed
1106 bool, // Diagnostic Interrupt button disable allowed
1107 bool // Standby (sleep) button disable allowed
1108 >
1109 ipmiGetChassisStatus()
Nan Lifdd8ec52016-08-28 03:57:40 +08001110{
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001111 using namespace chassis::internal;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001112 std::optional<uint2_t> restorePolicy =
1113 power_policy::getPowerRestorePolicy();
1114 std::optional<bool> powerGood = power_policy::getPowerStatus();
1115 if (!restorePolicy || !powerGood)
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001116 {
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001117 return ipmi::responseUnspecifiedError();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001118 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001119
1120 // Front Panel Button Capabilities and disable/enable status(Optional)
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001121 std::optional<bool> powerButtonReading =
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001122 getButtonEnabled(powerButtonPath, powerButtonIntf);
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001123 // allow disable if the interface is present
1124 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
1125 // default return the button is enabled (not disabled)
1126 bool powerButtonDisabled = false;
1127 if (powerButtonDisableAllow)
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001128 {
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001129 // return the real value of the button status, if present
1130 powerButtonDisabled = *powerButtonReading;
1131 }
1132
1133 std::optional<bool> resetButtonReading =
1134 getButtonEnabled(resetButtonPath, resetButtonIntf);
1135 // allow disable if the interface is present
1136 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
1137 // default return the button is enabled (not disabled)
1138 bool resetButtonDisabled = false;
1139 if (resetButtonDisableAllow)
1140 {
1141 // return the real value of the button status, if present
1142 resetButtonDisabled = *resetButtonReading;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001143 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001144
Yong Li70ce7352019-05-16 21:15:27 +08001145 bool powerDownAcFailed = power_policy::getACFailStatus();
1146
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001147 // This response has a lot of hard-coded, unsupported fields
1148 // They are set to false or 0
1149 constexpr bool powerOverload = false;
1150 constexpr bool chassisInterlock = false;
1151 constexpr bool powerFault = false;
1152 constexpr bool powerControlFault = false;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001153 constexpr bool powerDownOverload = false;
1154 constexpr bool powerDownInterlock = false;
1155 constexpr bool powerDownPowerFault = false;
1156 constexpr bool powerStatusIPMI = false;
1157 constexpr bool chassisIntrusionActive = false;
1158 constexpr bool frontPanelLockoutActive = false;
1159 constexpr bool driveFault = false;
1160 constexpr bool coolingFanFault = false;
1161 // chassisIdentifySupport set because this command is implemented
1162 constexpr bool chassisIdentifySupport = true;
Yong Lif4e38512019-05-21 14:46:55 +08001163 uint2_t chassisIdentifyState = static_cast<uint2_t>(chassisIDState);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001164 constexpr bool diagButtonDisabled = false;
1165 constexpr bool sleepButtonDisabled = false;
1166 constexpr bool diagButtonDisableAllow = false;
1167 constexpr bool sleepButtonDisableAllow = false;
1168
1169 return ipmi::responseSuccess(
1170 *powerGood, powerOverload, chassisInterlock, powerFault,
1171 powerControlFault, *restorePolicy,
1172 false, // reserved
1173
1174 powerDownAcFailed, powerDownOverload, powerDownInterlock,
1175 powerDownPowerFault, powerStatusIPMI,
1176 uint3_t(0), // reserved
1177
1178 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
1179 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
1180 false, // reserved
1181
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001182 powerButtonDisabled, resetButtonDisabled, diagButtonDisabled,
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001183 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
1184 diagButtonDisableAllow, sleepButtonDisableAllow);
Nan Lifdd8ec52016-08-28 03:57:40 +08001185}
Chris Austen7888c4d2015-12-03 15:26:20 -06001186
Vijay Khemka074f64d2020-03-03 15:08:43 -08001187enum class IpmiRestartCause
1188{
1189 Unknown = 0x0,
1190 RemoteCommand = 0x1,
1191 ResetButton = 0x2,
1192 PowerButton = 0x3,
1193 WatchdogTimer = 0x4,
1194 PowerPolicyAlwaysOn = 0x6,
1195 PowerPolicyPreviousState = 0x7,
1196 SoftReset = 0xa,
1197};
1198
1199static IpmiRestartCause
1200 restartCauseToIpmiRestartCause(State::Host::RestartCause cause)
1201{
1202 switch (cause)
1203 {
1204 case State::Host::RestartCause::Unknown:
1205 {
1206 return IpmiRestartCause::Unknown;
1207 }
1208 case State::Host::RestartCause::RemoteCommand:
1209 {
1210 return IpmiRestartCause::RemoteCommand;
1211 }
1212 case State::Host::RestartCause::ResetButton:
1213 {
1214 return IpmiRestartCause::ResetButton;
1215 }
1216 case State::Host::RestartCause::PowerButton:
1217 {
1218 return IpmiRestartCause::PowerButton;
1219 }
1220 case State::Host::RestartCause::WatchdogTimer:
1221 {
1222 return IpmiRestartCause::WatchdogTimer;
1223 }
1224 case State::Host::RestartCause::PowerPolicyAlwaysOn:
1225 {
1226 return IpmiRestartCause::PowerPolicyAlwaysOn;
1227 }
1228 case State::Host::RestartCause::PowerPolicyPreviousState:
1229 {
1230 return IpmiRestartCause::PowerPolicyPreviousState;
1231 }
1232 case State::Host::RestartCause::SoftReset:
1233 {
1234 return IpmiRestartCause::SoftReset;
1235 }
1236 default:
1237 {
1238 return IpmiRestartCause::Unknown;
1239 }
1240 }
1241}
1242
1243/*
1244 * getRestartCause
1245 * helper function for Get Host restart cause Command
1246 * return - optional value for RestartCause (no value on error)
1247 */
1248static std::optional<uint4_t> getRestartCause(ipmi::Context::ptr ctx)
1249{
1250 constexpr const char* restartCausePath =
1251 "/xyz/openbmc_project/control/host0/restart_cause";
1252 constexpr const char* restartCauseIntf =
1253 "xyz.openbmc_project.Control.Host.RestartCause";
1254
1255 std::string service;
1256 boost::system::error_code ec =
1257 ipmi::getService(ctx, restartCauseIntf, restartCausePath, service);
1258 if (!ec)
1259 {
1260 std::string restartCauseStr;
1261 ec = ipmi::getDbusProperty<std::string>(
1262 ctx, service, restartCausePath, restartCauseIntf, "RestartCause",
1263 restartCauseStr);
1264 if (!ec)
1265 {
1266 auto cause =
1267 State::Host::convertRestartCauseFromString(restartCauseStr);
1268 return restartCauseToIpmiRestartCause(cause);
1269 }
1270 }
1271
1272 log<level::ERR>("Failed to fetch RestartCause property",
1273 entry("ERROR=%s", ec.message().c_str()),
1274 entry("PATH=%s", restartCausePath),
1275 entry("INTERFACE=%s", restartCauseIntf));
1276 return std::nullopt;
1277}
1278
1279ipmi::RspType<uint4_t, // Restart Cause
1280 uint4_t, // reserved
1281 uint8_t // channel number (not supported)
1282 >
1283 ipmiGetSystemRestartCause(ipmi::Context::ptr ctx)
1284{
1285 std::optional<uint4_t> cause = getRestartCause(ctx);
1286 if (!cause)
1287 {
1288 return ipmi::responseUnspecifiedError();
1289 }
1290
1291 return ipmi::responseSuccess(cause.value(), RESERVED,
1292 CHANNEL_NOT_SUPPORTED);
1293}
1294
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301295//-------------------------------------------------------------
1296// Send a command to SoftPowerOff application to stop any timer
1297//-------------------------------------------------------------
1298int stop_soft_off_timer()
1299{
Patrick Venture0b02be92018-08-31 11:55:55 -07001300 constexpr auto iface = "org.freedesktop.DBus.Properties";
1301 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
1302 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301303
Patrick Venture0b02be92018-08-31 11:55:55 -07001304 constexpr auto property = "ResponseReceived";
1305 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
1306 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301307
1308 // Get the system bus where most system services are provided.
1309 auto bus = ipmid_get_sd_bus_connection();
1310
1311 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001312 // TODO openbmc/openbmc#1661 - Mapper refactor
1313 //
1314 // See openbmc/openbmc#1743 for some details but high level summary is that
1315 // for now the code will directly call the soft off interface due to a
1316 // race condition with mapper usage
1317 //
Patrick Venture0b02be92018-08-31 11:55:55 -07001318 // char *busname = nullptr;
1319 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
1320 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001321 //{
1322 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301323 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001324 // return r;
1325 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301326
1327 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001328 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -07001329 "Set", nullptr, nullptr, "ssv", soft_off_iface,
1330 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301331 if (rc < 0)
1332 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301333 log<level::ERR>("Failed to set property in SoftPowerOff object",
1334 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301335 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001336
Patrick Venture0b02be92018-08-31 11:55:55 -07001337 // TODO openbmc/openbmc#1661 - Mapper refactor
1338 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301339 return rc;
1340}
1341
vishwa36993272015-11-20 12:43:49 -06001342//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001343// Create file to indicate there is no need for softoff notification to host
1344//----------------------------------------------------------------------
1345void indicate_no_softoff_needed()
1346{
1347 fs::path path{HOST_INBAND_REQUEST_DIR};
1348 if (!fs::is_directory(path))
1349 {
1350 fs::create_directory(path);
1351 }
1352
1353 // Add the host instance (default 0 for now) to the file name
1354 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001355 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001356 size++; // null
1357 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001358 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001359
1360 // Append file name to directory and create it
1361 path /= buf.get();
1362 std::ofstream(path.c_str());
1363}
1364
anil kumar appanadafff5f2019-04-27 18:06:00 +00001365/** @brief Implementation of chassis control command
1366 *
1367 * @param - chassisControl command byte
1368 *
1369 * @return Success or InvalidFieldRequest.
1370 */
1371ipmi::RspType<> ipmiChassisControl(uint8_t chassisControl)
vishwa36993272015-11-20 12:43:49 -06001372{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001373 int rc = 0;
anil kumar appanadafff5f2019-04-27 18:06:00 +00001374 switch (chassisControl)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001375 {
1376 case CMD_POWER_ON:
1377 rc = initiate_state_transition(State::Host::Transition::On);
1378 break;
1379 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301380 // This path would be hit in 2 conditions.
1381 // 1: When user asks for power off using ipmi chassis command 0x04
1382 // 2: Host asking for power off post shutting down.
1383
1384 // If it's a host requested power off, then need to nudge Softoff
1385 // application that it needs to stop the watchdog timer if running.
1386 // If it is a user requested power off, then this is not really
1387 // needed. But then we need to differentiate between user and host
1388 // calling this same command
1389
1390 // For now, we are going ahead with trying to nudge the soft off and
1391 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001392 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301393
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001394 // Only request the Off transition if the soft power off
1395 // application is not running
1396 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001397 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001398 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301399 // that it should not run. Not doing this will result in State
1400 // manager doing a default soft power off when asked for power
1401 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001402 indicate_no_softoff_needed();
1403
1404 // Now request the shutdown
1405 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001406 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001407 else
1408 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301409 log<level::INFO>("Soft off is running, so let shutdown target "
1410 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001411 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001412 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301413
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001414 case CMD_HARD_RESET:
1415 case CMD_POWER_CYCLE:
1416 // SPEC has a section that says certain implementations can trigger
1417 // PowerOn if power is Off when a command to power cycle is
1418 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001419
1420 // First create a file to indicate to the soft off application
1421 // that it should not run since this is a direct user initiated
1422 // power reboot request (i.e. a reboot request that is not
1423 // originating via a soft power off SMS request)
1424 indicate_no_softoff_needed();
1425
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001426 rc = initiate_state_transition(State::Host::Transition::Reboot);
1427 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301428
1429 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1430 // Request Host State Manager to do a soft power off
1431 rc = initiate_state_transition(State::Host::Transition::Off);
1432 break;
1433
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +08001434 case CMD_PULSE_DIAGNOSTIC_INTR:
1435 rc = setNmiProperty(true);
1436 break;
1437
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001438 default:
1439 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301440 log<level::ERR>("Invalid Chassis Control command",
anil kumar appanadafff5f2019-04-27 18:06:00 +00001441 entry("CMD=0x%X", chassisControl));
1442 return ipmi::responseInvalidFieldRequest();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001443 }
1444 }
vishwa36993272015-11-20 12:43:49 -06001445
anil kumar appanadafff5f2019-04-27 18:06:00 +00001446 return ((rc < 0) ? ipmi::responseUnspecifiedError()
1447 : ipmi::responseSuccess());
vishwa36993272015-11-20 12:43:49 -06001448}
1449
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001450/** @brief Return D-Bus connection string to enclosure identify LED object
1451 *
1452 * @param[in, out] connection - connection to D-Bus object
1453 * @return a IPMI return code
1454 */
1455std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301456{
Tom Joseph5110c122018-03-23 17:55:40 +05301457 // lookup enclosure_identify group owner(s) in mapper
1458 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001459 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1460 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301461
1462 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001463 static const std::vector<std::string> interfaces = {
1464 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301465 mapperCall.append(interfaces);
1466 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1467 if (mapperReply.is_method_error())
1468 {
1469 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001470 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301471 }
1472 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1473 mapperReply.read(mapperResp);
1474
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001475 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301476 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001477 log<level::ERR>(
1478 "Invalid number of enclosure identify objects.",
1479 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001480 elog<InternalFailure>();
1481 }
1482 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1483 return pair.first;
1484}
Tom Joseph5110c122018-03-23 17:55:40 +05301485
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001486/** @brief Turn On/Off enclosure identify LED
1487 *
1488 * @param[in] flag - true to turn on LED, false to turn off
1489 * @return a IPMI return code
1490 */
1491void enclosureIdentifyLed(bool flag)
1492{
1493 using namespace chassis::internal;
1494 std::string connection = std::move(getEnclosureIdentifyConnection());
Vernon Mauery400cc782018-10-09 13:49:53 -07001495 auto msg = std::string("enclosureIdentifyLed(") +
1496 boost::lexical_cast<std::string>(flag) + ")";
1497 log<level::DEBUG>(msg.c_str());
Patrick Venture0b02be92018-08-31 11:55:55 -07001498 auto led =
1499 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1500 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001501 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Vernon Mauery16b86932019-05-01 08:36:11 -07001502 std::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001503 auto ledReply = dbus.call(led);
1504 if (ledReply.is_method_error())
1505 {
1506 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001507 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001508 elog<InternalFailure>();
1509 }
1510}
1511
1512/** @brief Callback method to turn off LED
1513 */
1514void enclosureIdentifyLedOff()
1515{
1516 try
1517 {
Yong Lif4e38512019-05-21 14:46:55 +08001518 chassisIDState = ChassisIDState::off;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001519 enclosureIdentifyLed(false);
1520 }
1521 catch (const InternalFailure& e)
1522 {
1523 report<InternalFailure>();
1524 }
1525}
1526
1527/** @brief Create timer to turn on and off the enclosure LED
1528 */
1529void createIdentifyTimer()
1530{
1531 if (!identifyTimer)
1532 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001533 identifyTimer =
1534 std::make_unique<phosphor::Timer>(enclosureIdentifyLedOff);
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001535 }
1536}
1537
Vernon Mauery400cc782018-10-09 13:49:53 -07001538ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
1539 std::optional<uint8_t> force)
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001540{
Vernon Mauery400cc782018-10-09 13:49:53 -07001541 uint8_t identifyInterval = interval.value_or(DEFAULT_IDENTIFY_TIME_OUT);
1542 bool forceIdentify = force.value_or(0) & 0x01;
Tom Josephbed26992018-07-31 23:00:24 +05301543
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001544 if (identifyInterval || forceIdentify)
1545 {
Vernon Mauery400cc782018-10-09 13:49:53 -07001546 // stop the timer if already started;
1547 // for force identify we should not turn off LED
Vernon Mauery1181af72018-10-08 12:05:00 -07001548 identifyTimer->stop();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001549 try
Tom Joseph5110c122018-03-23 17:55:40 +05301550 {
Yong Lif4e38512019-05-21 14:46:55 +08001551 chassisIDState = ChassisIDState::temporaryOn;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001552 enclosureIdentifyLed(true);
1553 }
1554 catch (const InternalFailure& e)
1555 {
1556 report<InternalFailure>();
Vernon Mauery400cc782018-10-09 13:49:53 -07001557 return ipmi::responseResponseError();
Tom Joseph5110c122018-03-23 17:55:40 +05301558 }
1559
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001560 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301561 {
Yong Lif4e38512019-05-21 14:46:55 +08001562 chassisIDState = ChassisIDState::indefiniteOn;
Vernon Mauery400cc782018-10-09 13:49:53 -07001563 return ipmi::responseSuccess();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001564 }
1565 // start the timer
1566 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001567 std::chrono::seconds(identifyInterval));
Vernon Mauery1181af72018-10-08 12:05:00 -07001568 identifyTimer->start(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301569 }
Tom Josephbed26992018-07-31 23:00:24 +05301570 else if (!identifyInterval)
1571 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001572 identifyTimer->stop();
Tom Josephbed26992018-07-31 23:00:24 +05301573 enclosureIdentifyLedOff();
1574 }
Vernon Mauery400cc782018-10-09 13:49:53 -07001575 return ipmi::responseSuccess();
Tom Joseph5110c122018-03-23 17:55:40 +05301576}
1577
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001578namespace boot_options
1579{
1580
1581using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1582using IpmiValue = uint8_t;
1583constexpr auto ipmiDefault = 0;
1584
Patrick Venture0b02be92018-08-31 11:55:55 -07001585std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001586 {0x01, Source::Sources::Network},
1587 {0x02, Source::Sources::Disk},
1588 {0x05, Source::Sources::ExternalMedia},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001589 {0x0f, Source::Sources::RemovableMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001590 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001591
Patrick Venture0b02be92018-08-31 11:55:55 -07001592std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Yong Li5833cb62019-10-30 13:27:12 +08001593#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001594 {0x03, Mode::Modes::Safe},
Yong Li5833cb62019-10-30 13:27:12 +08001595#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001596 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001597 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001598
Patrick Venture0b02be92018-08-31 11:55:55 -07001599std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001600 {Source::Sources::Network, 0x01},
1601 {Source::Sources::Disk, 0x02},
1602 {Source::Sources::ExternalMedia, 0x05},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001603 {Source::Sources::RemovableMedia, 0x0f},
Patrick Venture0b02be92018-08-31 11:55:55 -07001604 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001605
Patrick Venture0b02be92018-08-31 11:55:55 -07001606std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Yong Li5833cb62019-10-30 13:27:12 +08001607#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001608 {Mode::Modes::Safe, 0x03},
Yong Li5833cb62019-10-30 13:27:12 +08001609#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001610 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001611 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001612
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001613} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001614
Marri Devender Rao81719702018-05-07 00:53:48 -05001615/** @brief Set the property value for boot source
1616 * @param[in] source - boot source value
1617 * @return On failure return IPMI error.
1618 */
1619static ipmi_ret_t setBootSource(const Source::Sources& source)
1620{
1621 using namespace chassis::internal;
1622 using namespace chassis::internal::cache;
Vernon Mauery16b86932019-05-01 08:36:11 -07001623 std::variant<std::string> property = convertForMessage(source);
James Feist225dec82019-11-26 16:25:06 -08001624 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001625 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1626 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001627 auto method = dbus.new_method_call(
1628 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1629 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001630 method.append(bootSourceIntf, "BootSource", property);
1631 auto reply = dbus.call(method);
1632 if (reply.is_method_error())
1633 {
1634 log<level::ERR>("Error in BootSource Set");
1635 report<InternalFailure>();
1636 return IPMI_CC_UNSPECIFIED_ERROR;
1637 }
1638 return IPMI_CC_OK;
1639}
1640
Patrick Venture0b02be92018-08-31 11:55:55 -07001641/** @brief Set the property value for boot mode
Marri Devender Rao81719702018-05-07 00:53:48 -05001642 * @param[in] mode - boot mode value
1643 * @return On failure return IPMI error.
1644 */
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001645static ipmi::Cc setBootMode(const Mode::Modes& mode)
Marri Devender Rao81719702018-05-07 00:53:48 -05001646{
1647 using namespace chassis::internal;
1648 using namespace chassis::internal::cache;
Vernon Mauery16b86932019-05-01 08:36:11 -07001649 std::variant<std::string> property = convertForMessage(mode);
James Feist225dec82019-11-26 16:25:06 -08001650 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001651 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1652 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001653 auto method = dbus.new_method_call(
1654 objects.service(bootModeSetting, bootModeIntf).c_str(),
1655 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001656 method.append(bootModeIntf, "BootMode", property);
1657 auto reply = dbus.call(method);
1658 if (reply.is_method_error())
1659 {
1660 log<level::ERR>("Error in BootMode Set");
1661 report<InternalFailure>();
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001662 return ipmi::ccUnspecifiedError;
Marri Devender Rao81719702018-05-07 00:53:48 -05001663 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001664 return ipmi::ccSuccess;
Marri Devender Rao81719702018-05-07 00:53:48 -05001665}
1666
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001667ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1668 ipmi_request_t request,
1669 ipmi_response_t response,
1670 ipmi_data_len_t data_len,
1671 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001672{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001673 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001674 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
Patrick Venture0b02be92018-08-31 11:55:55 -07001675 char* p = NULL;
1676 get_sys_boot_options_response_t* resp =
1677 (get_sys_boot_options_response_t*)response;
1678 get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001679 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001680
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001681 std::memset(resp, 0, sizeof(*resp));
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001682 resp->version = setParmVersion;
Patrick Venture0b02be92018-08-31 11:55:55 -07001683 resp->parm = 5;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001684 resp->data[0] = setParmBootFlagsValidOneTime;
shgoupfd84fbbf2015-12-17 10:05:51 +08001685 /*
1686 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1687 * This is the only parameter used by petitboot.
1688 */
Patrick Venture0b02be92018-08-31 11:55:55 -07001689 if (reqptr->parameter ==
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001690 static_cast<uint8_t>(BootOptionParameter::bootFlags))
Patrick Venture0b02be92018-08-31 11:55:55 -07001691 {
shgoupfd84fbbf2015-12-17 10:05:51 +08001692
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001693 *data_len = static_cast<uint8_t>(BootOptionResponseSize::bootFlags);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001694 using namespace chassis::internal;
1695 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001696
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001697 try
ratagupta6f6bff2016-04-04 06:20:11 -05001698 {
James Feist225dec82019-11-26 16:25:06 -08001699 settings::Objects& objects = getObjects();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001700 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1701 const auto& bootSourceSetting =
1702 std::get<settings::Path>(bootSetting);
1703 auto oneTimeEnabled =
1704 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001705 auto method = dbus.new_method_call(
1706 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1707 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001708 method.append(bootSourceIntf, "BootSource");
1709 auto reply = dbus.call(method);
1710 if (reply.is_method_error())
1711 {
1712 log<level::ERR>("Error in BootSource Get");
1713 report<InternalFailure>();
1714 *data_len = 0;
1715 return IPMI_CC_UNSPECIFIED_ERROR;
1716 }
Vernon Mauery16b86932019-05-01 08:36:11 -07001717 std::variant<std::string> result;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001718 reply.read(result);
Vernon Maueryf442e112019-04-09 11:44:36 -07001719 auto bootSource =
1720 Source::convertSourcesFromString(std::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001721
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001722 bootSetting = settings::boot::setting(objects, bootModeIntf);
1723 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1724 method = dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001725 objects.service(bootModeSetting, bootModeIntf).c_str(),
1726 bootModeSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001727 method.append(bootModeIntf, "BootMode");
1728 reply = dbus.call(method);
1729 if (reply.is_method_error())
1730 {
1731 log<level::ERR>("Error in BootMode Get");
1732 report<InternalFailure>();
1733 *data_len = 0;
1734 return IPMI_CC_UNSPECIFIED_ERROR;
1735 }
1736 reply.read(result);
Vernon Maueryf442e112019-04-09 11:44:36 -07001737 auto bootMode =
1738 Mode::convertModesFromString(std::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001739
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001740 bootOption = sourceDbusToIpmi.at(bootSource);
1741 if ((Mode::Modes::Regular == bootMode) &&
1742 (Source::Sources::Default == bootSource))
1743 {
1744 bootOption = ipmiDefault;
1745 }
1746 else if (Source::Sources::Default == bootSource)
1747 {
1748 bootOption = modeDbusToIpmi.at(bootMode);
1749 }
1750 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001751
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001752 resp->data[0] = oneTimeEnabled ? setParmBootFlagsValidOneTime
1753 : setParmBootFlagsValidPermanent;
ratagupta6f6bff2016-04-04 06:20:11 -05001754
ratagupta6f6bff2016-04-04 06:20:11 -05001755 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001756 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001757 catch (InternalFailure& e)
1758 {
James Feist225dec82019-11-26 16:25:06 -08001759 cache::objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001760 report<InternalFailure>();
1761 *data_len = 0;
1762 return IPMI_CC_UNSPECIFIED_ERROR;
1763 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001764 }
1765 else if (reqptr->parameter ==
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001766 static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings))
Patrick Venture0b02be92018-08-31 11:55:55 -07001767 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001768
Patrick Venture0b02be92018-08-31 11:55:55 -07001769 *data_len =
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001770 static_cast<uint8_t>(BootOptionResponseSize::opalNetworkSettings);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001771
Patrick Venture0b02be92018-08-31 11:55:55 -07001772 resp->parm =
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001773 static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001774
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001775 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001776
Patrick Venture0b02be92018-08-31 11:55:55 -07001777 if (ret < 0)
1778 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001779
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301780 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001781 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001782 rc = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture0b02be92018-08-31 11:55:55 -07001783 }
1784 else
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001785 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001786 }
1787
Patrick Venture0b02be92018-08-31 11:55:55 -07001788 else
1789 {
1790 log<level::ERR>("Unsupported parameter",
1791 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001792 }
1793
1794 if (p)
1795 free(p);
1796
Ratan Guptafd28dd72016-08-01 04:58:01 -05001797 if (rc == IPMI_CC_OK)
1798 {
1799 *data_len += 2;
1800 }
1801
shgoupfd84fbbf2015-12-17 10:05:51 +08001802 return rc;
1803}
1804
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001805ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
1806 uint7_t parameterSelector,
1807 bool parameterIsValid,
1808 ipmi::message::Payload& data)
shgoupfd84fbbf2015-12-17 10:05:51 +08001809{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001810 using namespace boot_options;
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001811 ipmi::Cc rc;
shgoupfd84fbbf2015-12-17 10:05:51 +08001812
1813 /* 000101
1814 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1815 * This is the only parameter used by petitboot.
1816 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001817
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001818 if (parameterSelector ==
1819 static_cast<uint7_t>(BootOptionParameter::bootFlags))
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001820 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001821 uint5_t rsvd;
1822 bool validFlag;
1823 bool permanent;
1824 bool biosBootType;
1825 bool lockOutResetButton;
1826 bool screenBlank;
1827 uint4_t bootDeviceSelector;
1828 bool lockKeyboard;
1829 bool cmosClear;
1830 uint8_t data3;
1831 uint4_t biosInfo;
1832 uint4_t rsvd1;
1833 uint5_t deviceInstance;
1834 uint3_t rsvd2;
1835
1836 if (data.unpack(rsvd, biosBootType, permanent, validFlag,
1837 lockOutResetButton, screenBlank, bootDeviceSelector,
1838 lockKeyboard, cmosClear, data3, biosInfo, rsvd1,
1839 deviceInstance, rsvd2) != 0 ||
1840 !data.fullyUnpacked())
1841 {
1842 return ipmi::responseReqDataLenInvalid();
1843 }
1844 if (rsvd || rsvd1 || rsvd2)
1845 {
1846 return ipmi::responseInvalidFieldRequest();
1847 }
1848
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001849 using namespace chassis::internal;
1850 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001851 auto oneTimeEnabled = false;
1852 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301853 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001854 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001855
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001856 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001857 {
James Feist225dec82019-11-26 16:25:06 -08001858 settings::Objects& objects = getObjects();
1859
Patrick Venture0b02be92018-08-31 11:55:55 -07001860 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301861
1862 oneTimeEnabled =
1863 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1864
1865 /*
1866 * Check if the current boot setting is onetime or permanent, if the
1867 * request in the command is otherwise, then set the "Enabled"
1868 * property in one_time object path to 'True' to indicate onetime
1869 * and 'False' to indicate permanent.
1870 *
1871 * Once the onetime/permanent setting is applied, then the bootMode
1872 * and bootSource is updated for the corresponding object.
1873 */
1874 if ((permanent && oneTimeEnabled) ||
1875 (!permanent && !oneTimeEnabled))
1876 {
1877 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1878
Patrick Venture0b02be92018-08-31 11:55:55 -07001879 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
1880 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301881 }
1882
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001883 auto modeItr =
1884 modeIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
1885 auto sourceItr =
1886 sourceIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001887 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001888 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001889 rc = setBootSource(sourceItr->second);
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001890 if (rc != ipmi::ccSuccess)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001891 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001892 log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
1893 "setting boot source");
1894 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001895 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001896 // If a set boot device is mapping to a boot source, then reset
1897 // the boot mode D-Bus property to default.
1898 // This way the ipmid code can determine which property is not
1899 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001900 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001901 {
1902 setBootMode(Mode::Modes::Regular);
1903 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001904 }
1905 if (modeIpmiToDbus.end() != modeItr)
1906 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001907 rc = setBootMode(modeItr->second);
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001908 if (rc != ipmi::ccSuccess)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001909 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001910 log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
1911 "setting boot mode");
1912 return ipmi::responseUnspecifiedError();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001913 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001914 // If a set boot device is mapping to a boot mode, then reset
1915 // the boot source D-Bus property to default.
1916 // This way the ipmid code can determine which property is not
1917 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001918 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001919 {
1920 setBootSource(Source::Sources::Default);
1921 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001922 }
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001923 if ((modeIpmiToDbus.end() == modeItr) &&
1924 (sourceIpmiToDbus.end() == sourceItr))
1925 {
1926 // return error if boot option is not supported
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001927 log<level::ERR>(
1928 "ipmiChassisSetSysBootOptions: Boot option not supported");
1929 return ipmi::responseInvalidFieldRequest();
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001930 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001931 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001932 catch (sdbusplus::exception_t& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001933 {
James Feist225dec82019-11-26 16:25:06 -08001934 objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001935 report<InternalFailure>();
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301936 log<level::ERR>(
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001937 "ipmiChassisSetSysBootOptions: Error in setting Boot "
1938 "flag parameters");
1939 return ipmi::responseUnspecifiedError();
Ratan Guptafd28dd72016-08-01 04:58:01 -05001940 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001941 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001942 else if (parameterSelector ==
1943 static_cast<uint7_t>(BootOptionParameter::bootInfo))
Patrick Venture0b02be92018-08-31 11:55:55 -07001944 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001945 uint8_t writeMak;
1946 uint5_t bootInitiatorAckData;
1947 uint3_t rsvd;
1948
1949 if (data.unpack(writeMak, bootInitiatorAckData, rsvd) != 0 ||
1950 !data.fullyUnpacked())
1951 {
1952 return ipmi::responseReqDataLenInvalid();
1953 }
1954 if (rsvd)
1955 {
1956 return ipmi::responseInvalidFieldRequest();
1957 }
1958 // (ccSuccess). There is no implementation in OpenBMC for this
Tom Josephf536c902017-09-25 18:08:15 +05301959 // parameter. This is added to support the ipmitool command `chassis
1960 // bootdev` which sends set on parameter #4, before setting the boot
1961 // flags.
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001962 log<level::INFO>("ipmiChassisSetSysBootOptions: bootInfo parameter set "
1963 "successfully");
1964 data.trailingOk = true;
1965 return ipmi::responseSuccess();
Patrick Venture0b02be92018-08-31 11:55:55 -07001966 }
1967 else
1968 {
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001969 if ((parameterSelector >= static_cast<uint7_t>(oemParmStart)) &&
1970 (parameterSelector <= static_cast<uint7_t>(oemParmEnd)))
1971 {
1972 if (parameterSelector ==
1973 static_cast<uint7_t>(BootOptionParameter::opalNetworkSettings))
1974 {
1975 ipmi::Cc ret = setHostNetworkData(data);
1976 if (ret != ipmi::ccSuccess)
1977 {
1978 log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
1979 "setHostNetworkData");
1980 data.trailingOk = true;
1981 return ipmi::response(ret);
1982 }
1983 data.trailingOk = true;
1984 return ipmi::responseSuccess();
1985 }
1986 else
1987 {
1988 log<level::ERR>(
1989 "ipmiChassisSetSysBootOptions: Unsupported parameters",
1990 entry("PARAM=0x%x",
1991 static_cast<uint8_t>(parameterSelector)));
1992 data.trailingOk = true;
1993 return ipmi::responseParmNotSupported();
1994 }
1995 }
1996 data.trailingOk = true;
1997 return ipmi::responseParmNotSupported();
Adriana Kobylak40814c62015-10-27 15:58:44 -05001998 }
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00001999 return ipmi::responseSuccess();
Adriana Kobylak40814c62015-10-27 15:58:44 -05002000}
2001
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002002/** @brief implements Get POH counter command
2003 * @parameter
2004 * - none
2005 * @returns IPMI completion code plus response data
2006 * - minPerCount - Minutes per count
2007 * - counterReading - counter reading
2008 */
2009ipmi::RspType<uint8_t, // Minutes per count
2010 uint32_t // Counter reading
2011 >
2012 ipmiGetPOHCounter()
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002013{
2014 // sd_bus error
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002015 try
2016 {
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002017 return ipmi::responseSuccess(static_cast<uint8_t>(poh::minutesPerCount),
2018 getPOHCounter());
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002019 }
2020 catch (std::exception& e)
2021 {
2022 log<level::ERR>(e.what());
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002023 return ipmi::responseUnspecifiedError();
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002024 }
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002025}
2026
Jason M. Billsbc996a32019-06-17 15:46:37 -07002027ipmi::RspType<uint3_t, // policy support
2028 uint5_t // reserved
2029 >
Vernon Mauerye278ead2018-10-09 09:23:43 -07002030 ipmiChassisSetPowerRestorePolicy(boost::asio::yield_context yield,
Jason M. Billsbc996a32019-06-17 15:46:37 -07002031 uint3_t policy, uint5_t reserved)
Yong Lic6713cf2018-09-12 12:35:13 +08002032{
Yong Lic6713cf2018-09-12 12:35:13 +08002033 power_policy::DbusValue value =
2034 power_policy::RestorePolicy::Policy::AlwaysOff;
2035
Jason M. Billsbc996a32019-06-17 15:46:37 -07002036 if (reserved || (policy > power_policy::noChange))
Yong Lic6713cf2018-09-12 12:35:13 +08002037 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07002038 phosphor::logging::log<level::ERR>(
2039 "Reserved request parameter",
2040 entry("REQ=0x%x", static_cast<int>(policy)));
Jason M. Billsbc996a32019-06-17 15:46:37 -07002041 return ipmi::responseInvalidFieldRequest();
Yong Lic6713cf2018-09-12 12:35:13 +08002042 }
2043
Vernon Mauerye278ead2018-10-09 09:23:43 -07002044 if (policy == power_policy::noChange)
Yong Lic6713cf2018-09-12 12:35:13 +08002045 {
2046 // just return the supported policy
Jason M. Billsbc996a32019-06-17 15:46:37 -07002047 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08002048 }
2049
2050 for (auto const& it : power_policy::dbusToIpmi)
2051 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07002052 if (it.second == policy)
Yong Lic6713cf2018-09-12 12:35:13 +08002053 {
2054 value = it.first;
2055 break;
2056 }
2057 }
2058
2059 try
2060 {
James Feist225dec82019-11-26 16:25:06 -08002061 settings::Objects& objects = chassis::internal::cache::getObjects();
Yong Lic6713cf2018-09-12 12:35:13 +08002062 const settings::Path& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -08002063 objects.map.at(chassis::internal::powerRestoreIntf).front();
Vernon Mauery16b86932019-05-01 08:36:11 -07002064 std::variant<std::string> property = convertForMessage(value);
Yong Lic6713cf2018-09-12 12:35:13 +08002065
Vernon Mauerye278ead2018-10-09 09:23:43 -07002066 auto sdbusp = getSdBus();
2067 boost::system::error_code ec;
2068 sdbusp->yield_method_call<void>(
2069 yield, ec,
James Feist225dec82019-11-26 16:25:06 -08002070 objects
Yong Lic6713cf2018-09-12 12:35:13 +08002071 .service(powerRestoreSetting,
2072 chassis::internal::powerRestoreIntf)
2073 .c_str(),
Vernon Mauerye278ead2018-10-09 09:23:43 -07002074 powerRestoreSetting, ipmi::PROP_INTF, "Set",
2075 chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
2076 property);
2077 if (ec)
Yong Lic6713cf2018-09-12 12:35:13 +08002078 {
2079 phosphor::logging::log<level::ERR>("Unspecified Error");
Vernon Mauerye278ead2018-10-09 09:23:43 -07002080 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08002081 }
2082 }
2083 catch (InternalFailure& e)
2084 {
James Feist225dec82019-11-26 16:25:06 -08002085 chassis::internal::cache::objectsPtr.reset();
Yong Lic6713cf2018-09-12 12:35:13 +08002086 report<InternalFailure>();
Vernon Mauerye278ead2018-10-09 09:23:43 -07002087 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08002088 }
2089
Jason M. Billsbc996a32019-06-17 15:46:37 -07002090 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08002091}
2092
Kuiying Wang21addc52019-01-04 10:50:21 +08002093ipmi::RspType<> ipmiSetFrontPanelButtonEnables(
2094 ipmi::Context::ptr ctx, bool disablePowerButton, bool disableResetButton,
2095 bool disableDiagButton, bool disableSleepButton, uint4_t reserved)
2096{
2097 using namespace chassis::internal;
2098
2099 // set power button Enabled property
2100 bool success = setButtonEnabled(ctx, powerButtonPath, powerButtonIntf,
2101 !disablePowerButton);
2102
2103 // set reset button Enabled property
2104 success &= setButtonEnabled(ctx, resetButtonPath, resetButtonIntf,
2105 !disableResetButton);
2106
2107 if (!success)
2108 {
2109 // not all buttons were successfully set
2110 return ipmi::responseUnspecifiedError();
2111 }
2112 return ipmi::responseSuccess();
2113}
2114
Adriana Kobylak40814c62015-10-27 15:58:44 -05002115void register_netfn_chassis_functions()
2116{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05002117 createIdentifyTimer();
2118
Tom05732372016-09-06 17:21:23 +05302119 // Get Chassis Capabilities
anil kumar appana43263c62019-05-27 12:45:04 +00002120 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2121 ipmi::chassis::cmdGetChassisCapabilities,
2122 ipmi::Privilege::User, ipmiGetChassisCap);
Nan Li8d15fb42016-08-16 22:29:40 +08002123
Kuiying Wang21addc52019-01-04 10:50:21 +08002124 // Set Front Panel Button Enables
2125 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2126 ipmi::chassis::cmdSetFrontPanelButtonEnables,
2127 ipmi::Privilege::Admin,
2128 ipmiSetFrontPanelButtonEnables);
2129
Yong Liae4b0402018-11-02 11:12:14 +08002130 // Set Chassis Capabilities
anil kumar appana894d0222019-05-27 16:32:14 +00002131 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2132 ipmi::chassis::cmdSetChassisCapabilities,
2133 ipmi::Privilege::User, ipmiSetChassisCap);
Yong Liae4b0402018-11-02 11:12:14 +08002134
Tom05732372016-09-06 17:21:23 +05302135 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05302136 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07002137 ipmi_chassis_get_sys_boot_options,
2138 PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05002139
Tom05732372016-09-06 17:21:23 +05302140 // <Get Chassis Status>
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07002141 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2142 ipmi::chassis::cmdGetChassisStatus,
2143 ipmi::Privilege::User, ipmiGetChassisStatus);
Nan Lifdd8ec52016-08-28 03:57:40 +08002144
Vijay Khemka074f64d2020-03-03 15:08:43 -08002145 // <Chassis Get System Restart Cause>
2146 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2147 ipmi::chassis::cmdGetSystemRestartCause,
2148 ipmi::Privilege::User, ipmiGetSystemRestartCause);
2149
Tom05732372016-09-06 17:21:23 +05302150 // <Chassis Control>
anil kumar appanadafff5f2019-04-27 18:06:00 +00002151 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2152 ipmi::chassis::cmdChassisControl,
2153 ipmi::Privilege::Operator, ipmiChassisControl);
shgoupfd84fbbf2015-12-17 10:05:51 +08002154
Tom Joseph5110c122018-03-23 17:55:40 +05302155 // <Chassis Identify>
Vernon Mauery400cc782018-10-09 13:49:53 -07002156 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2157 ipmi::chassis::cmdChassisIdentify,
2158 ipmi::Privilege::Operator, ipmiChassisIdentify);
Tom Joseph5110c122018-03-23 17:55:40 +05302159
Tom05732372016-09-06 17:21:23 +05302160 // <Set System Boot Options>
jayaprakash Mutyalabfd8fc42020-05-05 22:38:03 +00002161 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2162 ipmi::chassis::cmdSetSystemBootOptions,
2163 ipmi::Privilege::Operator,
2164 ipmiChassisSetSysBootOptions);
2165
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05002166 // <Get POH Counter>
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00002167 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2168 ipmi::chassis::cmdGetPohCounter,
2169 ipmi::Privilege::User, ipmiGetPOHCounter);
Yong Lic6713cf2018-09-12 12:35:13 +08002170
2171 // <Set Power Restore Policy>
Vernon Mauerye278ead2018-10-09 09:23:43 -07002172 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
2173 ipmi::chassis::cmdSetPowerRestorePolicy,
2174 ipmi::Privilege::Operator,
2175 ipmiChassisSetPowerRestorePolicy);
vishwa36993272015-11-20 12:43:49 -06002176}