1 #include "chassishandler.h"
2 #include "ipmid-api.h"
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdint.h>
6 #include <mapper.h>
7 #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>
14 
15 //Defines
16 #define SET_PARM_VERSION                     0x01
17 #define SET_PARM_BOOT_FLAGS_PERMANENT        0x40 //boot flags data1 7th bit on
18 #define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME   0x80 //boot flags data1 8th bit on
19 #define SET_PARM_BOOT_FLAGS_VALID_PERMANENT  0xC0 //boot flags data1 7 & 8 bit on
20 
21 constexpr size_t SIZE_MAC  = 18;
22 constexpr size_t SIZE_BOOT_OPTION = (uint8_t)BootOptionResponseSize::
23                                              OPAL_NETWORK_SETTINGS;//Maximum size of the boot option parametrs
24 constexpr size_t SIZE_PREFIX = 7;
25 constexpr size_t MAX_PREFIX_VALUE = 32;
26 constexpr size_t SIZE_COOKIE = 4;
27 constexpr size_t SIZE_VERSION = 2;
28 constexpr auto   MAC_ADDRESS_FORMAT = "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx";
29 constexpr auto   IP_ADDRESS_FORMAT = "%d.%d.%d.%d";
30 constexpr auto   PREFIX_FORMAT = "%d";
31 constexpr auto   ADDR_TYPE_FORMAT = "%hhx";
32 //PetiBoot-Specific
33 static constexpr uint8_t net_conf_initial_bytes[] = {0x80,0x21, 0x70 ,0x62 ,0x21,
34                                   0x00 ,0x01 ,0x06 ,0x04};
35 
36 static constexpr size_t COOKIE_OFFSET = 1;
37 static constexpr size_t VERSION_OFFSET = 5;
38 static constexpr size_t MAC_OFFSET = 9;
39 static constexpr size_t ADDRTYPE_OFFSET = 16;
40 static constexpr size_t IPADDR_OFFSET = 17;
41 static constexpr size_t PREFIX_OFFSET = 21;
42 static constexpr size_t GATEWAY_OFFSET = 22;
43 
44 
45 // OpenBMC Chassis Manager dbus framework
46 const char  *chassis_object_name   =  "/org/openbmc/control/chassis0";
47 const char  *chassis_intf_name     =  "org.openbmc.control.Chassis";
48 
49 
50 void register_netfn_chassis_functions() __attribute__((constructor));
51 
52 // Host settings in dbus
53 // Service name should be referenced by connection name got via object mapper
54 const char *settings_object_name  =  "/org/openbmc/settings/host0";
55 const char *settings_intf_name    =  "org.freedesktop.DBus.Properties";
56 const char *host_intf_name        =  "org.openbmc.settings.Host";
57 
58 int dbus_get_property(const char *name, char **buf)
59 {
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 
67     // Get the system bus where most system services are provided.
68     bus = ipmid_get_sd_bus_connection();
69 
70     r = mapper_get_service(bus, settings_object_name, &connection);
71     if (r < 0) {
72         fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
73         goto finish;
74     }
75 
76     /*
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 */
91                            name);                                      /* second argument */
92 
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 
116 finish:
117     sd_bus_error_free(&error);
118     sd_bus_message_unref(m);
119     free(connection);
120 
121     return r;
122 }
123 
124 int dbus_set_property(const char * name, const char *value)
125 {
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 
132     // Get the system bus where most system services are provided.
133     bus = ipmid_get_sd_bus_connection();
134 
135     r = mapper_get_service(bus, settings_object_name, &connection);
136     if (r < 0) {
137         fprintf(stderr, "Failed to get connection, return value: %s.\n", strerror(-r));
138         goto finish;
139     }
140 
141     /*
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 */
156                            name,                                       /* second argument */
157                            "s",                                        /* third argument */
158                            value);                                     /* fourth argument */
159 
160     if (r < 0) {
161         fprintf(stderr, "Failed to issue method call: %s\n", error.message);
162         goto finish;
163     }
164 
165     printf("IPMID boot option property set: {%s}.\n", value);
166 
167 finish:
168     sd_bus_error_free(&error);
169     sd_bus_message_unref(m);
170     free(connection);
171 
172     return r;
173 }
174 
175 struct get_sys_boot_options_t {
176     uint8_t parameter;
177     uint8_t set;
178     uint8_t block;
179 }  __attribute__ ((packed));
180 
181 struct get_sys_boot_options_response_t {
182     uint8_t version;
183     uint8_t parm;
184     uint8_t data[SIZE_BOOT_OPTION];
185 }  __attribute__ ((packed));
186 
187 struct set_sys_boot_options_t {
188     uint8_t parameter;
189     uint8_t data[SIZE_BOOT_OPTION];
190 }  __attribute__ ((packed));
191 
192 struct 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 
202 void 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 
269 int  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 
385 int 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 
488 ipmi_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.
494     ipmi_ret_t rc = IPMI_CC_OK;
495     *data_len = 0;
496     return rc;
497 }
498 
499 //------------------------------------------------------------
500 // Calls into Chassis Control Dbus object to do the power off
501 //------------------------------------------------------------
502 int ipmi_chassis_power_control(const char *method)
503 {
504 	// sd_bus error
505 	int rc = 0;
506 	char  *busname = NULL;
507 
508 	// SD Bus error report mechanism.
509 	sd_bus_error bus_error = SD_BUS_ERROR_NULL;
510 
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();
517 	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 	}
522 	rc = sd_bus_call_method(bus_type,        		 // On the System Bus
523 							busname,        // Service to contact
524 							chassis_object_name,     // Object path
525 							chassis_intf_name,       // Interface name
526 							method,      		 // Method to be called
527 							&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 
539 finish:
540     sd_bus_error_free(&bus_error);
541     sd_bus_message_unref(response);
542     free(busname);
543 
544     return rc;
545 }
546 
547 
548 //----------------------------------------------------------------------
549 // Chassis Control commands
550 //----------------------------------------------------------------------
551 ipmi_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:
568 			rc = ipmi_chassis_power_control("powerOff");
569 			break;
570 		case CMD_HARD_RESET:
571 			rc = ipmi_chassis_power_control("reboot");
572 			break;
573 		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 
583 struct 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.
590 bootOptionTypeMap_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 
601 uint8_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 
617 char* 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 
636 ipmi_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 {
640     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;
645 
646     printf("IPMI GET_SYS_BOOT_OPTIONS\n");
647 
648     memset(resp,0,sizeof(*resp));
649     resp->version   = SET_PARM_VERSION;
650     resp->parm      = 5;
651     resp->data[0]   = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
652 
653 
654     /*
655      * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
656      * This is the only parameter used by petitboot.
657      */
658     if ( reqptr->parameter == static_cast<uint8_t>
659        ( BootOptionParameter::BOOT_FLAGS )) {
660 
661         *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
662         /* Get the boot device */
663         int r = dbus_get_property("boot_flags",&p);
664 
665         if (r < 0) {
666             fprintf(stderr, "Dbus get property(boot_flags) failed for get_sys_boot_options.\n");
667             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;
674 
675         }
676 
677         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 
692             printf("BootPolicy is[%s]", p);
693             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 
701     } 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 {
720         fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
721     }
722 
723     if (p)
724         free(p);
725 
726     if (rc == IPMI_CC_OK)
727     {
728         *data_len += 2;
729     }
730 
731     return rc;
732 }
733 
734 
735 
736 ipmi_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;
742     set_sys_boot_options_t *reqptr = (set_sys_boot_options_t *) request;
743 
744     printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",reqptr->parameter);
745 
746     // 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      */
753 
754     if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) {
755 
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 
765             int r = dbus_set_property("boot_flags",s);
766 
767             if (r < 0) {
768                 fprintf(stderr, "Dbus set property(boot_flags) failed for set_sys_boot_options.\n");
769                 rc = IPMI_CC_UNSPECIFIED_ERROR;
770             }
771         }
772 
773         /* setting the boot policy */
774         s = (char *)(((reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
775                     SET_PARM_BOOT_FLAGS_PERMANENT) ?"PERMANENT":"ONETIME");
776 
777         printf ( "\nBoot Policy is %s",s);
778         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         }
784 
785     } 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 {
795         fprintf(stderr, "Unsupported parameter 0x%x\n", reqptr->parameter);
796         rc = IPMI_CC_PARM_NOT_SUPPORTED;
797     }
798 
799     return rc;
800 }
801 
802 void 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);
809 
810     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);
812 
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);
815 }
816 
817