blob: b822212fa53b5d1162113f556f2a3a7aab9c3566 [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
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05005#include "ipmid.hpp"
6#include "settings.hpp"
Patrick Venture3a5071a2018-09-12 13:27:42 -07007#include "timer.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07008#include "types.hpp"
Ratan Guptacc8feb42017-07-25 21:52:10 +05309#include "utils.hpp"
Ratan Guptadcb10672017-07-10 10:33:50 +053010
Patrick Venture0b02be92018-08-31 11:55:55 -070011#include <arpa/inet.h>
12#include <endian.h>
Patrick Venture46470a32018-09-07 19:26:25 -070013#include <host-ipmid/ipmid-api.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070014#include <limits.h>
15#include <mapper.h>
16#include <netinet/in.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070017
Ratan Guptafd28dd72016-08-01 04:58:01 -050018#include <array>
Patrick Venture0b02be92018-08-31 11:55:55 -070019#include <chrono>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050020#include <fstream>
Tom Joseph5110c122018-03-23 17:55:40 +053021#include <future>
Patrick Venture3a5071a2018-09-12 13:27:42 -070022#include <map>
23#include <phosphor-logging/elog-errors.hpp>
24#include <phosphor-logging/log.hpp>
25#include <sdbusplus/bus.hpp>
26#include <sdbusplus/server/object.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070027#include <sstream>
Patrick Venture3a5071a2018-09-12 13:27:42 -070028#include <string>
29#include <xyz/openbmc_project/Common/error.hpp>
30#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
31#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
32#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
33#include <xyz/openbmc_project/State/Host/server.hpp>
34#include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
35
Vernon Mauery185b9f82018-07-20 10:52:36 -070036#if __has_include(<filesystem>)
37#include <filesystem>
38#elif __has_include(<experimental/filesystem>)
Andrew Geisslera6e3a302017-05-31 19:34:00 -050039#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070040namespace std
41{
42// splice experimental::filesystem into std
43namespace filesystem = std::experimental::filesystem;
44} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070045#else
Patrick Venture0b02be92018-08-31 11:55:55 -070046#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070047#endif
Patrick Venture0b02be92018-08-31 11:55:55 -070048
Patrick Venture0b02be92018-08-31 11:55:55 -070049// Defines
50#define SET_PARM_VERSION 0x01
51#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 // boot flags data1 7th bit on
52#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 // boot flags data1 8th bit on
53#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT \
54 0xC0 // boot flags data1 7 & 8 bit
55 // on
ratagupta6f6bff2016-04-04 06:20:11 -050056
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050057std::unique_ptr<phosphor::ipmi::Timer> identifyTimer = nullptr;
58
Patrick Venture0b02be92018-08-31 11:55:55 -070059constexpr size_t SIZE_MAC = 18;
60constexpr size_t SIZE_BOOT_OPTION = (uint8_t)
61 BootOptionResponseSize::OPAL_NETWORK_SETTINGS; // Maximum size of the boot
62 // option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050063constexpr size_t SIZE_PREFIX = 7;
64constexpr size_t MAX_PREFIX_VALUE = 32;
65constexpr size_t SIZE_COOKIE = 4;
66constexpr size_t SIZE_VERSION = 2;
Tom Joseph5110c122018-03-23 17:55:40 +053067constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053068
Patrick Venture0b02be92018-08-31 11:55:55 -070069// PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053070static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
Patrick Venture0b02be92018-08-31 11:55:55 -070071 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050072
73static constexpr size_t COOKIE_OFFSET = 1;
74static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053075static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050076static constexpr size_t MAC_OFFSET = 9;
77static constexpr size_t ADDRTYPE_OFFSET = 16;
78static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050079
Marri Devender Rao6706c1c2018-05-14 00:29:38 -050080static constexpr size_t encIdentifyObjectsSize = 1;
81static constexpr size_t chassisIdentifyReqLength = 2;
82static constexpr size_t identifyIntervalPos = 0;
83static constexpr size_t forceIdentifyPos = 1;
shgoupfd84fbbf2015-12-17 10:05:51 +080084
Adriana Kobylak40814c62015-10-27 15:58:44 -050085void register_netfn_chassis_functions() __attribute__((constructor));
86
shgoupfd84fbbf2015-12-17 10:05:51 +080087// Host settings in dbus
88// Service name should be referenced by connection name got via object mapper
Patrick Venture0b02be92018-08-31 11:55:55 -070089const char* settings_object_name = "/org/openbmc/settings/host0";
90const char* settings_intf_name = "org.freedesktop.DBus.Properties";
91const char* host_intf_name = "org.openbmc.settings.Host";
92const char* identify_led_object_name =
Tom Joseph5110c122018-03-23 17:55:40 +053093 "/xyz/openbmc_project/led/groups/enclosure_identify";
shgoupfd84fbbf2015-12-17 10:05:51 +080094
Ratan Guptadcb10672017-07-10 10:33:50 +053095constexpr auto SETTINGS_ROOT = "/";
96constexpr auto SETTINGS_MATCH = "host0";
Ratan Guptadcb10672017-07-10 10:33:50 +053097
98constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
99constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
100
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500101static constexpr auto chassisStateRoot = "/xyz/openbmc_project/state";
102static constexpr auto chassisPOHStateIntf =
Patrick Venture0b02be92018-08-31 11:55:55 -0700103 "xyz.openbmc_project.State.PowerOnHours";
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500104static constexpr auto pOHCounterProperty = "POHCounter";
105static constexpr auto match = "chassis0";
Ratan Guptadcb10672017-07-10 10:33:50 +0530106
Nan Li8d15fb42016-08-16 22:29:40 +0800107typedef struct
108{
109 uint8_t cap_flags;
110 uint8_t fru_info_dev_addr;
111 uint8_t sdr_dev_addr;
112 uint8_t sel_dev_addr;
113 uint8_t system_management_dev_addr;
114 uint8_t bridge_dev_addr;
Patrick Venture0b02be92018-08-31 11:55:55 -0700115} __attribute__((packed)) ipmi_chassis_cap_t;
Nan Li8d15fb42016-08-16 22:29:40 +0800116
Nan Lifdd8ec52016-08-28 03:57:40 +0800117typedef struct
118{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500119 uint8_t cur_power_state;
120 uint8_t last_power_event;
121 uint8_t misc_power_state;
122 uint8_t front_panel_button_cap_status;
Patrick Venture0b02be92018-08-31 11:55:55 -0700123} __attribute__((packed)) ipmi_get_chassis_status_t;
Nan Lifdd8ec52016-08-28 03:57:40 +0800124
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500125/**
126 * @struct Get POH counter command response data
127 */
128struct GetPOHCountResponse
129{
Patrick Venture0b02be92018-08-31 11:55:55 -0700130 uint8_t minPerCount; ///< Minutes per count
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500131 uint8_t counterReading[4]; ///< Counter reading
Patrick Venture0b02be92018-08-31 11:55:55 -0700132} __attribute__((packed));
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500133
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530134// Phosphor Host State manager
135namespace State = sdbusplus::xyz::openbmc_project::State::server;
136
Vernon Mauery185b9f82018-07-20 10:52:36 -0700137namespace fs = std::filesystem;
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500138
Ratan Guptadcb10672017-07-10 10:33:50 +0530139using namespace phosphor::logging;
140using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Marri Devender Rao81719702018-05-07 00:53:48 -0500141using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500142namespace chassis
143{
144namespace internal
145{
146
147constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
148constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500149constexpr auto powerRestoreIntf =
150 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500151sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
152
153namespace cache
154{
155
156settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500157 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500158
159} // namespace cache
160} // namespace internal
161} // namespace chassis
162
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500163namespace poh
164{
165
166constexpr auto minutesPerCount = 60;
167
168} // namespace poh
169
Patrick Venture0b02be92018-08-31 11:55:55 -0700170// TODO : Can remove the below function as we have
Ratan Guptadcb10672017-07-10 10:33:50 +0530171// new functions which uses sdbusplus.
172//
173// openbmc/openbmc#1489
Patrick Venture0b02be92018-08-31 11:55:55 -0700174int dbus_get_property(const char* name, char** buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800175{
176 sd_bus_error error = SD_BUS_ERROR_NULL;
Patrick Venture0b02be92018-08-31 11:55:55 -0700177 sd_bus_message* m = NULL;
178 sd_bus* bus = NULL;
179 char* temp_buf = NULL;
180 char* connection = NULL;
shgoupfd84fbbf2015-12-17 10:05:51 +0800181 int r;
182
Brad Bishop35518682016-07-22 08:35:41 -0400183 // Get the system bus where most system services are provided.
184 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800185
Brad Bishop35518682016-07-22 08:35:41 -0400186 r = mapper_get_service(bus, settings_object_name, &connection);
Patrick Venture0b02be92018-08-31 11:55:55 -0700187 if (r < 0)
188 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530189 log<level::ERR>("Failed to get connection",
190 entry("OBJ_NAME=%s", settings_object_name),
191 entry("ERRNO=0x%X", -r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800192 goto finish;
193 }
194
shgoupfd84fbbf2015-12-17 10:05:51 +0800195 /*
196 * Bus, service, object path, interface and method are provided to call
197 * the method.
198 * Signatures and input arguments are provided by the arguments at the
199 * end.
200 */
Patrick Venture0b02be92018-08-31 11:55:55 -0700201 r = sd_bus_call_method(bus, connection, /* service to contact */
202 settings_object_name, /* object path */
203 settings_intf_name, /* interface name */
204 "Get", /* method name */
205 &error, /* object to return error in */
206 &m, /* return message on success */
207 "ss", /* input signature */
208 host_intf_name, /* first argument */
209 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800210
Patrick Venture0b02be92018-08-31 11:55:55 -0700211 if (r < 0)
212 {
213 log<level::ERR>("Failed to issue Get method call",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530214 entry("ERRNO=0x%X", r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800215 goto finish;
216 }
217
Patrick Venture0b02be92018-08-31 11:55:55 -0700218 /*
219 * The output should be parsed exactly the same as the output formatting
220 * specified.
221 */
222 r = sd_bus_message_read(m, "v", "s", &temp_buf);
223 if (r < 0)
224 {
225 log<level::ERR>("Failed to parse response message",
226 entry("ERRNO=0x%X", -r));
227 goto finish;
228 }
229
230 *buf = strdup(temp_buf);
231 /* *buf = (char*) malloc(strlen(temp_buf));
232 if (*buf) {
233 strcpy(*buf, temp_buf);
234 }
235 */
236
237finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800238 sd_bus_error_free(&error);
239 sd_bus_message_unref(m);
240 free(connection);
241
242 return r;
243}
244
Patrick Venture0b02be92018-08-31 11:55:55 -0700245// TODO : Can remove the below function as we have
246// new functions which uses sdbusplus.
247//
248// openbmc/openbmc#1489
249
250int dbus_set_property(const char* name, const char* value)
251{
252 sd_bus_error error = SD_BUS_ERROR_NULL;
253 sd_bus_message* m = NULL;
254 sd_bus* bus = NULL;
255 char* connection = NULL;
256 int r;
257
258 // Get the system bus where most system services are provided.
259 bus = ipmid_get_sd_bus_connection();
260
261 r = mapper_get_service(bus, settings_object_name, &connection);
262 if (r < 0)
263 {
264 log<level::ERR>("Failed to get connection",
265 entry("OBJ_NAME=%s", settings_object_name),
266 entry("ERRNO=0x%X", -r));
267 goto finish;
268 }
269
270 /*
271 * Bus, service, object path, interface and method are provided to call
272 * the method.
273 * Signatures and input arguments are provided by the arguments at the
274 * end.
275 */
276 r = sd_bus_call_method(bus, connection, /* service to contact */
277 settings_object_name, /* object path */
278 settings_intf_name, /* interface name */
279 "Set", /* method name */
280 &error, /* object to return error in */
281 &m, /* return message on success */
282 "ssv", /* input signature */
283 host_intf_name, /* first argument */
284 name, /* second argument */
285 "s", /* third argument */
286 value); /* fourth argument */
287
288 if (r < 0)
289 {
290 log<level::ERR>("Failed to issue Set method call",
291 entry("ERRNO=0x%X", r));
292 goto finish;
293 }
294
295finish:
296 sd_bus_error_free(&error);
297 sd_bus_message_unref(m);
298 free(connection);
299
300 return r;
301}
302
303struct get_sys_boot_options_t
304{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500305 uint8_t parameter;
306 uint8_t set;
307 uint8_t block;
Patrick Venture0b02be92018-08-31 11:55:55 -0700308} __attribute__((packed));
Adriana Kobylak40814c62015-10-27 15:58:44 -0500309
Patrick Venture0b02be92018-08-31 11:55:55 -0700310struct get_sys_boot_options_response_t
311{
shgoupfd84fbbf2015-12-17 10:05:51 +0800312 uint8_t version;
313 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500314 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700315} __attribute__((packed));
shgoupfd84fbbf2015-12-17 10:05:51 +0800316
Patrick Venture0b02be92018-08-31 11:55:55 -0700317struct set_sys_boot_options_t
318{
shgoupfd84fbbf2015-12-17 10:05:51 +0800319 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500320 uint8_t data[SIZE_BOOT_OPTION];
Patrick Venture0b02be92018-08-31 11:55:55 -0700321} __attribute__((packed));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500322
Ratan Guptadcb10672017-07-10 10:33:50 +0530323int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500324{
Ratan Guptadcb10672017-07-10 10:33:50 +0530325 ipmi::PropertyMap properties;
326 int rc = 0;
Ratan Gupta8c31d232017-08-13 05:49:43 +0530327 uint8_t addrSize = ipmi::network::IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500328
Ratan Guptadcb10672017-07-10 10:33:50 +0530329 try
330 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700331 // TODO There may be cases where an interface is implemented by multiple
Ratan Guptadcb10672017-07-10 10:33:50 +0530332 // objects,to handle such cases we are interested on that object
333 // which are on interested busname.
334 // Currenlty mapper doesn't give the readable busname(gives busid)
335 // so we can't match with bus name so giving some object specific info
336 // as SETTINGS_MATCH.
337 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500338
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530339 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
Ratan Guptadcb10672017-07-10 10:33:50 +0530340
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530341 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
342 SETTINGS_ROOT, SETTINGS_MATCH);
343
344 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
345 SETTINGS_ROOT, SETTINGS_MATCH);
346
Patrick Venture0b02be92018-08-31 11:55:55 -0700347 properties = ipmi::getAllDbusProperties(
348 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE);
349 auto variant = ipmi::getDbusProperty(bus, macObjectInfo.second,
350 macObjectInfo.first, MAC_INTERFACE,
351 "MACAddress");
Ratan Guptadcb10672017-07-10 10:33:50 +0530352
Patrick Venture0b02be92018-08-31 11:55:55 -0700353 auto ipAddress = properties["Address"].get<std::string>();
Ratan Guptad70f4532017-08-04 02:07:31 +0530354
355 auto gateway = properties["Gateway"].get<std::string>();
356
357 auto prefix = properties["PrefixLength"].get<uint8_t>();
358
Patrick Venture0b02be92018-08-31 11:55:55 -0700359 uint8_t isStatic =
360 (properties["Origin"].get<std::string>() ==
361 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
362 ? 1
363 : 0;
Ratan Guptad70f4532017-08-04 02:07:31 +0530364
Ratan Guptacc8feb42017-07-25 21:52:10 +0530365 auto MACAddress = variant.get<std::string>();
366
Ratan Guptad70f4532017-08-04 02:07:31 +0530367 // it is expected here that we should get the valid data
368 // but we may also get the default values.
369 // Validation of the data is done by settings.
370 //
371 // if mac address is default mac address then
372 // don't send blank override.
Ratan Gupta8c31d232017-08-13 05:49:43 +0530373 if ((MACAddress == ipmi::network::DEFAULT_MAC_ADDRESS))
Ratan Guptad70f4532017-08-04 02:07:31 +0530374 {
375 memset(respptr->data, 0, SIZE_BOOT_OPTION);
376 rc = -1;
377 return rc;
378 }
379 // if addr is static then ipaddress,gateway,prefix
380 // should not be default one,don't send blank override.
381 if (isStatic)
382 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700383 if ((ipAddress == ipmi::network::DEFAULT_ADDRESS) ||
384 (gateway == ipmi::network::DEFAULT_ADDRESS) || (!prefix))
Ratan Guptad70f4532017-08-04 02:07:31 +0530385 {
386 memset(respptr->data, 0, SIZE_BOOT_OPTION);
387 rc = -1;
388 return rc;
389 }
390 }
391
Patrick Venture0b02be92018-08-31 11:55:55 -0700392 sscanf(
393 MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
394 (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
395 (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
396 (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
Ratan Guptadcb10672017-07-10 10:33:50 +0530397
Ratan Guptadcb10672017-07-10 10:33:50 +0530398 respptr->data[MAC_OFFSET + 6] = 0x00;
399
Patrick Venture0b02be92018-08-31 11:55:55 -0700400 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic, sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530401
402 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
Patrick Venture0b02be92018-08-31 11:55:55 -0700403 "xyz.openbmc_project.Network.IP.Protocol.IPv4")
404 ? AF_INET
405 : AF_INET6;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530406
Patrick Venture0b02be92018-08-31 11:55:55 -0700407 addrSize = (addressFamily == AF_INET)
408 ? ipmi::network::IPV4_ADDRESS_SIZE_BYTE
409 : ipmi::network::IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530410
411 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530412 inet_pton(addressFamily, ipAddress.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700413 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530414
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530415 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
416
417 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
418
419 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
420
Ratan Guptad70f4532017-08-04 02:07:31 +0530421 inet_pton(addressFamily, gateway.c_str(),
Patrick Venture0b02be92018-08-31 11:55:55 -0700422 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530423 }
424 catch (InternalFailure& e)
425 {
426 commit<InternalFailure>();
427 memset(respptr->data, 0, SIZE_BOOT_OPTION);
428 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500429 return rc;
430 }
431
Patrick Venture0b02be92018-08-31 11:55:55 -0700432 // PetiBoot-Specific
433 // If success then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530434 memcpy(respptr->data, net_conf_initial_bytes,
435 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500436
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530437 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
438
Ratan Guptafd28dd72016-08-01 04:58:01 -0500439#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530440 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500441
Ratan Guptadcb10672017-07-10 10:33:50 +0530442 for (uint8_t pos = 0; pos < index; pos++)
443 {
444 printf("%02x ", respptr->data[pos]);
445 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500446#endif
447
Ratan Guptafd28dd72016-08-01 04:58:01 -0500448 return rc;
449}
450
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530451/** @brief convert IPv4 and IPv6 addresses from binary to text form.
452 * @param[in] family - IPv4/Ipv6
453 * @param[in] data - req data pointer.
454 * @param[in] offset - offset in the data.
455 * @param[in] addrSize - size of the data which needs to be read from offset.
456 * @returns address in text form.
457 */
458
Patrick Venture0b02be92018-08-31 11:55:55 -0700459std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset,
460 uint8_t addrSize)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530461{
462 char ipAddr[INET6_ADDRSTRLEN] = {};
463
Patrick Venture0b02be92018-08-31 11:55:55 -0700464 switch (family)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530465 {
466 case AF_INET:
467 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700468 struct sockaddr_in addr4
469 {
470 };
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530471 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
472
Patrick Venture0b02be92018-08-31 11:55:55 -0700473 inet_ntop(AF_INET, &addr4.sin_addr, ipAddr, INET_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530474
475 break;
476 }
477 case AF_INET6:
478 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700479 struct sockaddr_in6 addr6
480 {
481 };
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530482 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
483
Patrick Venture0b02be92018-08-31 11:55:55 -0700484 inet_ntop(AF_INET6, &addr6.sin6_addr, ipAddr, INET6_ADDRSTRLEN);
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530485
486 break;
487 }
488 default:
489 {
490 return {};
491 }
492 }
493
494 return ipAddr;
495}
496
Ratan Guptadcb10672017-07-10 10:33:50 +0530497int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500498{
Ratan Guptadcb10672017-07-10 10:33:50 +0530499 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500500 std::string host_network_config;
Patrick Venture0b02be92018-08-31 11:55:55 -0700501 char mac[]{"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530502 std::string ipAddress, gateway;
Patrick Venture0b02be92018-08-31 11:55:55 -0700503 char addrOrigin{0};
504 uint8_t addrSize{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530505 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530506 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
Patrick Venture0b02be92018-08-31 11:55:55 -0700507 std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
508 uint8_t prefix{0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530509 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530510 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500511
Patrick Venture0b02be92018-08-31 11:55:55 -0700512 // cookie starts from second byte
Ratan Guptafd28dd72016-08-01 04:58:01 -0500513 // version starts from sixth byte
514
Ratan Guptadcb10672017-07-10 10:33:50 +0530515 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500516 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530517 do
518 {
519 // cookie == 0x21 0x70 0x62 0x21
520 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700521 (net_conf_initial_bytes + COOKIE_OFFSET),
522 SIZE_COOKIE) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530523 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700524 // cookie == 0
525 if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
526 SIZE_COOKIE) == 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530527 {
528 // need to zero out the network settings.
529 break;
530 }
531
532 log<level::ERR>("Invalid Cookie");
533 elog<InternalFailure>();
534 }
535
536 // vesion == 0x00 0x01
537 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
Patrick Venture0b02be92018-08-31 11:55:55 -0700538 (net_conf_initial_bytes + VERSION_OFFSET),
539 SIZE_VERSION) != 0)
Ratan Guptadcb10672017-07-10 10:33:50 +0530540 {
541
542 log<level::ERR>("Invalid Version");
543 elog<InternalFailure>();
544 }
545
Ratan Gupta8c31d232017-08-13 05:49:43 +0530546 snprintf(mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
Patrick Venture0b02be92018-08-31 11:55:55 -0700547 reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
548 reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
Ratan Guptadcb10672017-07-10 10:33:50 +0530549 reqptr->data[MAC_OFFSET + 4],
550 reqptr->data[MAC_OFFSET + 5]);
551
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530552 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
553 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530554
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530555 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530556 {
557 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530558 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530559 }
560
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530561 // Get the address size
Patrick Venture0b02be92018-08-31 11:55:55 -0700562 memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
563 sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530564
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530565 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530566
Ratan Guptad70f4532017-08-04 02:07:31 +0530567 memcpy(&prefix, &(reqptr->data[prefixOffset]),
568 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530569
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530570 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
571
Ratan Gupta8c31d232017-08-13 05:49:43 +0530572 if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530573 {
574 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
575 family = AF_INET6;
576 }
577
Patrick Venture0b02be92018-08-31 11:55:55 -0700578 ipAddress =
579 getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530580
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530581 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
582
Patrick Venture0b02be92018-08-31 11:55:55 -0700583 } while (0);
Ratan Guptadcb10672017-07-10 10:33:50 +0530584
Patrick Venture0b02be92018-08-31 11:55:55 -0700585 // Cookie == 0 or it is a valid cookie
586 host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
587 std::to_string(prefix) + ",gateway="s + gateway +
588 ",mac="s + mac + ",addressOrigin="s +
589 addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500590
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530591 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
592
593 auto ipObjectInfo = ipmi::getDbusObject(bus, IP_INTERFACE,
594 SETTINGS_ROOT, SETTINGS_MATCH);
595 auto macObjectInfo = ipmi::getDbusObject(bus, MAC_INTERFACE,
596 SETTINGS_ROOT, SETTINGS_MATCH);
Ratan Guptadcb10672017-07-10 10:33:50 +0530597 // set the dbus property
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530598 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700599 IP_INTERFACE, "Address", std::string(ipAddress));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530600 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700601 IP_INTERFACE, "PrefixLength", prefix);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530602 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700603 IP_INTERFACE, "Origin", addressOrigin);
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530604 ipmi::setDbusProperty(bus, ipObjectInfo.second, ipObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700605 IP_INTERFACE, "Gateway", std::string(gateway));
606 ipmi::setDbusProperty(
607 bus, ipObjectInfo.second, ipObjectInfo.first, IP_INTERFACE, "Type",
608 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
Ratan Gupta01d4bd12017-08-07 15:53:25 +0530609 ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
Patrick Venture0b02be92018-08-31 11:55:55 -0700610 MAC_INTERFACE, "MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500611
Patrick Venture0b02be92018-08-31 11:55:55 -0700612 log<level::DEBUG>(
613 "Network configuration changed",
614 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500615 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530616 catch (InternalFailure& e)
617 {
618 commit<InternalFailure>();
619 return -1;
620 }
621
622 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500623}
624
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500625uint32_t getPOHCounter()
626{
627 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
628
Patrick Venture0b02be92018-08-31 11:55:55 -0700629 auto chassisStateObj =
630 ipmi::getDbusObject(bus, chassisPOHStateIntf, chassisStateRoot, match);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500631
Patrick Venture0b02be92018-08-31 11:55:55 -0700632 auto service =
633 ipmi::getService(bus, chassisPOHStateIntf, chassisStateObj.first);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500634
Patrick Venture0b02be92018-08-31 11:55:55 -0700635 auto propValue =
636 ipmi::getDbusProperty(bus, service, chassisStateObj.first,
637 chassisPOHStateIntf, pOHCounterProperty);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -0500638
639 return propValue.get<uint32_t>();
640}
641
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500642ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
643 ipmi_request_t request,
644 ipmi_response_t response,
645 ipmi_data_len_t data_len,
646 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500647{
Adriana Kobylak40814c62015-10-27 15:58:44 -0500648 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800649 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500650 *data_len = 0;
651 return rc;
652}
653
Nan Li8d15fb42016-08-16 22:29:40 +0800654ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700655 ipmi_request_t request,
656 ipmi_response_t response,
657 ipmi_data_len_t data_len,
658 ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800659{
660 // sd_bus error
661 ipmi_ret_t rc = IPMI_CC_OK;
662
663 ipmi_chassis_cap_t chassis_cap{};
664
665 *data_len = sizeof(ipmi_chassis_cap_t);
666
667 // TODO: need future work. Get those flag from MRW.
668
669 // capabilities flags
670 // [7..4] - reserved
671 // [3] – 1b = provides power interlock (IPM 1.5)
672 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
Patrick Venture0b02be92018-08-31 11:55:55 -0700673 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has
674 // capabilities
675 // to lock out external power control and reset button or front
676 // panel interfaces and/or detect tampering with those
677 // interfaces).
Nan Li8d15fb42016-08-16 22:29:40 +0800678 // [0] -1b = Chassis provides intrusion (physical security) sensor.
679 // set to default value 0x0.
680 chassis_cap.cap_flags = 0x0;
681
682 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
683 // The 20h was given as those 5 device addresses.
684 // Chassis FRU info Device Address
685 chassis_cap.fru_info_dev_addr = 0x20;
686
687 // Chassis SDR Device Address
688 chassis_cap.sdr_dev_addr = 0x20;
689
690 // Chassis SEL Device Address
691 chassis_cap.sel_dev_addr = 0x20;
692
693 // Chassis System Management Device Address
694 chassis_cap.system_management_dev_addr = 0x20;
695
696 // Chassis Bridge Device Address.
697 chassis_cap.bridge_dev_addr = 0x20;
698
699 memcpy(response, &chassis_cap, *data_len);
700
701 return rc;
702}
703
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530704//------------------------------------------
705// Calls into Host State Manager Dbus object
706//------------------------------------------
707int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600708{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500709 // OpenBMC Host State Manager dbus framework
Patrick Venture0b02be92018-08-31 11:55:55 -0700710 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500711 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
Patrick Venture0b02be92018-08-31 11:55:55 -0700712 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
713 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530714
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500715 // sd_bus error
716 int rc = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700717 char* busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600718
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500719 // SD Bus error report mechanism.
720 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600721
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500722 // Gets a hook onto either a SYSTEM or SESSION bus
Patrick Venture0b02be92018-08-31 11:55:55 -0700723 sd_bus* bus_type = ipmid_get_sd_bus_connection();
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500724 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
725 if (rc < 0)
726 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700727 log<level::ERR>(
728 "Failed to get bus name",
729 entry("ERRNO=0x%X, OBJPATH=%s", -rc, HOST_STATE_MANAGER_ROOT));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500730 return rc;
731 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530732
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500733 // Convert to string equivalent of the passed in transition enum.
734 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530735
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500736 rc = sd_bus_call_method(bus_type, // On the system bus
737 busname, // Service to contact
738 HOST_STATE_MANAGER_ROOT, // Object path
739 DBUS_PROPERTY_IFACE, // Interface name
740 "Set", // Method to be called
741 &bus_error, // object to return error
742 nullptr, // Response buffer if any
743 "ssv", // Takes 3 arguments
Patrick Venture0b02be92018-08-31 11:55:55 -0700744 HOST_STATE_MANAGER_IFACE, PROPERTY, "s",
745 request.c_str());
746 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500747 {
748 log<level::ERR>("Failed to initiate transition",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530749 entry("ERRNO=0x%X, REQUEST=%s", -rc, request.c_str()));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500750 }
751 else
752 {
753 log<level::INFO>("Transition request initiated successfully");
754 }
vishwa36993272015-11-20 12:43:49 -0600755
756 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500757 free(busname);
vishwa36993272015-11-20 12:43:49 -0600758
Sergey Solomineb9b8142016-08-23 09:07:28 -0500759 return rc;
vishwa36993272015-11-20 12:43:49 -0600760}
761
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500762namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500763{
Nan Lifdd8ec52016-08-28 03:57:40 +0800764
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500765using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
766using IpmiValue = uint8_t;
767using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800768
Patrick Venture0b02be92018-08-31 11:55:55 -0700769std::map<DbusValue, IpmiValue> dbusToIpmi = {
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500770 {RestorePolicy::Policy::AlwaysOff, 0x00},
771 {RestorePolicy::Policy::Restore, 0x01},
Patrick Venture0b02be92018-08-31 11:55:55 -0700772 {RestorePolicy::Policy::AlwaysOn, 0x02}};
Nan Lifdd8ec52016-08-28 03:57:40 +0800773
Yong Lic6713cf2018-09-12 12:35:13 +0800774static constexpr uint8_t noChange = 0x03;
775static constexpr uint8_t allSupport = 0x01 | 0x02 | 0x04;
776static constexpr uint8_t policyBitMask = 0x07;
777static constexpr uint8_t setPolicyReqLen = 1;
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500778} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800779
780//----------------------------------------------------------------------
781// Get Chassis Status commands
782//----------------------------------------------------------------------
783ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500784 ipmi_request_t request,
785 ipmi_response_t response,
786 ipmi_data_len_t data_len,
787 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800788{
Patrick Venture0b02be92018-08-31 11:55:55 -0700789 const char* objname = "/org/openbmc/control/power0";
790 const char* intf = "org.openbmc.control.Power";
Nan Lifdd8ec52016-08-28 03:57:40 +0800791
Patrick Venture0b02be92018-08-31 11:55:55 -0700792 sd_bus* bus = NULL;
793 sd_bus_message* reply = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800794 int r = 0;
795 int pgood = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700796 char* busname = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800797 ipmi_ret_t rc = IPMI_CC_OK;
798 ipmi_get_chassis_status_t chassis_status{};
799
Nan Lifdd8ec52016-08-28 03:57:40 +0800800 uint8_t s = 0;
801
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500802 using namespace chassis::internal;
803 using namespace chassis::internal::cache;
804 using namespace power_policy;
805
Deepak Kodihallie6027092017-08-27 08:13:37 -0500806 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf).front();
Patrick Venture0b02be92018-08-31 11:55:55 -0700807 auto method = dbus.new_method_call(
808 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
809 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500810 method.append(powerRestoreIntf, "PowerRestorePolicy");
811 auto resp = dbus.call(method);
812 if (resp.is_method_error())
813 {
814 log<level::ERR>("Error in PowerRestorePolicy Get");
815 report<InternalFailure>();
816 *data_len = 0;
817 return IPMI_CC_UNSPECIFIED_ERROR;
818 }
819 sdbusplus::message::variant<std::string> result;
820 resp.read(result);
821 auto powerRestore =
822 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800823
824 *data_len = 4;
825
Tom Joseph63a00512017-08-09 23:39:59 +0530826 bus = ipmid_get_sd_bus_connection();
827
Nan Lifdd8ec52016-08-28 03:57:40 +0800828 r = mapper_get_service(bus, objname, &busname);
Patrick Venture0b02be92018-08-31 11:55:55 -0700829 if (r < 0)
830 {
831 log<level::ERR>("Failed to get bus name", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800832 rc = IPMI_CC_UNSPECIFIED_ERROR;
833 goto finish;
834 }
835
Patrick Venture0b02be92018-08-31 11:55:55 -0700836 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply,
837 "i");
838 if (r < 0)
839 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530840 log<level::ERR>("Failed to call sd_bus_get_property",
Patrick Venture0b02be92018-08-31 11:55:55 -0700841 entry("PROPERTY=%s", "pgood"), entry("ERRNO=0x%X", -r),
842 entry("BUS=%s", busname), entry("PATH=%s", objname),
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530843 entry("INTERFACE=%s", intf));
Nan Lifdd8ec52016-08-28 03:57:40 +0800844 rc = IPMI_CC_UNSPECIFIED_ERROR;
845 goto finish;
846 }
847
848 r = sd_bus_message_read(reply, "i", &pgood);
Patrick Venture0b02be92018-08-31 11:55:55 -0700849 if (r < 0)
850 {
851 log<level::ERR>("Failed to read sensor:", entry("ERRNO=0x%X", -r));
Nan Lifdd8ec52016-08-28 03:57:40 +0800852 rc = IPMI_CC_UNSPECIFIED_ERROR;
853 goto finish;
854 }
855
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500856 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800857
858 // Current Power State
859 // [7] reserved
860 // [6..5] power restore policy
861 // 00b = chassis stays powered off after AC/mains returns
862 // 01b = after AC returns, power is restored to the state that was
863 // in effect when AC/mains was lost.
864 // 10b = chassis always powers up after AC/mains returns
865 // 11b = unknow
866 // Set to 00b, by observing the hardware behavior.
Patrick Venture0b02be92018-08-31 11:55:55 -0700867 // Do we need to define a dbus property to identify the restore
868 // policy?
Nan Lifdd8ec52016-08-28 03:57:40 +0800869
870 // [4] power control fault
871 // 1b = controller attempted to turn system power on or off, but
872 // system did not enter desired state.
873 // Set to 0b, since We don't support it..
874
875 // [3] power fault
876 // 1b = fault detected in main power subsystem.
877 // set to 0b. for we don't support it.
878
879 // [2] 1b = interlock (chassis is presently shut down because a chassis
880 // panel interlock switch is active). (IPMI 1.5)
881 // set to 0b, for we don't support it.
882
883 // [1] power overload
884 // 1b = system shutdown because of power overload condition.
885 // set to 0b, for we don't support it.
886
887 // [0] power is on
888 // 1b = system power is on
889 // 0b = system power is off(soft-off S4/S5, or mechanical off)
890
Patrick Venture0b02be92018-08-31 11:55:55 -0700891 chassis_status.cur_power_state = ((s & 0x3) << 5) | (pgood & 0x1);
Nan Lifdd8ec52016-08-28 03:57:40 +0800892
893 // Last Power Event
894 // [7..5] – reserved
895 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
896 // [3] – 1b = last power down caused by power fault
897 // [2] – 1b = last power down caused by a power interlock being activated
898 // [1] – 1b = last power down caused by a Power overload
899 // [0] – 1b = AC failed
900 // set to 0x0, for we don't support these fields.
901
902 chassis_status.last_power_event = 0;
903
904 // Misc. Chassis State
905 // [7] – reserved
906 // [6] – 1b = Chassis Identify command and state info supported (Optional)
907 // 0b = Chassis Identify command support unspecified via this command.
908 // (The Get Command Support command , if implemented, would still
909 // indicate support for the Chassis Identify command)
Patrick Venture0b02be92018-08-31 11:55:55 -0700910 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved
911 // (return
Nan Lifdd8ec52016-08-28 03:57:40 +0800912 // as 00b) otherwise. Returns the present chassis identify state.
913 // Refer to the Chassis Identify command for more info.
914 // 00b = chassis identify state = Off
915 // 01b = chassis identify state = Temporary(timed) On
916 // 10b = chassis identify state = Indefinite On
917 // 11b = reserved
918 // [3] – 1b = Cooling/fan fault detected
919 // [2] – 1b = Drive Fault
920 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
921 // push-buttons disabled.)
922 // [0] – 1b = Chassis Intrusion active
923 // set to 0, for we don't support them.
924 chassis_status.misc_power_state = 0;
925
926 // Front Panel Button Capabilities and disable/enable status(Optional)
927 // set to 0, for we don't support them.
928 chassis_status.front_panel_button_cap_status = 0;
929
930 // Pack the actual response
931 memcpy(response, &chassis_status, *data_len);
932
933finish:
934 free(busname);
935 reply = sd_bus_message_unref(reply);
936
937 return rc;
938}
Chris Austen7888c4d2015-12-03 15:26:20 -0600939
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530940//-------------------------------------------------------------
941// Send a command to SoftPowerOff application to stop any timer
942//-------------------------------------------------------------
943int stop_soft_off_timer()
944{
Patrick Venture0b02be92018-08-31 11:55:55 -0700945 constexpr auto iface = "org.freedesktop.DBus.Properties";
946 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
947 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530948
Patrick Venture0b02be92018-08-31 11:55:55 -0700949 constexpr auto property = "ResponseReceived";
950 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
951 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530952
953 // Get the system bus where most system services are provided.
954 auto bus = ipmid_get_sd_bus_connection();
955
956 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500957 // TODO openbmc/openbmc#1661 - Mapper refactor
958 //
959 // See openbmc/openbmc#1743 for some details but high level summary is that
960 // for now the code will directly call the soft off interface due to a
961 // race condition with mapper usage
962 //
Patrick Venture0b02be92018-08-31 11:55:55 -0700963 // char *busname = nullptr;
964 // auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
965 // if (r < 0)
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500966 //{
967 // fprintf(stderr, "Failed to get %s bus name: %s\n",
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530968 // SOFTOFF_OBJPATH, -r);
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500969 // return r;
970 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530971
972 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -0500973 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Patrick Venture0b02be92018-08-31 11:55:55 -0700974 "Set", nullptr, nullptr, "ssv", soft_off_iface,
975 property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530976 if (rc < 0)
977 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530978 log<level::ERR>("Failed to set property in SoftPowerOff object",
979 entry("ERRNO=0x%X", -rc));
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530980 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500981
Patrick Venture0b02be92018-08-31 11:55:55 -0700982 // TODO openbmc/openbmc#1661 - Mapper refactor
983 // free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +0530984 return rc;
985}
986
vishwa36993272015-11-20 12:43:49 -0600987//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500988// Create file to indicate there is no need for softoff notification to host
989//----------------------------------------------------------------------
990void indicate_no_softoff_needed()
991{
992 fs::path path{HOST_INBAND_REQUEST_DIR};
993 if (!fs::is_directory(path))
994 {
995 fs::create_directory(path);
996 }
997
998 // Add the host instance (default 0 for now) to the file name
999 std::string file{HOST_INBAND_REQUEST_FILE};
Patrick Venture0b02be92018-08-31 11:55:55 -07001000 auto size = std::snprintf(nullptr, 0, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001001 size++; // null
1002 std::unique_ptr<char[]> buf(new char[size]);
Patrick Venture0b02be92018-08-31 11:55:55 -07001003 std::snprintf(buf.get(), size, file.c_str(), 0);
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001004
1005 // Append file name to directory and create it
1006 path /= buf.get();
1007 std::ofstream(path.c_str());
1008}
1009
1010//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -06001011// Chassis Control commands
1012//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001013ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1014 ipmi_request_t request,
1015 ipmi_response_t response,
1016 ipmi_data_len_t data_len,
1017 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -06001018{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001019 // Error from power off.
1020 int rc = 0;
vishwa36993272015-11-20 12:43:49 -06001021
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001022 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001023 *data_len = 0;
1024
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001025 // Catch the actual operaton by peeking into request buffer
Patrick Venture0b02be92018-08-31 11:55:55 -07001026 uint8_t chassis_ctrl_cmd = *(uint8_t*)request;
vishwa36993272015-11-20 12:43:49 -06001027
Patrick Venture0b02be92018-08-31 11:55:55 -07001028 switch (chassis_ctrl_cmd)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001029 {
1030 case CMD_POWER_ON:
1031 rc = initiate_state_transition(State::Host::Transition::On);
1032 break;
1033 case CMD_POWER_OFF:
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301034 // This path would be hit in 2 conditions.
1035 // 1: When user asks for power off using ipmi chassis command 0x04
1036 // 2: Host asking for power off post shutting down.
1037
1038 // If it's a host requested power off, then need to nudge Softoff
1039 // application that it needs to stop the watchdog timer if running.
1040 // If it is a user requested power off, then this is not really
1041 // needed. But then we need to differentiate between user and host
1042 // calling this same command
1043
1044 // For now, we are going ahead with trying to nudge the soft off and
1045 // interpret the failure to do so as a non softoff case
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001046 rc = stop_soft_off_timer();
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301047
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001048 // Only request the Off transition if the soft power off
1049 // application is not running
1050 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001051 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001052 // First create a file to indicate to the soft off application
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301053 // that it should not run. Not doing this will result in State
1054 // manager doing a default soft power off when asked for power
1055 // off.
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001056 indicate_no_softoff_needed();
1057
1058 // Now request the shutdown
1059 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001060 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001061 else
1062 {
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301063 log<level::INFO>("Soft off is running, so let shutdown target "
1064 "stop the host");
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001065 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001066 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301067
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001068 case CMD_HARD_RESET:
1069 case CMD_POWER_CYCLE:
1070 // SPEC has a section that says certain implementations can trigger
1071 // PowerOn if power is Off when a command to power cycle is
1072 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001073
1074 // First create a file to indicate to the soft off application
1075 // that it should not run since this is a direct user initiated
1076 // power reboot request (i.e. a reboot request that is not
1077 // originating via a soft power off SMS request)
1078 indicate_no_softoff_needed();
1079
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001080 rc = initiate_state_transition(State::Host::Transition::Reboot);
1081 break;
Vishwanatha Subbanna8b26d352017-08-04 18:35:18 +05301082
1083 case CMD_SOFT_OFF_VIA_OVER_TEMP:
1084 // Request Host State Manager to do a soft power off
1085 rc = initiate_state_transition(State::Host::Transition::Off);
1086 break;
1087
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001088 default:
1089 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301090 log<level::ERR>("Invalid Chassis Control command",
1091 entry("CMD=0x%X", chassis_ctrl_cmd));
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001092 rc = -1;
1093 }
1094 }
vishwa36993272015-11-20 12:43:49 -06001095
Patrick Venture0b02be92018-08-31 11:55:55 -07001096 return ((rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001097}
1098
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001099/** @brief Return D-Bus connection string to enclosure identify LED object
1100 *
1101 * @param[in, out] connection - connection to D-Bus object
1102 * @return a IPMI return code
1103 */
1104std::string getEnclosureIdentifyConnection()
Tom Joseph5110c122018-03-23 17:55:40 +05301105{
Tom Joseph5110c122018-03-23 17:55:40 +05301106 // lookup enclosure_identify group owner(s) in mapper
1107 auto mapperCall = chassis::internal::dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001108 ipmi::MAPPER_BUS_NAME, ipmi::MAPPER_OBJ, ipmi::MAPPER_INTF,
1109 "GetObject");
Tom Joseph5110c122018-03-23 17:55:40 +05301110
1111 mapperCall.append(identify_led_object_name);
Patrick Venture0b02be92018-08-31 11:55:55 -07001112 static const std::vector<std::string> interfaces = {
1113 "xyz.openbmc_project.Led.Group"};
Tom Joseph5110c122018-03-23 17:55:40 +05301114 mapperCall.append(interfaces);
1115 auto mapperReply = chassis::internal::dbus.call(mapperCall);
1116 if (mapperReply.is_method_error())
1117 {
1118 log<level::ERR>("Chassis Identify: Error communicating to mapper.");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001119 elog<InternalFailure>();
Tom Joseph5110c122018-03-23 17:55:40 +05301120 }
1121 std::vector<std::pair<std::string, std::vector<std::string>>> mapperResp;
1122 mapperReply.read(mapperResp);
1123
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001124 if (mapperResp.size() != encIdentifyObjectsSize)
Tom Joseph5110c122018-03-23 17:55:40 +05301125 {
Patrick Venture0b02be92018-08-31 11:55:55 -07001126 log<level::ERR>(
1127 "Invalid number of enclosure identify objects.",
1128 entry("ENC_IDENTITY_OBJECTS_SIZE=%d", mapperResp.size()));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001129 elog<InternalFailure>();
1130 }
1131 auto pair = mapperResp[encIdentifyObjectsSize - 1];
1132 return pair.first;
1133}
Tom Joseph5110c122018-03-23 17:55:40 +05301134
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001135/** @brief Turn On/Off enclosure identify LED
1136 *
1137 * @param[in] flag - true to turn on LED, false to turn off
1138 * @return a IPMI return code
1139 */
1140void enclosureIdentifyLed(bool flag)
1141{
1142 using namespace chassis::internal;
1143 std::string connection = std::move(getEnclosureIdentifyConnection());
Patrick Venture0b02be92018-08-31 11:55:55 -07001144 auto led =
1145 dbus.new_method_call(connection.c_str(), identify_led_object_name,
1146 "org.freedesktop.DBus.Properties", "Set");
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001147 led.append("xyz.openbmc_project.Led.Group", "Asserted",
Patrick Venture0b02be92018-08-31 11:55:55 -07001148 sdbusplus::message::variant<bool>(flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001149 auto ledReply = dbus.call(led);
1150 if (ledReply.is_method_error())
1151 {
1152 log<level::ERR>("Chassis Identify: Error Setting State On/Off\n",
Patrick Venture0b02be92018-08-31 11:55:55 -07001153 entry("LED_STATE=%d", flag));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001154 elog<InternalFailure>();
1155 }
1156}
1157
1158/** @brief Callback method to turn off LED
1159 */
1160void enclosureIdentifyLedOff()
1161{
1162 try
1163 {
1164 enclosureIdentifyLed(false);
1165 }
1166 catch (const InternalFailure& e)
1167 {
1168 report<InternalFailure>();
1169 }
1170}
1171
1172/** @brief Create timer to turn on and off the enclosure LED
1173 */
1174void createIdentifyTimer()
1175{
1176 if (!identifyTimer)
1177 {
1178 identifyTimer = std::make_unique<phosphor::ipmi::Timer>(
1179 ipmid_get_sd_event_connection(), enclosureIdentifyLedOff);
1180 }
1181}
1182
1183ipmi_ret_t ipmi_chassis_identify(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1184 ipmi_request_t request,
1185 ipmi_response_t response,
1186 ipmi_data_len_t data_len,
1187 ipmi_context_t context)
1188{
1189 if (*data_len > chassisIdentifyReqLength)
1190 {
1191 return IPMI_CC_REQ_DATA_LEN_INVALID;
1192 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001193 uint8_t identifyInterval =
1194 *data_len > identifyIntervalPos
1195 ? (static_cast<uint8_t*>(request))[identifyIntervalPos]
1196 : DEFAULT_IDENTIFY_TIME_OUT;
1197 bool forceIdentify =
1198 (*data_len == chassisIdentifyReqLength)
1199 ? (static_cast<uint8_t*>(request))[forceIdentifyPos] & 0x01
1200 : false;
Tom Josephbed26992018-07-31 23:00:24 +05301201
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001202 if (identifyInterval || forceIdentify)
1203 {
1204 // stop the timer if already started, for force identify we should
1205 // not turn off LED
1206 identifyTimer->setTimer(SD_EVENT_OFF);
1207 try
Tom Joseph5110c122018-03-23 17:55:40 +05301208 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001209 enclosureIdentifyLed(true);
1210 }
1211 catch (const InternalFailure& e)
1212 {
1213 report<InternalFailure>();
1214 return IPMI_CC_RESPONSE_ERROR;
Tom Joseph5110c122018-03-23 17:55:40 +05301215 }
1216
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001217 if (forceIdentify)
Tom Joseph5110c122018-03-23 17:55:40 +05301218 {
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001219 return IPMI_CC_OK;
1220 }
1221 // start the timer
1222 auto time = std::chrono::duration_cast<std::chrono::microseconds>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001223 std::chrono::seconds(identifyInterval));
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001224 identifyTimer->startTimer(time);
Tom Joseph5110c122018-03-23 17:55:40 +05301225 }
Tom Josephbed26992018-07-31 23:00:24 +05301226 else if (!identifyInterval)
1227 {
1228 identifyTimer->setTimer(SD_EVENT_OFF);
1229 enclosureIdentifyLedOff();
1230 }
Tom Joseph5110c122018-03-23 17:55:40 +05301231 return IPMI_CC_OK;
1232}
1233
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001234namespace boot_options
1235{
1236
1237using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1238using IpmiValue = uint8_t;
1239constexpr auto ipmiDefault = 0;
1240
Patrick Venture0b02be92018-08-31 11:55:55 -07001241std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001242 {0x01, Source::Sources::Network},
1243 {0x02, Source::Sources::Disk},
1244 {0x05, Source::Sources::ExternalMedia},
Patrick Venture0b02be92018-08-31 11:55:55 -07001245 {ipmiDefault, Source::Sources::Default}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001246
Patrick Venture0b02be92018-08-31 11:55:55 -07001247std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001248 {0x03, Mode::Modes::Safe},
1249 {0x06, Mode::Modes::Setup},
Patrick Venture0b02be92018-08-31 11:55:55 -07001250 {ipmiDefault, Mode::Modes::Regular}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001251
Patrick Venture0b02be92018-08-31 11:55:55 -07001252std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001253 {Source::Sources::Network, 0x01},
1254 {Source::Sources::Disk, 0x02},
1255 {Source::Sources::ExternalMedia, 0x05},
Patrick Venture0b02be92018-08-31 11:55:55 -07001256 {Source::Sources::Default, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001257
Patrick Venture0b02be92018-08-31 11:55:55 -07001258std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001259 {Mode::Modes::Safe, 0x03},
1260 {Mode::Modes::Setup, 0x06},
Patrick Venture0b02be92018-08-31 11:55:55 -07001261 {Mode::Modes::Regular, ipmiDefault}};
shgoupfd84fbbf2015-12-17 10:05:51 +08001262
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001263} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001264
Marri Devender Rao81719702018-05-07 00:53:48 -05001265/** @brief Set the property value for boot source
1266 * @param[in] source - boot source value
1267 * @return On failure return IPMI error.
1268 */
1269static ipmi_ret_t setBootSource(const Source::Sources& source)
1270{
1271 using namespace chassis::internal;
1272 using namespace chassis::internal::cache;
1273 sdbusplus::message::variant<std::string> property =
1274 convertForMessage(source);
1275 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1276 const auto& bootSourceSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001277 auto method = dbus.new_method_call(
1278 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1279 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001280 method.append(bootSourceIntf, "BootSource", property);
1281 auto reply = dbus.call(method);
1282 if (reply.is_method_error())
1283 {
1284 log<level::ERR>("Error in BootSource Set");
1285 report<InternalFailure>();
1286 return IPMI_CC_UNSPECIFIED_ERROR;
1287 }
1288 return IPMI_CC_OK;
1289}
1290
Patrick Venture0b02be92018-08-31 11:55:55 -07001291/** @brief Set the property value for boot mode
Marri Devender Rao81719702018-05-07 00:53:48 -05001292 * @param[in] mode - boot mode value
1293 * @return On failure return IPMI error.
1294 */
1295static ipmi_ret_t setBootMode(const Mode::Modes& mode)
1296{
1297 using namespace chassis::internal;
1298 using namespace chassis::internal::cache;
Patrick Venture0b02be92018-08-31 11:55:55 -07001299 sdbusplus::message::variant<std::string> property = convertForMessage(mode);
Marri Devender Rao81719702018-05-07 00:53:48 -05001300 auto bootSetting = settings::boot::setting(objects, bootModeIntf);
1301 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001302 auto method = dbus.new_method_call(
1303 objects.service(bootModeSetting, bootModeIntf).c_str(),
1304 bootModeSetting.c_str(), ipmi::PROP_INTF, "Set");
Marri Devender Rao81719702018-05-07 00:53:48 -05001305 method.append(bootModeIntf, "BootMode", property);
1306 auto reply = dbus.call(method);
1307 if (reply.is_method_error())
1308 {
1309 log<level::ERR>("Error in BootMode Set");
1310 report<InternalFailure>();
1311 return IPMI_CC_UNSPECIFIED_ERROR;
1312 }
1313 return IPMI_CC_OK;
1314}
1315
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001316ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1317 ipmi_request_t request,
1318 ipmi_response_t response,
1319 ipmi_data_len_t data_len,
1320 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001321{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001322 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001323 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
Patrick Venture0b02be92018-08-31 11:55:55 -07001324 char* p = NULL;
1325 get_sys_boot_options_response_t* resp =
1326 (get_sys_boot_options_response_t*)response;
1327 get_sys_boot_options_t* reqptr = (get_sys_boot_options_t*)request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001328 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001329
Patrick Venture0b02be92018-08-31 11:55:55 -07001330 memset(resp, 0, sizeof(*resp));
1331 resp->version = SET_PARM_VERSION;
1332 resp->parm = 5;
1333 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001334
shgoupfd84fbbf2015-12-17 10:05:51 +08001335 /*
1336 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1337 * This is the only parameter used by petitboot.
1338 */
Patrick Venture0b02be92018-08-31 11:55:55 -07001339 if (reqptr->parameter ==
1340 static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
1341 {
shgoupfd84fbbf2015-12-17 10:05:51 +08001342
Ratan Guptafd28dd72016-08-01 04:58:01 -05001343 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001344 using namespace chassis::internal;
1345 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001346
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001347 try
ratagupta6f6bff2016-04-04 06:20:11 -05001348 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001349 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
1350 const auto& bootSourceSetting =
1351 std::get<settings::Path>(bootSetting);
1352 auto oneTimeEnabled =
1353 std::get<settings::boot::OneTimeEnabled>(bootSetting);
Patrick Venture0b02be92018-08-31 11:55:55 -07001354 auto method = dbus.new_method_call(
1355 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1356 bootSourceSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001357 method.append(bootSourceIntf, "BootSource");
1358 auto reply = dbus.call(method);
1359 if (reply.is_method_error())
1360 {
1361 log<level::ERR>("Error in BootSource Get");
1362 report<InternalFailure>();
1363 *data_len = 0;
1364 return IPMI_CC_UNSPECIFIED_ERROR;
1365 }
1366 sdbusplus::message::variant<std::string> result;
1367 reply.read(result);
1368 auto bootSource =
1369 Source::convertSourcesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001370
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001371 bootSetting = settings::boot::setting(objects, bootModeIntf);
1372 const auto& bootModeSetting = std::get<settings::Path>(bootSetting);
1373 method = dbus.new_method_call(
Patrick Venture0b02be92018-08-31 11:55:55 -07001374 objects.service(bootModeSetting, bootModeIntf).c_str(),
1375 bootModeSetting.c_str(), ipmi::PROP_INTF, "Get");
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001376 method.append(bootModeIntf, "BootMode");
1377 reply = dbus.call(method);
1378 if (reply.is_method_error())
1379 {
1380 log<level::ERR>("Error in BootMode Get");
1381 report<InternalFailure>();
1382 *data_len = 0;
1383 return IPMI_CC_UNSPECIFIED_ERROR;
1384 }
1385 reply.read(result);
1386 auto bootMode =
1387 Mode::convertModesFromString(result.get<std::string>());
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001388
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001389 bootOption = sourceDbusToIpmi.at(bootSource);
1390 if ((Mode::Modes::Regular == bootMode) &&
1391 (Source::Sources::Default == bootSource))
1392 {
1393 bootOption = ipmiDefault;
1394 }
1395 else if (Source::Sources::Default == bootSource)
1396 {
1397 bootOption = modeDbusToIpmi.at(bootMode);
1398 }
1399 resp->data[1] = (bootOption << 2);
ratagupta6f6bff2016-04-04 06:20:11 -05001400
Patrick Venture0b02be92018-08-31 11:55:55 -07001401 resp->data[0] = oneTimeEnabled
1402 ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
1403 : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001404
ratagupta6f6bff2016-04-04 06:20:11 -05001405 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001406 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001407 catch (InternalFailure& e)
1408 {
1409 report<InternalFailure>();
1410 *data_len = 0;
1411 return IPMI_CC_UNSPECIFIED_ERROR;
1412 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001413 }
1414 else if (reqptr->parameter ==
1415 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
1416 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001417
Patrick Venture0b02be92018-08-31 11:55:55 -07001418 *data_len =
1419 static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001420
Patrick Venture0b02be92018-08-31 11:55:55 -07001421 resp->parm =
1422 static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001423
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001424 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001425
Patrick Venture0b02be92018-08-31 11:55:55 -07001426 if (ret < 0)
1427 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001428
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301429 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001430 "getHostNetworkData failed for get_sys_boot_options.");
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001431 rc = IPMI_CC_UNSPECIFIED_ERROR;
Patrick Venture0b02be92018-08-31 11:55:55 -07001432 }
1433 else
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001434 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001435 }
1436
Patrick Venture0b02be92018-08-31 11:55:55 -07001437 else
1438 {
1439 log<level::ERR>("Unsupported parameter",
1440 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001441 }
1442
1443 if (p)
1444 free(p);
1445
Ratan Guptafd28dd72016-08-01 04:58:01 -05001446 if (rc == IPMI_CC_OK)
1447 {
1448 *data_len += 2;
1449 }
1450
shgoupfd84fbbf2015-12-17 10:05:51 +08001451 return rc;
1452}
1453
shgoupfd84fbbf2015-12-17 10:05:51 +08001454ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001455 ipmi_request_t request,
1456 ipmi_response_t response,
1457 ipmi_data_len_t data_len,
1458 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001459{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001460 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001461 ipmi_ret_t rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001462 set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
shgoupfd84fbbf2015-12-17 10:05:51 +08001463
Patrick Venture0b02be92018-08-31 11:55:55 -07001464 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
1465 reqptr->parameter);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001466
shgoupfd84fbbf2015-12-17 10:05:51 +08001467 // This IPMI command does not have any resposne data
1468 *data_len = 0;
1469
1470 /* 000101
1471 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1472 * This is the only parameter used by petitboot.
1473 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001474
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001475 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1476 {
1477 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1478 using namespace chassis::internal;
1479 using namespace chassis::internal::cache;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001480 auto oneTimeEnabled = false;
1481 constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
Tom Joseph57e8eb72017-09-25 18:05:02 +05301482 constexpr auto oneTimePath =
Patrick Venture0b02be92018-08-31 11:55:55 -07001483 "/xyz/openbmc_project/control/host0/boot/one_time";
shgoupfd84fbbf2015-12-17 10:05:51 +08001484
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001485 try
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001486 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001487 bool permanent =
1488 (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
1489 SET_PARM_BOOT_FLAGS_PERMANENT;
1490
Patrick Venture0b02be92018-08-31 11:55:55 -07001491 auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301492
1493 oneTimeEnabled =
1494 std::get<settings::boot::OneTimeEnabled>(bootSetting);
1495
1496 /*
1497 * Check if the current boot setting is onetime or permanent, if the
1498 * request in the command is otherwise, then set the "Enabled"
1499 * property in one_time object path to 'True' to indicate onetime
1500 * and 'False' to indicate permanent.
1501 *
1502 * Once the onetime/permanent setting is applied, then the bootMode
1503 * and bootSource is updated for the corresponding object.
1504 */
1505 if ((permanent && oneTimeEnabled) ||
1506 (!permanent && !oneTimeEnabled))
1507 {
1508 auto service = ipmi::getService(dbus, enabledIntf, oneTimePath);
1509
Patrick Venture0b02be92018-08-31 11:55:55 -07001510 ipmi::setDbusProperty(dbus, service, oneTimePath, enabledIntf,
1511 "Enabled", !permanent);
Tom Joseph57e8eb72017-09-25 18:05:02 +05301512 }
1513
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001514 auto modeItr = modeIpmiToDbus.find(bootOption);
1515 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1516 if (sourceIpmiToDbus.end() != sourceItr)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001517 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001518 rc = setBootSource(sourceItr->second);
1519 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001520 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001521 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001522 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001523 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001524 // If a set boot device is mapping to a boot source, then reset
1525 // the boot mode D-Bus property to default.
1526 // This way the ipmid code can determine which property is not
1527 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001528 if (sourceItr->second != Source::Sources::Default)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001529 {
1530 setBootMode(Mode::Modes::Regular);
1531 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001532 }
1533 if (modeIpmiToDbus.end() != modeItr)
1534 {
Marri Devender Rao81719702018-05-07 00:53:48 -05001535 rc = setBootMode(modeItr->second);
1536 if (rc != IPMI_CC_OK)
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001537 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001538 *data_len = 0;
Marri Devender Rao81719702018-05-07 00:53:48 -05001539 return rc;
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001540 }
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001541 // If a set boot device is mapping to a boot mode, then reset
1542 // the boot source D-Bus property to default.
1543 // This way the ipmid code can determine which property is not
1544 // at the default value
Patrick Venture0b02be92018-08-31 11:55:55 -07001545 if (modeItr->second != Mode::Modes::Regular)
Marri Devender Rao54fa1302018-05-07 01:06:23 -05001546 {
1547 setBootSource(Source::Sources::Default);
1548 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001549 }
1550 }
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001551 catch (InternalFailure& e)
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001552 {
Deepak Kodihalli13791bd2017-08-28 06:50:51 -05001553 report<InternalFailure>();
1554 *data_len = 0;
1555 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001556 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001557 }
1558 else if (reqptr->parameter ==
1559 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
1560 {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001561
1562 int ret = setHostNetworkData(reqptr);
Patrick Venture0b02be92018-08-31 11:55:55 -07001563 if (ret < 0)
1564 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +05301565 log<level::ERR>(
Patrick Venture0b02be92018-08-31 11:55:55 -07001566 "setHostNetworkData failed for set_sys_boot_options");
Ratan Guptafd28dd72016-08-01 04:58:01 -05001567 rc = IPMI_CC_UNSPECIFIED_ERROR;
1568 }
Patrick Venture0b02be92018-08-31 11:55:55 -07001569 }
1570 else if (reqptr->parameter ==
1571 static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
1572 {
Tom Josephf536c902017-09-25 18:08:15 +05301573 // Handle parameter #4 and return command completed normally
1574 // (IPMI_CC_OK). There is no implementation in OpenBMC for this
1575 // parameter. This is added to support the ipmitool command `chassis
1576 // bootdev` which sends set on parameter #4, before setting the boot
1577 // flags.
1578 rc = IPMI_CC_OK;
Patrick Venture0b02be92018-08-31 11:55:55 -07001579 }
1580 else
1581 {
1582 log<level::ERR>("Unsupported parameter",
1583 entry("PARAM=0x%x", reqptr->parameter));
shgoupfd84fbbf2015-12-17 10:05:51 +08001584 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001585 }
1586
1587 return rc;
1588}
1589
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001590ipmi_ret_t ipmiGetPOHCounter(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1591 ipmi_request_t request, ipmi_response_t response,
1592 ipmi_data_len_t data_len, ipmi_context_t context)
1593{
1594 // sd_bus error
1595 ipmi_ret_t rc = IPMI_CC_OK;
1596
1597 auto resptr = reinterpret_cast<GetPOHCountResponse*>(response);
1598
1599 try
1600 {
1601 auto pohCounter = getPOHCounter();
1602 resptr->counterReading[0] = pohCounter;
1603 resptr->counterReading[1] = pohCounter >> 8;
1604 resptr->counterReading[2] = pohCounter >> 16;
1605 resptr->counterReading[3] = pohCounter >> 24;
1606 }
1607 catch (std::exception& e)
1608 {
1609 log<level::ERR>(e.what());
1610 return IPMI_CC_UNSPECIFIED_ERROR;
1611 }
1612
1613 resptr->minPerCount = poh::minutesPerCount;
1614 *data_len = sizeof(GetPOHCountResponse);
1615
1616 return rc;
1617}
1618
Yong Lic6713cf2018-09-12 12:35:13 +08001619ipmi_ret_t ipmi_chassis_set_power_restore_policy(
1620 ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_request_t request,
1621 ipmi_response_t response, ipmi_data_len_t data_len, ipmi_context_t context)
1622{
1623 auto* reqptr = reinterpret_cast<uint8_t*>(request);
1624 auto* resptr = reinterpret_cast<uint8_t*>(response);
1625 uint8_t reqPolicy = 0;
1626
1627 power_policy::DbusValue value =
1628 power_policy::RestorePolicy::Policy::AlwaysOff;
1629
1630 if (*data_len != power_policy::setPolicyReqLen)
1631 {
1632 phosphor::logging::log<level::ERR>("Unsupported request length",
1633 entry("LEN=0x%x", *data_len));
1634 *data_len = 0;
1635 return IPMI_CC_REQ_DATA_LEN_INVALID;
1636 }
1637
1638 reqPolicy = *reqptr & power_policy::policyBitMask;
1639 if (reqPolicy > power_policy::noChange)
1640 {
1641 phosphor::logging::log<level::ERR>("Reserved request parameter",
1642 entry("REQ=0x%x", reqPolicy));
1643 *data_len = 0;
1644 return IPMI_CC_PARM_NOT_SUPPORTED;
1645 }
1646
1647 if (reqPolicy == power_policy::noChange)
1648 {
1649 // just return the supported policy
1650 *resptr = power_policy::allSupport;
1651 *data_len = power_policy::setPolicyReqLen;
1652 return IPMI_CC_OK;
1653 }
1654
1655 for (auto const& it : power_policy::dbusToIpmi)
1656 {
1657 if (it.second == reqPolicy)
1658 {
1659 value = it.first;
1660 break;
1661 }
1662 }
1663
1664 try
1665 {
1666 const settings::Path& powerRestoreSetting =
1667 chassis::internal::cache::objects.map
1668 .at(chassis::internal::powerRestoreIntf)
1669 .front();
1670 sdbusplus::message::variant<std::string> property =
1671 convertForMessage(value);
1672
1673 auto method = chassis::internal::dbus.new_method_call(
1674 chassis::internal::cache::objects
1675 .service(powerRestoreSetting,
1676 chassis::internal::powerRestoreIntf)
1677 .c_str(),
1678 powerRestoreSetting.c_str(), ipmi::PROP_INTF, "Set");
1679
1680 method.append(chassis::internal::powerRestoreIntf, "PowerRestorePolicy",
1681 property);
1682 auto reply = chassis::internal::dbus.call(method);
1683 if (reply.is_method_error())
1684 {
1685 phosphor::logging::log<level::ERR>("Unspecified Error");
1686 *data_len = 0;
1687 return IPMI_CC_UNSPECIFIED_ERROR;
1688 }
1689 }
1690 catch (InternalFailure& e)
1691 {
1692 report<InternalFailure>();
1693 *data_len = 0;
1694 return IPMI_CC_UNSPECIFIED_ERROR;
1695 }
1696
1697 *data_len = power_policy::setPolicyReqLen;
1698 return IPMI_CC_OK;
1699}
1700
Adriana Kobylak40814c62015-10-27 15:58:44 -05001701void register_netfn_chassis_functions()
1702{
Marri Devender Rao6706c1c2018-05-14 00:29:38 -05001703 createIdentifyTimer();
1704
Tom05732372016-09-06 17:21:23 +05301705 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -07001706 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL,
1707 ipmi_chassis_wildcard, PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001708
Tom05732372016-09-06 17:21:23 +05301709 // Get Chassis Capabilities
Patrick Venture0b02be92018-08-31 11:55:55 -07001710 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL,
1711 ipmi_get_chassis_cap, PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001712
Tom05732372016-09-06 17:21:23 +05301713 // <Get System Boot Options>
Tom05732372016-09-06 17:21:23 +05301714 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001715 ipmi_chassis_get_sys_boot_options,
1716 PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001717
Tom05732372016-09-06 17:21:23 +05301718 // <Get Chassis Status>
Patrick Venture0b02be92018-08-31 11:55:55 -07001719 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL,
1720 ipmi_get_chassis_status, PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001721
Tom05732372016-09-06 17:21:23 +05301722 // <Chassis Control>
Patrick Venture0b02be92018-08-31 11:55:55 -07001723 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL,
1724 ipmi_chassis_control, PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001725
Tom Joseph5110c122018-03-23 17:55:40 +05301726 // <Chassis Identify>
Tom Joseph5110c122018-03-23 17:55:40 +05301727 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_IDENTIFY, NULL,
1728 ipmi_chassis_identify, PRIVILEGE_OPERATOR);
1729
Tom05732372016-09-06 17:21:23 +05301730 // <Set System Boot Options>
Tom05732372016-09-06 17:21:23 +05301731 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
Patrick Venture0b02be92018-08-31 11:55:55 -07001732 ipmi_chassis_set_sys_boot_options,
1733 PRIVILEGE_OPERATOR);
Nagaraju Gorugantia59d83f2018-04-06 05:55:42 -05001734 // <Get POH Counter>
1735 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_POH_COUNTER, NULL,
1736 ipmiGetPOHCounter, PRIVILEGE_USER);
Yong Lic6713cf2018-09-12 12:35:13 +08001737
1738 // <Set Power Restore Policy>
1739 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_RESTORE_POLICY, NULL,
1740 ipmi_chassis_set_power_restore_policy,
1741 PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001742}