blob: 0b503c7720568565097ce4200ea78647940168a6 [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) {
Sergey Solomineb9b8142016-08-23 09:07:28 -050082 fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +080083 goto finish;
84 }
85
shgoupfd84fbbf2015-12-17 10:05:51 +080086 /*
87 * Bus, service, object path, interface and method are provided to call
88 * the method.
89 * Signatures and input arguments are provided by the arguments at the
90 * end.
91 */
92 r = sd_bus_call_method(bus,
93 connection, /* service to contact */
94 settings_object_name, /* object path */
95 settings_intf_name, /* interface name */
96 "Get", /* method name */
97 &error, /* object to return error in */
98 &m, /* return message on success */
99 "ss", /* input signature */
100 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500101 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800102
103 if (r < 0) {
104 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
105 goto finish;
106 }
107
108 /*
109 * The output should be parsed exactly the same as the output formatting
110 * specified.
111 */
112 r = sd_bus_message_read(m, "v", "s", &temp_buf);
113 if (r < 0) {
114 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
115 goto finish;
116 }
117
118 asprintf(buf, "%s", temp_buf);
119/* *buf = (char*) malloc(strlen(temp_buf));
120 if (*buf) {
121 strcpy(*buf, temp_buf);
122 }
123*/
124 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
125
126finish:
127 sd_bus_error_free(&error);
128 sd_bus_message_unref(m);
129 free(connection);
130
131 return r;
132}
133
ratagupta6f6bff2016-04-04 06:20:11 -0500134int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800135{
136 sd_bus_error error = SD_BUS_ERROR_NULL;
137 sd_bus_message *m = NULL;
138 sd_bus *bus = NULL;
139 char *connection = NULL;
140 int r;
141
Brad Bishop35518682016-07-22 08:35:41 -0400142 // Get the system bus where most system services are provided.
143 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800144
Brad Bishop35518682016-07-22 08:35:41 -0400145 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800146 if (r < 0) {
Sergey Solomineb9b8142016-08-23 09:07:28 -0500147 fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800148 goto finish;
149 }
150
shgoupfd84fbbf2015-12-17 10:05:51 +0800151 /*
152 * Bus, service, object path, interface and method are provided to call
153 * the method.
154 * Signatures and input arguments are provided by the arguments at the
155 * end.
156 */
157 r = sd_bus_call_method(bus,
158 connection, /* service to contact */
159 settings_object_name, /* object path */
160 settings_intf_name, /* interface name */
161 "Set", /* method name */
162 &error, /* object to return error in */
163 &m, /* return message on success */
164 "ssv", /* input signature */
165 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500166 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800167 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500168 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800169
170 if (r < 0) {
171 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
172 goto finish;
173 }
174
ratagupta6f6bff2016-04-04 06:20:11 -0500175 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800176
177finish:
178 sd_bus_error_free(&error);
179 sd_bus_message_unref(m);
180 free(connection);
181
182 return r;
183}
184
Adriana Kobylak40814c62015-10-27 15:58:44 -0500185struct get_sys_boot_options_t {
186 uint8_t parameter;
187 uint8_t set;
188 uint8_t block;
189} __attribute__ ((packed));
190
shgoupfd84fbbf2015-12-17 10:05:51 +0800191struct get_sys_boot_options_response_t {
192 uint8_t version;
193 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500194 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800195} __attribute__ ((packed));
196
197struct set_sys_boot_options_t {
198 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500199 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800200} __attribute__ ((packed));
201
Ratan Guptafd28dd72016-08-01 04:58:01 -0500202struct host_network_config_t {
203 std::string ipaddress;
204 std::string prefix;
205 std::string gateway;
206 std::string macaddress;
207 std::string addrType;
208
209 host_network_config_t()=default;
210};
211
212void fillNetworkConfig( host_network_config_t & host_config ,
213 const std::string& conf_str ) {
214
215 constexpr auto COMMA_DELIMITER = ",";
216 constexpr auto EQUAL_DELIMITER = "=";
217 size_t commaDelimtrPos = 0;
218 size_t equalDelimtrPos = 0,commaDelimtrPrevPos = 0;
219 std::string value;
220 while ( commaDelimtrPos < conf_str.length() ) {
221
222 commaDelimtrPos = conf_str.find(COMMA_DELIMITER,commaDelimtrPos);
223 //This condition is to extract the last
224 //Substring as we will not be having the delimeter
225 //at end. std::string::npos is -1
226
227 if ( commaDelimtrPos == std::string::npos ) {
228 commaDelimtrPos = conf_str.length();
229 }
230
231 equalDelimtrPos = conf_str.find (EQUAL_DELIMITER,commaDelimtrPrevPos);
232
233 //foo,ipaddress=1234
234 if ( equalDelimtrPos == std::string::npos ) {
235
236 commaDelimtrPos++;
237 commaDelimtrPrevPos= commaDelimtrPos;
238 continue;
239 }
240
241 value = conf_str.substr((equalDelimtrPos+1),
242 commaDelimtrPos-(equalDelimtrPos+1));
243
244#ifdef _IPMI_DEBUG_
245 printf ("Name=[%s],Value=[%s],commaDelimtrPos=[%d],\
246 commaDelimtrPrevPos=[%d],equalDelimtrPos=[%d]\n",
247 name.c_str(),value.c_str(),commaDelimtrPos,
248 commaDelimtrPrevPos,equalDelimtrPos);
249#endif
250
251 if ( 0 == conf_str.compare(commaDelimtrPrevPos,
252 equalDelimtrPos-commaDelimtrPrevPos,"ipaddress" )) {
253
254 host_config.ipaddress = std::move(value);
255 }
256 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
257 equalDelimtrPos-commaDelimtrPrevPos,"prefix" )) {
258
259 host_config.prefix = std::move(value);
260 }
261 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
262 equalDelimtrPos-commaDelimtrPrevPos, "gateway" )) {
263 host_config.gateway = std::move(value);
264 }
265 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
266 equalDelimtrPos-commaDelimtrPrevPos, "mac" )) {
267 host_config.macaddress = std::move(value);
268 }
269 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
270 equalDelimtrPos-commaDelimtrPrevPos, "addr_type" )) {
271 host_config.addrType = std::move(value);
272 }
273
274 commaDelimtrPos++;
275 commaDelimtrPrevPos= commaDelimtrPos;
276 }
277}
278
279int getHostNetworkData(get_sys_boot_options_response_t* respptr)
280{
281
282 char *prop = nullptr;
283 int rc = dbus_get_property("network_config",&prop);
284
285 if ( rc < 0 ) {
286 fprintf(stderr, "Dbus get property(boot_flags) failed\
287 for get_sys_boot_options.\n");
288 return rc;
289 }
290
291 std::string conf_str(prop);
292
293 if ( prop ) {
294
295 free(prop);
296 prop = nullptr;
297 }
298
299 /* network_config property Value would be in the form of
300 * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
301 */
302
303 /* Parsing the string and fill the hostconfig structure with the
304 * values */
305
306 printf ("Configuration String[%s]\n ",conf_str.c_str());
307
308 host_network_config_t host_config;
309
310 // Fill the host_config from the configuration string
311 fillNetworkConfig(host_config,conf_str);
312
313 //Assigning the index as intialByteLength as it is fixed and prefilled.
314 printf ("host_config.macaddress.c_str()=[%s]\n",host_config.macaddress.c_str());
315 do{
316
317 rc = sscanf(host_config.macaddress.c_str(),MAC_ADDRESS_FORMAT,
318 (respptr->data+MAC_OFFSET), (respptr->data+MAC_OFFSET+1),
319 (respptr->data+MAC_OFFSET+2),(respptr->data+MAC_OFFSET+3),
320 (respptr->data+MAC_OFFSET+4), (respptr->data+MAC_OFFSET+5));
321
322
323 if ( rc < 6 ){
324 fprintf(stderr, "sscanf Failed in extracting mac address.\n");
325 rc = -1;
326 break;
327 }
328
329 //Conevrt the dhcp,ipaddress,mask and gateway as hex number
330 respptr->data[MAC_OFFSET+6]=0x00;
331
332 rc = sscanf(host_config.addrType.c_str(),ADDR_TYPE_FORMAT,
333 (respptr->data+ADDRTYPE_OFFSET));
334
335 if ( rc <= 0 ) {
336 fprintf(stderr, "sscanf Failed in extracting address type.\n");
337 rc = -1;
338 break;
339 }
340
341 //ipaddress and gateway would be in IPv4 format
342 rc = inet_pton(AF_INET,host_config.ipaddress.c_str(),
343 (respptr->data+IPADDR_OFFSET));
344
345 if ( rc <= 0 ) {
346 fprintf(stderr, "inet_pton failed during ipaddress coneversion\n");
347 rc = -1;
348 break;
349 }
350
351 rc = sscanf(host_config.prefix.c_str(),PREFIX_FORMAT,
352 (respptr->data+PREFIX_OFFSET));
353
354 if ( rc <= 0 ) {
355 fprintf(stderr, "sscanf failed during prefix extraction.\n");
356 rc = -1;
357 break;
358 }
359
360 rc = inet_pton(AF_INET,host_config.gateway.c_str(),
361 (respptr->data+GATEWAY_OFFSET));
362
363 if ( rc <= 0 ) {
364 fprintf(stderr, "inet_pton failed during gateway conversion.\n");
365 rc = -1;
366 break;
367 }
368
369 }while (0);
370
371 if ( rc ) {
372
373 //PetiBoot-Specific
374 //If sucess then copy the first 9 bytes to the data
375 //else set the respptr to 0
376
377 memcpy(respptr->data,net_conf_initial_bytes,
378 sizeof(net_conf_initial_bytes));
379
380#ifdef _IPMI_DEBUG_
381 printf ("\n===Printing the IPMI Formatted Data========\n");
382
383 for ( uint8_t pos = 0; pos<index; pos++ )
384 printf("%02x ", respptr->data[pos]);
385#endif
386
387 }else {
388
389 memset(respptr->data,0,SIZE_BOOT_OPTION);
390 }
391
392 return rc;
393}
394
395int setHostNetworkData(set_sys_boot_options_t * reqptr)
396{
397 std::string host_network_config;
398 char mac[SIZE_MAC] = {0};
399 char ipAddress[INET_ADDRSTRLEN] = {0};
400 char gateway[INET_ADDRSTRLEN] = {0};
401 char dhcp[SIZE_PREFIX] = {0};
402 char prefix[SIZE_PREFIX] = {0};
403 int rc = 0;
404 uint32_t zeroCookie=0;
405
406 //cookie starts from second byte
407 // version starts from sixth byte
408
409 do {
410
411 // cookie == 0x21 0x70 0x62 0x21
412 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
413 (net_conf_initial_bytes+COOKIE_OFFSET),
414 SIZE_COOKIE) != 0 ) {
415 //cookie == 0
416 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
417 &zeroCookie,
418 SIZE_COOKIE) == 0 ) {
419 rc = 0;
420 break;
421 }
422 //Invalid cookie
423 fprintf(stderr, "Invalid Cookie\n");
424 rc = -1;
425 break;
426 }
427 // vesion == 0x00 0x01
428 if ( memcmp(&(reqptr->data[VERSION_OFFSET]),
429 (net_conf_initial_bytes+VERSION_OFFSET),
430 SIZE_VERSION) != 0 ) {
431
432 fprintf(stderr, "Invalid Version\n");
433 rc = -1;
434 break;
435 }
436
437 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
438 reqptr->data[MAC_OFFSET],
439 reqptr->data[MAC_OFFSET+1],
440 reqptr->data[MAC_OFFSET+2],
441 reqptr->data[MAC_OFFSET+3],
442 reqptr->data[MAC_OFFSET+4],
443 reqptr->data[MAC_OFFSET+5]);
444
445 snprintf(dhcp,SIZE_PREFIX, ADDR_TYPE_FORMAT, reqptr->data[ADDRTYPE_OFFSET]);
446 //Validating the address type which could be
447 //either static or dynamic
448 if( *(reqptr->data+ADDRTYPE_OFFSET) > 1 ) {
449
450 fprintf(stderr, "Invalid Address Type\n");
451 rc = -1;
452 break;
453
454 }
455
456 snprintf(ipAddress, INET_ADDRSTRLEN, IP_ADDRESS_FORMAT,
457 reqptr->data[IPADDR_OFFSET], reqptr->data[IPADDR_OFFSET+1],
458 reqptr->data[IPADDR_OFFSET+2], reqptr->data[IPADDR_OFFSET+3]);
459
460 //validating prefix
461 if ( *(reqptr->data+PREFIX_OFFSET) > (uint8_t)MAX_PREFIX_VALUE ) {
462
463 fprintf(stderr, "Invalid Prefix\n");
464 rc = -1;
465 break;
466 }
467
468 snprintf(prefix,SIZE_PREFIX,PREFIX_FORMAT, reqptr->data[PREFIX_OFFSET]);
469
470 snprintf(gateway, INET_ADDRSTRLEN,IP_ADDRESS_FORMAT,
471 reqptr->data[GATEWAY_OFFSET], reqptr->data[GATEWAY_OFFSET+1],
472 reqptr->data[GATEWAY_OFFSET+2], reqptr->data[GATEWAY_OFFSET+3]);
473
474
475 }while(0);
476
477 if( !rc )
478 {
479 //Cookie == 0 or it is a valid cookie
480 host_network_config += "ipaddress="+std::string(ipAddress)+",prefix="+
481 std::string(prefix)+",gateway="+std::string(gateway)+
482 ",mac="+std::string(mac)+",addr_type="+std::string(dhcp);
483
484 printf ("Network configuration changed: %s\n",host_network_config.c_str());
485
486 rc = dbus_set_property("network_config",host_network_config.c_str());
487
488 if ( rc < 0 ) {
489 fprintf(stderr, "Dbus set property(network_config)\
490 failed for set_sys_boot_options.\n");
491 rc = -1;
492 }
493
494 }
495 return rc;
496}
497
Adriana Kobylak40814c62015-10-27 15:58:44 -0500498ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
499 ipmi_request_t request, ipmi_response_t response,
500 ipmi_data_len_t data_len, ipmi_context_t context)
501{
502 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
503 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800504 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500505 *data_len = 0;
506 return rc;
507}
508
Nan Li8d15fb42016-08-16 22:29:40 +0800509ipmi_ret_t ipmi_get_chassis_cap(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
510 ipmi_request_t request, ipmi_response_t response,
511 ipmi_data_len_t data_len, ipmi_context_t context)
512{
513 // sd_bus error
514 ipmi_ret_t rc = IPMI_CC_OK;
515
516 ipmi_chassis_cap_t chassis_cap{};
517
518 *data_len = sizeof(ipmi_chassis_cap_t);
519
520 // TODO: need future work. Get those flag from MRW.
521
522 // capabilities flags
523 // [7..4] - reserved
524 // [3] – 1b = provides power interlock (IPM 1.5)
525 // [2] – 1b = provides Diagnostic Interrupt (FP NMI)
526 // [1] – 1b = provides “Front Panel Lockout” (indicates that the chassis has capabilities
527 // to lock out external power control and reset button or front panel interfaces
528 // and/or detect tampering with those interfaces).
529 // [0] -1b = Chassis provides intrusion (physical security) sensor.
530 // set to default value 0x0.
531 chassis_cap.cap_flags = 0x0;
532
533 // Since we do not have a separate SDR Device/SEL Device/ FRU repository.
534 // The 20h was given as those 5 device addresses.
535 // Chassis FRU info Device Address
536 chassis_cap.fru_info_dev_addr = 0x20;
537
538 // Chassis SDR Device Address
539 chassis_cap.sdr_dev_addr = 0x20;
540
541 // Chassis SEL Device Address
542 chassis_cap.sel_dev_addr = 0x20;
543
544 // Chassis System Management Device Address
545 chassis_cap.system_management_dev_addr = 0x20;
546
547 // Chassis Bridge Device Address.
548 chassis_cap.bridge_dev_addr = 0x20;
549
550 memcpy(response, &chassis_cap, *data_len);
551
552 return rc;
553}
554
vishwa36993272015-11-20 12:43:49 -0600555//------------------------------------------------------------
556// Calls into Chassis Control Dbus object to do the power off
557//------------------------------------------------------------
Chris Austen7888c4d2015-12-03 15:26:20 -0600558int ipmi_chassis_power_control(const char *method)
vishwa36993272015-11-20 12:43:49 -0600559{
560 // sd_bus error
561 int rc = 0;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500562 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600563
Sergey Solomineb9b8142016-08-23 09:07:28 -0500564 // SD Bus error report mechanism.
565 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600566
567 // Response from the call. Although there is no response for this call,
568 // obligated to mention this to make compiler happy.
569 sd_bus_message *response = NULL;
570
571 // Gets a hook onto either a SYSTEM or SESSION bus
572 sd_bus *bus_type = ipmid_get_sd_bus_connection();
Sergey Solomineb9b8142016-08-23 09:07:28 -0500573 rc = mapper_get_service(bus_type, chassis_object_name, &busname);
574 if (rc < 0) {
575 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-rc));
576 goto finish;
577 }
vishwa36993272015-11-20 12:43:49 -0600578 rc = sd_bus_call_method(bus_type, // On the System Bus
Sergey Solomineb9b8142016-08-23 09:07:28 -0500579 busname, // Service to contact
vishwa36993272015-11-20 12:43:49 -0600580 chassis_object_name, // Object path
581 chassis_intf_name, // Interface name
Chris Austen7888c4d2015-12-03 15:26:20 -0600582 method, // Method to be called
vishwa36993272015-11-20 12:43:49 -0600583 &bus_error, // object to return error
584 &response, // Response buffer if any
585 NULL); // No input arguments
586 if(rc < 0)
587 {
588 fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message);
589 }
590 else
591 {
592 printf("Chassis Power Off initiated successfully\n");
593 }
594
Sergey Solomineb9b8142016-08-23 09:07:28 -0500595finish:
vishwa36993272015-11-20 12:43:49 -0600596 sd_bus_error_free(&bus_error);
597 sd_bus_message_unref(response);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500598 free(busname);
vishwa36993272015-11-20 12:43:49 -0600599
Sergey Solomineb9b8142016-08-23 09:07:28 -0500600 return rc;
vishwa36993272015-11-20 12:43:49 -0600601}
602
Chris Austen7888c4d2015-12-03 15:26:20 -0600603
vishwa36993272015-11-20 12:43:49 -0600604//----------------------------------------------------------------------
605// Chassis Control commands
606//----------------------------------------------------------------------
607ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
608 ipmi_request_t request, ipmi_response_t response,
609 ipmi_data_len_t data_len, ipmi_context_t context)
610{
611 // Error from power off.
612 int rc = 0;
613
614 // No response for this command.
615 *data_len = 0;
616
617 // Catch the actual operaton by peeking into request buffer
618 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
619 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
620
621 switch(chassis_ctrl_cmd)
622 {
623 case CMD_POWER_OFF:
Chris Austen7888c4d2015-12-03 15:26:20 -0600624 rc = ipmi_chassis_power_control("powerOff");
vishwa36993272015-11-20 12:43:49 -0600625 break;
Chris Austen7888c4d2015-12-03 15:26:20 -0600626 case CMD_HARD_RESET:
627 rc = ipmi_chassis_power_control("reboot");
628 break;
vishwa36993272015-11-20 12:43:49 -0600629 default:
630 {
631 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
632 rc = -1;
633 }
634 }
635
636 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
637}
638
shgoupfd84fbbf2015-12-17 10:05:51 +0800639struct bootOptionTypeMap_t {
640 uint8_t ipmibootflag;
641 char dbusname[8];
642};
643
644#define INVALID_STRING "Invalid"
645// dbus supports this list of boot devices.
646bootOptionTypeMap_t g_bootOptionTypeMap_t[] = {
647
648 {0x01, "Network"},
649 {0x02, "Disk"},
650 {0x03, "Safe"},
651 {0x05, "CDROM"},
652 {0x06, "Setup"},
653 {0x00, "Default"},
654 {0xFF, INVALID_STRING}
655};
656
657uint8_t get_ipmi_boot_option(char *p) {
658
659 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
660
661 while (s->ipmibootflag != 0xFF) {
662 if (!strcmp(s->dbusname,p))
663 break;
664 s++;
665 }
666
667 if (!s->ipmibootflag)
668 printf("Failed to find Sensor Type %s\n", p);
669
670 return s->ipmibootflag;
671}
672
673char* get_boot_option_by_ipmi(uint8_t p) {
674
675 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
676
677 while (s->ipmibootflag != 0xFF) {
678
679 if (s->ipmibootflag == p)
680 break;
681
682 s++;
683 }
684
685
686 if (!s->ipmibootflag)
687 printf("Failed to find Sensor Type 0x%x\n", p);
688
689 return s->dbusname;
690}
691
Adriana Kobylak40814c62015-10-27 15:58:44 -0500692ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
693 ipmi_request_t request, ipmi_response_t response,
694 ipmi_data_len_t data_len, ipmi_context_t context)
695{
shgoupfd84fbbf2015-12-17 10:05:51 +0800696 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
697 char *p = NULL;
698 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
699 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
700 uint8_t s;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500701
702 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
703
shgoupfd84fbbf2015-12-17 10:05:51 +0800704 memset(resp,0,sizeof(*resp));
705 resp->version = SET_PARM_VERSION;
706 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -0500707 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500708
Adriana Kobylak40814c62015-10-27 15:58:44 -0500709
shgoupfd84fbbf2015-12-17 10:05:51 +0800710 /*
711 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
712 * This is the only parameter used by petitboot.
713 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500714 if ( reqptr->parameter == static_cast<uint8_t>
715 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800716
Ratan Guptafd28dd72016-08-01 04:58:01 -0500717 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
ratagupta6f6bff2016-04-04 06:20:11 -0500718 /* Get the boot device */
719 int r = dbus_get_property("boot_flags",&p);
shgoupfd84fbbf2015-12-17 10:05:51 +0800720
721 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500722 fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800723 rc = IPMI_CC_UNSPECIFIED_ERROR;
724
725 } else {
726
727 s = get_ipmi_boot_option(p);
728 resp->data[1] = (s << 2);
729 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -0500730
shgoupfd84fbbf2015-12-17 10:05:51 +0800731 }
732
ratagupta6f6bff2016-04-04 06:20:11 -0500733 if (p)
734 {
735 free(p);
736 p = NULL;
737 }
738
739 /* Get the boot policy */
740 r = dbus_get_property("boot_policy",&p);
741
742 if (r < 0) {
743 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
744 rc = IPMI_CC_UNSPECIFIED_ERROR;
745
746 } else {
747
Ratan Guptafd28dd72016-08-01 04:58:01 -0500748 printf("BootPolicy is[%s]", p);
ratagupta6f6bff2016-04-04 06:20:11 -0500749 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
750 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
751 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
752 rc = IPMI_CC_OK;
753
754 }
755
756
Ratan Guptafd28dd72016-08-01 04:58:01 -0500757 } else if ( reqptr->parameter == static_cast<uint8_t>
758 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
759
760 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
761
762 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
763
764 int ret = getHostNetworkData(resp);
765
766 if (ret < 0) {
767
768 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
769 rc = IPMI_CC_UNSPECIFIED_ERROR;
770
771 }else
772 rc = IPMI_CC_OK;
773 }
774
775 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -0500776 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +0800777 }
778
779 if (p)
780 free(p);
781
Ratan Guptafd28dd72016-08-01 04:58:01 -0500782 if (rc == IPMI_CC_OK)
783 {
784 *data_len += 2;
785 }
786
shgoupfd84fbbf2015-12-17 10:05:51 +0800787 return rc;
788}
789
790
791
792ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
793 ipmi_request_t request, ipmi_response_t response,
794 ipmi_data_len_t data_len, ipmi_context_t context)
795{
796 ipmi_ret_t rc = IPMI_CC_OK;
797 char *s;
shgoupfd84fbbf2015-12-17 10:05:51 +0800798 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
799
Ratan Guptafd28dd72016-08-01 04:58:01 -0500800 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
801
shgoupfd84fbbf2015-12-17 10:05:51 +0800802 // This IPMI command does not have any resposne data
803 *data_len = 0;
804
805 /* 000101
806 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
807 * This is the only parameter used by petitboot.
808 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500809
810 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800811
812 s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
813
814 printf("%d: %s\n", __LINE__, s);
815 if (!strcmp(s,INVALID_STRING)) {
816
817 rc = IPMI_CC_PARM_NOT_SUPPORTED;
818
819 } else {
820
ratagupta6f6bff2016-04-04 06:20:11 -0500821 int r = dbus_set_property("boot_flags",s);
shgoupfd84fbbf2015-12-17 10:05:51 +0800822
823 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500824 fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800825 rc = IPMI_CC_UNSPECIFIED_ERROR;
826 }
827 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500828
ratagupta6f6bff2016-04-04 06:20:11 -0500829 /* setting the boot policy */
830 s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
Ratan Guptafd28dd72016-08-01 04:58:01 -0500831 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -0500832
Ratan Guptafd28dd72016-08-01 04:58:01 -0500833 printf ( "\nBoot Policy is %s",s);
ratagupta6f6bff2016-04-04 06:20:11 -0500834 int r = dbus_set_property("boot_policy",s);
835
836 if (r < 0) {
837 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
838 rc = IPMI_CC_UNSPECIFIED_ERROR;
839 }
shgoupfd84fbbf2015-12-17 10:05:51 +0800840
Ratan Guptafd28dd72016-08-01 04:58:01 -0500841 } else if (reqptr->parameter ==
842 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
843
844 int ret = setHostNetworkData(reqptr);
845 if (ret < 0) {
846 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
847 rc = IPMI_CC_UNSPECIFIED_ERROR;
848 }
849 }
850 else {
shgoupfd84fbbf2015-12-17 10:05:51 +0800851 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
852 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500853 }
854
855 return rc;
856}
857
858void register_netfn_chassis_functions()
859{
860 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
861 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard);
862
Nan Li8d15fb42016-08-16 22:29:40 +0800863 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP);
864 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_GET_CHASSIS_CAP, NULL, ipmi_get_chassis_cap);
865
Adriana Kobylak40814c62015-10-27 15:58:44 -0500866 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
867 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 -0500868
vishwa36993272015-11-20 12:43:49 -0600869 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
870 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control);
shgoupfd84fbbf2015-12-17 10:05:51 +0800871
872 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
873 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_set_sys_boot_options);
vishwa36993272015-11-20 12:43:49 -0600874}
shgoupfd84fbbf2015-12-17 10:05:51 +0800875