blob: f81c2bf944a37c2d1a99b9b61914218ab23522e7 [file] [log] [blame]
Adriana Kobylak40814c62015-10-27 15:58:44 -05001#include "chassishandler.h"
Patrick Williams37af7332016-09-02 21:21:42 -05002#include "host-ipmid/ipmid-api.h"
Ratan Guptadcb10672017-07-10 10:33:50 +05303#include "types.hpp"
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05004#include "ipmid.hpp"
5#include "settings.hpp"
Ratan Guptadcb10672017-07-10 10:33:50 +05306
Adriana Kobylak40814c62015-10-27 15:58:44 -05007#include <stdio.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05008#include <stdlib.h>
Adriana Kobylak40814c62015-10-27 15:58:44 -05009#include <stdint.h>
Brad Bishop35518682016-07-22 08:35:41 -040010#include <mapper.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -050011#include <arpa/inet.h>
12#include <netinet/in.h>
13#include <limits.h>
14#include <string.h>
15#include <endian.h>
16#include <sstream>
17#include <array>
Andrew Geisslera6e3a302017-05-31 19:34:00 -050018#include <fstream>
19#include <experimental/filesystem>
Ratan Guptadcb10672017-07-10 10:33:50 +053020#include <string>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050021#include <map>
Ratan Guptadcb10672017-07-10 10:33:50 +053022
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053023#include <phosphor-logging/log.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053024#include <phosphor-logging/elog-errors.hpp>
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +053025#include <xyz/openbmc_project/State/Host/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053026#include "xyz/openbmc_project/Common/error.hpp"
27
28#include <sdbusplus/bus.hpp>
29#include <sdbusplus/server/object.hpp>
Deepak Kodihalli8cc19362017-07-21 11:18:38 -050030#include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
31#include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
Deepak Kodihalli18b70d12017-07-21 13:36:33 -050032#include <xyz/openbmc_project/Control/Power/RestorePolicy/server.hpp>
Ratan Guptadcb10672017-07-10 10:33:50 +053033
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053034#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050035
36//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050037#define SET_PARM_VERSION 0x01
38#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050039#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050040#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050041
Ratan Guptafd28dd72016-08-01 04:58:01 -050042constexpr size_t SIZE_MAC = 18;
43constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050044 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050045constexpr size_t SIZE_PREFIX = 7;
46constexpr size_t MAX_PREFIX_VALUE = 32;
47constexpr size_t SIZE_COOKIE = 4;
48constexpr size_t SIZE_VERSION = 2;
Ratan Guptad70f4532017-08-04 02:07:31 +053049constexpr auto MAC_ADDRESS_FORMAT = "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx";
50constexpr auto IP_ADDRESS_FORMAT = "%u.%u.%u.%u";
Matthew Barth8b470052016-09-21 10:02:57 -050051constexpr auto PREFIX_FORMAT = "%hhd";
Ratan Guptafd28dd72016-08-01 04:58:01 -050052constexpr auto ADDR_TYPE_FORMAT = "%hhx";
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053053constexpr auto IPV4_ADDRESS_SIZE_BYTE = 4;
54constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16;
Ratan Guptad70f4532017-08-04 02:07:31 +053055constexpr auto DEFAULT_MAC_ADDRESS = "00:00:00:00:00:00";
56constexpr auto DEFAULT_ADDRESS = "0.0.0.0";
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053057
Ratan Guptafd28dd72016-08-01 04:58:01 -050058//PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053059static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
60 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
shgoupfd84fbbf2015-12-17 10:05:51 +080069
Adriana Kobylak40814c62015-10-27 15:58:44 -050070void register_netfn_chassis_functions() __attribute__((constructor));
71
shgoupfd84fbbf2015-12-17 10:05:51 +080072// Host settings in dbus
73// Service name should be referenced by connection name got via object mapper
74const char *settings_object_name = "/org/openbmc/settings/host0";
75const char *settings_intf_name = "org.freedesktop.DBus.Properties";
76const char *host_intf_name = "org.openbmc.settings.Host";
77
Ratan Guptadcb10672017-07-10 10:33:50 +053078constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
79constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
80constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
81
82constexpr auto SETTINGS_ROOT = "/";
83constexpr auto SETTINGS_MATCH = "host0";
84constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
85
86constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
87constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
88
89constexpr auto METHOD_GET = "Get";
90constexpr auto METHOD_GET_ALL = "GetAll";
91constexpr auto METHOD_SET = "Set";
92
Nan Li8d15fb42016-08-16 22:29:40 +080093typedef struct
94{
95 uint8_t cap_flags;
96 uint8_t fru_info_dev_addr;
97 uint8_t sdr_dev_addr;
98 uint8_t sel_dev_addr;
99 uint8_t system_management_dev_addr;
100 uint8_t bridge_dev_addr;
101}__attribute__((packed)) ipmi_chassis_cap_t;
102
Nan Lifdd8ec52016-08-28 03:57:40 +0800103typedef struct
104{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500105 uint8_t cur_power_state;
106 uint8_t last_power_event;
107 uint8_t misc_power_state;
108 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +0800109}__attribute__((packed)) ipmi_get_chassis_status_t;
110
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530111// Phosphor Host State manager
112namespace State = sdbusplus::xyz::openbmc_project::State::server;
113
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500114namespace fs = std::experimental::filesystem;
115
Ratan Guptadcb10672017-07-10 10:33:50 +0530116using namespace phosphor::logging;
117using namespace sdbusplus::xyz::openbmc_project::Common::Error;
118
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500119namespace chassis
120{
121namespace internal
122{
123
124constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
125constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500126constexpr auto powerRestoreIntf =
127 "xyz.openbmc_project.Control.Power.RestorePolicy";
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500128sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
129
130namespace cache
131{
132
133settings::Objects objects(dbus,
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500134 {bootModeIntf, bootSourceIntf, powerRestoreIntf});
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500135
136} // namespace cache
137} // namespace internal
138} // namespace chassis
139
Ratan Guptadcb10672017-07-10 10:33:50 +0530140/** @brief Gets the dbus object info implementing the given interface
141 * from the given subtree.
142 * @param[in] interface - Dbus interface.
143 * @param[in] serviceRoot - subtree from where the search should start.
144 * @param[in] match - identifier for object.
145 * @return On success returns the object having objectpath and servicename.
146 */
147
148//TODO There may be cases where an interface is implemented by multiple
149// objects,to handle such cases we are interested on that object
150// which are on interested busname.
151// Currently mapper doesn't give the readable busname(gives busid) so we can't
152// use busname to find the object,will do later once the support is there.
153
154ipmi::DbusObjectInfo getDbusObject(const std::string& interface,
155 const std::string& serviceRoot = SETTINGS_ROOT,
156 const std::string& match = "")
157{
158 std::vector<std::string>interfaces;
159 interfaces.emplace_back(interface);
160
161 auto bus = sdbusplus::bus::new_default();
162 auto depth = 0;
163
164 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME,
165 MAPPER_OBJ,
166 MAPPER_INTF,
167 "GetSubTree");
168
169 mapperCall.append(serviceRoot);
170 mapperCall.append(depth);
171 mapperCall.append(interfaces);
172
173 auto mapperReply = bus.call(mapperCall);
174 if (mapperReply.is_method_error())
175 {
176 log<level::ERR>("Error in mapper call");
177 elog<InternalFailure>();
178 }
179
180 ipmi::ObjectTree objectTree;
181 mapperReply.read(objectTree);
182
183 if (objectTree.empty())
184 {
185 log<level::ERR>("No Object have impelmented the interface",
186 entry("INTERFACE=%s", interface.c_str()));
187 elog<InternalFailure>();
188 }
189
190 ipmi::DbusObjectInfo objectInfo;
191
192 // if match is empty then return the first object
193 if(match == "")
194 {
195 objectInfo = make_pair(objectTree.begin()->first,
196 objectTree.begin()->second.begin()->first);
197 return objectInfo;
198 }
199
200 // else search the match string in the object path
201 auto objectFound = false;
202 for (auto& object : objectTree)
203 {
204 if(object.first.find(match)!= std::string::npos)
205 {
206 objectFound = true;
207 objectInfo = make_pair(object.first, object.second.begin()->first);
208 break;
209 }
210 }
211
212 if(!objectFound)
213 {
214 log<level::ERR>("Failed to find object which matches",
215 entry("MATCH=%s",match.c_str()));
216 elog<InternalFailure>();
217 }
218 return objectInfo;
219
220}
221
222/** @brief Gets the value associated with the given object
223 * and the interface.
224 * @param[in] service - Dbus service name.
225 * @param[in] objPath - Dbus object path.
226 * @param[in] interface - Dbus interface.
227 * @param[in] property - name of the property.
228 * @return On success returns the value of the property.
229 */
230std::string getDbusProperty(const std::string& service,
231 const std::string& objPath,
232 const std::string& interface,
233 const std::string& property)
234{
235
236 sdbusplus::message::variant<std::string> name;
237
238 auto bus = sdbusplus::bus::new_default();
239
240 auto method = bus.new_method_call(
241 service.c_str(),
242 objPath.c_str(),
243 PROP_INTF,
244 METHOD_GET);
245
246 method.append(interface, property);
247
248 auto reply = bus.call(method);
249
250 if (reply.is_method_error())
251 {
252 log<level::ERR>("Failed to get property",
253 entry("PROPERTY=%s", property.c_str()),
254 entry("PATH=%s", objPath.c_str()),
255 entry("INTERFACE=%s", interface.c_str()));
256 elog<InternalFailure>();
257 }
258
259 reply.read(name);
260
261 return name.get<std::string>();
262}
263
264/** @brief Gets all the properties associated with the given object
265 * and the interface.
266 * @param[in] service - Dbus service name.
267 * @param[in] objPath - Dbus object path.
268 * @param[in] interface - Dbus interface.
269 * @return On success returns the map of name value pair.
270 */
271ipmi::PropertyMap getAllDbusProperties(const std::string& service,
272 const std::string& objPath,
273 const std::string& interface)
274{
275 ipmi::PropertyMap properties;
276 auto bus = sdbusplus::bus::new_default();
277
278 auto method = bus.new_method_call(
279 service.c_str(),
280 objPath.c_str(),
281 PROP_INTF,
282 METHOD_GET_ALL);
283
284 method.append(interface);
285
286 auto reply = bus.call(method);
287
288 if (reply.is_method_error())
289 {
290 log<level::ERR>("Failed to get all properties",
291 entry("PATH=%s", objPath.c_str()),
292 entry("INTERFACE=%s", interface.c_str()));
293 elog<InternalFailure>();
294 }
295
296 reply.read(properties);
297 return properties;
298}
299
300/** @brief Sets the property value of the given object.
301 * @param[in] service - Dbus service name.
302 * @param[in] objPath - Dbus object path.
303 * @param[in] interface - Dbus interface.
304 * @param[in] property - name of the property.
305 * @param[in] value - value which needs to be set.
306 */
307void setDbusProperty(const std::string& service,
308 const std::string& objPath,
309 const std::string& interface,
310 const std::string& property,
311 const ipmi::Value& value)
312{
313 auto bus = sdbusplus::bus::new_default();
314
315 auto method = bus.new_method_call(
316 service.c_str(),
317 objPath.c_str(),
318 PROP_INTF,
319 METHOD_SET);
320
321 method.append(interface);
322 method.append(property, value);
323
324 if (!bus.call(method))
325 {
326 log<level::ERR>("Failed to set property",
327 entry("PROPERTY=%s", property.c_str()),
328 entry("PATH=%s",objPath.c_str()),
329 entry("INTERFACE=%s",interface.c_str()));
330 elog<InternalFailure>();
331 }
332
333}
334
335//TODO : Can remove the below function as we have
336// new functions which uses sdbusplus.
337//
338// openbmc/openbmc#1489
ratagupta6f6bff2016-04-04 06:20:11 -0500339int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800340{
341 sd_bus_error error = SD_BUS_ERROR_NULL;
342 sd_bus_message *m = NULL;
343 sd_bus *bus = NULL;
344 char *temp_buf = NULL;
345 char *connection = NULL;
346 int r;
347
Brad Bishop35518682016-07-22 08:35:41 -0400348 // Get the system bus where most system services are provided.
349 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800350
Brad Bishop35518682016-07-22 08:35:41 -0400351 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800352 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400353 fprintf(stderr, "Failed to get %s connection: %s\n",
354 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800355 goto finish;
356 }
357
shgoupfd84fbbf2015-12-17 10:05:51 +0800358 /*
359 * Bus, service, object path, interface and method are provided to call
360 * the method.
361 * Signatures and input arguments are provided by the arguments at the
362 * end.
363 */
364 r = sd_bus_call_method(bus,
365 connection, /* service to contact */
366 settings_object_name, /* object path */
367 settings_intf_name, /* interface name */
368 "Get", /* method name */
369 &error, /* object to return error in */
370 &m, /* return message on success */
371 "ss", /* input signature */
372 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500373 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800374
375 if (r < 0) {
376 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
377 goto finish;
378 }
379
380 /*
381 * The output should be parsed exactly the same as the output formatting
382 * specified.
383 */
384 r = sd_bus_message_read(m, "v", "s", &temp_buf);
385 if (r < 0) {
386 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
387 goto finish;
388 }
389
Matthew Barth56181052017-01-23 09:36:29 -0600390 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500391 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800392 if (*buf) {
393 strcpy(*buf, temp_buf);
394 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500395 */
shgoupfd84fbbf2015-12-17 10:05:51 +0800396 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
397
398finish:
399 sd_bus_error_free(&error);
400 sd_bus_message_unref(m);
401 free(connection);
402
403 return r;
404}
405
Ratan Guptadcb10672017-07-10 10:33:50 +0530406//TODO : Can remove the below function as we have
407// new functions which uses sdbusplus.
408//
409// openbmc/openbmc#1489
410
ratagupta6f6bff2016-04-04 06:20:11 -0500411int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800412{
413 sd_bus_error error = SD_BUS_ERROR_NULL;
414 sd_bus_message *m = NULL;
415 sd_bus *bus = NULL;
416 char *connection = NULL;
417 int r;
418
Brad Bishop35518682016-07-22 08:35:41 -0400419 // Get the system bus where most system services are provided.
420 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800421
Brad Bishop35518682016-07-22 08:35:41 -0400422 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800423 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400424 fprintf(stderr, "Failed to get %s connection: %s\n",
425 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800426 goto finish;
427 }
428
shgoupfd84fbbf2015-12-17 10:05:51 +0800429 /*
430 * Bus, service, object path, interface and method are provided to call
431 * the method.
432 * Signatures and input arguments are provided by the arguments at the
433 * end.
434 */
435 r = sd_bus_call_method(bus,
436 connection, /* service to contact */
437 settings_object_name, /* object path */
438 settings_intf_name, /* interface name */
439 "Set", /* method name */
440 &error, /* object to return error in */
441 &m, /* return message on success */
442 "ssv", /* input signature */
443 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500444 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800445 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500446 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800447
448 if (r < 0) {
449 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
450 goto finish;
451 }
452
ratagupta6f6bff2016-04-04 06:20:11 -0500453 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800454
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500455 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800456 sd_bus_error_free(&error);
457 sd_bus_message_unref(m);
458 free(connection);
459
460 return r;
461}
462
Adriana Kobylak40814c62015-10-27 15:58:44 -0500463struct get_sys_boot_options_t {
464 uint8_t parameter;
465 uint8_t set;
466 uint8_t block;
467} __attribute__ ((packed));
468
shgoupfd84fbbf2015-12-17 10:05:51 +0800469struct get_sys_boot_options_response_t {
470 uint8_t version;
471 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500472 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800473} __attribute__ ((packed));
474
475struct set_sys_boot_options_t {
476 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500477 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800478} __attribute__ ((packed));
479
Ratan Guptafd28dd72016-08-01 04:58:01 -0500480
Ratan Guptadcb10672017-07-10 10:33:50 +0530481int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500482{
Ratan Guptadcb10672017-07-10 10:33:50 +0530483 ipmi::PropertyMap properties;
484 int rc = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530485 uint8_t addrSize = IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500486
Ratan Guptadcb10672017-07-10 10:33:50 +0530487 try
488 {
489 //TODO There may be cases where an interface is implemented by multiple
490 // objects,to handle such cases we are interested on that object
491 // which are on interested busname.
492 // Currenlty mapper doesn't give the readable busname(gives busid)
493 // so we can't match with bus name so giving some object specific info
494 // as SETTINGS_MATCH.
495 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500496
Ratan Guptadcb10672017-07-10 10:33:50 +0530497 auto ipObjectInfo = getDbusObject(IP_INTERFACE, SETTINGS_ROOT,
498 SETTINGS_MATCH);
499 auto macObjectInfo = getDbusObject(MAC_INTERFACE, SETTINGS_ROOT,
500 SETTINGS_MATCH);
501
502 properties = getAllDbusProperties(ipObjectInfo.second,
503 ipObjectInfo.first, IP_INTERFACE);
504 auto MACAddress =
505 getDbusProperty(macObjectInfo.second, macObjectInfo.first,
506 MAC_INTERFACE, "MACAddress");
507
Ratan Guptad70f4532017-08-04 02:07:31 +0530508 auto ipAddress = properties["Address"].get<std::string>();
509
510 auto gateway = properties["Gateway"].get<std::string>();
511
512 auto prefix = properties["PrefixLength"].get<uint8_t>();
513
514 uint8_t isStatic = (properties["Origin"].get<std::string>() ==
515 "xyz.openbmc_project.Network.IP.AddressOrigin.Static")
516 ? 1 : 0;
517
518 // it is expected here that we should get the valid data
519 // but we may also get the default values.
520 // Validation of the data is done by settings.
521 //
522 // if mac address is default mac address then
523 // don't send blank override.
524 if ((MACAddress == DEFAULT_MAC_ADDRESS))
525 {
526 memset(respptr->data, 0, SIZE_BOOT_OPTION);
527 rc = -1;
528 return rc;
529 }
530 // if addr is static then ipaddress,gateway,prefix
531 // should not be default one,don't send blank override.
532 if (isStatic)
533 {
534 if((ipAddress == DEFAULT_ADDRESS) ||
535 (gateway == DEFAULT_ADDRESS) ||
536 (!prefix))
537 {
538 memset(respptr->data, 0, SIZE_BOOT_OPTION);
539 rc = -1;
540 return rc;
541 }
542 }
543
Ratan Guptadcb10672017-07-10 10:33:50 +0530544 sscanf(MACAddress.c_str(), MAC_ADDRESS_FORMAT,
545 (respptr->data + MAC_OFFSET),
546 (respptr->data + MAC_OFFSET + 1),
547 (respptr->data + MAC_OFFSET + 2),
548 (respptr->data + MAC_OFFSET + 3),
549 (respptr->data + MAC_OFFSET + 4),
550 (respptr->data + MAC_OFFSET + 5));
551
Ratan Guptadcb10672017-07-10 10:33:50 +0530552 respptr->data[MAC_OFFSET + 6] = 0x00;
553
Ratan Guptad70f4532017-08-04 02:07:31 +0530554 memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
555 sizeof(isStatic));
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530556
557 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
558 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
559 AF_INET : AF_INET6;
560
561 addrSize = (addressFamily == AF_INET) ? IPV4_ADDRESS_SIZE_BYTE :
562 IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530563
564 // ipaddress and gateway would be in IPv4 format
Ratan Guptad70f4532017-08-04 02:07:31 +0530565 inet_pton(addressFamily, ipAddress.c_str(),
566 (respptr->data + IPADDR_OFFSET));
Ratan Guptadcb10672017-07-10 10:33:50 +0530567
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530568 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
569
570 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
571
572 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
573
Ratan Guptad70f4532017-08-04 02:07:31 +0530574 inet_pton(addressFamily, gateway.c_str(),
575 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530576
577 }
578 catch (InternalFailure& e)
579 {
580 commit<InternalFailure>();
581 memset(respptr->data, 0, SIZE_BOOT_OPTION);
582 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500583 return rc;
584 }
585
Ratan Guptadcb10672017-07-10 10:33:50 +0530586 //PetiBoot-Specific
587 //If sucess then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530588 memcpy(respptr->data, net_conf_initial_bytes,
589 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500590
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530591 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
592
Ratan Guptafd28dd72016-08-01 04:58:01 -0500593#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530594 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500595
Ratan Guptadcb10672017-07-10 10:33:50 +0530596 for (uint8_t pos = 0; pos < index; pos++)
597 {
598 printf("%02x ", respptr->data[pos]);
599 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500600#endif
601
Ratan Guptafd28dd72016-08-01 04:58:01 -0500602 return rc;
603}
604
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530605/** @brief convert IPv4 and IPv6 addresses from binary to text form.
606 * @param[in] family - IPv4/Ipv6
607 * @param[in] data - req data pointer.
608 * @param[in] offset - offset in the data.
609 * @param[in] addrSize - size of the data which needs to be read from offset.
610 * @returns address in text form.
611 */
612
613std::string getAddrStr(uint8_t family, uint8_t* data,
614 uint8_t offset, uint8_t addrSize)
615{
616 char ipAddr[INET6_ADDRSTRLEN] = {};
617
618 switch(family)
619 {
620 case AF_INET:
621 {
622 struct sockaddr_in addr4 {};
623 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
624
625 inet_ntop(AF_INET, &addr4.sin_addr,
626 ipAddr, INET_ADDRSTRLEN);
627
628 break;
629 }
630 case AF_INET6:
631 {
632 struct sockaddr_in6 addr6 {};
633 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
634
635 inet_ntop(AF_INET6, &addr6.sin6_addr,
636 ipAddr, INET6_ADDRSTRLEN);
637
638 break;
639 }
640 default:
641 {
642 return {};
643 }
644 }
645
646 return ipAddr;
647}
648
Ratan Guptadcb10672017-07-10 10:33:50 +0530649int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500650{
Ratan Guptadcb10672017-07-10 10:33:50 +0530651 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500652 std::string host_network_config;
Ratan Guptad70f4532017-08-04 02:07:31 +0530653 char mac[] {"00:00:00:00:00:00"};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530654 std::string ipAddress, gateway;
655 char addrOrigin {0};
656 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530657 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530658 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
659 std::string addressType =
660 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530661 uint8_t prefix {0};
662 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530663 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500664
665 //cookie starts from second byte
666 // version starts from sixth byte
667
Ratan Guptadcb10672017-07-10 10:33:50 +0530668 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500669 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530670 do
671 {
672 // cookie == 0x21 0x70 0x62 0x21
673 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
674 (net_conf_initial_bytes + COOKIE_OFFSET),
675 SIZE_COOKIE) != 0)
676 {
677 //cookie == 0
678 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
679 &zeroCookie,
680 SIZE_COOKIE) == 0)
681 {
682 // need to zero out the network settings.
683 break;
684 }
685
686 log<level::ERR>("Invalid Cookie");
687 elog<InternalFailure>();
688 }
689
690 // vesion == 0x00 0x01
691 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
692 (net_conf_initial_bytes + VERSION_OFFSET),
693 SIZE_VERSION) != 0)
694 {
695
696 log<level::ERR>("Invalid Version");
697 elog<InternalFailure>();
698 }
699
700 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
701 reqptr->data[MAC_OFFSET],
702 reqptr->data[MAC_OFFSET + 1],
703 reqptr->data[MAC_OFFSET + 2],
704 reqptr->data[MAC_OFFSET + 3],
705 reqptr->data[MAC_OFFSET + 4],
706 reqptr->data[MAC_OFFSET + 5]);
707
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530708 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
709 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530710
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530711 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530712 {
713 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530714 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530715 }
716
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530717 // Get the address size
718 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530719
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530720 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530721
Ratan Guptad70f4532017-08-04 02:07:31 +0530722 memcpy(&prefix, &(reqptr->data[prefixOffset]),
723 sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530724
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530725 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
726
727 if (addrSize != IPV4_ADDRESS_SIZE_BYTE)
728 {
729 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
730 family = AF_INET6;
731 }
732
733 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
Ratan Guptad70f4532017-08-04 02:07:31 +0530734
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530735 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
736
Ratan Guptadcb10672017-07-10 10:33:50 +0530737 } while(0);
738
Ratan Guptafd28dd72016-08-01 04:58:01 -0500739 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530740 host_network_config += "ipaddress="s + ipAddress +
741 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
742 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500743
Ratan Guptafd28dd72016-08-01 04:58:01 -0500744
Ratan Guptadcb10672017-07-10 10:33:50 +0530745 auto ipObjectInfo = getDbusObject(IP_INTERFACE, SETTINGS_ROOT,
746 SETTINGS_MATCH);
747 auto macObjectInfo = getDbusObject(MAC_INTERFACE, SETTINGS_ROOT,
748 SETTINGS_MATCH);
749 // set the dbus property
750 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
751 IP_INTERFACE, "Address", std::string(ipAddress));
752 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
753 IP_INTERFACE, "PrefixLength", prefix);
754 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
755 IP_INTERFACE, "Origin", addressOrigin);
756 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
757 IP_INTERFACE, "Gateway", std::string(gateway));
758 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
759 IP_INTERFACE, "Type",
760 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
761 setDbusProperty(macObjectInfo.second, macObjectInfo.first,
762 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500763
Ratan Guptad70f4532017-08-04 02:07:31 +0530764 log<level::DEBUG>("Network configuration changed",
765 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
766
Ratan Guptafd28dd72016-08-01 04:58:01 -0500767 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530768 catch (InternalFailure& e)
769 {
770 commit<InternalFailure>();
771 return -1;
772 }
773
774 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500775}
776
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500777ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
778 ipmi_request_t request,
779 ipmi_response_t response,
780 ipmi_data_len_t data_len,
781 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500782{
783 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
784 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800785 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500786 *data_len = 0;
787 return rc;
788}
789
Nan Li8d15fb42016-08-16 22:29:40 +0800790ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500791 ipmi_request_t request, ipmi_response_t response,
792 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800793{
794 // sd_bus error
795 ipmi_ret_t rc = IPMI_CC_OK;
796
797 ipmi_chassis_cap_t chassis_cap{};
798
799 *data_len = sizeof(ipmi_chassis_cap_t);
800
801 // TODO: need future work. Get those flag from MRW.
802
803 // capabilities flags
804 // [7..4] - reserved
805 // [3] – 1b = provides power interlock (IPM 1.5)
806 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
807 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
808 // to lock out external power control and reset button or front panel interfaces
809 // and/or detect tampering with those interfaces).
810 // [0] -1b = Chassis provides intrusion (physical security) sensor.
811 // set to default value 0x0.
812 chassis_cap.cap_flags = 0x0;
813
814 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
815 // The 20h was given as those 5 device addresses.
816 // Chassis FRU info Device Address
817 chassis_cap.fru_info_dev_addr = 0x20;
818
819 // Chassis SDR Device Address
820 chassis_cap.sdr_dev_addr = 0x20;
821
822 // Chassis SEL Device Address
823 chassis_cap.sel_dev_addr = 0x20;
824
825 // Chassis System Management Device Address
826 chassis_cap.system_management_dev_addr = 0x20;
827
828 // Chassis Bridge Device Address.
829 chassis_cap.bridge_dev_addr = 0x20;
830
831 memcpy(response, &chassis_cap, *data_len);
832
833 return rc;
834}
835
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530836//------------------------------------------
837// Calls into Host State Manager Dbus object
838//------------------------------------------
839int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600840{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500841 // OpenBMC Host State Manager dbus framework
842 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
843 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
844 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
845 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530846
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500847 // sd_bus error
848 int rc = 0;
849 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600850
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500851 // SD Bus error report mechanism.
852 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600853
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500854 // Gets a hook onto either a SYSTEM or SESSION bus
855 sd_bus *bus_type = ipmid_get_sd_bus_connection();
856 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
857 if (rc < 0)
858 {
859 log<level::ERR>("Failed to get bus name",
860 entry("ERROR=%s, OBJPATH=%s",
861 strerror(-rc), HOST_STATE_MANAGER_ROOT));
862 return rc;
863 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530864
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500865 // Convert to string equivalent of the passed in transition enum.
866 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530867
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500868 rc = sd_bus_call_method(bus_type, // On the system bus
869 busname, // Service to contact
870 HOST_STATE_MANAGER_ROOT, // Object path
871 DBUS_PROPERTY_IFACE, // Interface name
872 "Set", // Method to be called
873 &bus_error, // object to return error
874 nullptr, // Response buffer if any
875 "ssv", // Takes 3 arguments
876 HOST_STATE_MANAGER_IFACE,
877 PROPERTY,
878 "s", request.c_str());
879 if(rc < 0)
880 {
881 log<level::ERR>("Failed to initiate transition",
882 entry("ERROR=%s, REQUEST=%s",
883 bus_error.message, request.c_str()));
884 }
885 else
886 {
887 log<level::INFO>("Transition request initiated successfully");
888 }
vishwa36993272015-11-20 12:43:49 -0600889
890 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500891 free(busname);
vishwa36993272015-11-20 12:43:49 -0600892
Sergey Solomineb9b8142016-08-23 09:07:28 -0500893 return rc;
vishwa36993272015-11-20 12:43:49 -0600894}
895
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500896namespace power_policy
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500897{
Nan Lifdd8ec52016-08-28 03:57:40 +0800898
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500899using namespace sdbusplus::xyz::openbmc_project::Control::Power::server;
900using IpmiValue = uint8_t;
901using DbusValue = RestorePolicy::Policy;
Nan Lifdd8ec52016-08-28 03:57:40 +0800902
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500903std::map<DbusValue, IpmiValue> dbusToIpmi =
904{
905 {RestorePolicy::Policy::AlwaysOff, 0x00},
906 {RestorePolicy::Policy::Restore, 0x01},
907 {RestorePolicy::Policy::AlwaysOn, 0x02}
908};
Nan Lifdd8ec52016-08-28 03:57:40 +0800909
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500910} // namespace power_policy
Nan Lifdd8ec52016-08-28 03:57:40 +0800911
912//----------------------------------------------------------------------
913// Get Chassis Status commands
914//----------------------------------------------------------------------
915ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500916 ipmi_request_t request,
917 ipmi_response_t response,
918 ipmi_data_len_t data_len,
919 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800920{
921 const char *objname = "/org/openbmc/control/power0";
922 const char *intf = "org.openbmc.control.Power";
923
924 sd_bus *bus = NULL;
925 sd_bus_message *reply = NULL;
926 int r = 0;
927 int pgood = 0;
928 char *busname = NULL;
929 ipmi_ret_t rc = IPMI_CC_OK;
930 ipmi_get_chassis_status_t chassis_status{};
931
Nan Lifdd8ec52016-08-28 03:57:40 +0800932 uint8_t s = 0;
933
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500934 using namespace chassis::internal;
935 using namespace chassis::internal::cache;
936 using namespace power_policy;
937
938 const auto& powerRestoreSetting = objects.map.at(powerRestoreIntf);
939 auto method =
940 dbus.new_method_call(
941 objects.service(powerRestoreSetting, powerRestoreIntf).c_str(),
942 powerRestoreSetting.c_str(),
943 PROP_INTF,
944 "Get");
945 method.append(powerRestoreIntf, "PowerRestorePolicy");
946 auto resp = dbus.call(method);
947 if (resp.is_method_error())
948 {
949 log<level::ERR>("Error in PowerRestorePolicy Get");
950 report<InternalFailure>();
951 *data_len = 0;
952 return IPMI_CC_UNSPECIFIED_ERROR;
953 }
954 sdbusplus::message::variant<std::string> result;
955 resp.read(result);
956 auto powerRestore =
957 RestorePolicy::convertPolicyFromString(result.get<std::string>());
Nan Lifdd8ec52016-08-28 03:57:40 +0800958
959 *data_len = 4;
960
961 r = mapper_get_service(bus, objname, &busname);
962 if (r < 0) {
963 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-r));
964 rc = IPMI_CC_UNSPECIFIED_ERROR;
965 goto finish;
966 }
967
968 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
969 if (r < 0) {
970 fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r));
971 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
972 busname, objname, intf);
973 rc = IPMI_CC_UNSPECIFIED_ERROR;
974 goto finish;
975 }
976
977 r = sd_bus_message_read(reply, "i", &pgood);
978 if (r < 0) {
979 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
980 rc = IPMI_CC_UNSPECIFIED_ERROR;
981 goto finish;
982 }
983
984 printf("pgood is 0x%02x\n", pgood);
985
Deepak Kodihalli18b70d12017-07-21 13:36:33 -0500986 s = dbusToIpmi.at(powerRestore);
Nan Lifdd8ec52016-08-28 03:57:40 +0800987
988 // Current Power State
989 // [7] reserved
990 // [6..5] power restore policy
991 // 00b = chassis stays powered off after AC/mains returns
992 // 01b = after AC returns, power is restored to the state that was
993 // in effect when AC/mains was lost.
994 // 10b = chassis always powers up after AC/mains returns
995 // 11b = unknow
996 // Set to 00b, by observing the hardware behavior.
997 // Do we need to define a dbus property to identify the restore policy?
998
999 // [4] power control fault
1000 // 1b = controller attempted to turn system power on or off, but
1001 // system did not enter desired state.
1002 // Set to 0b, since We don't support it..
1003
1004 // [3] power fault
1005 // 1b = fault detected in main power subsystem.
1006 // set to 0b. for we don't support it.
1007
1008 // [2] 1b = interlock (chassis is presently shut down because a chassis
1009 // panel interlock switch is active). (IPMI 1.5)
1010 // set to 0b, for we don't support it.
1011
1012 // [1] power overload
1013 // 1b = system shutdown because of power overload condition.
1014 // set to 0b, for we don't support it.
1015
1016 // [0] power is on
1017 // 1b = system power is on
1018 // 0b = system power is off(soft-off S4/S5, or mechanical off)
1019
1020 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
1021
1022 // Last Power Event
1023 // [7..5] – reserved
1024 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
1025 // [3] – 1b = last power down caused by power fault
1026 // [2] – 1b = last power down caused by a power interlock being activated
1027 // [1] – 1b = last power down caused by a Power overload
1028 // [0] – 1b = AC failed
1029 // set to 0x0, for we don't support these fields.
1030
1031 chassis_status.last_power_event = 0;
1032
1033 // Misc. Chassis State
1034 // [7] – reserved
1035 // [6] – 1b = Chassis Identify command and state info supported (Optional)
1036 // 0b = Chassis Identify command support unspecified via this command.
1037 // (The Get Command Support command , if implemented, would still
1038 // indicate support for the Chassis Identify command)
1039 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
1040 // as 00b) otherwise. Returns the present chassis identify state.
1041 // Refer to the Chassis Identify command for more info.
1042 // 00b = chassis identify state = Off
1043 // 01b = chassis identify state = Temporary(timed) On
1044 // 10b = chassis identify state = Indefinite On
1045 // 11b = reserved
1046 // [3] – 1b = Cooling/fan fault detected
1047 // [2] – 1b = Drive Fault
1048 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
1049 // push-buttons disabled.)
1050 // [0] – 1b = Chassis Intrusion active
1051 // set to 0, for we don't support them.
1052 chassis_status.misc_power_state = 0;
1053
1054 // Front Panel Button Capabilities and disable/enable status(Optional)
1055 // set to 0, for we don't support them.
1056 chassis_status.front_panel_button_cap_status = 0;
1057
1058 // Pack the actual response
1059 memcpy(response, &chassis_status, *data_len);
1060
1061finish:
1062 free(busname);
1063 reply = sd_bus_message_unref(reply);
1064
1065 return rc;
1066}
Chris Austen7888c4d2015-12-03 15:26:20 -06001067
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301068//-------------------------------------------------------------
1069// Send a command to SoftPowerOff application to stop any timer
1070//-------------------------------------------------------------
1071int stop_soft_off_timer()
1072{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301073 constexpr auto iface = "org.freedesktop.DBus.Properties";
1074 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001075 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301076
1077 constexpr auto property = "ResponseReceived";
1078 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001079 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301080
1081 // Get the system bus where most system services are provided.
1082 auto bus = ipmid_get_sd_bus_connection();
1083
1084 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001085 // TODO openbmc/openbmc#1661 - Mapper refactor
1086 //
1087 // See openbmc/openbmc#1743 for some details but high level summary is that
1088 // for now the code will directly call the soft off interface due to a
1089 // race condition with mapper usage
1090 //
1091 //char *busname = nullptr;
1092 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
1093 //if (r < 0)
1094 //{
1095 // fprintf(stderr, "Failed to get %s bus name: %s\n",
1096 // SOFTOFF_OBJPATH, strerror(-r));
1097 // return r;
1098 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301099
1100 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001101 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001102 "Set", nullptr, nullptr, "ssv",
1103 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301104 if (rc < 0)
1105 {
1106 fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n",
1107 strerror(-rc));
1108 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001109
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001110 //TODO openbmc/openbmc#1661 - Mapper refactor
1111 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301112 return rc;
1113}
1114
vishwa36993272015-11-20 12:43:49 -06001115//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001116// Create file to indicate there is no need for softoff notification to host
1117//----------------------------------------------------------------------
1118void indicate_no_softoff_needed()
1119{
1120 fs::path path{HOST_INBAND_REQUEST_DIR};
1121 if (!fs::is_directory(path))
1122 {
1123 fs::create_directory(path);
1124 }
1125
1126 // Add the host instance (default 0 for now) to the file name
1127 std::string file{HOST_INBAND_REQUEST_FILE};
1128 auto size = std::snprintf(nullptr,0,file.c_str(),0);
1129 size++; // null
1130 std::unique_ptr<char[]> buf(new char[size]);
1131 std::snprintf(buf.get(),size,file.c_str(),0);
1132
1133 // Append file name to directory and create it
1134 path /= buf.get();
1135 std::ofstream(path.c_str());
1136}
1137
1138//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -06001139// Chassis Control commands
1140//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001141ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1142 ipmi_request_t request,
1143 ipmi_response_t response,
1144 ipmi_data_len_t data_len,
1145 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -06001146{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001147 // Error from power off.
1148 int rc = 0;
vishwa36993272015-11-20 12:43:49 -06001149
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001150 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001151 *data_len = 0;
1152
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001153 // Catch the actual operaton by peeking into request buffer
1154 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
1155 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
vishwa36993272015-11-20 12:43:49 -06001156
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001157 switch(chassis_ctrl_cmd)
1158 {
1159 case CMD_POWER_ON:
1160 rc = initiate_state_transition(State::Host::Transition::On);
1161 break;
1162 case CMD_POWER_OFF:
1163 // Need to Nudge SoftPowerOff application that it needs to stop the
1164 // watchdog timer if running.
1165 rc = stop_soft_off_timer();
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001166 // Only request the Off transition if the soft power off
1167 // application is not running
1168 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001169 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001170 log<level::INFO>("Did not find soft off service so request "
1171 "Host:Transition:Off");
1172
1173 // First create a file to indicate to the soft off application
1174 // that it should not run since this is a direct user initiated
1175 // power off request (i.e. a power off request that is not
1176 // originating via a soft power off SMS request)
1177 indicate_no_softoff_needed();
1178
1179 // Now request the shutdown
1180 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001181 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001182 else
1183 {
1184 log<level::INFO>("Soft off is running, so let that stop "
1185 "the host");
1186 }
1187
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001188 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301189
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001190 case CMD_HARD_RESET:
1191 case CMD_POWER_CYCLE:
1192 // SPEC has a section that says certain implementations can trigger
1193 // PowerOn if power is Off when a command to power cycle is
1194 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001195
1196 // First create a file to indicate to the soft off application
1197 // that it should not run since this is a direct user initiated
1198 // power reboot request (i.e. a reboot request that is not
1199 // originating via a soft power off SMS request)
1200 indicate_no_softoff_needed();
1201
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001202 rc = initiate_state_transition(State::Host::Transition::Reboot);
1203 break;
1204 default:
1205 {
1206 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
1207 rc = -1;
1208 }
1209 }
vishwa36993272015-11-20 12:43:49 -06001210
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001211 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001212}
1213
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001214namespace boot_options
1215{
1216
1217using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1218using IpmiValue = uint8_t;
1219constexpr auto ipmiDefault = 0;
1220
1221std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1222{
1223 {0x01, Source::Sources::Network},
1224 {0x02, Source::Sources::Disk},
1225 {0x05, Source::Sources::ExternalMedia},
1226 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001227};
1228
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001229std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1230{
1231 {0x03, Mode::Modes::Safe},
1232 {0x06, Mode::Modes::Setup},
1233 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001234};
1235
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001236std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1237{
1238 {Source::Sources::Network, 0x01},
1239 {Source::Sources::Disk, 0x02},
1240 {Source::Sources::ExternalMedia, 0x05},
1241 {Source::Sources::Default, ipmiDefault}
1242};
shgoupfd84fbbf2015-12-17 10:05:51 +08001243
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001244std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1245{
1246 {Mode::Modes::Safe, 0x03},
1247 {Mode::Modes::Setup, 0x06},
1248 {Mode::Modes::Regular, ipmiDefault}
1249};
shgoupfd84fbbf2015-12-17 10:05:51 +08001250
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001251} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001252
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001253ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1254 ipmi_request_t request,
1255 ipmi_response_t response,
1256 ipmi_data_len_t data_len,
1257 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001258{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001259 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001260 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1261 char *p = NULL;
1262 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1263 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001264 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001265
1266 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
1267
shgoupfd84fbbf2015-12-17 10:05:51 +08001268 memset(resp,0,sizeof(*resp));
1269 resp->version = SET_PARM_VERSION;
1270 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001271 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001272
Adriana Kobylak40814c62015-10-27 15:58:44 -05001273
shgoupfd84fbbf2015-12-17 10:05:51 +08001274 /*
1275 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1276 * This is the only parameter used by petitboot.
1277 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001278 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001279 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001280
Ratan Guptafd28dd72016-08-01 04:58:01 -05001281 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001282 using namespace chassis::internal;
1283 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001284
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001285 const auto& bootSourceSetting = objects.map.at(bootSourceIntf);
1286 auto method =
1287 dbus.new_method_call(
1288 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1289 bootSourceSetting.c_str(),
1290 PROP_INTF,
1291 "Get");
1292 method.append(bootSourceIntf, "BootSource");
1293 auto reply = dbus.call(method);
1294 if (reply.is_method_error())
ratagupta6f6bff2016-04-04 06:20:11 -05001295 {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001296 log<level::ERR>("Error in BootSource Get");
1297 report<InternalFailure>();
1298 *data_len = 0;
1299 return IPMI_CC_UNSPECIFIED_ERROR;
ratagupta6f6bff2016-04-04 06:20:11 -05001300 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001301 sdbusplus::message::variant<std::string> result;
1302 reply.read(result);
1303 auto bootSource =
1304 Source::convertSourcesFromString(result.get<std::string>());
1305
1306 const auto& bootModeSetting = objects.map.at(bootModeIntf);
1307 method = dbus.new_method_call(
1308 objects.service(bootModeSetting, bootModeIntf).c_str(),
1309 bootModeSetting.c_str(),
1310 PROP_INTF,
1311 "Get");
1312 method.append(bootModeIntf, "BootMode");
1313 reply = dbus.call(method);
1314 if (reply.is_method_error())
1315 {
1316 log<level::ERR>("Error in BootMode Get");
1317 report<InternalFailure>();
1318 *data_len = 0;
1319 return IPMI_CC_UNSPECIFIED_ERROR;
1320 }
1321 reply.read(result);
1322 auto bootMode = Mode::convertModesFromString(result.get<std::string>());
1323
1324 bootOption = sourceDbusToIpmi.at(bootSource);
1325 if ((Mode::Modes::Regular == bootMode) &&
1326 (Source::Sources::Default == bootSource))
1327 {
1328 bootOption = ipmiDefault;
1329 }
1330 else if (Source::Sources::Default == bootSource)
1331 {
1332 bootOption = modeDbusToIpmi.at(bootMode);
1333 }
1334 resp->data[1] = (bootOption << 2);
1335 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001336
1337 /* Get the boot policy */
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001338 int r = dbus_get_property("boot_policy",&p);
ratagupta6f6bff2016-04-04 06:20:11 -05001339
1340 if (r < 0) {
1341 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
1342 rc = IPMI_CC_UNSPECIFIED_ERROR;
1343
1344 } else {
1345
George Keishing012d6a42017-06-14 03:06:48 -05001346 printf("BootPolicy is [%s]\n", p);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001347 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
1348 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1349 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001350 rc = IPMI_CC_OK;
1351
1352 }
1353
1354
Ratan Guptafd28dd72016-08-01 04:58:01 -05001355 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001356 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001357
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001358 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001359
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001360 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001361
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001362 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001363
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001364 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001365
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001366 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
1367 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001368
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001369 }else
1370 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001371 }
1372
1373 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -05001374 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +08001375 }
1376
1377 if (p)
1378 free(p);
1379
Ratan Guptafd28dd72016-08-01 04:58:01 -05001380 if (rc == IPMI_CC_OK)
1381 {
1382 *data_len += 2;
1383 }
1384
shgoupfd84fbbf2015-12-17 10:05:51 +08001385 return rc;
1386}
1387
1388
1389
1390ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001391 ipmi_request_t request,
1392 ipmi_response_t response,
1393 ipmi_data_len_t data_len,
1394 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001395{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001396 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001397 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001398 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1399
Ratan Guptafd28dd72016-08-01 04:58:01 -05001400 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1401
shgoupfd84fbbf2015-12-17 10:05:51 +08001402 // This IPMI command does not have any resposne data
1403 *data_len = 0;
1404
1405 /* 000101
1406 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1407 * This is the only parameter used by petitboot.
1408 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001409
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001410 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1411 {
1412 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1413 using namespace chassis::internal;
1414 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001415
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001416 auto modeItr = modeIpmiToDbus.find(bootOption);
1417 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1418 if ((ipmiDefault == bootOption) ||
1419 (sourceIpmiToDbus.end() != sourceItr))
1420 {
1421 sdbusplus::message::variant<std::string> property =
1422 convertForMessage(sourceItr->second);
1423 const auto& bootSourceSetting =
1424 objects.map.at(bootSourceIntf);
1425 auto method =
1426 dbus.new_method_call(
1427 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1428 bootSourceSetting.c_str(),
1429 PROP_INTF,
1430 "Set");
1431 method.append(bootSourceIntf, "BootSource", property);
1432 auto reply = dbus.call(method);
1433 if (reply.is_method_error())
1434 {
1435 log<level::ERR>("Error in BootSource Set");
1436 report<InternalFailure>();
1437 *data_len = 0;
1438 return IPMI_CC_UNSPECIFIED_ERROR;
1439 }
1440 }
1441 if ((ipmiDefault == bootOption) ||
1442 (modeIpmiToDbus.end() != modeItr))
1443 {
1444 sdbusplus::message::variant<std::string> property =
1445 convertForMessage(modeItr->second);
1446 const auto& bootModeSetting = objects.map.at(bootModeIntf);
1447 auto method =
1448 dbus.new_method_call(
1449 objects.service(bootModeSetting, bootModeIntf).c_str(),
1450 bootModeSetting.c_str(),
1451 PROP_INTF,
1452 "Set");
1453 method.append(bootModeIntf, "BootMode", property);
1454 auto reply = dbus.call(method);
1455 if (reply.is_method_error())
1456 {
1457 log<level::ERR>("Error in BootMode Set");
1458 report<InternalFailure>();
1459 *data_len = 0;
1460 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001461 }
1462 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001463
ratagupta6f6bff2016-04-04 06:20:11 -05001464 /* setting the boot policy */
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001465 std::string value =
1466 (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001467 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -05001468
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001469 printf ( "\nBoot Policy is %s",value.c_str());
1470 int r = dbus_set_property("boot_policy",value.c_str());
ratagupta6f6bff2016-04-04 06:20:11 -05001471
1472 if (r < 0) {
1473 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
1474 rc = IPMI_CC_UNSPECIFIED_ERROR;
1475 }
shgoupfd84fbbf2015-12-17 10:05:51 +08001476
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001477 } else if (reqptr->parameter ==
1478 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001479
1480 int ret = setHostNetworkData(reqptr);
1481 if (ret < 0) {
1482 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
1483 rc = IPMI_CC_UNSPECIFIED_ERROR;
1484 }
1485 }
1486 else {
shgoupfd84fbbf2015-12-17 10:05:51 +08001487 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
1488 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001489 }
1490
1491 return rc;
1492}
1493
1494void register_netfn_chassis_functions()
1495{
Tom05732372016-09-06 17:21:23 +05301496 // <Wildcard Command>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001497 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +05301498 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1499 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001500
Tom05732372016-09-06 17:21:23 +05301501 // Get Chassis Capabilities
Nan Li8d15fb42016-08-16 22:29:40 +08001502 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
Tom05732372016-09-06 17:21:23 +05301503 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1504 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001505
Tom05732372016-09-06 17:21:23 +05301506 // <Get System Boot Options>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001507 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301508 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1509 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001510
Tom05732372016-09-06 17:21:23 +05301511 // <Get Chassis Status>
Nan Lifdd8ec52016-08-28 03:57:40 +08001512 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS);
Tom05732372016-09-06 17:21:23 +05301513 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1514 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001515
Tom05732372016-09-06 17:21:23 +05301516 // <Chassis Control>
vishwa36993272015-11-20 12:43:49 -06001517 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
Tom05732372016-09-06 17:21:23 +05301518 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1519 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001520
Tom05732372016-09-06 17:21:23 +05301521 // <Set System Boot Options>
shgoupfd84fbbf2015-12-17 10:05:51 +08001522 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301523 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1524 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001525}