blob: c6753e8b4043e132c009312a9b07d0359a6ec1f1 [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
ratagupta6f6bff2016-04-04 06:20:11 -050058int dbus_get_property(const char *name, char **buf)
shgoupfd84fbbf2015-12-17 10:05:51 +080059{
60 sd_bus_error error = SD_BUS_ERROR_NULL;
61 sd_bus_message *m = NULL;
62 sd_bus *bus = NULL;
63 char *temp_buf = NULL;
64 char *connection = NULL;
65 int r;
66
Brad Bishop35518682016-07-22 08:35:41 -040067 // Get the system bus where most system services are provided.
68 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +080069
Brad Bishop35518682016-07-22 08:35:41 -040070 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +080071 if (r < 0) {
Sergey Solomineb9b8142016-08-23 09:07:28 -050072 fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +080073 goto finish;
74 }
75
shgoupfd84fbbf2015-12-17 10:05:51 +080076 /*
77 * Bus, service, object path, interface and method are provided to call
78 * the method.
79 * Signatures and input arguments are provided by the arguments at the
80 * end.
81 */
82 r = sd_bus_call_method(bus,
83 connection, /* service to contact */
84 settings_object_name, /* object path */
85 settings_intf_name, /* interface name */
86 "Get", /* method name */
87 &error, /* object to return error in */
88 &m, /* return message on success */
89 "ss", /* input signature */
90 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -050091 name); /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +080092
93 if (r < 0) {
94 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
95 goto finish;
96 }
97
98 /*
99 * The output should be parsed exactly the same as the output formatting
100 * specified.
101 */
102 r = sd_bus_message_read(m, "v", "s", &temp_buf);
103 if (r < 0) {
104 fprintf(stderr, "Failed to parse response message: %s\n", strerror(-r));
105 goto finish;
106 }
107
108 asprintf(buf, "%s", temp_buf);
109/* *buf = (char*) malloc(strlen(temp_buf));
110 if (*buf) {
111 strcpy(*buf, temp_buf);
112 }
113*/
114 printf("IPMID boot option property get: {%s}.\n", (char *) temp_buf);
115
116finish:
117 sd_bus_error_free(&error);
118 sd_bus_message_unref(m);
119 free(connection);
120
121 return r;
122}
123
ratagupta6f6bff2016-04-04 06:20:11 -0500124int dbus_set_property(const char * name, const char *value)
shgoupfd84fbbf2015-12-17 10:05:51 +0800125{
126 sd_bus_error error = SD_BUS_ERROR_NULL;
127 sd_bus_message *m = NULL;
128 sd_bus *bus = NULL;
129 char *connection = NULL;
130 int r;
131
Brad Bishop35518682016-07-22 08:35:41 -0400132 // Get the system bus where most system services are provided.
133 bus = ipmid_get_sd_bus_connection();
shgoupfd84fbbf2015-12-17 10:05:51 +0800134
Brad Bishop35518682016-07-22 08:35:41 -0400135 r = mapper_get_service(bus, settings_object_name, &connection);
shgoupfd84fbbf2015-12-17 10:05:51 +0800136 if (r < 0) {
Sergey Solomineb9b8142016-08-23 09:07:28 -0500137 fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
shgoupfd84fbbf2015-12-17 10:05:51 +0800138 goto finish;
139 }
140
shgoupfd84fbbf2015-12-17 10:05:51 +0800141 /*
142 * Bus, service, object path, interface and method are provided to call
143 * the method.
144 * Signatures and input arguments are provided by the arguments at the
145 * end.
146 */
147 r = sd_bus_call_method(bus,
148 connection, /* service to contact */
149 settings_object_name, /* object path */
150 settings_intf_name, /* interface name */
151 "Set", /* method name */
152 &error, /* object to return error in */
153 &m, /* return message on success */
154 "ssv", /* input signature */
155 host_intf_name, /* first argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500156 name, /* second argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800157 "s", /* third argument */
ratagupta6f6bff2016-04-04 06:20:11 -0500158 value); /* fourth argument */
shgoupfd84fbbf2015-12-17 10:05:51 +0800159
160 if (r < 0) {
161 fprintf(stderr, "Failed to issue method call: %s\n", error.message);
162 goto finish;
163 }
164
ratagupta6f6bff2016-04-04 06:20:11 -0500165 printf("IPMID boot option property set: {%s}.\n", value);
shgoupfd84fbbf2015-12-17 10:05:51 +0800166
167finish:
168 sd_bus_error_free(&error);
169 sd_bus_message_unref(m);
170 free(connection);
171
172 return r;
173}
174
Adriana Kobylak40814c62015-10-27 15:58:44 -0500175struct get_sys_boot_options_t {
176 uint8_t parameter;
177 uint8_t set;
178 uint8_t block;
179} __attribute__ ((packed));
180
shgoupfd84fbbf2015-12-17 10:05:51 +0800181struct get_sys_boot_options_response_t {
182 uint8_t version;
183 uint8_t parm;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500184 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800185} __attribute__ ((packed));
186
187struct set_sys_boot_options_t {
188 uint8_t parameter;
Ratan Guptafd28dd72016-08-01 04:58:01 -0500189 uint8_t data[SIZE_BOOT_OPTION];
shgoupfd84fbbf2015-12-17 10:05:51 +0800190} __attribute__ ((packed));
191
Ratan Guptafd28dd72016-08-01 04:58:01 -0500192struct host_network_config_t {
193 std::string ipaddress;
194 std::string prefix;
195 std::string gateway;
196 std::string macaddress;
197 std::string addrType;
198
199 host_network_config_t()=default;
200};
201
202void fillNetworkConfig( host_network_config_t & host_config ,
203 const std::string& conf_str ) {
204
205 constexpr auto COMMA_DELIMITER = ",";
206 constexpr auto EQUAL_DELIMITER = "=";
207 size_t commaDelimtrPos = 0;
208 size_t equalDelimtrPos = 0,commaDelimtrPrevPos = 0;
209 std::string value;
210 while ( commaDelimtrPos < conf_str.length() ) {
211
212 commaDelimtrPos = conf_str.find(COMMA_DELIMITER,commaDelimtrPos);
213 //This condition is to extract the last
214 //Substring as we will not be having the delimeter
215 //at end. std::string::npos is -1
216
217 if ( commaDelimtrPos == std::string::npos ) {
218 commaDelimtrPos = conf_str.length();
219 }
220
221 equalDelimtrPos = conf_str.find (EQUAL_DELIMITER,commaDelimtrPrevPos);
222
223 //foo,ipaddress=1234
224 if ( equalDelimtrPos == std::string::npos ) {
225
226 commaDelimtrPos++;
227 commaDelimtrPrevPos= commaDelimtrPos;
228 continue;
229 }
230
231 value = conf_str.substr((equalDelimtrPos+1),
232 commaDelimtrPos-(equalDelimtrPos+1));
233
234#ifdef _IPMI_DEBUG_
235 printf ("Name=[%s],Value=[%s],commaDelimtrPos=[%d],\
236 commaDelimtrPrevPos=[%d],equalDelimtrPos=[%d]\n",
237 name.c_str(),value.c_str(),commaDelimtrPos,
238 commaDelimtrPrevPos,equalDelimtrPos);
239#endif
240
241 if ( 0 == conf_str.compare(commaDelimtrPrevPos,
242 equalDelimtrPos-commaDelimtrPrevPos,"ipaddress" )) {
243
244 host_config.ipaddress = std::move(value);
245 }
246 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
247 equalDelimtrPos-commaDelimtrPrevPos,"prefix" )) {
248
249 host_config.prefix = std::move(value);
250 }
251 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
252 equalDelimtrPos-commaDelimtrPrevPos, "gateway" )) {
253 host_config.gateway = std::move(value);
254 }
255 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
256 equalDelimtrPos-commaDelimtrPrevPos, "mac" )) {
257 host_config.macaddress = std::move(value);
258 }
259 else if ( 0 == conf_str.compare(commaDelimtrPrevPos,
260 equalDelimtrPos-commaDelimtrPrevPos, "addr_type" )) {
261 host_config.addrType = std::move(value);
262 }
263
264 commaDelimtrPos++;
265 commaDelimtrPrevPos= commaDelimtrPos;
266 }
267}
268
269int getHostNetworkData(get_sys_boot_options_response_t* respptr)
270{
271
272 char *prop = nullptr;
273 int rc = dbus_get_property("network_config",&prop);
274
275 if ( rc < 0 ) {
276 fprintf(stderr, "Dbus get property(boot_flags) failed\
277 for get_sys_boot_options.\n");
278 return rc;
279 }
280
281 std::string conf_str(prop);
282
283 if ( prop ) {
284
285 free(prop);
286 prop = nullptr;
287 }
288
289 /* network_config property Value would be in the form of
290 * ipaddress=1.1.1.1,prefix=16,gateway=2.2.2.2,mac=11:22:33:44:55:66,dhcp=0
291 */
292
293 /* Parsing the string and fill the hostconfig structure with the
294 * values */
295
296 printf ("Configuration String[%s]\n ",conf_str.c_str());
297
298 host_network_config_t host_config;
299
300 // Fill the host_config from the configuration string
301 fillNetworkConfig(host_config,conf_str);
302
303 //Assigning the index as intialByteLength as it is fixed and prefilled.
304 printf ("host_config.macaddress.c_str()=[%s]\n",host_config.macaddress.c_str());
305 do{
306
307 rc = sscanf(host_config.macaddress.c_str(),MAC_ADDRESS_FORMAT,
308 (respptr->data+MAC_OFFSET), (respptr->data+MAC_OFFSET+1),
309 (respptr->data+MAC_OFFSET+2),(respptr->data+MAC_OFFSET+3),
310 (respptr->data+MAC_OFFSET+4), (respptr->data+MAC_OFFSET+5));
311
312
313 if ( rc < 6 ){
314 fprintf(stderr, "sscanf Failed in extracting mac address.\n");
315 rc = -1;
316 break;
317 }
318
319 //Conevrt the dhcp,ipaddress,mask and gateway as hex number
320 respptr->data[MAC_OFFSET+6]=0x00;
321
322 rc = sscanf(host_config.addrType.c_str(),ADDR_TYPE_FORMAT,
323 (respptr->data+ADDRTYPE_OFFSET));
324
325 if ( rc <= 0 ) {
326 fprintf(stderr, "sscanf Failed in extracting address type.\n");
327 rc = -1;
328 break;
329 }
330
331 //ipaddress and gateway would be in IPv4 format
332 rc = inet_pton(AF_INET,host_config.ipaddress.c_str(),
333 (respptr->data+IPADDR_OFFSET));
334
335 if ( rc <= 0 ) {
336 fprintf(stderr, "inet_pton failed during ipaddress coneversion\n");
337 rc = -1;
338 break;
339 }
340
341 rc = sscanf(host_config.prefix.c_str(),PREFIX_FORMAT,
342 (respptr->data+PREFIX_OFFSET));
343
344 if ( rc <= 0 ) {
345 fprintf(stderr, "sscanf failed during prefix extraction.\n");
346 rc = -1;
347 break;
348 }
349
350 rc = inet_pton(AF_INET,host_config.gateway.c_str(),
351 (respptr->data+GATEWAY_OFFSET));
352
353 if ( rc <= 0 ) {
354 fprintf(stderr, "inet_pton failed during gateway conversion.\n");
355 rc = -1;
356 break;
357 }
358
359 }while (0);
360
361 if ( rc ) {
362
363 //PetiBoot-Specific
364 //If sucess then copy the first 9 bytes to the data
365 //else set the respptr to 0
366
367 memcpy(respptr->data,net_conf_initial_bytes,
368 sizeof(net_conf_initial_bytes));
369
370#ifdef _IPMI_DEBUG_
371 printf ("\n===Printing the IPMI Formatted Data========\n");
372
373 for ( uint8_t pos = 0; pos<index; pos++ )
374 printf("%02x ", respptr->data[pos]);
375#endif
376
377 }else {
378
379 memset(respptr->data,0,SIZE_BOOT_OPTION);
380 }
381
382 return rc;
383}
384
385int setHostNetworkData(set_sys_boot_options_t * reqptr)
386{
387 std::string host_network_config;
388 char mac[SIZE_MAC] = {0};
389 char ipAddress[INET_ADDRSTRLEN] = {0};
390 char gateway[INET_ADDRSTRLEN] = {0};
391 char dhcp[SIZE_PREFIX] = {0};
392 char prefix[SIZE_PREFIX] = {0};
393 int rc = 0;
394 uint32_t zeroCookie=0;
395
396 //cookie starts from second byte
397 // version starts from sixth byte
398
399 do {
400
401 // cookie == 0x21 0x70 0x62 0x21
402 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
403 (net_conf_initial_bytes+COOKIE_OFFSET),
404 SIZE_COOKIE) != 0 ) {
405 //cookie == 0
406 if ( memcmp(&(reqptr->data[COOKIE_OFFSET]),
407 &zeroCookie,
408 SIZE_COOKIE) == 0 ) {
409 rc = 0;
410 break;
411 }
412 //Invalid cookie
413 fprintf(stderr, "Invalid Cookie\n");
414 rc = -1;
415 break;
416 }
417 // vesion == 0x00 0x01
418 if ( memcmp(&(reqptr->data[VERSION_OFFSET]),
419 (net_conf_initial_bytes+VERSION_OFFSET),
420 SIZE_VERSION) != 0 ) {
421
422 fprintf(stderr, "Invalid Version\n");
423 rc = -1;
424 break;
425 }
426
427 snprintf(mac, SIZE_MAC, MAC_ADDRESS_FORMAT,
428 reqptr->data[MAC_OFFSET],
429 reqptr->data[MAC_OFFSET+1],
430 reqptr->data[MAC_OFFSET+2],
431 reqptr->data[MAC_OFFSET+3],
432 reqptr->data[MAC_OFFSET+4],
433 reqptr->data[MAC_OFFSET+5]);
434
435 snprintf(dhcp,SIZE_PREFIX, ADDR_TYPE_FORMAT, reqptr->data[ADDRTYPE_OFFSET]);
436 //Validating the address type which could be
437 //either static or dynamic
438 if( *(reqptr->data+ADDRTYPE_OFFSET) > 1 ) {
439
440 fprintf(stderr, "Invalid Address Type\n");
441 rc = -1;
442 break;
443
444 }
445
446 snprintf(ipAddress, INET_ADDRSTRLEN, IP_ADDRESS_FORMAT,
447 reqptr->data[IPADDR_OFFSET], reqptr->data[IPADDR_OFFSET+1],
448 reqptr->data[IPADDR_OFFSET+2], reqptr->data[IPADDR_OFFSET+3]);
449
450 //validating prefix
451 if ( *(reqptr->data+PREFIX_OFFSET) > (uint8_t)MAX_PREFIX_VALUE ) {
452
453 fprintf(stderr, "Invalid Prefix\n");
454 rc = -1;
455 break;
456 }
457
458 snprintf(prefix,SIZE_PREFIX,PREFIX_FORMAT, reqptr->data[PREFIX_OFFSET]);
459
460 snprintf(gateway, INET_ADDRSTRLEN,IP_ADDRESS_FORMAT,
461 reqptr->data[GATEWAY_OFFSET], reqptr->data[GATEWAY_OFFSET+1],
462 reqptr->data[GATEWAY_OFFSET+2], reqptr->data[GATEWAY_OFFSET+3]);
463
464
465 }while(0);
466
467 if( !rc )
468 {
469 //Cookie == 0 or it is a valid cookie
470 host_network_config += "ipaddress="+std::string(ipAddress)+",prefix="+
471 std::string(prefix)+",gateway="+std::string(gateway)+
472 ",mac="+std::string(mac)+",addr_type="+std::string(dhcp);
473
474 printf ("Network configuration changed: %s\n",host_network_config.c_str());
475
476 rc = dbus_set_property("network_config",host_network_config.c_str());
477
478 if ( rc < 0 ) {
479 fprintf(stderr, "Dbus set property(network_config)\
480 failed for set_sys_boot_options.\n");
481 rc = -1;
482 }
483
484 }
485 return rc;
486}
487
Adriana Kobylak40814c62015-10-27 15:58:44 -0500488ipmi_ret_t ipmi_chassis_wildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
489 ipmi_request_t request, ipmi_response_t response,
490 ipmi_data_len_t data_len, ipmi_context_t context)
491{
492 printf("Handling CHASSIS WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
493 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800494 ipmi_ret_t rc = IPMI_CC_INVALID;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500495 *data_len = 0;
496 return rc;
497}
498
vishwa36993272015-11-20 12:43:49 -0600499//------------------------------------------------------------
500// Calls into Chassis Control Dbus object to do the power off
501//------------------------------------------------------------
Chris Austen7888c4d2015-12-03 15:26:20 -0600502int ipmi_chassis_power_control(const char *method)
vishwa36993272015-11-20 12:43:49 -0600503{
504 // sd_bus error
505 int rc = 0;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500506 char *busname = NULL;
vishwa36993272015-11-20 12:43:49 -0600507
Sergey Solomineb9b8142016-08-23 09:07:28 -0500508 // SD Bus error report mechanism.
509 sd_bus_error bus_error = SD_BUS_ERROR_NULL;
vishwa36993272015-11-20 12:43:49 -0600510
511 // Response from the call. Although there is no response for this call,
512 // obligated to mention this to make compiler happy.
513 sd_bus_message *response = NULL;
514
515 // Gets a hook onto either a SYSTEM or SESSION bus
516 sd_bus *bus_type = ipmid_get_sd_bus_connection();
Sergey Solomineb9b8142016-08-23 09:07:28 -0500517 rc = mapper_get_service(bus_type, chassis_object_name, &busname);
518 if (rc < 0) {
519 fprintf(stderr, "Failed to get bus name, return value: %s.\n", strerror(-rc));
520 goto finish;
521 }
vishwa36993272015-11-20 12:43:49 -0600522 rc = sd_bus_call_method(bus_type, // On the System Bus
Sergey Solomineb9b8142016-08-23 09:07:28 -0500523 busname, // Service to contact
vishwa36993272015-11-20 12:43:49 -0600524 chassis_object_name, // Object path
525 chassis_intf_name, // Interface name
Chris Austen7888c4d2015-12-03 15:26:20 -0600526 method, // Method to be called
vishwa36993272015-11-20 12:43:49 -0600527 &bus_error, // object to return error
528 &response, // Response buffer if any
529 NULL); // No input arguments
530 if(rc < 0)
531 {
532 fprintf(stderr,"ERROR initiating Power Off:[%s]\n",bus_error.message);
533 }
534 else
535 {
536 printf("Chassis Power Off initiated successfully\n");
537 }
538
Sergey Solomineb9b8142016-08-23 09:07:28 -0500539finish:
vishwa36993272015-11-20 12:43:49 -0600540 sd_bus_error_free(&bus_error);
541 sd_bus_message_unref(response);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500542 free(busname);
vishwa36993272015-11-20 12:43:49 -0600543
Sergey Solomineb9b8142016-08-23 09:07:28 -0500544 return rc;
vishwa36993272015-11-20 12:43:49 -0600545}
546
Chris Austen7888c4d2015-12-03 15:26:20 -0600547
vishwa36993272015-11-20 12:43:49 -0600548//----------------------------------------------------------------------
549// Chassis Control commands
550//----------------------------------------------------------------------
551ipmi_ret_t ipmi_chassis_control(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
552 ipmi_request_t request, ipmi_response_t response,
553 ipmi_data_len_t data_len, ipmi_context_t context)
554{
555 // Error from power off.
556 int rc = 0;
557
558 // No response for this command.
559 *data_len = 0;
560
561 // Catch the actual operaton by peeking into request buffer
562 uint8_t chassis_ctrl_cmd = *(uint8_t *)request;
563 printf("Chassis Control Command: Operation:[0x%X]\n",chassis_ctrl_cmd);
564
565 switch(chassis_ctrl_cmd)
566 {
567 case CMD_POWER_OFF:
Chris Austen7888c4d2015-12-03 15:26:20 -0600568 rc = ipmi_chassis_power_control("powerOff");
vishwa36993272015-11-20 12:43:49 -0600569 break;
Chris Austen7888c4d2015-12-03 15:26:20 -0600570 case CMD_HARD_RESET:
571 rc = ipmi_chassis_power_control("reboot");
572 break;
vishwa36993272015-11-20 12:43:49 -0600573 default:
574 {
575 fprintf(stderr, "Invalid Chassis Control command:[0x%X] received\n",chassis_ctrl_cmd);
576 rc = -1;
577 }
578 }
579
580 return ( (rc < 0) ? IPMI_CC_INVALID : IPMI_CC_OK);
581}
582
shgoupfd84fbbf2015-12-17 10:05:51 +0800583struct bootOptionTypeMap_t {
584 uint8_t ipmibootflag;
585 char dbusname[8];
586};
587
588#define INVALID_STRING "Invalid"
589// dbus supports this list of boot devices.
590bootOptionTypeMap_t g_bootOptionTypeMap_t[] = {
591
592 {0x01, "Network"},
593 {0x02, "Disk"},
594 {0x03, "Safe"},
595 {0x05, "CDROM"},
596 {0x06, "Setup"},
597 {0x00, "Default"},
598 {0xFF, INVALID_STRING}
599};
600
601uint8_t get_ipmi_boot_option(char *p) {
602
603 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
604
605 while (s->ipmibootflag != 0xFF) {
606 if (!strcmp(s->dbusname,p))
607 break;
608 s++;
609 }
610
611 if (!s->ipmibootflag)
612 printf("Failed to find Sensor Type %s\n", p);
613
614 return s->ipmibootflag;
615}
616
617char* get_boot_option_by_ipmi(uint8_t p) {
618
619 bootOptionTypeMap_t *s = g_bootOptionTypeMap_t;
620
621 while (s->ipmibootflag != 0xFF) {
622
623 if (s->ipmibootflag == p)
624 break;
625
626 s++;
627 }
628
629
630 if (!s->ipmibootflag)
631 printf("Failed to find Sensor Type 0x%x\n", p);
632
633 return s->dbusname;
634}
635
Adriana Kobylak40814c62015-10-27 15:58:44 -0500636ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
637 ipmi_request_t request, ipmi_response_t response,
638 ipmi_data_len_t data_len, ipmi_context_t context)
639{
shgoupfd84fbbf2015-12-17 10:05:51 +0800640 ipmi_ret_t rc = IPMI_CC_PARM_NOT_SUPPORTED;
641 char *p = NULL;
642 get_sys_boot_options_response_t *resp = (get_sys_boot_options_response_t *) response;
643 get_sys_boot_options_t *reqptr = (get_sys_boot_options_t*) request;
644 uint8_t s;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500645
646 printf("IPMI GET_SYS_BOOT_OPTIONS\n");
647
shgoupfd84fbbf2015-12-17 10:05:51 +0800648 memset(resp,0,sizeof(*resp));
649 resp->version = SET_PARM_VERSION;
650 resp->parm = 5;
ratagupta6f6bff2016-04-04 06:20:11 -0500651 resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500652
Adriana Kobylak40814c62015-10-27 15:58:44 -0500653
shgoupfd84fbbf2015-12-17 10:05:51 +0800654 /*
655 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
656 * This is the only parameter used by petitboot.
657 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500658 if ( reqptr->parameter == static_cast<uint8_t>
659 ( BootOptionParameter::BOOT_FLAGS )) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800660
Ratan Guptafd28dd72016-08-01 04:58:01 -0500661 *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
ratagupta6f6bff2016-04-04 06:20:11 -0500662 /* Get the boot device */
663 int r = dbus_get_property("boot_flags",&p);
shgoupfd84fbbf2015-12-17 10:05:51 +0800664
665 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500666 fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800667 rc = IPMI_CC_UNSPECIFIED_ERROR;
668
669 } else {
670
671 s = get_ipmi_boot_option(p);
672 resp->data[1] = (s << 2);
673 rc = IPMI_CC_OK;
ratagupta6f6bff2016-04-04 06:20:11 -0500674
shgoupfd84fbbf2015-12-17 10:05:51 +0800675 }
676
ratagupta6f6bff2016-04-04 06:20:11 -0500677 if (p)
678 {
679 free(p);
680 p = NULL;
681 }
682
683 /* Get the boot policy */
684 r = dbus_get_property("boot_policy",&p);
685
686 if (r < 0) {
687 fprintf(stderr, "Dbus get property(boot_policy) failed for get_sys_boot_options.\n");
688 rc = IPMI_CC_UNSPECIFIED_ERROR;
689
690 } else {
691
Ratan Guptafd28dd72016-08-01 04:58:01 -0500692 printf("BootPolicy is[%s]", p);
ratagupta6f6bff2016-04-04 06:20:11 -0500693 resp->data[0] = (strncmp(p,"ONETIME",strlen("ONETIME"))==0) ?
694 SET_PARM_BOOT_FLAGS_VALID_ONE_TIME:
695 SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
696 rc = IPMI_CC_OK;
697
698 }
699
700
Ratan Guptafd28dd72016-08-01 04:58:01 -0500701 } else if ( reqptr->parameter == static_cast<uint8_t>
702 ( BootOptionParameter::OPAL_NETWORK_SETTINGS )) {
703
704 *data_len = static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
705
706 resp->parm = static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
707
708 int ret = getHostNetworkData(resp);
709
710 if (ret < 0) {
711
712 fprintf(stderr, "getHostNetworkData failed for get_sys_boot_options.\n");
713 rc = IPMI_CC_UNSPECIFIED_ERROR;
714
715 }else
716 rc = IPMI_CC_OK;
717 }
718
719 else {
Adriana Kobylak40814c62015-10-27 15:58:44 -0500720 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
shgoupfd84fbbf2015-12-17 10:05:51 +0800721 }
722
723 if (p)
724 free(p);
725
Ratan Guptafd28dd72016-08-01 04:58:01 -0500726 if (rc == IPMI_CC_OK)
727 {
728 *data_len += 2;
729 }
730
shgoupfd84fbbf2015-12-17 10:05:51 +0800731 return rc;
732}
733
734
735
736ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
737 ipmi_request_t request, ipmi_response_t response,
738 ipmi_data_len_t data_len, ipmi_context_t context)
739{
740 ipmi_ret_t rc = IPMI_CC_OK;
741 char *s;
shgoupfd84fbbf2015-12-17 10:05:51 +0800742 set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
743
Ratan Guptafd28dd72016-08-01 04:58:01 -0500744 printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
745
shgoupfd84fbbf2015-12-17 10:05:51 +0800746 // This IPMI command does not have any resposne data
747 *data_len = 0;
748
749 /* 000101
750 * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
751 * This is the only parameter used by petitboot.
752 */
Ratan Guptafd28dd72016-08-01 04:58:01 -0500753
754 if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
shgoupfd84fbbf2015-12-17 10:05:51 +0800755
756 s = get_boot_option_by_ipmi(((reqptr->data[1] & 0x3C) >> 2));
757
758 printf("%d: %s\n", __LINE__, s);
759 if (!strcmp(s,INVALID_STRING)) {
760
761 rc = IPMI_CC_PARM_NOT_SUPPORTED;
762
763 } else {
764
ratagupta6f6bff2016-04-04 06:20:11 -0500765 int r = dbus_set_property("boot_flags",s);
shgoupfd84fbbf2015-12-17 10:05:51 +0800766
767 if (r < 0) {
ratagupta6f6bff2016-04-04 06:20:11 -0500768 fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
shgoupfd84fbbf2015-12-17 10:05:51 +0800769 rc = IPMI_CC_UNSPECIFIED_ERROR;
770 }
771 }
Ratan Guptafd28dd72016-08-01 04:58:01 -0500772
ratagupta6f6bff2016-04-04 06:20:11 -0500773 /* setting the boot policy */
774 s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
Ratan Guptafd28dd72016-08-01 04:58:01 -0500775 SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
ratagupta6f6bff2016-04-04 06:20:11 -0500776
Ratan Guptafd28dd72016-08-01 04:58:01 -0500777 printf ( "\nBoot Policy is %s",s);
ratagupta6f6bff2016-04-04 06:20:11 -0500778 int r = dbus_set_property("boot_policy",s);
779
780 if (r < 0) {
781 fprintf(stderr, "Dbus set property(boot_policy) failed for set_sys_boot_options.\n");
782 rc = IPMI_CC_UNSPECIFIED_ERROR;
783 }
shgoupfd84fbbf2015-12-17 10:05:51 +0800784
Ratan Guptafd28dd72016-08-01 04:58:01 -0500785 } else if (reqptr->parameter ==
786 (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) {
787
788 int ret = setHostNetworkData(reqptr);
789 if (ret < 0) {
790 fprintf(stderr, "setHostNetworkData failed for set_sys_boot_options.\n");
791 rc = IPMI_CC_UNSPECIFIED_ERROR;
792 }
793 }
794 else {
shgoupfd84fbbf2015-12-17 10:05:51 +0800795 fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
796 rc = IPMI_CC_PARM_NOT_SUPPORTED;
Adriana Kobylak40814c62015-10-27 15:58:44 -0500797 }
798
799 return rc;
800}
801
802void register_netfn_chassis_functions()
803{
804 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_WILDCARD);
805 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_WILDCARD, NULL, ipmi_chassis_wildcard);
806
807 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_GET_SYS_BOOT_OPTIONS);
808 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 -0500809
vishwa36993272015-11-20 12:43:49 -0600810 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL);
811 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_CHASSIS_CONTROL, NULL, ipmi_chassis_control);
shgoupfd84fbbf2015-12-17 10:05:51 +0800812
813 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS);
814 ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL, ipmi_chassis_set_sys_boot_options);
vishwa36993272015-11-20 12:43:49 -0600815}
shgoupfd84fbbf2015-12-17 10:05:51 +0800816