blob: 6c8b8e01e91d58f214cdcd5e039970e7d54ec98d [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>
Ratan Guptadcb10672017-07-10 10:33:50 +053032
Vishwanatha Subbannab891a572017-03-31 11:34:48 +053033#include "config.h"
ratagupta6f6bff2016-04-04 06:20:11 -050034
35//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050036#define SET_PARM_VERSION 0x01
37#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050038#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050039#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050040
Ratan Guptafd28dd72016-08-01 04:58:01 -050041constexpr size_t SIZE_MAC = 18;
42constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -050043 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
Ratan Guptafd28dd72016-08-01 04:58:01 -050044constexpr size_t SIZE_PREFIX = 7;
45constexpr size_t MAX_PREFIX_VALUE = 32;
46constexpr size_t SIZE_COOKIE = 4;
47constexpr size_t SIZE_VERSION = 2;
48constexpr auto MAC_ADDRESS_FORMAT = "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx";
49constexpr auto IP_ADDRESS_FORMAT = "%d.%d.%d.%d";
Matthew Barth8b470052016-09-21 10:02:57 -050050constexpr auto PREFIX_FORMAT = "%hhd";
Ratan Guptafd28dd72016-08-01 04:58:01 -050051constexpr auto ADDR_TYPE_FORMAT = "%hhx";
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053052constexpr auto IPV4_ADDRESS_SIZE_BYTE = 4;
53constexpr auto IPV6_ADDRESS_SIZE_BYTE = 16;
54
Ratan Guptafd28dd72016-08-01 04:58:01 -050055//PetiBoot-Specific
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053056static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
57 0x21, 0x00, 0x01, 0x06};
Ratan Guptafd28dd72016-08-01 04:58:01 -050058
59static constexpr size_t COOKIE_OFFSET = 1;
60static constexpr size_t VERSION_OFFSET = 5;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +053061static constexpr size_t ADDR_SIZE_OFFSET = 8;
Ratan Guptafd28dd72016-08-01 04:58:01 -050062static constexpr size_t MAC_OFFSET = 9;
63static constexpr size_t ADDRTYPE_OFFSET = 16;
64static constexpr size_t IPADDR_OFFSET = 17;
ratagupta6f6bff2016-04-04 06:20:11 -050065
shgoupfd84fbbf2015-12-17 10:05:51 +080066
Adriana Kobylak40814c62015-10-27 15:58:44 -050067void register_netfn_chassis_functions() __attribute__((constructor));
68
shgoupfd84fbbf2015-12-17 10:05:51 +080069// Host settings in dbus
70// Service name should be referenced by connection name got via object mapper
71const char *settings_object_name = "/org/openbmc/settings/host0";
72const char *settings_intf_name = "org.freedesktop.DBus.Properties";
73const char *host_intf_name = "org.openbmc.settings.Host";
74
Ratan Guptadcb10672017-07-10 10:33:50 +053075constexpr auto MAPPER_BUS_NAME = "xyz.openbmc_project.ObjectMapper";
76constexpr auto MAPPER_OBJ = "/xyz/openbmc_project/object_mapper";
77constexpr auto MAPPER_INTF = "xyz.openbmc_project.ObjectMapper";
78
79constexpr auto SETTINGS_ROOT = "/";
80constexpr auto SETTINGS_MATCH = "host0";
81constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
82
83constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP";
84constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress";
85
86constexpr auto METHOD_GET = "Get";
87constexpr auto METHOD_GET_ALL = "GetAll";
88constexpr auto METHOD_SET = "Set";
89
Nan Li8d15fb42016-08-16 22:29:40 +080090typedef struct
91{
92 uint8_t cap_flags;
93 uint8_t fru_info_dev_addr;
94 uint8_t sdr_dev_addr;
95 uint8_t sel_dev_addr;
96 uint8_t system_management_dev_addr;
97 uint8_t bridge_dev_addr;
98}__attribute__((packed)) ipmi_chassis_cap_t;
99
Nan Lifdd8ec52016-08-28 03:57:40 +0800100typedef struct
101{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500102 uint8_t cur_power_state;
103 uint8_t last_power_event;
104 uint8_t misc_power_state;
105 uint8_t front_panel_button_cap_status;
Nan Lifdd8ec52016-08-28 03:57:40 +0800106}__attribute__((packed)) ipmi_get_chassis_status_t;
107
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530108// Phosphor Host State manager
109namespace State = sdbusplus::xyz::openbmc_project::State::server;
110
Andrew Geisslera6e3a302017-05-31 19:34:00 -0500111namespace fs = std::experimental::filesystem;
112
Ratan Guptadcb10672017-07-10 10:33:50 +0530113using namespace phosphor::logging;
114using namespace sdbusplus::xyz::openbmc_project::Common::Error;
115
Deepak Kodihalli8cc19362017-07-21 11:18:38 -0500116namespace chassis
117{
118namespace internal
119{
120
121constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
122constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
123sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection());
124
125namespace cache
126{
127
128settings::Objects objects(dbus,
129 {bootModeIntf, bootSourceIntf});
130
131} // namespace cache
132} // namespace internal
133} // namespace chassis
134
Ratan Guptadcb10672017-07-10 10:33:50 +0530135/** @brief Gets the dbus object info implementing the given interface
136 * from the given subtree.
137 * @param[in] interface - Dbus interface.
138 * @param[in] serviceRoot - subtree from where the search should start.
139 * @param[in] match - identifier for object.
140 * @return On success returns the object having objectpath and servicename.
141 */
142
143//TODO There may be cases where an interface is implemented by multiple
144// objects,to handle such cases we are interested on that object
145// which are on interested busname.
146// Currently mapper doesn't give the readable busname(gives busid) so we can't
147// use busname to find the object,will do later once the support is there.
148
149ipmi::DbusObjectInfo getDbusObject(const std::string& interface,
150 const std::string& serviceRoot = SETTINGS_ROOT,
151 const std::string& match = "")
152{
153 std::vector<std::string>interfaces;
154 interfaces.emplace_back(interface);
155
156 auto bus = sdbusplus::bus::new_default();
157 auto depth = 0;
158
159 auto mapperCall = bus.new_method_call(MAPPER_BUS_NAME,
160 MAPPER_OBJ,
161 MAPPER_INTF,
162 "GetSubTree");
163
164 mapperCall.append(serviceRoot);
165 mapperCall.append(depth);
166 mapperCall.append(interfaces);
167
168 auto mapperReply = bus.call(mapperCall);
169 if (mapperReply.is_method_error())
170 {
171 log<level::ERR>("Error in mapper call");
172 elog<InternalFailure>();
173 }
174
175 ipmi::ObjectTree objectTree;
176 mapperReply.read(objectTree);
177
178 if (objectTree.empty())
179 {
180 log<level::ERR>("No Object have impelmented the interface",
181 entry("INTERFACE=%s", interface.c_str()));
182 elog<InternalFailure>();
183 }
184
185 ipmi::DbusObjectInfo objectInfo;
186
187 // if match is empty then return the first object
188 if(match == "")
189 {
190 objectInfo = make_pair(objectTree.begin()->first,
191 objectTree.begin()->second.begin()->first);
192 return objectInfo;
193 }
194
195 // else search the match string in the object path
196 auto objectFound = false;
197 for (auto& object : objectTree)
198 {
199 if(object.first.find(match)!= std::string::npos)
200 {
201 objectFound = true;
202 objectInfo = make_pair(object.first, object.second.begin()->first);
203 break;
204 }
205 }
206
207 if(!objectFound)
208 {
209 log<level::ERR>("Failed to find object which matches",
210 entry("MATCH=%s",match.c_str()));
211 elog<InternalFailure>();
212 }
213 return objectInfo;
214
215}
216
217/** @brief Gets the value associated with the given object
218 * and the interface.
219 * @param[in] service - Dbus service name.
220 * @param[in] objPath - Dbus object path.
221 * @param[in] interface - Dbus interface.
222 * @param[in] property - name of the property.
223 * @return On success returns the value of the property.
224 */
225std::string getDbusProperty(const std::string& service,
226 const std::string& objPath,
227 const std::string& interface,
228 const std::string& property)
229{
230
231 sdbusplus::message::variant<std::string> name;
232
233 auto bus = sdbusplus::bus::new_default();
234
235 auto method = bus.new_method_call(
236 service.c_str(),
237 objPath.c_str(),
238 PROP_INTF,
239 METHOD_GET);
240
241 method.append(interface, property);
242
243 auto reply = bus.call(method);
244
245 if (reply.is_method_error())
246 {
247 log<level::ERR>("Failed to get property",
248 entry("PROPERTY=%s", property.c_str()),
249 entry("PATH=%s", objPath.c_str()),
250 entry("INTERFACE=%s", interface.c_str()));
251 elog<InternalFailure>();
252 }
253
254 reply.read(name);
255
256 return name.get<std::string>();
257}
258
259/** @brief Gets all the properties associated with the given object
260 * and the interface.
261 * @param[in] service - Dbus service name.
262 * @param[in] objPath - Dbus object path.
263 * @param[in] interface - Dbus interface.
264 * @return On success returns the map of name value pair.
265 */
266ipmi::PropertyMap getAllDbusProperties(const std::string& service,
267 const std::string& objPath,
268 const std::string& interface)
269{
270 ipmi::PropertyMap properties;
271 auto bus = sdbusplus::bus::new_default();
272
273 auto method = bus.new_method_call(
274 service.c_str(),
275 objPath.c_str(),
276 PROP_INTF,
277 METHOD_GET_ALL);
278
279 method.append(interface);
280
281 auto reply = bus.call(method);
282
283 if (reply.is_method_error())
284 {
285 log<level::ERR>("Failed to get all properties",
286 entry("PATH=%s", objPath.c_str()),
287 entry("INTERFACE=%s", interface.c_str()));
288 elog<InternalFailure>();
289 }
290
291 reply.read(properties);
292 return properties;
293}
294
295/** @brief Sets the property value of the given object.
296 * @param[in] service - Dbus service name.
297 * @param[in] objPath - Dbus object path.
298 * @param[in] interface - Dbus interface.
299 * @param[in] property - name of the property.
300 * @param[in] value - value which needs to be set.
301 */
302void setDbusProperty(const std::string& service,
303 const std::string& objPath,
304 const std::string& interface,
305 const std::string& property,
306 const ipmi::Value& value)
307{
308 auto bus = sdbusplus::bus::new_default();
309
310 auto method = bus.new_method_call(
311 service.c_str(),
312 objPath.c_str(),
313 PROP_INTF,
314 METHOD_SET);
315
316 method.append(interface);
317 method.append(property, value);
318
319 if (!bus.call(method))
320 {
321 log<level::ERR>("Failed to set property",
322 entry("PROPERTY=%s", property.c_str()),
323 entry("PATH=%s",objPath.c_str()),
324 entry("INTERFACE=%s",interface.c_str()));
325 elog<InternalFailure>();
326 }
327
328}
329
330//TODO : Can remove the below function as we have
331// new functions which uses sdbusplus.
332//
333// openbmc/openbmc#1489
ratagupta6f6bff2016-04-04 06:20:11 -0500334int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +0800335{
336 sd_bus_error error = SD_BUS_ERROR_NULL;
337 sd_bus_message *m = NULL;
338 sd_bus *bus = NULL;
339 char *temp_buf = NULL;
340 char *connection = NULL;
341 int r;
342
Brad Bishop35518682016-07-22 08:35:41 -0400343 // Get the system bus where most system services are provided.
344 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800345
Brad Bishop35518682016-07-22 08:35:41 -0400346 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800347 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400348 fprintf(stderr, "Failed to get %s connection: %s\n",
349 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800350 goto finish;
351 }
352
shgoupfd84fbbf2015-12-17 10:05:51 +0800353 /*
354 * Bus, service, object path, interface and method are provided to call
355 * the method.
356 * Signatures and input arguments are provided by the arguments at the
357 * end.
358 */
359 r = sd_bus_call_method(bus,
360 connection, /* service to contact */
361 settings_object_name, /* object path */
362 settings_intf_name, /* interface name */
363 "Get", /* method name */
364 &error, /* object to return error in */
365 &m, /* return message on success */
366 "ss", /* input signature */
367 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500368 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800369
370 if (r < 0) {
371 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
372 goto finish;
373 }
374
375 /*
376 * The output should be parsed exactly the same as the output formatting
377 * specified.
378 */
379 r = sd_bus_message_read(m, "v", "s", &temp_buf);
380 if (r < 0) {
381 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
382 goto finish;
383 }
384
Matthew Barth56181052017-01-23 09:36:29 -0600385 *buf = strdup(temp_buf);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500386 /* *buf = (char*) malloc(strlen(temp_buf));
shgoupfd84fbbf2015-12-17 10:05:51 +0800387 if (*buf) {
388 strcpy(*buf, temp_buf);
389 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500390 */
shgoupfd84fbbf2015-12-17 10:05:51 +0800391 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
392
393finish:
394 sd_bus_error_free(&error);
395 sd_bus_message_unref(m);
396 free(connection);
397
398 return r;
399}
400
Ratan Guptadcb10672017-07-10 10:33:50 +0530401//TODO : Can remove the below function as we have
402// new functions which uses sdbusplus.
403//
404// openbmc/openbmc#1489
405
ratagupta6f6bff2016-04-04 06:20:11 -0500406int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800407{
408 sd_bus_error error = SD_BUS_ERROR_NULL;
409 sd_bus_message *m = NULL;
410 sd_bus *bus = NULL;
411 char *connection = NULL;
412 int r;
413
Brad Bishop35518682016-07-22 08:35:41 -0400414 // Get the system bus where most system services are provided.
415 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800416
Brad Bishop35518682016-07-22 08:35:41 -0400417 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800418 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400419 fprintf(stderr, "Failed to get %s connection: %s\n",
420 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800421 goto finish;
422 }
423
shgoupfd84fbbf2015-12-17 10:05:51 +0800424 /*
425 * Bus, service, object path, interface and method are provided to call
426 * the method.
427 * Signatures and input arguments are provided by the arguments at the
428 * end.
429 */
430 r = sd_bus_call_method(bus,
431 connection, /* service to contact */
432 settings_object_name, /* object path */
433 settings_intf_name, /* interface name */
434 "Set", /* method name */
435 &error, /* object to return error in */
436 &m, /* return message on success */
437 "ssv", /* input signature */
438 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500439 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800440 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500441 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800442
443 if (r < 0) {
444 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
445 goto finish;
446 }
447
ratagupta6f6bff2016-04-04 06:20:11 -0500448 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800449
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500450 finish:
shgoupfd84fbbf2015-12-17 10:05:51 +0800451 sd_bus_error_free(&error);
452 sd_bus_message_unref(m);
453 free(connection);
454
455 return r;
456}
457
Adriana Kobylak40814c62015-10-27 15:58:44 -0500458struct get_sys_boot_options_t {
459 uint8_t parameter;
460 uint8_t set;
461 uint8_t block;
462} __attribute__ ((packed));
463
shgoupfd84fbbf2015-12-17 10:05:51 +0800464struct get_sys_boot_options_response_t {
465 uint8_t version;
466 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500467 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800468} __attribute__ ((packed));
469
470struct set_sys_boot_options_t {
471 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500472 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800473} __attribute__ ((packed));
474
Ratan Guptafd28dd72016-08-01 04:58:01 -0500475
Ratan Guptadcb10672017-07-10 10:33:50 +0530476int getHostNetworkData(get_sys_boot_options_response_t* respptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500477{
Ratan Guptadcb10672017-07-10 10:33:50 +0530478 ipmi::PropertyMap properties;
479 int rc = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530480 uint8_t addrSize = IPV4_ADDRESS_SIZE_BYTE;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500481
Ratan Guptadcb10672017-07-10 10:33:50 +0530482 try
483 {
484 //TODO There may be cases where an interface is implemented by multiple
485 // objects,to handle such cases we are interested on that object
486 // which are on interested busname.
487 // Currenlty mapper doesn't give the readable busname(gives busid)
488 // so we can't match with bus name so giving some object specific info
489 // as SETTINGS_MATCH.
490 // Later SETTINGS_MATCH will be replaced with busname.
Ratan Guptafd28dd72016-08-01 04:58:01 -0500491
Ratan Guptadcb10672017-07-10 10:33:50 +0530492 auto ipObjectInfo = getDbusObject(IP_INTERFACE, SETTINGS_ROOT,
493 SETTINGS_MATCH);
494 auto macObjectInfo = getDbusObject(MAC_INTERFACE, SETTINGS_ROOT,
495 SETTINGS_MATCH);
496
497 properties = getAllDbusProperties(ipObjectInfo.second,
498 ipObjectInfo.first, IP_INTERFACE);
499 auto MACAddress =
500 getDbusProperty(macObjectInfo.second, macObjectInfo.first,
501 MAC_INTERFACE, "MACAddress");
502
503 sscanf(MACAddress.c_str(), MAC_ADDRESS_FORMAT,
504 (respptr->data + MAC_OFFSET),
505 (respptr->data + MAC_OFFSET + 1),
506 (respptr->data + MAC_OFFSET + 2),
507 (respptr->data + MAC_OFFSET + 3),
508 (respptr->data + MAC_OFFSET + 4),
509 (respptr->data + MAC_OFFSET + 5));
510
511
512 respptr->data[MAC_OFFSET + 6] = 0x00;
513
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530514 uint8_t addrOrigin = (properties["Origin"].get<std::string>() ==
Ratan Guptadcb10672017-07-10 10:33:50 +0530515 "xyz.openbmc_project.Network.IP.AddressOrigin.Static") ? 1 : 0;
516
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530517 memcpy(respptr->data + ADDRTYPE_OFFSET, &addrOrigin,
518 sizeof(addrOrigin));
519
520 uint8_t addressFamily = (properties["Type"].get<std::string>() ==
521 "xyz.openbmc_project.Network.IP.Protocol.IPv4") ?
522 AF_INET : AF_INET6;
523
524 addrSize = (addressFamily == AF_INET) ? IPV4_ADDRESS_SIZE_BYTE :
525 IPV6_ADDRESS_SIZE_BYTE;
Ratan Guptadcb10672017-07-10 10:33:50 +0530526
527 // ipaddress and gateway would be in IPv4 format
528
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530529 inet_pton(addressFamily,
530 properties["Address"].get<std::string>().c_str(),
Ratan Guptadcb10672017-07-10 10:33:50 +0530531 (respptr->data + IPADDR_OFFSET));
532
533 uint8_t prefix = properties["PrefixLength"].get<uint8_t>();
Ratan Guptadcb10672017-07-10 10:33:50 +0530534
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530535 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
536
537 memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
538
539 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
540
541 inet_pton(addressFamily,
542 properties["Gateway"].get<std::string>().c_str(),
543 (respptr->data + gatewayOffset));
Ratan Guptadcb10672017-07-10 10:33:50 +0530544
545 }
546 catch (InternalFailure& e)
547 {
548 commit<InternalFailure>();
549 memset(respptr->data, 0, SIZE_BOOT_OPTION);
550 rc = -1;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500551 return rc;
552 }
553
Ratan Guptadcb10672017-07-10 10:33:50 +0530554 //PetiBoot-Specific
555 //If sucess then copy the first 9 bytes to the data
Ratan Guptadcb10672017-07-10 10:33:50 +0530556 memcpy(respptr->data, net_conf_initial_bytes,
557 sizeof(net_conf_initial_bytes));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500558
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530559 memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
560
Ratan Guptafd28dd72016-08-01 04:58:01 -0500561#ifdef _IPMI_DEBUG_
Ratan Guptadcb10672017-07-10 10:33:50 +0530562 printf("\n===Printing the IPMI Formatted Data========\n");
Ratan Guptafd28dd72016-08-01 04:58:01 -0500563
Ratan Guptadcb10672017-07-10 10:33:50 +0530564 for (uint8_t pos = 0; pos < index; pos++)
565 {
566 printf("%02x ", respptr->data[pos]);
567 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500568#endif
569
Ratan Guptafd28dd72016-08-01 04:58:01 -0500570 return rc;
571}
572
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530573/** @brief convert IPv4 and IPv6 addresses from binary to text form.
574 * @param[in] family - IPv4/Ipv6
575 * @param[in] data - req data pointer.
576 * @param[in] offset - offset in the data.
577 * @param[in] addrSize - size of the data which needs to be read from offset.
578 * @returns address in text form.
579 */
580
581std::string getAddrStr(uint8_t family, uint8_t* data,
582 uint8_t offset, uint8_t addrSize)
583{
584 char ipAddr[INET6_ADDRSTRLEN] = {};
585
586 switch(family)
587 {
588 case AF_INET:
589 {
590 struct sockaddr_in addr4 {};
591 memcpy(&addr4.sin_addr.s_addr, &data[offset], addrSize);
592
593 inet_ntop(AF_INET, &addr4.sin_addr,
594 ipAddr, INET_ADDRSTRLEN);
595
596 break;
597 }
598 case AF_INET6:
599 {
600 struct sockaddr_in6 addr6 {};
601 memcpy(&addr6.sin6_addr.s6_addr, &data[offset], addrSize);
602
603 inet_ntop(AF_INET6, &addr6.sin6_addr,
604 ipAddr, INET6_ADDRSTRLEN);
605
606 break;
607 }
608 default:
609 {
610 return {};
611 }
612 }
613
614 return ipAddr;
615}
616
Ratan Guptadcb10672017-07-10 10:33:50 +0530617int setHostNetworkData(set_sys_boot_options_t* reqptr)
Ratan Guptafd28dd72016-08-01 04:58:01 -0500618{
Ratan Guptadcb10672017-07-10 10:33:50 +0530619 using namespace std::string_literals;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500620 std::string host_network_config;
621 char mac[SIZE_MAC] = {0};
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530622 std::string ipAddress, gateway;
623 char addrOrigin {0};
624 uint8_t addrSize {0};
Ratan Guptadcb10672017-07-10 10:33:50 +0530625 std::string addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530626 "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
627 std::string addressType =
628 "xyz.openbmc_project.Network.IP.Protocol.IPv4";
Ratan Guptadcb10672017-07-10 10:33:50 +0530629 uint8_t prefix {0};
630 uint32_t zeroCookie = 0;
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530631 uint8_t family = AF_INET;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500632
633 //cookie starts from second byte
634 // version starts from sixth byte
635
Ratan Guptadcb10672017-07-10 10:33:50 +0530636 try
Ratan Guptafd28dd72016-08-01 04:58:01 -0500637 {
Ratan Guptadcb10672017-07-10 10:33:50 +0530638 do
639 {
640 // cookie == 0x21 0x70 0x62 0x21
641 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
642 (net_conf_initial_bytes + COOKIE_OFFSET),
643 SIZE_COOKIE) != 0)
644 {
645 //cookie == 0
646 if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
647 &zeroCookie,
648 SIZE_COOKIE) == 0)
649 {
650 // need to zero out the network settings.
651 break;
652 }
653
654 log<level::ERR>("Invalid Cookie");
655 elog<InternalFailure>();
656 }
657
658 // vesion == 0x00 0x01
659 if (memcmp(&(reqptr->data[VERSION_OFFSET]),
660 (net_conf_initial_bytes + VERSION_OFFSET),
661 SIZE_VERSION) != 0)
662 {
663
664 log<level::ERR>("Invalid Version");
665 elog<InternalFailure>();
666 }
667
668 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
669 reqptr->data[MAC_OFFSET],
670 reqptr->data[MAC_OFFSET + 1],
671 reqptr->data[MAC_OFFSET + 2],
672 reqptr->data[MAC_OFFSET + 3],
673 reqptr->data[MAC_OFFSET + 4],
674 reqptr->data[MAC_OFFSET + 5]);
675
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530676 memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
677 sizeof(decltype(addrOrigin)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530678
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530679 if (addrOrigin)
Ratan Guptadcb10672017-07-10 10:33:50 +0530680 {
681 addressOrigin =
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530682 "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
Ratan Guptadcb10672017-07-10 10:33:50 +0530683 }
684
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530685 // Get the address size
686 memcpy(&addrSize ,&reqptr->data[ADDR_SIZE_OFFSET], sizeof(addrSize));
Ratan Guptadcb10672017-07-10 10:33:50 +0530687
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530688 uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
Ratan Guptadcb10672017-07-10 10:33:50 +0530689
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530690 memcpy(&prefix, &(reqptr->data[prefixOffset]), sizeof(decltype(prefix)));
Ratan Guptadcb10672017-07-10 10:33:50 +0530691
Ratan Gupta6ec7daa2017-07-15 14:13:01 +0530692 uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
693
694 if (addrSize != IPV4_ADDRESS_SIZE_BYTE)
695 {
696 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
697 family = AF_INET6;
698 }
699
700 ipAddress = getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
701 gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
702
Ratan Guptadcb10672017-07-10 10:33:50 +0530703 } while(0);
704
Ratan Guptafd28dd72016-08-01 04:58:01 -0500705 //Cookie == 0 or it is a valid cookie
Ratan Guptadcb10672017-07-10 10:33:50 +0530706 host_network_config += "ipaddress="s + ipAddress +
707 ",prefix="s + std::to_string(prefix) + ",gateway="s + gateway +
708 ",mac="s + mac + ",addressOrigin="s + addressOrigin;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500709
Ratan Guptadcb10672017-07-10 10:33:50 +0530710 log<level::DEBUG>("Network configuration changed",
711 entry("NETWORKCONFIG=%s", host_network_config.c_str()));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500712
Ratan Guptadcb10672017-07-10 10:33:50 +0530713 auto ipObjectInfo = getDbusObject(IP_INTERFACE, SETTINGS_ROOT,
714 SETTINGS_MATCH);
715 auto macObjectInfo = getDbusObject(MAC_INTERFACE, SETTINGS_ROOT,
716 SETTINGS_MATCH);
717 // set the dbus property
718 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
719 IP_INTERFACE, "Address", std::string(ipAddress));
720 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
721 IP_INTERFACE, "PrefixLength", prefix);
722 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
723 IP_INTERFACE, "Origin", addressOrigin);
724 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
725 IP_INTERFACE, "Gateway", std::string(gateway));
726 setDbusProperty(ipObjectInfo.second, ipObjectInfo.first,
727 IP_INTERFACE, "Type",
728 std::string("xyz.openbmc_project.Network.IP.Protocol.IPv4"));
729 setDbusProperty(macObjectInfo.second, macObjectInfo.first,
730 MAC_INTERFACE,"MACAddress", std::string(mac));
Ratan Guptafd28dd72016-08-01 04:58:01 -0500731
732 }
Ratan Guptadcb10672017-07-10 10:33:50 +0530733 catch (InternalFailure& e)
734 {
735 commit<InternalFailure>();
736 return -1;
737 }
738
739 return 0;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500740}
741
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500742ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
743 ipmi_request_t request,
744 ipmi_response_t response,
745 ipmi_data_len_t data_len,
746 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -0500747{
748 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
749 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800750 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500751 *data_len = 0;
752 return rc;
753}
754
Nan Li8d15fb42016-08-16 22:29:40 +0800755ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500756 ipmi_request_t request, ipmi_response_t response,
757 ipmi_data_len_t data_len, ipmi_context_t context)
Nan Li8d15fb42016-08-16 22:29:40 +0800758{
759 // sd_bus error
760 ipmi_ret_t rc = IPMI_CC_OK;
761
762 ipmi_chassis_cap_t chassis_cap{};
763
764 *data_len = sizeof(ipmi_chassis_cap_t);
765
766 // TODO: need future work. Get those flag from MRW.
767
768 // capabilities flags
769 // [7..4] - reserved
770 // [3] – 1b = provides power interlock (IPM 1.5)
771 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
772 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
773 // to lock out external power control and reset button or front panel interfaces
774 // and/or detect tampering with those interfaces).
775 // [0] -1b = Chassis provides intrusion (physical security) sensor.
776 // set to default value 0x0.
777 chassis_cap.cap_flags = 0x0;
778
779 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
780 // The 20h was given as those 5 device addresses.
781 // Chassis FRU info Device Address
782 chassis_cap.fru_info_dev_addr = 0x20;
783
784 // Chassis SDR Device Address
785 chassis_cap.sdr_dev_addr = 0x20;
786
787 // Chassis SEL Device Address
788 chassis_cap.sel_dev_addr = 0x20;
789
790 // Chassis System Management Device Address
791 chassis_cap.system_management_dev_addr = 0x20;
792
793 // Chassis Bridge Device Address.
794 chassis_cap.bridge_dev_addr = 0x20;
795
796 memcpy(response, &chassis_cap, *data_len);
797
798 return rc;
799}
800
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530801//------------------------------------------
802// Calls into Host State Manager Dbus object
803//------------------------------------------
804int initiate_state_transition(State::Host::Transition transition)
vishwa36993272015-11-20 12:43:49 -0600805{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500806 // OpenBMC Host State Manager dbus framework
807 constexpr auto HOST_STATE_MANAGER_ROOT = "/xyz/openbmc_project/state/host0";
808 constexpr auto HOST_STATE_MANAGER_IFACE = "xyz.openbmc_project.State.Host";
809 constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
810 constexpr auto PROPERTY = "RequestedHostTransition";
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530811
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500812 // sd_bus error
813 int rc = 0;
814 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600815
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500816 // SD Bus error report mechanism.
817 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600818
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500819 // Gets a hook onto either a SYSTEM or SESSION bus
820 sd_bus *bus_type = ipmid_get_sd_bus_connection();
821 rc = mapper_get_service(bus_type, HOST_STATE_MANAGER_ROOT, &busname);
822 if (rc < 0)
823 {
824 log<level::ERR>("Failed to get bus name",
825 entry("ERROR=%s, OBJPATH=%s",
826 strerror(-rc), HOST_STATE_MANAGER_ROOT));
827 return rc;
828 }
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530829
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500830 // Convert to string equivalent of the passed in transition enum.
831 auto request = State::convertForMessage(transition);
Vishwanatha Subbannab12b0c02017-03-07 18:17:19 +0530832
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500833 rc = sd_bus_call_method(bus_type, // On the system bus
834 busname, // Service to contact
835 HOST_STATE_MANAGER_ROOT, // Object path
836 DBUS_PROPERTY_IFACE, // Interface name
837 "Set", // Method to be called
838 &bus_error, // object to return error
839 nullptr, // Response buffer if any
840 "ssv", // Takes 3 arguments
841 HOST_STATE_MANAGER_IFACE,
842 PROPERTY,
843 "s", request.c_str());
844 if(rc < 0)
845 {
846 log<level::ERR>("Failed to initiate transition",
847 entry("ERROR=%s, REQUEST=%s",
848 bus_error.message, request.c_str()));
849 }
850 else
851 {
852 log<level::INFO>("Transition request initiated successfully");
853 }
vishwa36993272015-11-20 12:43:49 -0600854
855 sd_bus_error_free(&bus_error);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500856 free(busname);
vishwa36993272015-11-20 12:43:49 -0600857
Sergey Solomineb9b8142016-08-23 09:07:28 -0500858 return rc;
vishwa36993272015-11-20 12:43:49 -0600859}
860
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500861struct hostPowerPolicyTypeMap_t
862{
Nan Lifdd8ec52016-08-28 03:57:40 +0800863 uint8_t policyNum;
864 char policyName[19];
865};
866
867hostPowerPolicyTypeMap_t g_hostPowerPolicyTypeMap_t[] = {
868
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500869 {0x00, "LEAVE_OFF"},
870 {0x01, "RESTORE_LAST_STATE"},
871 {0x02, "ALWAYS_POWER_ON"},
872 {0x03, "UNKNOWN"}
Nan Lifdd8ec52016-08-28 03:57:40 +0800873};
874
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500875uint8_t get_host_power_policy(char *p)
876{
Nan Lifdd8ec52016-08-28 03:57:40 +0800877
878 hostPowerPolicyTypeMap_t *s = g_hostPowerPolicyTypeMap_t;
879
880 while (s->policyNum != 0x03) {
881 if (!strcmp(s->policyName,p))
882 break;
883 s++;
884 }
885
886 return s->policyNum;
887}
888
889//----------------------------------------------------------------------
890// Get Chassis Status commands
891//----------------------------------------------------------------------
892ipmi_ret_t ipmi_get_chassis_status(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500893 ipmi_request_t request,
894 ipmi_response_t response,
895 ipmi_data_len_t data_len,
896 ipmi_context_t context)
Nan Lifdd8ec52016-08-28 03:57:40 +0800897{
898 const char *objname = "/org/openbmc/control/power0";
899 const char *intf = "org.openbmc.control.Power";
900
901 sd_bus *bus = NULL;
902 sd_bus_message *reply = NULL;
903 int r = 0;
904 int pgood = 0;
905 char *busname = NULL;
906 ipmi_ret_t rc = IPMI_CC_OK;
907 ipmi_get_chassis_status_t chassis_status{};
908
909 char *p = NULL;
910 uint8_t s = 0;
911
912 // Get the system bus where most system services are provided.
913 bus = ipmid_get_sd_bus_connection();
914
915 *data_len = 4;
916
917 r = mapper_get_service(bus, objname, &busname);
918 if (r < 0) {
919 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-r));
920 rc = IPMI_CC_UNSPECIFIED_ERROR;
921 goto finish;
922 }
923
924 r = sd_bus_get_property(bus, busname, objname, intf, "pgood", NULL, &reply, "i");
925 if (r < 0) {
926 fprintf(stderr, "Failed to call sd_bus_get_property:%d, %s\n", r, strerror(-r));
927 fprintf(stderr, "Bus: %s, Path: %s, Interface: %s\n",
928 busname, objname, intf);
929 rc = IPMI_CC_UNSPECIFIED_ERROR;
930 goto finish;
931 }
932
933 r = sd_bus_message_read(reply, "i", &pgood);
934 if (r < 0) {
935 fprintf(stderr, "Failed to read sensor: %s\n", strerror(-r));
936 rc = IPMI_CC_UNSPECIFIED_ERROR;
937 goto finish;
938 }
939
940 printf("pgood is 0x%02x\n", pgood);
941
942 // Get Power Policy
943 r = dbus_get_property("power_policy",&p);
944
945 if (r < 0) {
946 fprintf(stderr, "Dbus get property(power_policy) failed for get_sys_boot_options.\n");
947 rc = IPMI_CC_UNSPECIFIED_ERROR;
948 } else {
949 s = get_host_power_policy(p);
950 }
951
952 if (p)
953 {
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -0500954 free(p);
955 p = NULL;
Nan Lifdd8ec52016-08-28 03:57:40 +0800956 }
957
958 // Current Power State
959 // [7] reserved
960 // [6..5] power restore policy
961 // 00b = chassis stays powered off after AC/mains returns
962 // 01b = after AC returns, power is restored to the state that was
963 // in effect when AC/mains was lost.
964 // 10b = chassis always powers up after AC/mains returns
965 // 11b = unknow
966 // Set to 00b, by observing the hardware behavior.
967 // Do we need to define a dbus property to identify the restore policy?
968
969 // [4] power control fault
970 // 1b = controller attempted to turn system power on or off, but
971 // system did not enter desired state.
972 // Set to 0b, since We don't support it..
973
974 // [3] power fault
975 // 1b = fault detected in main power subsystem.
976 // set to 0b. for we don't support it.
977
978 // [2] 1b = interlock (chassis is presently shut down because a chassis
979 // panel interlock switch is active). (IPMI 1.5)
980 // set to 0b, for we don't support it.
981
982 // [1] power overload
983 // 1b = system shutdown because of power overload condition.
984 // set to 0b, for we don't support it.
985
986 // [0] power is on
987 // 1b = system power is on
988 // 0b = system power is off(soft-off S4/S5, or mechanical off)
989
990 chassis_status.cur_power_state = ((s & 0x3)<<5) | (pgood & 0x1);
991
992 // Last Power Event
993 // [7..5] – reserved
994 // [4] – 1b = last ‘Power is on’ state was entered via IPMI command
995 // [3] – 1b = last power down caused by power fault
996 // [2] – 1b = last power down caused by a power interlock being activated
997 // [1] – 1b = last power down caused by a Power overload
998 // [0] – 1b = AC failed
999 // set to 0x0, for we don't support these fields.
1000
1001 chassis_status.last_power_event = 0;
1002
1003 // Misc. Chassis State
1004 // [7] – reserved
1005 // [6] – 1b = Chassis Identify command and state info supported (Optional)
1006 // 0b = Chassis Identify command support unspecified via this command.
1007 // (The Get Command Support command , if implemented, would still
1008 // indicate support for the Chassis Identify command)
1009 // [5..4] – Chassis Identify State. Mandatory when bit[6] =1b, reserved (return
1010 // as 00b) otherwise. Returns the present chassis identify state.
1011 // Refer to the Chassis Identify command for more info.
1012 // 00b = chassis identify state = Off
1013 // 01b = chassis identify state = Temporary(timed) On
1014 // 10b = chassis identify state = Indefinite On
1015 // 11b = reserved
1016 // [3] – 1b = Cooling/fan fault detected
1017 // [2] – 1b = Drive Fault
1018 // [1] – 1b = Front Panel Lockout active (power off and reset via chassis
1019 // push-buttons disabled.)
1020 // [0] – 1b = Chassis Intrusion active
1021 // set to 0, for we don't support them.
1022 chassis_status.misc_power_state = 0;
1023
1024 // Front Panel Button Capabilities and disable/enable status(Optional)
1025 // set to 0, for we don't support them.
1026 chassis_status.front_panel_button_cap_status = 0;
1027
1028 // Pack the actual response
1029 memcpy(response, &chassis_status, *data_len);
1030
1031finish:
1032 free(busname);
1033 reply = sd_bus_message_unref(reply);
1034
1035 return rc;
1036}
Chris Austen7888c4d2015-12-03 15:26:20 -06001037
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301038//-------------------------------------------------------------
1039// Send a command to SoftPowerOff application to stop any timer
1040//-------------------------------------------------------------
1041int stop_soft_off_timer()
1042{
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301043 constexpr auto iface = "org.freedesktop.DBus.Properties";
1044 constexpr auto soft_off_iface = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001045 "SoftPowerOff";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301046
1047 constexpr auto property = "ResponseReceived";
1048 constexpr auto value = "xyz.openbmc_project.Ipmi.Internal."
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001049 "SoftPowerOff.HostResponse.HostShutdown";
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301050
1051 // Get the system bus where most system services are provided.
1052 auto bus = ipmid_get_sd_bus_connection();
1053
1054 // Get the service name
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001055 // TODO openbmc/openbmc#1661 - Mapper refactor
1056 //
1057 // See openbmc/openbmc#1743 for some details but high level summary is that
1058 // for now the code will directly call the soft off interface due to a
1059 // race condition with mapper usage
1060 //
1061 //char *busname = nullptr;
1062 //auto r = mapper_get_service(bus, SOFTOFF_OBJPATH, &busname);
1063 //if (r < 0)
1064 //{
1065 // fprintf(stderr, "Failed to get %s bus name: %s\n",
1066 // SOFTOFF_OBJPATH, strerror(-r));
1067 // return r;
1068 //}
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301069
1070 // No error object or reply expected.
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001071 int rc = sd_bus_call_method(bus, SOFTOFF_BUSNAME, SOFTOFF_OBJPATH, iface,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001072 "Set", nullptr, nullptr, "ssv",
1073 soft_off_iface, property, "s", value);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301074 if (rc < 0)
1075 {
1076 fprintf(stderr, "Failed to set property in SoftPowerOff object: %s\n",
1077 strerror(-rc));
1078 }
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001079
Andrew Geissler2b4e4592017-06-08 11:18:35 -05001080 //TODO openbmc/openbmc#1661 - Mapper refactor
1081 //free(busname);
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301082 return rc;
1083}
1084
vishwa36993272015-11-20 12:43:49 -06001085//----------------------------------------------------------------------
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001086// Create file to indicate there is no need for softoff notification to host
1087//----------------------------------------------------------------------
1088void indicate_no_softoff_needed()
1089{
1090 fs::path path{HOST_INBAND_REQUEST_DIR};
1091 if (!fs::is_directory(path))
1092 {
1093 fs::create_directory(path);
1094 }
1095
1096 // Add the host instance (default 0 for now) to the file name
1097 std::string file{HOST_INBAND_REQUEST_FILE};
1098 auto size = std::snprintf(nullptr,0,file.c_str(),0);
1099 size++; // null
1100 std::unique_ptr<char[]> buf(new char[size]);
1101 std::snprintf(buf.get(),size,file.c_str(),0);
1102
1103 // Append file name to directory and create it
1104 path /= buf.get();
1105 std::ofstream(path.c_str());
1106}
1107
1108//----------------------------------------------------------------------
vishwa36993272015-11-20 12:43:49 -06001109// Chassis Control commands
1110//----------------------------------------------------------------------
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001111ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1112 ipmi_request_t request,
1113 ipmi_response_t response,
1114 ipmi_data_len_t data_len,
1115 ipmi_context_t context)
vishwa36993272015-11-20 12:43:49 -06001116{
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001117 // Error from power off.
1118 int rc = 0;
vishwa36993272015-11-20 12:43:49 -06001119
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001120 // No response for this command.
vishwa36993272015-11-20 12:43:49 -06001121 *data_len = 0;
1122
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001123 // Catch the actual operaton by peeking into request buffer
1124 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
1125 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
vishwa36993272015-11-20 12:43:49 -06001126
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001127 switch(chassis_ctrl_cmd)
1128 {
1129 case CMD_POWER_ON:
1130 rc = initiate_state_transition(State::Host::Transition::On);
1131 break;
1132 case CMD_POWER_OFF:
1133 // Need to Nudge SoftPowerOff application that it needs to stop the
1134 // watchdog timer if running.
1135 rc = stop_soft_off_timer();
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001136 // Only request the Off transition if the soft power off
1137 // application is not running
1138 if (rc < 0)
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001139 {
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001140 log<level::INFO>("Did not find soft off service so request "
1141 "Host:Transition:Off");
1142
1143 // First create a file to indicate to the soft off application
1144 // that it should not run since this is a direct user initiated
1145 // power off request (i.e. a power off request that is not
1146 // originating via a soft power off SMS request)
1147 indicate_no_softoff_needed();
1148
1149 // Now request the shutdown
1150 rc = initiate_state_transition(State::Host::Transition::Off);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001151 }
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001152 else
1153 {
1154 log<level::INFO>("Soft off is running, so let that stop "
1155 "the host");
1156 }
1157
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001158 break;
Vishwanatha Subbanna83b5c1c2017-01-25 18:41:51 +05301159
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001160 case CMD_HARD_RESET:
1161 case CMD_POWER_CYCLE:
1162 // SPEC has a section that says certain implementations can trigger
1163 // PowerOn if power is Off when a command to power cycle is
1164 // requested
Andrew Geisslera6e3a302017-05-31 19:34:00 -05001165
1166 // First create a file to indicate to the soft off application
1167 // that it should not run since this is a direct user initiated
1168 // power reboot request (i.e. a reboot request that is not
1169 // originating via a soft power off SMS request)
1170 indicate_no_softoff_needed();
1171
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001172 rc = initiate_state_transition(State::Host::Transition::Reboot);
1173 break;
1174 default:
1175 {
1176 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
1177 rc = -1;
1178 }
1179 }
vishwa36993272015-11-20 12:43:49 -06001180
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001181 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
vishwa36993272015-11-20 12:43:49 -06001182}
1183
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001184namespace boot_options
1185{
1186
1187using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
1188using IpmiValue = uint8_t;
1189constexpr auto ipmiDefault = 0;
1190
1191std::map<IpmiValue, Source::Sources> sourceIpmiToDbus =
1192{
1193 {0x01, Source::Sources::Network},
1194 {0x02, Source::Sources::Disk},
1195 {0x05, Source::Sources::ExternalMedia},
1196 {ipmiDefault, Source::Sources::Default}
shgoupfd84fbbf2015-12-17 10:05:51 +08001197};
1198
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001199std::map<IpmiValue, Mode::Modes> modeIpmiToDbus =
1200{
1201 {0x03, Mode::Modes::Safe},
1202 {0x06, Mode::Modes::Setup},
1203 {ipmiDefault, Mode::Modes::Regular}
shgoupfd84fbbf2015-12-17 10:05:51 +08001204};
1205
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001206std::map<Source::Sources, IpmiValue> sourceDbusToIpmi =
1207{
1208 {Source::Sources::Network, 0x01},
1209 {Source::Sources::Disk, 0x02},
1210 {Source::Sources::ExternalMedia, 0x05},
1211 {Source::Sources::Default, ipmiDefault}
1212};
shgoupfd84fbbf2015-12-17 10:05:51 +08001213
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001214std::map<Mode::Modes, IpmiValue> modeDbusToIpmi =
1215{
1216 {Mode::Modes::Safe, 0x03},
1217 {Mode::Modes::Setup, 0x06},
1218 {Mode::Modes::Regular, ipmiDefault}
1219};
shgoupfd84fbbf2015-12-17 10:05:51 +08001220
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001221} // namespace boot_options
shgoupfd84fbbf2015-12-17 10:05:51 +08001222
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001223ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
1224 ipmi_request_t request,
1225 ipmi_response_t response,
1226 ipmi_data_len_t data_len,
1227 ipmi_context_t context)
Adriana Kobylak40814c62015-10-27 15:58:44 -05001228{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001229 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001230 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
1231 char *p = NULL;
1232 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
1233 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001234 IpmiValue bootOption = ipmiDefault;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001235
1236 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
1237
shgoupfd84fbbf2015-12-17 10:05:51 +08001238 memset(resp,0,sizeof(*resp));
1239 resp->version = SET_PARM_VERSION;
1240 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -05001241 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001242
Adriana Kobylak40814c62015-10-27 15:58:44 -05001243
shgoupfd84fbbf2015-12-17 10:05:51 +08001244 /*
1245 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1246 * This is the only parameter used by petitboot.
1247 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001248 if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001249 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +08001250
Ratan Guptafd28dd72016-08-01 04:58:01 -05001251 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001252 using namespace chassis::internal;
1253 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001254
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001255 const auto& bootSourceSetting = objects.map.at(bootSourceIntf);
1256 auto method =
1257 dbus.new_method_call(
1258 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1259 bootSourceSetting.c_str(),
1260 PROP_INTF,
1261 "Get");
1262 method.append(bootSourceIntf, "BootSource");
1263 auto reply = dbus.call(method);
1264 if (reply.is_method_error())
ratagupta6f6bff2016-04-04 06:20:11 -05001265 {
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001266 log<level::ERR>("Error in BootSource Get");
1267 report<InternalFailure>();
1268 *data_len = 0;
1269 return IPMI_CC_UNSPECIFIED_ERROR;
ratagupta6f6bff2016-04-04 06:20:11 -05001270 }
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001271 sdbusplus::message::variant<std::string> result;
1272 reply.read(result);
1273 auto bootSource =
1274 Source::convertSourcesFromString(result.get<std::string>());
1275
1276 const auto& bootModeSetting = objects.map.at(bootModeIntf);
1277 method = dbus.new_method_call(
1278 objects.service(bootModeSetting, bootModeIntf).c_str(),
1279 bootModeSetting.c_str(),
1280 PROP_INTF,
1281 "Get");
1282 method.append(bootModeIntf, "BootMode");
1283 reply = dbus.call(method);
1284 if (reply.is_method_error())
1285 {
1286 log<level::ERR>("Error in BootMode Get");
1287 report<InternalFailure>();
1288 *data_len = 0;
1289 return IPMI_CC_UNSPECIFIED_ERROR;
1290 }
1291 reply.read(result);
1292 auto bootMode = Mode::convertModesFromString(result.get<std::string>());
1293
1294 bootOption = sourceDbusToIpmi.at(bootSource);
1295 if ((Mode::Modes::Regular == bootMode) &&
1296 (Source::Sources::Default == bootSource))
1297 {
1298 bootOption = ipmiDefault;
1299 }
1300 else if (Source::Sources::Default == bootSource)
1301 {
1302 bootOption = modeDbusToIpmi.at(bootMode);
1303 }
1304 resp->data[1] = (bootOption << 2);
1305 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -05001306
1307 /* Get the boot policy */
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001308 int r = dbus_get_property("boot_policy",&p);
ratagupta6f6bff2016-04-04 06:20:11 -05001309
1310 if (r < 0) {
1311 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
1312 rc = IPMI_CC_UNSPECIFIED_ERROR;
1313
1314 } else {
1315
George Keishing012d6a42017-06-14 03:06:48 -05001316 printf("BootPolicy is [%s]\n", p);
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001317 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
1318 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
1319 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
ratagupta6f6bff2016-04-04 06:20:11 -05001320 rc = IPMI_CC_OK;
1321
1322 }
1323
1324
Ratan Guptafd28dd72016-08-01 04:58:01 -05001325 } else if ( reqptr->parameter == static_cast<uint8_t>
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001326 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001327
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001328 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001329
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001330 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001331
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001332 int ret = getHostNetworkData(resp);
Ratan Guptafd28dd72016-08-01 04:58:01 -05001333
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001334 if (ret < 0) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001335
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001336 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
1337 rc = IPMI_CC_UNSPECIFIED_ERROR;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001338
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001339 }else
1340 rc = IPMI_CC_OK;
Ratan Guptafd28dd72016-08-01 04:58:01 -05001341 }
1342
1343 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -05001344 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +08001345 }
1346
1347 if (p)
1348 free(p);
1349
Ratan Guptafd28dd72016-08-01 04:58:01 -05001350 if (rc == IPMI_CC_OK)
1351 {
1352 *data_len += 2;
1353 }
1354
shgoupfd84fbbf2015-12-17 10:05:51 +08001355 return rc;
1356}
1357
1358
1359
1360ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001361 ipmi_request_t request,
1362 ipmi_response_t response,
1363 ipmi_data_len_t data_len,
1364 ipmi_context_t context)
shgoupfd84fbbf2015-12-17 10:05:51 +08001365{
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001366 using namespace boot_options;
shgoupfd84fbbf2015-12-17 10:05:51 +08001367 ipmi_ret_t rc = IPMI_CC_OK;
shgoupfd84fbbf2015-12-17 10:05:51 +08001368 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
1369
Ratan Guptafd28dd72016-08-01 04:58:01 -05001370 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
1371
shgoupfd84fbbf2015-12-17 10:05:51 +08001372 // This IPMI command does not have any resposne data
1373 *data_len = 0;
1374
1375 /* 000101
1376 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
1377 * This is the only parameter used by petitboot.
1378 */
Ratan Guptafd28dd72016-08-01 04:58:01 -05001379
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001380 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
1381 {
1382 IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
1383 using namespace chassis::internal;
1384 using namespace chassis::internal::cache;
shgoupfd84fbbf2015-12-17 10:05:51 +08001385
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001386 auto modeItr = modeIpmiToDbus.find(bootOption);
1387 auto sourceItr = sourceIpmiToDbus.find(bootOption);
1388 if ((ipmiDefault == bootOption) ||
1389 (sourceIpmiToDbus.end() != sourceItr))
1390 {
1391 sdbusplus::message::variant<std::string> property =
1392 convertForMessage(sourceItr->second);
1393 const auto& bootSourceSetting =
1394 objects.map.at(bootSourceIntf);
1395 auto method =
1396 dbus.new_method_call(
1397 objects.service(bootSourceSetting, bootSourceIntf).c_str(),
1398 bootSourceSetting.c_str(),
1399 PROP_INTF,
1400 "Set");
1401 method.append(bootSourceIntf, "BootSource", property);
1402 auto reply = dbus.call(method);
1403 if (reply.is_method_error())
1404 {
1405 log<level::ERR>("Error in BootSource Set");
1406 report<InternalFailure>();
1407 *data_len = 0;
1408 return IPMI_CC_UNSPECIFIED_ERROR;
1409 }
1410 }
1411 if ((ipmiDefault == bootOption) ||
1412 (modeIpmiToDbus.end() != modeItr))
1413 {
1414 sdbusplus::message::variant<std::string> property =
1415 convertForMessage(modeItr->second);
1416 const auto& bootModeSetting = objects.map.at(bootModeIntf);
1417 auto method =
1418 dbus.new_method_call(
1419 objects.service(bootModeSetting, bootModeIntf).c_str(),
1420 bootModeSetting.c_str(),
1421 PROP_INTF,
1422 "Set");
1423 method.append(bootModeIntf, "BootMode", property);
1424 auto reply = dbus.call(method);
1425 if (reply.is_method_error())
1426 {
1427 log<level::ERR>("Error in BootMode Set");
1428 report<InternalFailure>();
1429 *data_len = 0;
1430 return IPMI_CC_UNSPECIFIED_ERROR;
shgoupfd84fbbf2015-12-17 10:05:51 +08001431 }
1432 }
Ratan Guptafd28dd72016-08-01 04:58:01 -05001433
ratagupta6f6bff2016-04-04 06:20:11 -05001434 /* setting the boot policy */
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001435 std::string value =
1436 (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001437 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -05001438
Deepak Kodihalli8cc19362017-07-21 11:18:38 -05001439 printf ( "\nBoot Policy is %s",value.c_str());
1440 int r = dbus_set_property("boot_policy",value.c_str());
ratagupta6f6bff2016-04-04 06:20:11 -05001441
1442 if (r < 0) {
1443 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
1444 rc = IPMI_CC_UNSPECIFIED_ERROR;
1445 }
shgoupfd84fbbf2015-12-17 10:05:51 +08001446
Andrew Geisslerfca6a4f2017-05-30 10:55:39 -05001447 } else if (reqptr->parameter ==
1448 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
Ratan Guptafd28dd72016-08-01 04:58:01 -05001449
1450 int ret = setHostNetworkData(reqptr);
1451 if (ret < 0) {
1452 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
1453 rc = IPMI_CC_UNSPECIFIED_ERROR;
1454 }
1455 }
1456 else {
shgoupfd84fbbf2015-12-17 10:05:51 +08001457 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
1458 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -05001459 }
1460
1461 return rc;
1462}
1463
1464void register_netfn_chassis_functions()
1465{
Tom05732372016-09-06 17:21:23 +05301466 // <Wildcard Command>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001467 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
Tom05732372016-09-06 17:21:23 +05301468 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard,
1469 PRIVILEGE_USER);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001470
Tom05732372016-09-06 17:21:23 +05301471 // Get Chassis Capabilities
Nan Li8d15fb42016-08-16 22:29:40 +08001472 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
Tom05732372016-09-06 17:21:23 +05301473 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap,
1474 PRIVILEGE_USER);
Nan Li8d15fb42016-08-16 22:29:40 +08001475
Tom05732372016-09-06 17:21:23 +05301476 // <Get System Boot Options>
Adriana Kobylak40814c62015-10-27 15:58:44 -05001477 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301478 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL,
1479 ipmi_chassis_get_sys_boot_options, PRIVILEGE_OPERATOR);
Adriana Kobylak40814c62015-10-27 15:58:44 -05001480
Tom05732372016-09-06 17:21:23 +05301481 // <Get Chassis Status>
Nan Lifdd8ec52016-08-28 03:57:40 +08001482 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS);
Tom05732372016-09-06 17:21:23 +05301483 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_STATUS, NULL, ipmi_get_chassis_status,
1484 PRIVILEGE_USER);
Nan Lifdd8ec52016-08-28 03:57:40 +08001485
Tom05732372016-09-06 17:21:23 +05301486 // <Chassis Control>
vishwa36993272015-11-20 12:43:49 -06001487 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
Tom05732372016-09-06 17:21:23 +05301488 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control,
1489 PRIVILEGE_OPERATOR);
shgoupfd84fbbf2015-12-17 10:05:51 +08001490
Tom05732372016-09-06 17:21:23 +05301491 // <Set System Boot Options>
shgoupfd84fbbf2015-12-17 10:05:51 +08001492 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
Tom05732372016-09-06 17:21:23 +05301493 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
1494 ipmi_chassis_set_sys_boot_options, PRIVILEGE_OPERATOR);
vishwa36993272015-11-20 12:43:49 -06001495}