blob: 734ccde555fcb4e896c4ea4c6430c94a4c07e383 [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
Patrick Venture0b02be92018-08-31 11:55:55 -070037// Defines
38#define SET_PARM_VERSION 0x01
Vernon Mauery1181af72018-10-08 12:05:00 -070039#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40
40#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80
41#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0
ratagupta6f6bff2016-04-04 06:20:11 -050042
Lei YU4b0ddb62019-01-25 16:43:50 +080043std::unique_ptr<phosphor::Timer> identifyTimer
44 __attribute__((init_priority(101)));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050045
Yong Lif4e38512019-05-21 14:46:55 +080046static ChassisIDState chassisIDState = ChassisIDState::reserved;
47
Patrick Venture0b02be92018-08-31 11:55:55 -070048constexpr size_t SIZE_MAC = 18;
49constexpr size_t SIZE_BOOT_OPTION = (uint8_t)
50 BootOptionResponseSize::OPAL_NETWORK_SETTINGS; // Maximum size of the boot
51 // option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050052constexpr size_t SIZE_PREFIX = 7;
53constexpr size_t MAX_PREFIX_VALUE = 32;
54constexpr size_t SIZE_COOKIE = 4;
55constexpr size_t SIZE_VERSION = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053056constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053057
Patrick Venture0b02be92018-08-31 11:55:55 -070058// PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053059static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
Patrick Venture0b02be92018-08-31 11:55:55 -070060 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050061
62static constexpr size_t COOKIE_OFFSET = 1;
63static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053064static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050065static constexpr size_t MAC_OFFSET = 9;
66static constexpr size_t ADDRTYPE_OFFSET = 16;
67static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050068
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050069static constexpr size_t encIdentifyObjectsSize = 1;
70static constexpr size_t chassisIdentifyReqLength = 2;
71static constexpr size_t identifyIntervalPos = 0;
72static constexpr size_t forceIdentifyPos = 1;
shgoupfd84fbbf2015-12-17 10:05:51 +080073
Adriana Kobylak40814c62015-10-27 15:58:44 -050074void register_netfn_chassis_functions() __attribute__((constructor));
75
shgoupfd84fbbf2015-12-17 10:05:51 +080076// Host settings in dbus
77// Service name should be referenced by connection name got via object mapper
Patrick Venture0b02be92018-08-31 11:55:55 -070078const char* settings_object_name = "/org/openbmc/settings/host0";
79const char* settings_intf_name = "org.freedesktop.DBus.Properties";
Patrick Venture0b02be92018-08-31 11:55:55 -070080const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053081 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080082
Ratan Guptadcb10672017-07-10 10:33:50 +053083constexpr auto SETTINGS_ROOT = "/";
84constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053085
86constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
87constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
88
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050089static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
90static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -070091 "xyz.openbmc_project.State.PowerOnHours";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -050092static constexpr auto pOHCounterProperty = "POHCounter";
93static constexpr auto match = "chassis0";
Yong Liae4b0402018-11-02 11:12:14 +080094const static constexpr char chassisCapIntf[] =
95 "xyz.openbmc_project.Control.ChassisCapabilities";
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -080096const static constexpr char chassisIntrusionProp[] = "ChassisIntrusionEnabled";
97const static constexpr char chassisFrontPanelLockoutProp[] =
98 "ChassisFrontPanelLockoutEnabled";
99const static constexpr char chassisNMIProp[] = "ChassisNMIEnabled";
100const static constexpr char chassisPowerInterlockProp[] =
101 "ChassisPowerInterlockEnabled";
Yong Liae4b0402018-11-02 11:12:14 +0800102const static constexpr char chassisFRUDevAddrProp[] = "FRUDeviceAddress";
103const static constexpr char chassisSDRDevAddrProp[] = "SDRDeviceAddress";
104const static constexpr char chassisSELDevAddrProp[] = "SELDeviceAddress";
105const static constexpr char chassisSMDevAddrProp[] = "SMDeviceAddress";
106const static constexpr char chassisBridgeDevAddrProp[] = "BridgeDeviceAddress";
107static constexpr uint8_t chassisCapFlagMask = 0x0f;
108static constexpr uint8_t chassisCapAddrMask = 0xfe;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700109static constexpr const char* powerButtonIntf =
110 "xyz.openbmc_project.Chassis.Buttons.Power";
111static constexpr const char* powerButtonPath =
112 "/xyz/openbmc_project/Chassis/Buttons/Power0";
113static constexpr const char* resetButtonIntf =
114 "xyz.openbmc_project.Chassis.Buttons.Reset";
115static constexpr const char* resetButtonPath =
116 "/xyz/openbmc_project/Chassis/Buttons/Reset0";
Ratan Guptadcb10672017-07-10 10:33:50 +0530117
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530118// Phosphor Host State manager
119namespace State = sdbusplus::xyz::openbmc_project::State::server;
120
Vernon Mauery185b9f82018-07-20 10:52:36 -0700121namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500122
Ratan Guptadcb10672017-07-10 10:33:50 +0530123using namespace phosphor::logging;
124using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500125using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
William A. Kennington III4c008022018-10-12 17:18:14 -0700126
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500127namespace chassis
128{
129namespace internal
130{
131
132constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
133constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500134constexpr auto powerRestoreIntf =
135 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500136sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
137
138namespace cache
139{
140
James Feist225dec82019-11-26 16:25:06 -0800141std::unique_ptr<settings::Objects> objectsPtr = nullptr;
142
143settings::Objects& getObjects()
144{
145 if (objectsPtr == nullptr)
146 {
147 objectsPtr = std::make_unique<settings::Objects>(
148 dbus, std::vector<std::string>{bootModeIntf, bootSourceIntf,
149 powerRestoreIntf});
150 }
151 return *objectsPtr;
152}
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500153
154} // namespace cache
155} // namespace internal
156} // namespace chassis
157
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500158namespace poh
159{
160
161constexpr auto minutesPerCount = 60;
162
163} // namespace poh
164
Patrick Venture0b02be92018-08-31 11:55:55 -0700165struct get_sys_boot_options_t
166{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500167 uint8_t parameter;
168 uint8_t set;
169 uint8_t block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700170} __attribute__((packed));
Adriana Kobylak40814c62015-10-27 15:58:44 -0500171
Patrick Venture0b02be92018-08-31 11:55:55 -0700172struct get_sys_boot_options_response_t
173{
shgoupfd84fbbf2015-12-17 10:05:51 +0800174 uint8_t version;
175 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500176 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700177} __attribute__((packed));
shgoupfd84fbbf2015-12-17 10:05:51 +0800178
Patrick Venture0b02be92018-08-31 11:55:55 -0700179struct set_sys_boot_options_t
180{
shgoupfd84fbbf2015-12-17 10:05:51 +0800181 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500182 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700183} __attribute__((packed));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500184
Ratan Guptadcb10672017-07-10 10:33:50 +0530185int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500186{
Ratan Guptadcb10672017-07-10 10:33:50 +0530187 ipmi::PropertyMap properties;
188 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530189 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500190
Ratan Guptadcb10672017-07-10 10:33:50 +0530191 try
192 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700193 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530194 // objects,to handle such cases we are interested on that object
195 // which are on interested busname.
196 // Currenlty mapper doesn't give the readable busname(gives busid)
197 // so we can't match with bus name so giving some object specific info
198 // as SETTINGS_MATCH.
199 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500200
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530201 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530202
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530203 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
204 SETTINGS_ROOT, SETTINGS_MATCH);
205
206 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
207 SETTINGS_ROOT, SETTINGS_MATCH);
208
Patrick Venture0b02be92018-08-31 11:55:55 -0700209 properties = ipmi::getAllDbusProperties(
210 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
211 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
212 macObjectInfo.first, MAC_INTERFACE,
213 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530214
Vernon Maueryf442e112019-04-09 11:44:36 -0700215 auto ipAddress = std::get<std::string>(properties["Address"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530216
Vernon Maueryf442e112019-04-09 11:44:36 -0700217 auto gateway = std::get<std::string>(properties["Gateway"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530218
Vernon Maueryf442e112019-04-09 11:44:36 -0700219 auto prefix = std::get<uint8_t>(properties["PrefixLength"]);
Ratan Guptad70f4532017-08-04 02:07:31 +0530220
Patrick Venture0b02be92018-08-31 11:55:55 -0700221 uint8_t isStatic =
Vernon Maueryf442e112019-04-09 11:44:36 -0700222 (std::get<std::string>(properties["Origin"]) ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700223 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
224 ? 1
225 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530226
Vernon Maueryf442e112019-04-09 11:44:36 -0700227 auto MACAddress = std::get<std::string>(variant);
Ratan Guptacc8feb42017-07-25 21:52:10 +0530228
Ratan Guptad70f4532017-08-04 02:07:31 +0530229 // it is expected here that we should get the valid data
230 // but we may also get the default values.
231 // Validation of the data is done by settings.
232 //
233 // if mac address is default mac address then
234 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530235 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530236 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700237 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530238 rc = -1;
239 return rc;
240 }
241 // if addr is static then ipaddress,gateway,prefix
242 // should not be default one,don't send blank override.
243 if (isStatic)
244 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700245 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
246 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530247 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700248 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptad70f4532017-08-04 02:07:31 +0530249 rc = -1;
250 return rc;
251 }
252 }
253
Patrick Venture0b02be92018-08-31 11:55:55 -0700254 sscanf(
255 MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
256 (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
257 (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
258 (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
Ratan Guptadcb10672017-07-10 10:33:50 +0530259
Ratan Guptadcb10672017-07-10 10:33:50 +0530260 respptr->data[MAC_OFFSET + 6] = 0x00;
261
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700262 std::memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
263 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530264
Vernon Maueryf442e112019-04-09 11:44:36 -0700265 uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
266 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
267 ? AF_INET
268 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530269
Patrick Venture0b02be92018-08-31 11:55:55 -0700270 addrSize = (addressFamily == AF_INET)
271 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
272 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530273
274 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530275 inet_pton(addressFamily, ipAddress.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700276 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530277
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530278 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
279
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700280 std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530281
282 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
283
Ratan Guptad70f4532017-08-04 02:07:31 +0530284 inet_pton(addressFamily, gateway.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700285 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530286 }
287 catch (InternalFailure& e)
288 {
289 commit<InternalFailure>();
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700290 std::memset(respptr->data, 0, SIZE_BOOT_OPTION);
Ratan Guptadcb10672017-07-10 10:33:50 +0530291 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500292 return rc;
293 }
294
Patrick Venture0b02be92018-08-31 11:55:55 -0700295 // PetiBoot-Specific
296 // If success then copy the first 9 bytes to the data
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700297 std::memcpy(respptr->data, net_conf_initial_bytes,
298 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500299
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700300 std::memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530301
Ratan Guptafd28dd72016-08-01 04:58:01 -0500302#ifdef _IPMI_DEBUG_
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700303 std::printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500304
Ratan Guptadcb10672017-07-10 10:33:50 +0530305 for (uint8_t pos = 0; pos < index; pos++)
306 {
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700307 std::printf("%02x ", respptr->data[pos]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530308 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500309#endif
310
Ratan Guptafd28dd72016-08-01 04:58:01 -0500311 return rc;
312}
313
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530314/** @brief convert IPv4 and IPv6 addresses from binary to text form.
315 * @param[in] family - IPv4/Ipv6
316 * @param[in] data - req data pointer.
317 * @param[in] offset - offset in the data.
318 * @param[in] addrSize - size of the data which needs to be read from offset.
319 * @returns address in text form.
320 */
321
Patrick Venture0b02be92018-08-31 11:55:55 -0700322std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
323 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530324{
325 char ipAddr[INET6_ADDRSTRLEN] = {};
326
Patrick Venture0b02be92018-08-31 11:55:55 -0700327 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530328 {
329 case AF_INET:
330 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700331 struct sockaddr_in addr4
332 {
333 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700334 std::memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530335
Patrick Venture0b02be92018-08-31 11:55:55 -0700336 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530337
338 break;
339 }
340 case AF_INET6:
341 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700342 struct sockaddr_in6 addr6
343 {
344 };
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700345 std::memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530346
Patrick Venture0b02be92018-08-31 11:55:55 -0700347 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530348
349 break;
350 }
351 default:
352 {
353 return {};
354 }
355 }
356
357 return ipAddr;
358}
359
Ratan Guptadcb10672017-07-10 10:33:50 +0530360int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500361{
Ratan Guptadcb10672017-07-10 10:33:50 +0530362 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500363 std::string host_network_config;
Patrick Venture0b02be92018-08-31 11:55:55 -0700364 char mac[]{"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530365 std::string ipAddress, gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700366 char addrOrigin{0};
367 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530368 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530369 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700370 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
371 uint8_t prefix{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530372 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530373 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500374
Patrick Venture0b02be92018-08-31 11:55:55 -0700375 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500376 // version starts from sixth byte
377
Ratan Guptadcb10672017-07-10 10:33:50 +0530378 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500379 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530380 do
381 {
382 // cookie == 0x21 0x70 0x62 0x21
383 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700384 (net_conf_initial_bytes + COOKIE_OFFSET),
385 SIZE_COOKIE) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530386 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700387 // cookie == 0
388 if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
389 SIZE_COOKIE) == 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530390 {
391 // need to zero out the network settings.
392 break;
393 }
394
395 log<level::ERR>("Invalid Cookie");
396 elog<InternalFailure>();
397 }
398
399 // vesion == 0x00 0x01
400 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700401 (net_conf_initial_bytes + VERSION_OFFSET),
402 SIZE_VERSION) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530403 {
404
405 log<level::ERR>("Invalid Version");
406 elog<InternalFailure>();
407 }
408
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700409 std::snprintf(
410 mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
411 reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
412 reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
413 reqptr->data[MAC_OFFSET + 4], reqptr->data[MAC_OFFSET + 5]);
Ratan Guptadcb10672017-07-10 10:33:50 +0530414
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700415 std::memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
416 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530417
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530418 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530419 {
420 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530421 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530422 }
423
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530424 // Get the address size
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700425 std::memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
426 sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530427
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530428 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530429
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700430 std::memcpy(&prefix, &(reqptr->data[prefixOffset]),
431 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530432
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530433 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
434
Ratan Gupta8c31d232017-08-13 05:49:43 +0530435 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530436 {
437 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
438 family = AF_INET6;
439 }
440
Patrick Venture0b02be92018-08-31 11:55:55 -0700441 ipAddress =
442 getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530443
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530444 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
445
Patrick Venture0b02be92018-08-31 11:55:55 -0700446 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530447
Patrick Venture0b02be92018-08-31 11:55:55 -0700448 // Cookie == 0 or it is a valid cookie
449 host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
450 std::to_string(prefix) + ",gateway="s + gateway +
451 ",mac="s + mac + ",addressOrigin="s +
452 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500453
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530454 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
455
456 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
457 SETTINGS_ROOT, SETTINGS_MATCH);
458 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
459 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530460 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530461 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700462 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530463 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700464 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530465 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700466 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530467 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700468 IP_INTERFACE, "Gateway", std::string(gateway));
469 ipmi::setDbusProperty(
470 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
471 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530472 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700473 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500474
Patrick Venture0b02be92018-08-31 11:55:55 -0700475 log<level::DEBUG>(
476 "Network configuration changed",
477 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500478 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530479 catch (InternalFailure& e)
480 {
481 commit<InternalFailure>();
482 return -1;
483 }
484
485 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500486}
487
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500488uint32_t getPOHCounter()
489{
490 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
491
Patrick Venture0b02be92018-08-31 11:55:55 -0700492 auto chassisStateObj =
493 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500494
Patrick Venture0b02be92018-08-31 11:55:55 -0700495 auto service =
496 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500497
Patrick Venture0b02be92018-08-31 11:55:55 -0700498 auto propValue =
499 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
500 chassisPOHStateIntf, pOHCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500501
Vernon Maueryf442e112019-04-09 11:44:36 -0700502 return std::get<uint32_t>(propValue);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500503}
504
anil kumar appana43263c62019-05-27 12:45:04 +0000505/** @brief Implements the get chassis capabilities command
506 *
507 * @returns IPMI completion code plus response data
508 * chassisCapFlags - chassis capability flag
509 * chassisFRUInfoDevAddr - chassis FRU info Device Address
510 * chassisSDRDevAddr - chassis SDR device address
511 * chassisSELDevAddr - chassis SEL device address
512 * chassisSMDevAddr - chassis system management device address
513 * chassisBridgeDevAddr - chassis bridge device address
514 */
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800515ipmi::RspType<bool, // chassis intrusion sensor
516 bool, // chassis Front panel lockout
517 bool, // chassis NMI
518 bool, // chassis power interlock
519 uint4_t, // reserved
anil kumar appana43263c62019-05-27 12:45:04 +0000520 uint8_t, // chassis FRU info Device Address
521 uint8_t, // chassis SDR device address
522 uint8_t, // chassis SEL device address
523 uint8_t, // chassis system management device address
524 uint8_t // chassis bridge device address
525 >
526 ipmiGetChassisCap()
Nan Li8d15fb42016-08-16 22:29:40 +0800527{
anil kumar appana43263c62019-05-27 12:45:04 +0000528 ipmi::PropertyMap properties;
Yong Liae4b0402018-11-02 11:12:14 +0800529 try
530 {
531 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
Nan Li8d15fb42016-08-16 22:29:40 +0800532
Yong Liae4b0402018-11-02 11:12:14 +0800533 ipmi::DbusObjectInfo chassisCapObject =
534 ipmi::getDbusObject(bus, chassisCapIntf);
Nan Li8d15fb42016-08-16 22:29:40 +0800535
Yong Liae4b0402018-11-02 11:12:14 +0800536 // capabilities flags
537 // [7..4] - reserved
538 // [3] – 1b = provides power interlock (IPM 1.5)
539 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
540 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis
541 // has capabilities
542 // to lock out external power control and reset button or
543 // front panel interfaces and/or detect tampering with those
544 // interfaces).
545 // [0] -1b = Chassis provides intrusion (physical security) sensor.
546 // set to default value 0x0.
Nan Li8d15fb42016-08-16 22:29:40 +0800547
anil kumar appana43263c62019-05-27 12:45:04 +0000548 properties =
549 ipmi::getAllDbusProperties(bus, chassisCapObject.second,
550 chassisCapObject.first, chassisCapIntf);
Yong Liae4b0402018-11-02 11:12:14 +0800551 }
552 catch (std::exception& e)
553 {
anil kumar appana43263c62019-05-27 12:45:04 +0000554 log<level::ERR>("Failed to fetch Chassis Capability properties",
555 entry("ERROR=%s", e.what()));
556 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800557 }
558
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800559 bool* chassisIntrusionFlag =
560 std::get_if<bool>(&properties[chassisIntrusionProp]);
561 if (chassisIntrusionFlag == nullptr)
anil kumar appana43263c62019-05-27 12:45:04 +0000562 {
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800563 log<level::ERR>("Error to get chassis Intrusion flags");
564 return ipmi::responseUnspecifiedError();
565 }
566 bool* chassisFrontPanelFlag =
567 std::get_if<bool>(&properties[chassisFrontPanelLockoutProp]);
568 if (chassisFrontPanelFlag == nullptr)
569 {
570 log<level::ERR>("Error to get chassis intrusion flags");
571 return ipmi::responseUnspecifiedError();
572 }
573 bool* chassisNMIFlag = std::get_if<bool>(&properties[chassisNMIProp]);
574 if (chassisNMIFlag == nullptr)
575 {
576 log<level::ERR>("Error to get chassis NMI flags");
577 return ipmi::responseUnspecifiedError();
578 }
579 bool* chassisPowerInterlockFlag =
580 std::get_if<bool>(&properties[chassisPowerInterlockProp]);
581 if (chassisPowerInterlockFlag == nullptr)
582 {
583 log<level::ERR>("Error to get chassis power interlock flags");
anil kumar appana43263c62019-05-27 12:45:04 +0000584 return ipmi::responseUnspecifiedError();
585 }
586 uint8_t* chassisFRUInfoDevAddr =
587 std::get_if<uint8_t>(&properties[chassisFRUDevAddrProp]);
588 if (chassisFRUInfoDevAddr == nullptr)
589 {
590 log<level::ERR>("Error to get chassis FRU info device address");
591 return ipmi::responseUnspecifiedError();
592 }
593 uint8_t* chassisSDRDevAddr =
594 std::get_if<uint8_t>(&properties[chassisSDRDevAddrProp]);
595 if (chassisSDRDevAddr == nullptr)
596 {
597 log<level::ERR>("Error to get chassis SDR device address");
598 return ipmi::responseUnspecifiedError();
599 }
600 uint8_t* chassisSELDevAddr =
601 std::get_if<uint8_t>(&properties[chassisSELDevAddrProp]);
602 if (chassisSELDevAddr == nullptr)
603 {
604 log<level::ERR>("Error to get chassis SEL device address");
605 return ipmi::responseUnspecifiedError();
606 }
607 uint8_t* chassisSMDevAddr =
608 std::get_if<uint8_t>(&properties[chassisSMDevAddrProp]);
609 if (chassisSMDevAddr == nullptr)
610 {
611 log<level::ERR>("Error to get chassis SM device address");
612 return ipmi::responseUnspecifiedError();
613 }
614 uint8_t* chassisBridgeDevAddr =
615 std::get_if<uint8_t>(&properties[chassisBridgeDevAddrProp]);
616 if (chassisBridgeDevAddr == nullptr)
617 {
618 log<level::ERR>("Error to get chassis bridge device address");
619 return ipmi::responseUnspecifiedError();
620 }
621
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800622 return ipmi::responseSuccess(*chassisIntrusionFlag, *chassisFrontPanelFlag,
623 *chassisNMIFlag, *chassisPowerInterlockFlag, 0,
624 *chassisFRUInfoDevAddr, *chassisSDRDevAddr,
625 *chassisSELDevAddr, *chassisSMDevAddr,
626 *chassisBridgeDevAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800627}
628
anil kumar appana894d0222019-05-27 16:32:14 +0000629/** @brief implements set chassis capalibities command
630 * @param intrusion - chassis intrusion
631 * @param fpLockout - frontpannel lockout
632 * @param reserved1 - skip one bit
633 * @param fruDeviceAddr - chassis FRU info Device Address
634 * @param sdrDeviceAddr - chassis SDR device address
635 * @param selDeviceAddr - chassis SEL device address
636 * @param smDeviceAddr - chassis system management device address
637 * @param bridgeDeviceAddr - chassis bridge device address
638 *
639 * @returns IPMI completion code
640 */
641ipmi::RspType<> ipmiSetChassisCap(bool intrusion, bool fpLockout,
642 uint6_t reserved1,
643
644 uint8_t fruDeviceAddr,
645
646 uint8_t sdrDeviceAddr,
647
648 uint8_t selDeviceAddr,
649
650 uint8_t smDeviceAddr,
651
652 uint8_t bridgeDeviceAddr)
Yong Liae4b0402018-11-02 11:12:14 +0800653{
Yong Liae4b0402018-11-02 11:12:14 +0800654
655 // check input data
anil kumar appana894d0222019-05-27 16:32:14 +0000656 if (reserved1 != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800657 {
anil kumar appana894d0222019-05-27 16:32:14 +0000658 log<level::ERR>("Unsupported request parameter");
659 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800660 }
661
anil kumar appana894d0222019-05-27 16:32:14 +0000662 if ((fruDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800663 {
664 log<level::ERR>("Unsupported request parameter(FRU Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000665 entry("REQ=0x%x", fruDeviceAddr));
666 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800667 }
anil kumar appana894d0222019-05-27 16:32:14 +0000668 if ((sdrDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800669 {
670 log<level::ERR>("Unsupported request parameter(SDR Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000671 entry("REQ=0x%x", sdrDeviceAddr));
672 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800673 }
674
anil kumar appana894d0222019-05-27 16:32:14 +0000675 if ((selDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800676 {
677 log<level::ERR>("Unsupported request parameter(SEL Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000678 entry("REQ=0x%x", selDeviceAddr));
679 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800680 }
681
anil kumar appana894d0222019-05-27 16:32:14 +0000682 if ((smDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800683 {
anil kumar appana894d0222019-05-27 16:32:14 +0000684 log<level::ERR>("Unsupported request parameter(SM Addr)",
685 entry("REQ=0x%x", smDeviceAddr));
686 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800687 }
688
anil kumar appana894d0222019-05-27 16:32:14 +0000689 if ((bridgeDeviceAddr & ~chassisCapAddrMask) != 0)
Yong Liae4b0402018-11-02 11:12:14 +0800690 {
691 log<level::ERR>("Unsupported request parameter(Bridge Addr)",
anil kumar appana894d0222019-05-27 16:32:14 +0000692 entry("REQ=0x%x", bridgeDeviceAddr));
693 return ipmi::responseInvalidFieldRequest();
Yong Liae4b0402018-11-02 11:12:14 +0800694 }
695
696 try
697 {
698 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
699 ipmi::DbusObjectInfo chassisCapObject =
700 ipmi::getDbusObject(bus, chassisCapIntf);
701
702 ipmi::setDbusProperty(bus, chassisCapObject.second,
703 chassisCapObject.first, chassisCapIntf,
Karthick Sundarrajan86d8bd72019-11-26 12:48:50 -0800704 chassisIntrusionProp, intrusion);
705
706 ipmi::setDbusProperty(bus, chassisCapObject.second,
707 chassisCapObject.first, chassisCapIntf,
708 chassisFrontPanelLockoutProp, fpLockout);
Yong Liae4b0402018-11-02 11:12:14 +0800709
710 ipmi::setDbusProperty(bus, chassisCapObject.second,
711 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000712 chassisFRUDevAddrProp, fruDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800713
714 ipmi::setDbusProperty(bus, chassisCapObject.second,
715 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000716 chassisSDRDevAddrProp, sdrDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800717
718 ipmi::setDbusProperty(bus, chassisCapObject.second,
719 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000720 chassisSELDevAddrProp, selDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800721
722 ipmi::setDbusProperty(bus, chassisCapObject.second,
723 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000724 chassisSMDevAddrProp, smDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800725
726 ipmi::setDbusProperty(bus, chassisCapObject.second,
727 chassisCapObject.first, chassisCapIntf,
anil kumar appana894d0222019-05-27 16:32:14 +0000728 chassisBridgeDevAddrProp, bridgeDeviceAddr);
Yong Liae4b0402018-11-02 11:12:14 +0800729 }
730 catch (std::exception& e)
731 {
732 log<level::ERR>(e.what());
anil kumar appana894d0222019-05-27 16:32:14 +0000733 return ipmi::responseUnspecifiedError();
Yong Liae4b0402018-11-02 11:12:14 +0800734 }
anil kumar appana894d0222019-05-27 16:32:14 +0000735 return ipmi::responseSuccess();
Nan Li8d15fb42016-08-16 22:29:40 +0800736}
737
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530738//------------------------------------------
739// Calls into Host State Manager Dbus object
740//------------------------------------------
741int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600742{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500743 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700744 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500745 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700746 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
747 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530748
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500749 // sd_bus error
750 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700751 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600752
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500753 // SD Bus error report mechanism.
754 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600755
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500756 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700757 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500758 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
759 if (rc < 0)
760 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700761 log<level::ERR>(
762 "Failed to get bus name",
763 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500764 return rc;
765 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530766
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500767 // Convert to string equivalent of the passed in transition enum.
768 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530769
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500770 rc = sd_bus_call_method(bus_type, // On the system bus
771 busname, // Service to contact
772 HOST_STATE_MANAGER_ROOT, // Object path
773 DBUS_PROPERTY_IFACE, // Interface name
774 "Set", // Method to be called
775 &bus_error, // object to return error
776 nullptr, // Response buffer if any
777 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700778 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
779 request.c_str());
780 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500781 {
782 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530783 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500784 }
785 else
786 {
787 log<level::INFO>("Transition request initiated successfully");
788 }
vishwa36993272015-11-20 12:43:49 -0600789
790 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500791 free(busname);
vishwa36993272015-11-20 12:43:49 -0600792
Sergey Solomineb9b8142016-08-23 09:07:28 -0500793 return rc;
vishwa36993272015-11-20 12:43:49 -0600794}
795
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +0800796//------------------------------------------
797// Set Enabled property to inform NMI source
798// handling to trigger a NMI_OUT BSOD.
799//------------------------------------------
800int setNmiProperty(const bool value)
801{
802 constexpr const char* nmiSourceObjPath =
803 "/xyz/openbmc_project/Chassis/Control/NMISource";
804 constexpr const char* nmiSourceIntf =
805 "xyz.openbmc_project.Chassis.Control.NMISource";
806 std::string bmcSourceSignal = "xyz.openbmc_project.Chassis.Control."
807 "NMISource.BMCSourceSignal.ChassisCmd";
808 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
809
810 try
811 {
812 auto service = ipmi::getService(*busp, nmiSourceIntf, nmiSourceObjPath);
813 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
814 "BMCSource", bmcSourceSignal);
815 ipmi::setDbusProperty(*busp, service, nmiSourceObjPath, nmiSourceIntf,
816 "Enabled", value);
817 }
818 catch (std::exception& e)
819 {
820 log<level::ERR>("Failed to trigger NMI_OUT",
821 entry("EXCEPTION=%s", e.what()));
822 return -1;
823 }
824
825 return 0;
826}
827
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500828namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500829{
Nan Lifdd8ec52016-08-28 03:57:40 +0800830
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500831using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
832using IpmiValue = uint8_t;
833using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800834
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700835const std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500836 {RestorePolicy::Policy::AlwaysOff, 0x00},
837 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700838 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800839
Yong Lic6713cf2018-09-12 12:35:13 +0800840static constexpr uint8_t noChange = 0x03;
841static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700842
843/* helper function for Get Chassis Status Command
844 */
845std::optional<uint2_t> getPowerRestorePolicy()
846{
847 uint2_t restorePolicy = 0;
848 using namespace chassis::internal;
849
James Feist225dec82019-11-26 16:25:06 -0800850 settings::Objects& objects = cache::getObjects();
851
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700852 try
853 {
854 const auto& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -0800855 objects.map.at(powerRestoreIntf).front();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700856 ipmi::Value result = ipmi::getDbusProperty(
857 *getSdBus(),
James Feist225dec82019-11-26 16:25:06 -0800858 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700859 powerRestoreSetting.c_str(), powerRestoreIntf,
860 "PowerRestorePolicy");
861 auto powerRestore = RestorePolicy::convertPolicyFromString(
862 std::get<std::string>(result));
863 restorePolicy = dbusToIpmi.at(powerRestore);
864 }
865 catch (const std::exception& e)
866 {
867 log<level::ERR>(
868 "Failed to fetch pgood property", entry("ERROR=%s", e.what()),
James Feist225dec82019-11-26 16:25:06 -0800869 entry("PATH=%s", objects.map.at(powerRestoreIntf).front().c_str()),
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700870 entry("INTERFACE=%s", powerRestoreIntf));
James Feist225dec82019-11-26 16:25:06 -0800871 cache::objectsPtr.reset();
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700872 return std::nullopt;
873 }
874 return std::make_optional(restorePolicy);
875}
876
877/*
878 * getPowerStatus
879 * helper function for Get Chassis Status Command
880 * return - optional value for pgood (no value on error)
881 */
882std::optional<bool> getPowerStatus()
883{
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700884 bool powerGood = false;
885 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
886 try
887 {
Jason M. Bills3de424c2019-05-21 09:57:16 -0700888 constexpr const char* chassisStatePath =
889 "/xyz/openbmc_project/state/chassis0";
890 constexpr const char* chassisStateIntf =
891 "xyz.openbmc_project.State.Chassis";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700892 auto service =
Jason M. Bills3de424c2019-05-21 09:57:16 -0700893 ipmi::getService(*busp, chassisStateIntf, chassisStatePath);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700894
Jason M. Bills3de424c2019-05-21 09:57:16 -0700895 ipmi::Value powerState =
896 ipmi::getDbusProperty(*busp, service, chassisStatePath,
897 chassisStateIntf, "CurrentPowerState");
898 powerGood = std::get<std::string>(powerState) ==
899 "xyz.openbmc_project.State.Chassis.PowerState.On";
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700900 }
901 catch (const std::exception& e)
902 {
903 try
904 {
905 // FIXME: some legacy modules use the older path; try that next
906 constexpr const char* legacyPwrCtrlObj =
907 "/org/openbmc/control/power0";
908 constexpr const char* legacyPwrCtrlIntf =
909 "org.openbmc.control.Power";
910 auto service =
911 ipmi::getService(*busp, legacyPwrCtrlIntf, legacyPwrCtrlObj);
912
913 ipmi::Value variant = ipmi::getDbusProperty(
914 *busp, service, legacyPwrCtrlObj, legacyPwrCtrlIntf, "pgood");
915 powerGood = static_cast<bool>(std::get<int>(variant));
916 }
917 catch (const std::exception& e)
918 {
919 log<level::ERR>("Failed to fetch pgood property",
Jason M. Bills3de424c2019-05-21 09:57:16 -0700920 entry("ERROR=%s", e.what()));
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700921 return std::nullopt;
922 }
923 }
924 return std::make_optional(powerGood);
925}
926
Yong Li70ce7352019-05-16 21:15:27 +0800927/*
928 * getACFailStatus
929 * helper function for Get Chassis Status Command
930 * return - bool value for ACFail (false on error)
931 */
932bool getACFailStatus()
933{
934 constexpr const char* powerControlObj =
935 "/xyz/openbmc_project/Chassis/Control/Power0";
936 constexpr const char* powerControlIntf =
937 "xyz.openbmc_project.Chassis.Control.Power";
938 bool acFail = false;
939 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
940 try
941 {
942 auto service =
943 ipmi::getService(*bus, powerControlIntf, powerControlObj);
944
945 ipmi::Value variant = ipmi::getDbusProperty(
946 *bus, service, powerControlObj, powerControlIntf, "PFail");
947 acFail = std::get<bool>(variant);
948 }
949 catch (const std::exception& e)
950 {
951 log<level::ERR>("Failed to fetch PFail property",
952 entry("ERROR=%s", e.what()),
953 entry("PATH=%s", powerControlObj),
954 entry("INTERFACE=%s", powerControlIntf));
955 }
956 return acFail;
957}
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500958} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800959
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700960static std::optional<bool> getButtonEnabled(const std::string& buttonPath,
961 const std::string& buttonIntf)
962{
963 std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
964 bool buttonDisabled = false;
965 try
966 {
967 auto service = ipmi::getService(*busp, buttonIntf, buttonPath);
968 ipmi::Value enabled = ipmi::getDbusProperty(*busp, service, buttonPath,
969 buttonIntf, "Enabled");
970 buttonDisabled = !std::get<bool>(enabled);
971 }
972 catch (sdbusplus::exception::SdBusError& e)
973 {
974 log<level::ERR>("Fail to get button Enabled property",
975 entry("PATH=%s", buttonPath.c_str()),
976 entry("ERROR=%s", e.what()));
977 return std::nullopt;
978 }
979 return std::make_optional(buttonDisabled);
980}
981
Nan Lifdd8ec52016-08-28 03:57:40 +0800982//----------------------------------------------------------------------
983// Get Chassis Status commands
984//----------------------------------------------------------------------
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -0700985ipmi::RspType<bool, // Power is on
986 bool, // Power overload
987 bool, // Interlock
988 bool, // power fault
989 bool, // power control fault
990 uint2_t, // power restore policy
991 bool, // reserved
992
993 bool, // AC failed
994 bool, // last power down caused by a Power overload
995 bool, // last power down caused by a power interlock
996 bool, // last power down caused by power fault
997 bool, // last ‘Power is on’ state was entered via IPMI command
998 uint3_t, // reserved
999
1000 bool, // Chassis intrusion active
1001 bool, // Front Panel Lockout active
1002 bool, // Drive Fault
1003 bool, // Cooling/fan fault detected
1004 uint2_t, // Chassis Identify State
1005 bool, // Chassis Identify command and state info supported
1006 bool, // reserved
1007
1008 bool, // Power off button disabled
1009 bool, // Reset button disabled
1010 bool, // Diagnostic Interrupt button disabled
1011 bool, // Standby (sleep) button disabled
1012 bool, // Power off button disable allowed
1013 bool, // Reset button disable allowed
1014 bool, // Diagnostic Interrupt button disable allowed
1015 bool // Standby (sleep) button disable allowed
1016 >
1017 ipmiGetChassisStatus()
Nan Lifdd8ec52016-08-28 03:57:40 +08001018{
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001019 using namespace chassis::internal;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001020 std::optional<uint2_t> restorePolicy =
1021 power_policy::getPowerRestorePolicy();
1022 std::optional<bool> powerGood = power_policy::getPowerStatus();
1023 if (!restorePolicy || !powerGood)
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001024 {
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001025 return ipmi::responseUnspecifiedError();
Deepak Kodihalli18b70d12017-07-21 13:36:33 -05001026 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001027
1028 // Front Panel Button Capabilities and disable/enable status(Optional)
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001029 std::optional<bool> powerButtonReading =
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001030 getButtonEnabled(powerButtonPath, powerButtonIntf);
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001031 // allow disable if the interface is present
1032 bool powerButtonDisableAllow = static_cast<bool>(powerButtonReading);
1033 // default return the button is enabled (not disabled)
1034 bool powerButtonDisabled = false;
1035 if (powerButtonDisableAllow)
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001036 {
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001037 // return the real value of the button status, if present
1038 powerButtonDisabled = *powerButtonReading;
1039 }
1040
1041 std::optional<bool> resetButtonReading =
1042 getButtonEnabled(resetButtonPath, resetButtonIntf);
1043 // allow disable if the interface is present
1044 bool resetButtonDisableAllow = static_cast<bool>(resetButtonReading);
1045 // default return the button is enabled (not disabled)
1046 bool resetButtonDisabled = false;
1047 if (resetButtonDisableAllow)
1048 {
1049 // return the real value of the button status, if present
1050 resetButtonDisabled = *resetButtonReading;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001051 }
Nan Lifdd8ec52016-08-28 03:57:40 +08001052
Yong Li70ce7352019-05-16 21:15:27 +08001053 bool powerDownAcFailed = power_policy::getACFailStatus();
1054
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001055 // This response has a lot of hard-coded, unsupported fields
1056 // They are set to false or 0
1057 constexpr bool powerOverload = false;
1058 constexpr bool chassisInterlock = false;
1059 constexpr bool powerFault = false;
1060 constexpr bool powerControlFault = false;
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001061 constexpr bool powerDownOverload = false;
1062 constexpr bool powerDownInterlock = false;
1063 constexpr bool powerDownPowerFault = false;
1064 constexpr bool powerStatusIPMI = false;
1065 constexpr bool chassisIntrusionActive = false;
1066 constexpr bool frontPanelLockoutActive = false;
1067 constexpr bool driveFault = false;
1068 constexpr bool coolingFanFault = false;
1069 // chassisIdentifySupport set because this command is implemented
1070 constexpr bool chassisIdentifySupport = true;
Yong Lif4e38512019-05-21 14:46:55 +08001071 uint2_t chassisIdentifyState = static_cast<uint2_t>(chassisIDState);
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001072 constexpr bool diagButtonDisabled = false;
1073 constexpr bool sleepButtonDisabled = false;
1074 constexpr bool diagButtonDisableAllow = false;
1075 constexpr bool sleepButtonDisableAllow = false;
1076
1077 return ipmi::responseSuccess(
1078 *powerGood, powerOverload, chassisInterlock, powerFault,
1079 powerControlFault, *restorePolicy,
1080 false, // reserved
1081
1082 powerDownAcFailed, powerDownOverload, powerDownInterlock,
1083 powerDownPowerFault, powerStatusIPMI,
1084 uint3_t(0), // reserved
1085
1086 chassisIntrusionActive, frontPanelLockoutActive, driveFault,
1087 coolingFanFault, chassisIdentifyState, chassisIdentifySupport,
1088 false, // reserved
1089
Vernon Mauery6d5b2f72019-05-16 14:48:47 -07001090 powerButtonDisabled, resetButtonDisabled, diagButtonDisabled,
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001091 sleepButtonDisabled, powerButtonDisableAllow, resetButtonDisableAllow,
1092 diagButtonDisableAllow, sleepButtonDisableAllow);
Nan Lifdd8ec52016-08-28 03:57:40 +08001093}
Chris Austen7888c4d2015-12-03 15:26:20 -06001094
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301095//-------------------------------------------------------------
1096// Send a command to SoftPowerOff application to stop any timer
1097//-------------------------------------------------------------
1098int stop_soft_off_timer()
1099{
Patrick Venture0b02be92018-08-31 11:55:55 -07001100 constexpr auto iface = "org.freedesktop.DBus.Properties";
1101 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
1102 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301103
Patrick Venture0b02be92018-08-31 11:55:55 -07001104 constexpr auto property = "ResponseReceived";
1105 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
1106 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301107
1108 // Get the system bus where most system services are provided.
1109 auto bus = ipmid_get_sd_bus_connection();
1110
1111 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001112 // TODO openbmc/openbmc#1661 - Mapper refactor
1113 //
1114 // See openbmc/openbmc#1743 for some details but high level summary is that
1115 // for now the code will directly call the soft off interface due to a
1116 // race condition with mapper usage
1117 //
Patrick Venture0b02be92018-08-31 11:55:55 -07001118 // char *busname = nullptr;
1119 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
1120 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001121 //{
1122 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301123 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001124 // return r;
1125 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301126
1127 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001128 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -07001129 "Set", nullptr, nullptr, "ssv", soft_off_iface,
1130 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301131 if (rc < 0)
1132 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301133 log<level::ERR>("Failed to set property in SoftPowerOff object",
1134 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301135 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001136
Patrick Venture0b02be92018-08-31 11:55:55 -07001137 // TODO openbmc/openbmc#1661 - Mapper refactor
1138 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301139 return rc;
1140}
1141
vishwa36993272015-11-20 12:43:49 -06001142//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001143// Create file to indicate there is no need for softoff notification to host
1144//----------------------------------------------------------------------
1145void indicate_no_softoff_needed()
1146{
1147 fs::path path{HOST_INBAND_REQUEST_DIR};
1148 if (!fs::is_directory(path))
1149 {
1150 fs::create_directory(path);
1151 }
1152
1153 // Add the host instance (default 0 for now) to the file name
1154 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001155 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001156 size++; // null
1157 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001158 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001159
1160 // Append file name to directory and create it
1161 path /= buf.get();
1162 std::ofstream(path.c_str());
1163}
1164
anil kumar appanadafff5f2019-04-27 18:06:00 +00001165/** @brief Implementation of chassis control command
1166 *
1167 * @param - chassisControl command byte
1168 *
1169 * @return Success or InvalidFieldRequest.
1170 */
1171ipmi::RspType<> ipmiChassisControl(uint8_t chassisControl)
vishwa36993272015-11-20 12:43:49 -06001172{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001173 int rc = 0;
anil kumar appanadafff5f2019-04-27 18:06:00 +00001174 switch (chassisControl)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001175 {
1176 case CMD_POWER_ON:
1177 rc = initiate_state_transition(State::Host::Transition::On);
1178 break;
1179 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301180 // This path would be hit in 2 conditions.
1181 // 1: When user asks for power off using ipmi chassis command 0x04
1182 // 2: Host asking for power off post shutting down.
1183
1184 // If it's a host requested power off, then need to nudge Softoff
1185 // application that it needs to stop the watchdog timer if running.
1186 // If it is a user requested power off, then this is not really
1187 // needed. But then we need to differentiate between user and host
1188 // calling this same command
1189
1190 // For now, we are going ahead with trying to nudge the soft off and
1191 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001192 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301193
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001194 // Only request the Off transition if the soft power off
1195 // application is not running
1196 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001197 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001198 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301199 // that it should not run. Not doing this will result in State
1200 // manager doing a default soft power off when asked for power
1201 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001202 indicate_no_softoff_needed();
1203
1204 // Now request the shutdown
1205 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001206 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001207 else
1208 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301209 log<level::INFO>("Soft off is running, so let shutdown target "
1210 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001211 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001212 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301213
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001214 case CMD_HARD_RESET:
1215 case CMD_POWER_CYCLE:
1216 // SPEC has a section that says certain implementations can trigger
1217 // PowerOn if power is Off when a command to power cycle is
1218 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001219
1220 // First create a file to indicate to the soft off application
1221 // that it should not run since this is a direct user initiated
1222 // power reboot request (i.e. a reboot request that is not
1223 // originating via a soft power off SMS request)
1224 indicate_no_softoff_needed();
1225
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001226 rc = initiate_state_transition(State::Host::Transition::Reboot);
1227 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301228
1229 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1230 // Request Host State Manager to do a soft power off
1231 rc = initiate_state_transition(State::Host::Transition::Off);
1232 break;
1233
Kuiying Wang6b0ceaa2019-11-05 15:13:40 +08001234 case CMD_PULSE_DIAGNOSTIC_INTR:
1235 rc = setNmiProperty(true);
1236 break;
1237
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001238 default:
1239 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301240 log<level::ERR>("Invalid Chassis Control command",
anil kumar appanadafff5f2019-04-27 18:06:00 +00001241 entry("CMD=0x%X", chassisControl));
1242 return ipmi::responseInvalidFieldRequest();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001243 }
1244 }
vishwa36993272015-11-20 12:43:49 -06001245
anil kumar appanadafff5f2019-04-27 18:06:00 +00001246 return ((rc < 0) ? ipmi::responseUnspecifiedError()
1247 : ipmi::responseSuccess());
vishwa36993272015-11-20 12:43:49 -06001248}
1249
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001250/** @brief Return D-Bus connection string to enclosure identify LED object
1251 *
1252 * @param[in, out] connection - connection to D-Bus object
1253 * @return a IPMI return code
1254 */
1255std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301256{
Tom Joseph5110c122018-03-23 17:55:40 +05301257 // lookup enclosure_identify group owner(s) in mapper
1258 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001259 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1260 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301261
1262 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001263 static const std::vector<std::string> interfaces = {
1264 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301265 mapperCall.append(interfaces);
1266 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1267 if (mapperReply.is_method_error())
1268 {
1269 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001270 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301271 }
1272 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1273 mapperReply.read(mapperResp);
1274
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001275 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301276 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001277 log<level::ERR>(
1278 "Invalid number of enclosure identify objects.",
1279 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001280 elog<InternalFailure>();
1281 }
1282 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1283 return pair.first;
1284}
Tom Joseph5110c122018-03-23 17:55:40 +05301285
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001286/** @brief Turn On/Off enclosure identify LED
1287 *
1288 * @param[in] flag - true to turn on LED, false to turn off
1289 * @return a IPMI return code
1290 */
1291void enclosureIdentifyLed(bool flag)
1292{
1293 using namespace chassis::internal;
1294 std::string connection = std::move(getEnclosureIdentifyConnection());
Vernon Mauery400cc782018-10-09 13:49:53 -07001295 auto msg = std::string("enclosureIdentifyLed(") +
1296 boost::lexical_cast<std::string>(flag) + ")";
1297 log<level::DEBUG>(msg.c_str());
Patrick Venture0b02be92018-08-31 11:55:55 -07001298 auto led =
1299 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1300 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001301 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Vernon Mauery16b86932019-05-01 08:36:11 -07001302 std::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001303 auto ledReply = dbus.call(led);
1304 if (ledReply.is_method_error())
1305 {
1306 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001307 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001308 elog<InternalFailure>();
1309 }
1310}
1311
1312/** @brief Callback method to turn off LED
1313 */
1314void enclosureIdentifyLedOff()
1315{
1316 try
1317 {
Yong Lif4e38512019-05-21 14:46:55 +08001318 chassisIDState = ChassisIDState::off;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001319 enclosureIdentifyLed(false);
1320 }
1321 catch (const InternalFailure& e)
1322 {
1323 report<InternalFailure>();
1324 }
1325}
1326
1327/** @brief Create timer to turn on and off the enclosure LED
1328 */
1329void createIdentifyTimer()
1330{
1331 if (!identifyTimer)
1332 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001333 identifyTimer =
1334 std::make_unique<phosphor::Timer>(enclosureIdentifyLedOff);
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001335 }
1336}
1337
Vernon Mauery400cc782018-10-09 13:49:53 -07001338ipmi::RspType<> ipmiChassisIdentify(std::optional<uint8_t> interval,
1339 std::optional<uint8_t> force)
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001340{
Vernon Mauery400cc782018-10-09 13:49:53 -07001341 uint8_t identifyInterval = interval.value_or(DEFAULT_IDENTIFY_TIME_OUT);
1342 bool forceIdentify = force.value_or(0) & 0x01;
Tom Josephbed26992018-07-31 23:00:24 +05301343
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001344 if (identifyInterval || forceIdentify)
1345 {
Vernon Mauery400cc782018-10-09 13:49:53 -07001346 // stop the timer if already started;
1347 // for force identify we should not turn off LED
Vernon Mauery1181af72018-10-08 12:05:00 -07001348 identifyTimer->stop();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001349 try
Tom Joseph5110c122018-03-23 17:55:40 +05301350 {
Yong Lif4e38512019-05-21 14:46:55 +08001351 chassisIDState = ChassisIDState::temporaryOn;
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001352 enclosureIdentifyLed(true);
1353 }
1354 catch (const InternalFailure& e)
1355 {
1356 report<InternalFailure>();
Vernon Mauery400cc782018-10-09 13:49:53 -07001357 return ipmi::responseResponseError();
Tom Joseph5110c122018-03-23 17:55:40 +05301358 }
1359
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001360 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301361 {
Yong Lif4e38512019-05-21 14:46:55 +08001362 chassisIDState = ChassisIDState::indefiniteOn;
Vernon Mauery400cc782018-10-09 13:49:53 -07001363 return ipmi::responseSuccess();
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001364 }
1365 // start the timer
1366 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001367 std::chrono::seconds(identifyInterval));
Vernon Mauery1181af72018-10-08 12:05:00 -07001368 identifyTimer->start(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301369 }
Tom Josephbed26992018-07-31 23:00:24 +05301370 else if (!identifyInterval)
1371 {
Vernon Mauery1181af72018-10-08 12:05:00 -07001372 identifyTimer->stop();
Tom Josephbed26992018-07-31 23:00:24 +05301373 enclosureIdentifyLedOff();
1374 }
Vernon Mauery400cc782018-10-09 13:49:53 -07001375 return ipmi::responseSuccess();
Tom Joseph5110c122018-03-23 17:55:40 +05301376}
1377
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001378namespace boot_options
1379{
1380
1381using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1382using IpmiValue = uint8_t;
1383constexpr auto ipmiDefault = 0;
1384
Patrick Venture0b02be92018-08-31 11:55:55 -07001385std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001386 {0x01, Source::Sources::Network},
1387 {0x02, Source::Sources::Disk},
1388 {0x05, Source::Sources::ExternalMedia},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001389 {0x0f, Source::Sources::RemovableMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001390 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001391
Patrick Venture0b02be92018-08-31 11:55:55 -07001392std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Yong Li5833cb62019-10-30 13:27:12 +08001393#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001394 {0x03, Mode::Modes::Safe},
Yong Li5833cb62019-10-30 13:27:12 +08001395#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001396 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001397 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001398
Patrick Venture0b02be92018-08-31 11:55:55 -07001399std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001400 {Source::Sources::Network, 0x01},
1401 {Source::Sources::Disk, 0x02},
1402 {Source::Sources::ExternalMedia, 0x05},
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001403 {Source::Sources::RemovableMedia, 0x0f},
Patrick Venture0b02be92018-08-31 11:55:55 -07001404 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001405
Patrick Venture0b02be92018-08-31 11:55:55 -07001406std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Yong Li5833cb62019-10-30 13:27:12 +08001407#ifdef ENABLE_BOOT_FLAG_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001408 {Mode::Modes::Safe, 0x03},
Yong Li5833cb62019-10-30 13:27:12 +08001409#endif // ENABLE_BOOT_SAFE_MODE_SUPPORT
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001410 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001411 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001412
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001413} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001414
Marri Devender Rao81719702018-05-07 00:53:48 -05001415/** @brief Set the property value for boot source
1416 * @param[in] source - boot source value
1417 * @return On failure return IPMI error.
1418 */
1419static ipmi_ret_t setBootSource(const Source::Sources& source)
1420{
1421 using namespace chassis::internal;
1422 using namespace chassis::internal::cache;
Vernon Mauery16b86932019-05-01 08:36:11 -07001423 std::variant<std::string> property = convertForMessage(source);
James Feist225dec82019-11-26 16:25:06 -08001424 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001425 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1426 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001427 auto method = dbus.new_method_call(
1428 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1429 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001430 method.append(bootSourceIntf, "BootSource", property);
1431 auto reply = dbus.call(method);
1432 if (reply.is_method_error())
1433 {
1434 log<level::ERR>("Error in BootSource Set");
1435 report<InternalFailure>();
1436 return IPMI_CC_UNSPECIFIED_ERROR;
1437 }
1438 return IPMI_CC_OK;
1439}
1440
Patrick Venture0b02be92018-08-31 11:55:55 -07001441/** @brief Set the property value for boot mode
Marri Devender Rao81719702018-05-07 00:53:48 -05001442 * @param[in] mode - boot mode value
1443 * @return On failure return IPMI error.
1444 */
1445static ipmi_ret_t setBootMode(const Mode::Modes& mode)
1446{
1447 using namespace chassis::internal;
1448 using namespace chassis::internal::cache;
Vernon Mauery16b86932019-05-01 08:36:11 -07001449 std::variant<std::string> property = convertForMessage(mode);
James Feist225dec82019-11-26 16:25:06 -08001450 settings::Objects& objects = getObjects();
Marri Devender Rao81719702018-05-07 00:53:48 -05001451 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1452 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001453 auto method = dbus.new_method_call(
1454 objects.service(bootModeSetting, bootModeIntf).c_str(),
1455 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001456 method.append(bootModeIntf, "BootMode", property);
1457 auto reply = dbus.call(method);
1458 if (reply.is_method_error())
1459 {
1460 log<level::ERR>("Error in BootMode Set");
1461 report<InternalFailure>();
1462 return IPMI_CC_UNSPECIFIED_ERROR;
1463 }
1464 return IPMI_CC_OK;
1465}
1466
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001467ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1468 ipmi_request_t request,
1469 ipmi_response_t response,
1470 ipmi_data_len_t data_len,
1471 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001472{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001473 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001474 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
Patrick Venture0b02be92018-08-31 11:55:55 -07001475 char* p = NULL;
1476 get_sys_boot_options_response_t* resp =
1477 (get_sys_boot_options_response_t*)response;
1478 get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001479 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001480
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001481 std::memset(resp, 0, sizeof(*resp));
Patrick Venture0b02be92018-08-31 11:55:55 -07001482 resp->version = SET_PARM_VERSION;
1483 resp->parm = 5;
1484 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001485
shgoupfd84fbbf2015-12-17 10:05:51 +08001486 /*
1487 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1488 * This is the only parameter used by petitboot.
1489 */
Patrick Venture0b02be92018-08-31 11:55:55 -07001490 if (reqptr->parameter ==
1491 static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
1492 {
shgoupfd84fbbf2015-12-17 10:05:51 +08001493
Ratan Guptafd28dd72016-08-01 04:58:01 -05001494 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001495 using namespace chassis::internal;
1496 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001497
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001498 try
ratagupta6f6bff2016-04-04 06:20:11 -05001499 {
James Feist225dec82019-11-26 16:25:06 -08001500 settings::Objects& objects = getObjects();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001501 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1502 const auto& bootSourceSetting =
1503 std::get<settings::Path>(bootSetting);
1504 auto oneTimeEnabled =
1505 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001506 auto method = dbus.new_method_call(
1507 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1508 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001509 method.append(bootSourceIntf, "BootSource");
1510 auto reply = dbus.call(method);
1511 if (reply.is_method_error())
1512 {
1513 log<level::ERR>("Error in BootSource Get");
1514 report<InternalFailure>();
1515 *data_len = 0;
1516 return IPMI_CC_UNSPECIFIED_ERROR;
1517 }
Vernon Mauery16b86932019-05-01 08:36:11 -07001518 std::variant<std::string> result;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001519 reply.read(result);
Vernon Maueryf442e112019-04-09 11:44:36 -07001520 auto bootSource =
1521 Source::convertSourcesFromString(std::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001522
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001523 bootSetting = settings::boot::setting(objects, bootModeIntf);
1524 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1525 method = dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001526 objects.service(bootModeSetting, bootModeIntf).c_str(),
1527 bootModeSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001528 method.append(bootModeIntf, "BootMode");
1529 reply = dbus.call(method);
1530 if (reply.is_method_error())
1531 {
1532 log<level::ERR>("Error in BootMode Get");
1533 report<InternalFailure>();
1534 *data_len = 0;
1535 return IPMI_CC_UNSPECIFIED_ERROR;
1536 }
1537 reply.read(result);
Vernon Maueryf442e112019-04-09 11:44:36 -07001538 auto bootMode =
1539 Mode::convertModesFromString(std::get<std::string>(result));
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001540
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001541 bootOption = sourceDbusToIpmi.at(bootSource);
1542 if ((Mode::Modes::Regular == bootMode) &&
1543 (Source::Sources::Default == bootSource))
1544 {
1545 bootOption = ipmiDefault;
1546 }
1547 else if (Source::Sources::Default == bootSource)
1548 {
1549 bootOption = modeDbusToIpmi.at(bootMode);
1550 }
1551 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001552
Patrick Venture0b02be92018-08-31 11:55:55 -07001553 resp->data[0] = oneTimeEnabled
1554 ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
1555 : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001556
ratagupta6f6bff2016-04-04 06:20:11 -05001557 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001558 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001559 catch (InternalFailure& e)
1560 {
James Feist225dec82019-11-26 16:25:06 -08001561 cache::objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001562 report<InternalFailure>();
1563 *data_len = 0;
1564 return IPMI_CC_UNSPECIFIED_ERROR;
1565 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001566 }
1567 else if (reqptr->parameter ==
1568 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
1569 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001570
Patrick Venture0b02be92018-08-31 11:55:55 -07001571 *data_len =
1572 static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001573
Patrick Venture0b02be92018-08-31 11:55:55 -07001574 resp->parm =
1575 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001576
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001577 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001578
Patrick Venture0b02be92018-08-31 11:55:55 -07001579 if (ret < 0)
1580 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001581
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301582 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001583 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001584 rc = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture0b02be92018-08-31 11:55:55 -07001585 }
1586 else
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001587 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001588 }
1589
Patrick Venture0b02be92018-08-31 11:55:55 -07001590 else
1591 {
1592 log<level::ERR>("Unsupported parameter",
1593 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001594 }
1595
1596 if (p)
1597 free(p);
1598
Ratan Guptafd28dd72016-08-01 04:58:01 -05001599 if (rc == IPMI_CC_OK)
1600 {
1601 *data_len += 2;
1602 }
1603
shgoupfd84fbbf2015-12-17 10:05:51 +08001604 return rc;
1605}
1606
shgoupfd84fbbf2015-12-17 10:05:51 +08001607ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001608 ipmi_request_t request,
1609 ipmi_response_t response,
1610 ipmi_data_len_t data_len,
1611 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001612{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001613 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001614 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001615 set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
shgoupfd84fbbf2015-12-17 10:05:51 +08001616
Patrick Ventureb51bf9c2018-09-10 15:53:14 -07001617 std::printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
1618 reqptr->parameter);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001619
shgoupfd84fbbf2015-12-17 10:05:51 +08001620 // This IPMI command does not have any resposne data
1621 *data_len = 0;
1622
1623 /* 000101
1624 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1625 * This is the only parameter used by petitboot.
1626 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001627
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001628 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1629 {
1630 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1631 using namespace chassis::internal;
1632 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001633 auto oneTimeEnabled = false;
1634 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301635 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001636 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001637
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001638 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001639 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001640 bool permanent =
1641 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1642 SET_PARM_BOOT_FLAGS_PERMANENT;
1643
James Feist225dec82019-11-26 16:25:06 -08001644 settings::Objects& objects = getObjects();
1645
Patrick Venture0b02be92018-08-31 11:55:55 -07001646 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301647
1648 oneTimeEnabled =
1649 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1650
1651 /*
1652 * Check if the current boot setting is onetime or permanent, if the
1653 * request in the command is otherwise, then set the "Enabled"
1654 * property in one_time object path to 'True' to indicate onetime
1655 * and 'False' to indicate permanent.
1656 *
1657 * Once the onetime/permanent setting is applied, then the bootMode
1658 * and bootSource is updated for the corresponding object.
1659 */
1660 if ((permanent && oneTimeEnabled) ||
1661 (!permanent && !oneTimeEnabled))
1662 {
1663 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1664
Patrick Venture0b02be92018-08-31 11:55:55 -07001665 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
1666 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301667 }
1668
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001669 auto modeItr = modeIpmiToDbus.find(bootOption);
1670 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1671 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001672 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001673 rc = setBootSource(sourceItr->second);
1674 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001675 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001676 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001677 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001678 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001679 // If a set boot device is mapping to a boot source, then reset
1680 // the boot mode D-Bus property to default.
1681 // This way the ipmid code can determine which property is not
1682 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001683 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001684 {
1685 setBootMode(Mode::Modes::Regular);
1686 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001687 }
1688 if (modeIpmiToDbus.end() != modeItr)
1689 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001690 rc = setBootMode(modeItr->second);
1691 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001692 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001693 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001694 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001695 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001696 // If a set boot device is mapping to a boot mode, then reset
1697 // the boot source D-Bus property to default.
1698 // This way the ipmid code can determine which property is not
1699 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001700 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001701 {
1702 setBootSource(Source::Sources::Default);
1703 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001704 }
Jia, chunhui67c5e5d2019-05-06 11:29:54 +08001705 if ((modeIpmiToDbus.end() == modeItr) &&
1706 (sourceIpmiToDbus.end() == sourceItr))
1707 {
1708 // return error if boot option is not supported
1709 *data_len = 0;
1710 return IPMI_CC_INVALID_FIELD_REQUEST;
1711 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001712 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001713 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001714 {
James Feist225dec82019-11-26 16:25:06 -08001715 objectsPtr.reset();
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001716 report<InternalFailure>();
1717 *data_len = 0;
1718 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001719 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001720 }
1721 else if (reqptr->parameter ==
1722 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
1723 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001724
1725 int ret = setHostNetworkData(reqptr);
Patrick Venture0b02be92018-08-31 11:55:55 -07001726 if (ret < 0)
1727 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301728 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001729 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001730 rc = IPMI_CC_UNSPECIFIED_ERROR;
1731 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001732 }
1733 else if (reqptr->parameter ==
1734 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
1735 {
Tom Josephf536c902017-09-25 18:08:15 +05301736 // Handle parameter #4 and return command completed normally
1737 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1738 // parameter. This is added to support the ipmitool command `chassis
1739 // bootdev` which sends set on parameter #4, before setting the boot
1740 // flags.
1741 rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001742 }
1743 else
1744 {
1745 log<level::ERR>("Unsupported parameter",
1746 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001747 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001748 }
1749
1750 return rc;
1751}
1752
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00001753/** @brief implements Get POH counter command
1754 * @parameter
1755 * - none
1756 * @returns IPMI completion code plus response data
1757 * - minPerCount - Minutes per count
1758 * - counterReading - counter reading
1759 */
1760ipmi::RspType<uint8_t, // Minutes per count
1761 uint32_t // Counter reading
1762 >
1763 ipmiGetPOHCounter()
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001764{
1765 // sd_bus error
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001766 try
1767 {
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00001768 return ipmi::responseSuccess(static_cast<uint8_t>(poh::minutesPerCount),
1769 getPOHCounter());
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001770 }
1771 catch (std::exception& e)
1772 {
1773 log<level::ERR>(e.what());
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00001774 return ipmi::responseUnspecifiedError();
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001775 }
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001776}
1777
Jason M. Billsbc996a32019-06-17 15:46:37 -07001778ipmi::RspType<uint3_t, // policy support
1779 uint5_t // reserved
1780 >
Vernon Mauerye278ead2018-10-09 09:23:43 -07001781 ipmiChassisSetPowerRestorePolicy(boost::asio::yield_context yield,
Jason M. Billsbc996a32019-06-17 15:46:37 -07001782 uint3_t policy, uint5_t reserved)
Yong Lic6713cf2018-09-12 12:35:13 +08001783{
Yong Lic6713cf2018-09-12 12:35:13 +08001784 power_policy::DbusValue value =
1785 power_policy::RestorePolicy::Policy::AlwaysOff;
1786
Jason M. Billsbc996a32019-06-17 15:46:37 -07001787 if (reserved || (policy > power_policy::noChange))
Yong Lic6713cf2018-09-12 12:35:13 +08001788 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07001789 phosphor::logging::log<level::ERR>(
1790 "Reserved request parameter",
1791 entry("REQ=0x%x", static_cast<int>(policy)));
Jason M. Billsbc996a32019-06-17 15:46:37 -07001792 return ipmi::responseInvalidFieldRequest();
Yong Lic6713cf2018-09-12 12:35:13 +08001793 }
1794
Vernon Mauerye278ead2018-10-09 09:23:43 -07001795 if (policy == power_policy::noChange)
Yong Lic6713cf2018-09-12 12:35:13 +08001796 {
1797 // just return the supported policy
Jason M. Billsbc996a32019-06-17 15:46:37 -07001798 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08001799 }
1800
1801 for (auto const& it : power_policy::dbusToIpmi)
1802 {
Vernon Mauerye278ead2018-10-09 09:23:43 -07001803 if (it.second == policy)
Yong Lic6713cf2018-09-12 12:35:13 +08001804 {
1805 value = it.first;
1806 break;
1807 }
1808 }
1809
1810 try
1811 {
James Feist225dec82019-11-26 16:25:06 -08001812 settings::Objects& objects = chassis::internal::cache::getObjects();
Yong Lic6713cf2018-09-12 12:35:13 +08001813 const settings::Path& powerRestoreSetting =
James Feist225dec82019-11-26 16:25:06 -08001814 objects.map.at(chassis::internal::powerRestoreIntf).front();
Vernon Mauery16b86932019-05-01 08:36:11 -07001815 std::variant<std::string> property = convertForMessage(value);
Yong Lic6713cf2018-09-12 12:35:13 +08001816
Vernon Mauerye278ead2018-10-09 09:23:43 -07001817 auto sdbusp = getSdBus();
1818 boost::system::error_code ec;
1819 sdbusp->yield_method_call<void>(
1820 yield, ec,
James Feist225dec82019-11-26 16:25:06 -08001821 objects
Yong Lic6713cf2018-09-12 12:35:13 +08001822 .service(powerRestoreSetting,
1823 chassis::internal::powerRestoreIntf)
1824 .c_str(),
Vernon Mauerye278ead2018-10-09 09:23:43 -07001825 powerRestoreSetting, ipmi::PROP_INTF, "Set",
1826 chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
1827 property);
1828 if (ec)
Yong Lic6713cf2018-09-12 12:35:13 +08001829 {
1830 phosphor::logging::log<level::ERR>("Unspecified Error");
Vernon Mauerye278ead2018-10-09 09:23:43 -07001831 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08001832 }
1833 }
1834 catch (InternalFailure& e)
1835 {
James Feist225dec82019-11-26 16:25:06 -08001836 chassis::internal::cache::objectsPtr.reset();
Yong Lic6713cf2018-09-12 12:35:13 +08001837 report<InternalFailure>();
Vernon Mauerye278ead2018-10-09 09:23:43 -07001838 return ipmi::responseUnspecifiedError();
Yong Lic6713cf2018-09-12 12:35:13 +08001839 }
1840
Jason M. Billsbc996a32019-06-17 15:46:37 -07001841 return ipmi::responseSuccess(power_policy::allSupport, reserved);
Yong Lic6713cf2018-09-12 12:35:13 +08001842}
1843
Adriana Kobylak40814c62015-10-27 15:58:44 -05001844void register_netfn_chassis_functions()
1845{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001846 createIdentifyTimer();
1847
Tom05732372016-09-06 17:21:23 +05301848 // Get Chassis Capabilities
anil kumar appana43263c62019-05-27 12:45:04 +00001849 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1850 ipmi::chassis::cmdGetChassisCapabilities,
1851 ipmi::Privilege::User, ipmiGetChassisCap);
Nan Li8d15fb42016-08-16 22:29:40 +08001852
Yong Liae4b0402018-11-02 11:12:14 +08001853 // Set Chassis Capabilities
anil kumar appana894d0222019-05-27 16:32:14 +00001854 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1855 ipmi::chassis::cmdSetChassisCapabilities,
1856 ipmi::Privilege::User, ipmiSetChassisCap);
Yong Liae4b0402018-11-02 11:12:14 +08001857
Tom05732372016-09-06 17:21:23 +05301858 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301859 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001860 ipmi_chassis_get_sys_boot_options,
1861 PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001862
Tom05732372016-09-06 17:21:23 +05301863 // <Get Chassis Status>
Vernon Mauery4a8a4eb2019-04-04 15:09:37 -07001864 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1865 ipmi::chassis::cmdGetChassisStatus,
1866 ipmi::Privilege::User, ipmiGetChassisStatus);
Nan Lifdd8ec52016-08-28 03:57:40 +08001867
Tom05732372016-09-06 17:21:23 +05301868 // <Chassis Control>
anil kumar appanadafff5f2019-04-27 18:06:00 +00001869 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1870 ipmi::chassis::cmdChassisControl,
1871 ipmi::Privilege::Operator, ipmiChassisControl);
shgoupfd84fbbf2015-12-17 10:05:51 +08001872
Tom Joseph5110c122018-03-23 17:55:40 +05301873 // <Chassis Identify>
Vernon Mauery400cc782018-10-09 13:49:53 -07001874 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1875 ipmi::chassis::cmdChassisIdentify,
1876 ipmi::Privilege::Operator, ipmiChassisIdentify);
Tom Joseph5110c122018-03-23 17:55:40 +05301877
Tom05732372016-09-06 17:21:23 +05301878 // <Set System Boot Options>
Tom05732372016-09-06 17:21:23 +05301879 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001880 ipmi_chassis_set_sys_boot_options,
1881 PRIVILEGE_OPERATOR);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001882 // <Get POH Counter>
anil kumar appanaa5a76eb2019-04-30 14:57:24 +00001883 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1884 ipmi::chassis::cmdGetPohCounter,
1885 ipmi::Privilege::User, ipmiGetPOHCounter);
Yong Lic6713cf2018-09-12 12:35:13 +08001886
1887 // <Set Power Restore Policy>
Vernon Mauerye278ead2018-10-09 09:23:43 -07001888 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
1889 ipmi::chassis::cmdSetPowerRestorePolicy,
1890 ipmi::Privilege::Operator,
1891 ipmiChassisSetPowerRestorePolicy);
vishwa36993272015-11-20 12:43:49 -06001892}