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