blob: a20d062d19b384cc1b49e71a521e0eb53b16405a [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"
Adriana Kobylak40814c62015-10-27 15:58:44 -05003#include <stdio.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05004#include <stdlib.h>
Adriana Kobylak40814c62015-10-27 15:58:44 -05005#include <stdint.h>
Brad Bishop35518682016-07-22 08:35:41 -04006#include <mapper.h>
Ratan Guptafd28dd72016-08-01 04:58:01 -05007#include <arpa/inet.h>
8#include <netinet/in.h>
9#include <limits.h>
10#include <string.h>
11#include <endian.h>
12#include <sstream>
13#include <array>
ratagupta6f6bff2016-04-04 06:20:11 -050014
15//Defines
Ratan Guptafd28dd72016-08-01 04:58:01 -050016#define SET_PARM_VERSION 0x01
17#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40 //boot flags data1 7th bit on
ratagupta6f6bff2016-04-04 06:20:11 -050018#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80 //boot flags data1 8th bit on
Ratan Guptafd28dd72016-08-01 04:58:01 -050019#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0 //boot flags data1 7 & 8 bit on
ratagupta6f6bff2016-04-04 06:20:11 -050020
Ratan Guptafd28dd72016-08-01 04:58:01 -050021constexpr size_t SIZE_MAC = 18;
22constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
23 OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
24constexpr size_t SIZE_PREFIX = 7;
25constexpr size_t MAX_PREFIX_VALUE = 32;
26constexpr size_t SIZE_COOKIE = 4;
27constexpr size_t SIZE_VERSION = 2;
28constexpr auto MAC_ADDRESS_FORMAT = "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx";
29constexpr auto IP_ADDRESS_FORMAT = "%d.%d.%d.%d";
Matthew Barth8b470052016-09-21 10:02:57 -050030constexpr auto PREFIX_FORMAT = "%hhd";
Ratan Guptafd28dd72016-08-01 04:58:01 -050031constexpr auto ADDR_TYPE_FORMAT = "%hhx";
32//PetiBoot-Specific
33static constexpr uint8_t net_conf_initial_bytes[] = {0x80,0x21, 0x70 ,0x62 ,0x21,
34 0x00 ,0x01 ,0x06 ,0x04};
35
36static constexpr size_t COOKIE_OFFSET = 1;
37static constexpr size_t VERSION_OFFSET = 5;
38static constexpr size_t MAC_OFFSET = 9;
39static constexpr size_t ADDRTYPE_OFFSET = 16;
40static constexpr size_t IPADDR_OFFSET = 17;
41static constexpr size_t PREFIX_OFFSET = 21;
42static constexpr size_t GATEWAY_OFFSET = 22;
ratagupta6f6bff2016-04-04 06:20:11 -050043
44
vishwa36993272015-11-20 12:43:49 -060045// OpenBMC Chassis Manager dbus framework
vishwa36993272015-11-20 12:43:49 -060046const char *chassis_object_name = "/org/openbmc/control/chassis0";
47const char *chassis_intf_name = "org.openbmc.control.Chassis";
48
shgoupfd84fbbf2015-12-17 10:05:51 +080049
Adriana Kobylak40814c62015-10-27 15:58:44 -050050void register_netfn_chassis_functions() __attribute__((constructor));
51
shgoupfd84fbbf2015-12-17 10:05:51 +080052// Host settings in dbus
53// Service name should be referenced by connection name got via object mapper
54const char *settings_object_name = "/org/openbmc/settings/host0";
55const char *settings_intf_name = "org.freedesktop.DBus.Properties";
56const char *host_intf_name = "org.openbmc.settings.Host";
57
Nan Li8d15fb42016-08-16 22:29:40 +080058typedef struct
59{
60 uint8_t cap_flags;
61 uint8_t fru_info_dev_addr;
62 uint8_t sdr_dev_addr;
63 uint8_t sel_dev_addr;
64 uint8_t system_management_dev_addr;
65 uint8_t bridge_dev_addr;
66}__attribute__((packed)) ipmi_chassis_cap_t;
67
ratagupta6f6bff2016-04-04 06:20:11 -050068int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +080069{
70 sd_bus_error error = SD_BUS_ERROR_NULL;
71 sd_bus_message *m = NULL;
72 sd_bus *bus = NULL;
73 char *temp_buf = NULL;
74 char *connection = NULL;
75 int r;
76
Brad Bishop35518682016-07-22 08:35:41 -040077 // Get the system bus where most system services are provided.
78 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +080079
Brad Bishop35518682016-07-22 08:35:41 -040080 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +080081 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -040082 fprintf(stderr, "Failed to get %s connection: %s\n",
83 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +080084 goto finish;
85 }
86
shgoupfd84fbbf2015-12-17 10:05:51 +080087 /*
88 * Bus, service, object path, interface and method are provided to call
89 * the method.
90 * Signatures and input arguments are provided by the arguments at the
91 * end.
92 */
93 r = sd_bus_call_method(bus,
94 connection, /* service to contact */
95 settings_object_name, /* object path */
96 settings_intf_name, /* interface name */
97 "Get", /* method name */
98 &error, /* object to return error in */
99 &m, /* return message on success */
100 "ss", /* input signature */
101 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500102 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800103
104 if (r < 0) {
105 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
106 goto finish;
107 }
108
109 /*
110 * The output should be parsed exactly the same as the output formatting
111 * specified.
112 */
113 r = sd_bus_message_read(m, "v", "s", &temp_buf);
114 if (r < 0) {
115 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
116 goto finish;
117 }
118
119 asprintf(buf, "%s", temp_buf);
120/* *buf = (char*) malloc(strlen(temp_buf));
121 if (*buf) {
122 strcpy(*buf, temp_buf);
123 }
124*/
125 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
126
127finish:
128 sd_bus_error_free(&error);
129 sd_bus_message_unref(m);
130 free(connection);
131
132 return r;
133}
134
ratagupta6f6bff2016-04-04 06:20:11 -0500135int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800136{
137 sd_bus_error error = SD_BUS_ERROR_NULL;
138 sd_bus_message *m = NULL;
139 sd_bus *bus = NULL;
140 char *connection = NULL;
141 int r;
142
Brad Bishop35518682016-07-22 08:35:41 -0400143 // Get the system bus where most system services are provided.
144 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800145
Brad Bishop35518682016-07-22 08:35:41 -0400146 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800147 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400148 fprintf(stderr, "Failed to get %s connection: %s\n",
149 settings_object_name, strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800150 goto finish;
151 }
152
shgoupfd84fbbf2015-12-17 10:05:51 +0800153 /*
154 * Bus, service, object path, interface and method are provided to call
155 * the method.
156 * Signatures and input arguments are provided by the arguments at the
157 * end.
158 */
159 r = sd_bus_call_method(bus,
160 connection, /* service to contact */
161 settings_object_name, /* object path */
162 settings_intf_name, /* interface name */
163 "Set", /* method name */
164 &error, /* object to return error in */
165 &m, /* return message on success */
166 "ssv", /* input signature */
167 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500168 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800169 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500170 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800171
172 if (r < 0) {
173 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
174 goto finish;
175 }
176
ratagupta6f6bff2016-04-04 06:20:11 -0500177 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800178
179finish:
180 sd_bus_error_free(&error);
181 sd_bus_message_unref(m);
182 free(connection);
183
184 return r;
185}
186
Adriana Kobylak40814c62015-10-27 15:58:44 -0500187struct get_sys_boot_options_t {
188 uint8_t parameter;
189 uint8_t set;
190 uint8_t block;
191} __attribute__ ((packed));
192
shgoupfd84fbbf2015-12-17 10:05:51 +0800193struct get_sys_boot_options_response_t {
194 uint8_t version;
195 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500196 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800197} __attribute__ ((packed));
198
199struct set_sys_boot_options_t {
200 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500201 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800202} __attribute__ ((packed));
203
Ratan Guptafd28dd72016-08-01 04:58:01 -0500204struct host_network_config_t {
205 std::string ipaddress;
206 std::string prefix;
207 std::string gateway;
208 std::string macaddress;
209 std::string addrType;
210
211 host_network_config_t()=default;
212};
213
214void fillNetworkConfig( host_network_config_t & host_config ,
215 const std::string& conf_str ) {
216
217 constexpr auto COMMA_DELIMITER = ",";
218 constexpr auto EQUAL_DELIMITER = "=";
219 size_t commaDelimtrPos = 0;
220 size_t equalDelimtrPos = 0,commaDelimtrPrevPos = 0;
221 std::string value;
222 while ( commaDelimtrPos < conf_str.length() ) {
223
224 commaDelimtrPos = conf_str.find(COMMA_DELIMITER,commaDelimtrPos);
225 //This condition is to extract the last
226 //Substring as we will not be having the delimeter
227 //at end. std::string::npos is -1
228
229 if ( commaDelimtrPos == std::string::npos ) {
230 commaDelimtrPos = conf_str.length();
231 }
232
233 equalDelimtrPos = conf_str.find (EQUAL_DELIMITER,commaDelimtrPrevPos);
234
235 //foo,ipaddress=1234
236 if ( equalDelimtrPos == std::string::npos ) {
237
238 commaDelimtrPos++;
239 commaDelimtrPrevPos= commaDelimtrPos;
240 continue;
241 }
242
243 value = conf_str.substr((equalDelimtrPos+1),
244 commaDelimtrPos-(equalDelimtrPos+1));
245
246#ifdef _IPMI_DEBUG_
247 printf ("Name=[%s],Value=[%s],commaDelimtrPos=[%d],\
248 commaDelimtrPrevPos=[%d],equalDelimtrPos=[%d]\n",
249 name.c_str(),value.c_str(),commaDelimtrPos,
250 commaDelimtrPrevPos,equalDelimtrPos);
251#endif
252
253 if ( 0 == conf_str.compare(commaDelimtrPrevPos,
254 equalDelimtrPos-commaDelimtrPrevPos,"ipaddress" )) {
255
256 host_config.ipaddress = std::move(value);
257 }
258 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
259 equalDelimtrPos-commaDelimtrPrevPos,"prefix" )) {
260
261 host_config.prefix = std::move(value);
262 }
263 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
264 equalDelimtrPos-commaDelimtrPrevPos, "gateway" )) {
265 host_config.gateway = std::move(value);
266 }
267 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
268 equalDelimtrPos-commaDelimtrPrevPos, "mac" )) {
269 host_config.macaddress = std::move(value);
270 }
271 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
272 equalDelimtrPos-commaDelimtrPrevPos, "addr_type" )) {
273 host_config.addrType = std::move(value);
274 }
275
276 commaDelimtrPos++;
277 commaDelimtrPrevPos= commaDelimtrPos;
278 }
279}
280
281int getHostNetworkData(get_sys_boot_options_response_t* respptr)
282{
283
284 char *prop = nullptr;
285 int rc = dbus_get_property("network_config",&prop);
286
287 if ( rc < 0 ) {
288 fprintf(stderr, "Dbus get property(boot_flags) failed\
289 for get_sys_boot_options.\n");
290 return rc;
291 }
292
293 std::string conf_str(prop);
294
295 if ( prop ) {
296
297 free(prop);
298 prop = nullptr;
299 }
300
301 /* network_config property Value would be in the form of
302 * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
303 */
304
305 /* Parsing the string and fill the hostconfig structure with the
306 * values */
307
308 printf ("Configuration String[%s]\n ",conf_str.c_str());
309
310 host_network_config_t host_config;
311
312 // Fill the host_config from the configuration string
313 fillNetworkConfig(host_config,conf_str);
314
315 //Assigning the index as intialByteLength as it is fixed and prefilled.
316 printf ("host_config.macaddress.c_str()=[%s]\n",host_config.macaddress.c_str());
317 do{
318
319 rc = sscanf(host_config.macaddress.c_str(),MAC_ADDRESS_FORMAT,
320 (respptr->data+MAC_OFFSET), (respptr->data+MAC_OFFSET+1),
321 (respptr->data+MAC_OFFSET+2),(respptr->data+MAC_OFFSET+3),
322 (respptr->data+MAC_OFFSET+4), (respptr->data+MAC_OFFSET+5));
323
324
325 if ( rc < 6 ){
326 fprintf(stderr, "sscanf Failed in extracting mac address.\n");
327 rc = -1;
328 break;
329 }
330
331 //Conevrt the dhcp,ipaddress,mask and gateway as hex number
332 respptr->data[MAC_OFFSET+6]=0x00;
333
334 rc = sscanf(host_config.addrType.c_str(),ADDR_TYPE_FORMAT,
335 (respptr->data+ADDRTYPE_OFFSET));
336
337 if ( rc <= 0 ) {
338 fprintf(stderr, "sscanf Failed in extracting address type.\n");
339 rc = -1;
340 break;
341 }
342
343 //ipaddress and gateway would be in IPv4 format
344 rc = inet_pton(AF_INET,host_config.ipaddress.c_str(),
345 (respptr->data+IPADDR_OFFSET));
346
347 if ( rc <= 0 ) {
348 fprintf(stderr, "inet_pton failed during ipaddress coneversion\n");
349 rc = -1;
350 break;
351 }
352
353 rc = sscanf(host_config.prefix.c_str(),PREFIX_FORMAT,
354 (respptr->data+PREFIX_OFFSET));
355
356 if ( rc <= 0 ) {
357 fprintf(stderr, "sscanf failed during prefix extraction.\n");
358 rc = -1;
359 break;
360 }
361
362 rc = inet_pton(AF_INET,host_config.gateway.c_str(),
363 (respptr->data+GATEWAY_OFFSET));
364
365 if ( rc <= 0 ) {
366 fprintf(stderr, "inet_pton failed during gateway conversion.\n");
367 rc = -1;
368 break;
369 }
370
371 }while (0);
372
373 if ( rc ) {
374
375 //PetiBoot-Specific
376 //If sucess then copy the first 9 bytes to the data
377 //else set the respptr to 0
378
379 memcpy(respptr->data,net_conf_initial_bytes,
380 sizeof(net_conf_initial_bytes));
381
382#ifdef _IPMI_DEBUG_
383 printf ("\n===Printing the IPMI Formatted Data========\n");
384
385 for ( uint8_t pos = 0; pos<index; pos++ )
386 printf("%02x ", respptr->data[pos]);
387#endif
388
389 }else {
390
391 memset(respptr->data,0,SIZE_BOOT_OPTION);
392 }
393
394 return rc;
395}
396
397int setHostNetworkData(set_sys_boot_options_t * reqptr)
398{
399 std::string host_network_config;
400 char mac[SIZE_MAC] = {0};
401 char ipAddress[INET_ADDRSTRLEN] = {0};
402 char gateway[INET_ADDRSTRLEN] = {0};
403 char dhcp[SIZE_PREFIX] = {0};
404 char prefix[SIZE_PREFIX] = {0};
405 int rc = 0;
406 uint32_t zeroCookie=0;
407
408 //cookie starts from second byte
409 // version starts from sixth byte
410
411 do {
412
413 // cookie == 0x21 0x70 0x62 0x21
414 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
415 (net_conf_initial_bytes+COOKIE_OFFSET),
416 SIZE_COOKIE) != 0 ) {
417 //cookie == 0
418 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
419 &zeroCookie,
420 SIZE_COOKIE) == 0 ) {
421 rc = 0;
422 break;
423 }
424 //Invalid cookie
425 fprintf(stderr, "Invalid Cookie\n");
426 rc = -1;
427 break;
428 }
429 // vesion == 0x00 0x01
430 if ( memcmp(&(reqptr->data[VERSION_OFFSET]),
431 (net_conf_initial_bytes+VERSION_OFFSET),
432 SIZE_VERSION) != 0 ) {
433
434 fprintf(stderr, "Invalid Version\n");
435 rc = -1;
436 break;
437 }
438
439 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
440 reqptr->data[MAC_OFFSET],
441 reqptr->data[MAC_OFFSET+1],
442 reqptr->data[MAC_OFFSET+2],
443 reqptr->data[MAC_OFFSET+3],
444 reqptr->data[MAC_OFFSET+4],
445 reqptr->data[MAC_OFFSET+5]);
446
447 snprintf(dhcp,SIZE_PREFIX, ADDR_TYPE_FORMAT, reqptr->data[ADDRTYPE_OFFSET]);
448 //Validating the address type which could be
449 //either static or dynamic
450 if( *(reqptr->data+ADDRTYPE_OFFSET) > 1 ) {
451
452 fprintf(stderr, "Invalid Address Type\n");
453 rc = -1;
454 break;
455
456 }
457
458 snprintf(ipAddress, INET_ADDRSTRLEN, IP_ADDRESS_FORMAT,
459 reqptr->data[IPADDR_OFFSET], reqptr->data[IPADDR_OFFSET+1],
460 reqptr->data[IPADDR_OFFSET+2], reqptr->data[IPADDR_OFFSET+3]);
461
462 //validating prefix
463 if ( *(reqptr->data+PREFIX_OFFSET) > (uint8_t)MAX_PREFIX_VALUE ) {
464
465 fprintf(stderr, "Invalid Prefix\n");
466 rc = -1;
467 break;
468 }
469
470 snprintf(prefix,SIZE_PREFIX,PREFIX_FORMAT, reqptr->data[PREFIX_OFFSET]);
471
472 snprintf(gateway, INET_ADDRSTRLEN,IP_ADDRESS_FORMAT,
473 reqptr->data[GATEWAY_OFFSET], reqptr->data[GATEWAY_OFFSET+1],
474 reqptr->data[GATEWAY_OFFSET+2], reqptr->data[GATEWAY_OFFSET+3]);
475
476
477 }while(0);
478
479 if( !rc )
480 {
481 //Cookie == 0 or it is a valid cookie
482 host_network_config += "ipaddress="+std::string(ipAddress)+",prefix="+
483 std::string(prefix)+",gateway="+std::string(gateway)+
484 ",mac="+std::string(mac)+",addr_type="+std::string(dhcp);
485
486 printf ("Network configuration changed: %s\n",host_network_config.c_str());
487
488 rc = dbus_set_property("network_config",host_network_config.c_str());
489
490 if ( rc < 0 ) {
491 fprintf(stderr, "Dbus set property(network_config)\
492 failed for set_sys_boot_options.\n");
493 rc = -1;
494 }
495
496 }
497 return rc;
498}
499
Adriana Kobylak40814c62015-10-27 15:58:44 -0500500ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
501 ipmi_request_t request, ipmi_response_t response,
502 ipmi_data_len_t data_len, ipmi_context_t context)
503{
504 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
505 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800506 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500507 *data_len = 0;
508 return rc;
509}
510
Nan Li8d15fb42016-08-16 22:29:40 +0800511ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
512 ipmi_request_t request, ipmi_response_t response,
513 ipmi_data_len_t data_len, ipmi_context_t context)
514{
515 // sd_bus error
516 ipmi_ret_t rc = IPMI_CC_OK;
517
518 ipmi_chassis_cap_t chassis_cap{};
519
520 *data_len = sizeof(ipmi_chassis_cap_t);
521
522 // TODO: need future work. Get those flag from MRW.
523
524 // capabilities flags
525 // [7..4] - reserved
526 // [3] – 1b = provides power interlock (IPM 1.5)
527 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
528 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
529 // to lock out external power control and reset button or front panel interfaces
530 // and/or detect tampering with those interfaces).
531 // [0] -1b = Chassis provides intrusion (physical security) sensor.
532 // set to default value 0x0.
533 chassis_cap.cap_flags = 0x0;
534
535 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
536 // The 20h was given as those 5 device addresses.
537 // Chassis FRU info Device Address
538 chassis_cap.fru_info_dev_addr = 0x20;
539
540 // Chassis SDR Device Address
541 chassis_cap.sdr_dev_addr = 0x20;
542
543 // Chassis SEL Device Address
544 chassis_cap.sel_dev_addr = 0x20;
545
546 // Chassis System Management Device Address
547 chassis_cap.system_management_dev_addr = 0x20;
548
549 // Chassis Bridge Device Address.
550 chassis_cap.bridge_dev_addr = 0x20;
551
552 memcpy(response, &chassis_cap, *data_len);
553
554 return rc;
555}
556
vishwa36993272015-11-20 12:43:49 -0600557//------------------------------------------------------------
558// Calls into Chassis Control Dbus object to do the power off
559//------------------------------------------------------------
Chris Austen7888c4d2015-12-03 15:26:20 -0600560int ipmi_chassis_power_control(const char *method)
vishwa36993272015-11-20 12:43:49 -0600561{
562 // sd_bus error
563 int rc = 0;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500564 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600565
Sergey Solomineb9b8142016-08-23 09:07:28 -0500566 // SD Bus error report mechanism.
567 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600568
569 // Response from the call. Although there is no response for this call,
570 // obligated to mention this to make compiler happy.
571 sd_bus_message *response = NULL;
572
573 // Gets a hook onto either a SYSTEM or SESSION bus
574 sd_bus *bus_type = ipmid_get_sd_bus_connection();
Sergey Solomineb9b8142016-08-23 09:07:28 -0500575 rc = mapper_get_service(bus_type, chassis_object_name, &busname);
576 if (rc < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400577 fprintf(stderr, "Failed to get %s bus name: %s\n",
578 chassis_object_name, strerror(-rc));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500579 goto finish;
580 }
vishwa36993272015-11-20 12:43:49 -0600581 rc = sd_bus_call_method(bus_type, // On the System Bus
Sergey Solomineb9b8142016-08-23 09:07:28 -0500582 busname, // Service to contact
vishwa36993272015-11-20 12:43:49 -0600583 chassis_object_name, // Object path
584 chassis_intf_name, // Interface name
Chris Austen7888c4d2015-12-03 15:26:20 -0600585 method, // Method to be called
vishwa36993272015-11-20 12:43:49 -0600586 &bus_error, // object to return error
587 &response, // Response buffer if any
588 NULL); // No input arguments
589 if(rc < 0)
590 {
591 fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message);
592 }
593 else
594 {
595 printf("Chassis Power Off initiated successfully\n");
596 }
597
Sergey Solomineb9b8142016-08-23 09:07:28 -0500598finish:
vishwa36993272015-11-20 12:43:49 -0600599 sd_bus_error_free(&bus_error);
600 sd_bus_message_unref(response);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500601 free(busname);
vishwa36993272015-11-20 12:43:49 -0600602
Sergey Solomineb9b8142016-08-23 09:07:28 -0500603 return rc;
vishwa36993272015-11-20 12:43:49 -0600604}
605
Chris Austen7888c4d2015-12-03 15:26:20 -0600606
vishwa36993272015-11-20 12:43:49 -0600607//----------------------------------------------------------------------
608// Chassis Control commands
609//----------------------------------------------------------------------
610ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
611 ipmi_request_t request, ipmi_response_t response,
612 ipmi_data_len_t data_len, ipmi_context_t context)
613{
614 // Error from power off.
615 int rc = 0;
616
617 // No response for this command.
618 *data_len = 0;
619
620 // Catch the actual operaton by peeking into request buffer
621 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
622 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
623
624 switch(chassis_ctrl_cmd)
625 {
626 case CMD_POWER_OFF:
Chris Austen7888c4d2015-12-03 15:26:20 -0600627 rc = ipmi_chassis_power_control("powerOff");
vishwa36993272015-11-20 12:43:49 -0600628 break;
Chris Austen7888c4d2015-12-03 15:26:20 -0600629 case CMD_HARD_RESET:
630 rc = ipmi_chassis_power_control("reboot");
631 break;
vishwa36993272015-11-20 12:43:49 -0600632 default:
633 {
634 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
635 rc = -1;
636 }
637 }
638
639 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
640}
641
shgoupfd84fbbf2015-12-17 10:05:51 +0800642struct bootOptionTypeMap_t {
643 uint8_t ipmibootflag;
644 char dbusname[8];
645};
646
647#define INVALID_STRING "Invalid"
648// dbus supports this list of boot devices.
649bootOptionTypeMap_t g_bootOptionTypeMap_t[] = {
650
651 {0x01, "Network"},
652 {0x02, "Disk"},
653 {0x03, "Safe"},
654 {0x05, "CDROM"},
655 {0x06, "Setup"},
656 {0x00, "Default"},
657 {0xFF, INVALID_STRING}
658};
659
660uint8_t get_ipmi_boot_option(char *p) {
661
662 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
663
664 while (s->ipmibootflag != 0xFF) {
665 if (!strcmp(s->dbusname,p))
666 break;
667 s++;
668 }
669
670 if (!s->ipmibootflag)
671 printf("Failed to find Sensor Type %s\n", p);
672
673 return s->ipmibootflag;
674}
675
676char* get_boot_option_by_ipmi(uint8_t p) {
677
678 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
679
680 while (s->ipmibootflag != 0xFF) {
681
682 if (s->ipmibootflag == p)
683 break;
684
685 s++;
686 }
687
688
689 if (!s->ipmibootflag)
690 printf("Failed to find Sensor Type 0x%x\n", p);
691
692 return s->dbusname;
693}
694
Adriana Kobylak40814c62015-10-27 15:58:44 -0500695ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
696 ipmi_request_t request, ipmi_response_t response,
697 ipmi_data_len_t data_len, ipmi_context_t context)
698{
shgoupfd84fbbf2015-12-17 10:05:51 +0800699 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
700 char *p = NULL;
701 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
702 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
703 uint8_t s;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500704
705 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
706
shgoupfd84fbbf2015-12-17 10:05:51 +0800707 memset(resp,0,sizeof(*resp));
708 resp->version = SET_PARM_VERSION;
709 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -0500710 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500711
Adriana Kobylak40814c62015-10-27 15:58:44 -0500712
shgoupfd84fbbf2015-12-17 10:05:51 +0800713 /*
714 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
715 * This is the only parameter used by petitboot.
716 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500717 if ( reqptr->parameter == static_cast<uint8_t>
718 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800719
Ratan Guptafd28dd72016-08-01 04:58:01 -0500720 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
ratagupta6f6bff2016-04-04 06:20:11 -0500721 /* Get the boot device */
722 int r = dbus_get_property("boot_flags",&p);
shgoupfd84fbbf2015-12-17 10:05:51 +0800723
724 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500725 fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800726 rc = IPMI_CC_UNSPECIFIED_ERROR;
727
728 } else {
729
730 s = get_ipmi_boot_option(p);
731 resp->data[1] = (s << 2);
732 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -0500733
shgoupfd84fbbf2015-12-17 10:05:51 +0800734 }
735
ratagupta6f6bff2016-04-04 06:20:11 -0500736 if (p)
737 {
738 free(p);
739 p = NULL;
740 }
741
742 /* Get the boot policy */
743 r = dbus_get_property("boot_policy",&p);
744
745 if (r < 0) {
746 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
747 rc = IPMI_CC_UNSPECIFIED_ERROR;
748
749 } else {
750
Ratan Guptafd28dd72016-08-01 04:58:01 -0500751 printf("BootPolicy is[%s]", p);
ratagupta6f6bff2016-04-04 06:20:11 -0500752 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
753 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
754 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
755 rc = IPMI_CC_OK;
756
757 }
758
759
Ratan Guptafd28dd72016-08-01 04:58:01 -0500760 } else if ( reqptr->parameter == static_cast<uint8_t>
761 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
762
763 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
764
765 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
766
767 int ret = getHostNetworkData(resp);
768
769 if (ret < 0) {
770
771 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
772 rc = IPMI_CC_UNSPECIFIED_ERROR;
773
774 }else
775 rc = IPMI_CC_OK;
776 }
777
778 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -0500779 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +0800780 }
781
782 if (p)
783 free(p);
784
Ratan Guptafd28dd72016-08-01 04:58:01 -0500785 if (rc == IPMI_CC_OK)
786 {
787 *data_len += 2;
788 }
789
shgoupfd84fbbf2015-12-17 10:05:51 +0800790 return rc;
791}
792
793
794
795ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
796 ipmi_request_t request, ipmi_response_t response,
797 ipmi_data_len_t data_len, ipmi_context_t context)
798{
799 ipmi_ret_t rc = IPMI_CC_OK;
800 char *s;
shgoupfd84fbbf2015-12-17 10:05:51 +0800801 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
802
Ratan Guptafd28dd72016-08-01 04:58:01 -0500803 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
804
shgoupfd84fbbf2015-12-17 10:05:51 +0800805 // This IPMI command does not have any resposne data
806 *data_len = 0;
807
808 /* 000101
809 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
810 * This is the only parameter used by petitboot.
811 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500812
813 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800814
815 s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
816
817 printf("%d: %s\n", __LINE__, s);
818 if (!strcmp(s,INVALID_STRING)) {
819
820 rc = IPMI_CC_PARM_NOT_SUPPORTED;
821
822 } else {
823
ratagupta6f6bff2016-04-04 06:20:11 -0500824 int r = dbus_set_property("boot_flags",s);
shgoupfd84fbbf2015-12-17 10:05:51 +0800825
826 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500827 fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800828 rc = IPMI_CC_UNSPECIFIED_ERROR;
829 }
830 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500831
ratagupta6f6bff2016-04-04 06:20:11 -0500832 /* setting the boot policy */
833 s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
Ratan Guptafd28dd72016-08-01 04:58:01 -0500834 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -0500835
Ratan Guptafd28dd72016-08-01 04:58:01 -0500836 printf ( "\nBoot Policy is %s",s);
ratagupta6f6bff2016-04-04 06:20:11 -0500837 int r = dbus_set_property("boot_policy",s);
838
839 if (r < 0) {
840 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
841 rc = IPMI_CC_UNSPECIFIED_ERROR;
842 }
shgoupfd84fbbf2015-12-17 10:05:51 +0800843
Ratan Guptafd28dd72016-08-01 04:58:01 -0500844 } else if (reqptr->parameter ==
845 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
846
847 int ret = setHostNetworkData(reqptr);
848 if (ret < 0) {
849 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
850 rc = IPMI_CC_UNSPECIFIED_ERROR;
851 }
852 }
853 else {
shgoupfd84fbbf2015-12-17 10:05:51 +0800854 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
855 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500856 }
857
858 return rc;
859}
860
861void register_netfn_chassis_functions()
862{
863 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
864 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard);
865
Nan Li8d15fb42016-08-16 22:29:40 +0800866 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
867 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap);
868
Adriana Kobylak40814c62015-10-27 15:58:44 -0500869 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
870 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_get_sys_boot_options);
Adriana Kobylak40814c62015-10-27 15:58:44 -0500871
vishwa36993272015-11-20 12:43:49 -0600872 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
873 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control);
shgoupfd84fbbf2015-12-17 10:05:51 +0800874
875 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
876 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_set_sys_boot_options);
vishwa36993272015-11-20 12:43:49 -0600877}
shgoupfd84fbbf2015-12-17 10:05:51 +0800878