1 #include "apphandler.h" 2 #include "host-ipmid/ipmid-api.h" 3 #include "ipmid.hpp" 4 #include <stdio.h> 5 #include <string.h> 6 #include <stdint.h> 7 #include <systemd/sd-bus.h> 8 #include <mapper.h> 9 #include <array> 10 #include <arpa/inet.h> 11 #include "transporthandler.h" 12 13 extern sd_bus *bus; 14 15 constexpr auto app_obj = "/org/openbmc/NetworkManager/Interface"; 16 constexpr auto app_ifc = "org.openbmc.NetworkManager"; 17 constexpr auto app_nwinterface = "eth0"; 18 19 void register_netfn_app_functions() __attribute__((constructor)); 20 21 // Offset in get device id command. 22 typedef struct 23 { 24 uint8_t id; 25 uint8_t revision; 26 uint8_t fw[2]; 27 uint8_t ipmi_ver; 28 uint8_t addn_dev_support; 29 uint8_t manuf_id[3]; 30 uint8_t prod_id[2]; 31 uint8_t aux[4]; 32 }__attribute__((packed)) ipmi_device_id_t; 33 34 ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 35 ipmi_request_t request, ipmi_response_t response, 36 ipmi_data_len_t data_len, ipmi_context_t context) 37 { 38 ipmi_ret_t rc = IPMI_CC_OK; 39 *data_len = 0; 40 41 printf("IPMI SET ACPI STATE Ignoring for now\n"); 42 return rc; 43 } 44 45 46 typedef struct 47 { 48 char major; 49 char minor; 50 uint16_t d[2]; 51 } rev_t; 52 53 54 /* Currently only supports the vx.x-x-[-x] format Will return -1 if not in */ 55 /* the format this routine knows how to parse */ 56 /* version = v0.6-19-gf363f61-dirty */ 57 /* ^ ^ ^^ ^ */ 58 /* | | |----------|-- additional details */ 59 /* | |---------------- Minor */ 60 /* |------------------ Major */ 61 /* Additional details : If the option group exists it will force Auxiliary */ 62 /* Firmware Revision Information 4th byte to 1 indicating the build was */ 63 /* derived with additional edits */ 64 int convert_version(const char *p, rev_t *rev) 65 { 66 char *s, *token; 67 uint16_t commits; 68 69 if (*p != 'v') 70 return -1; 71 p++; 72 73 s = strdup(p); 74 token = strtok(s,".-"); 75 76 rev->major = (int8_t) atoi(token); 77 78 token = strtok(NULL, ".-"); 79 rev->minor = (int8_t) atoi(token); 80 81 // Capture the number of commits on top of the minor tag. 82 // I'm using BE format like the ipmi spec asked for 83 token = strtok(NULL,".-"); 84 85 if (token) { 86 commits = (int16_t) atoi(token); 87 rev->d[0] = (commits>>8) | (commits<<8); 88 89 // commit number we skip 90 token = strtok(NULL,".-"); 91 92 } else { 93 rev->d[0] = 0; 94 } 95 96 // Any value of the optional parameter forces it to 1 97 if (token) 98 token = strtok(NULL,".-"); 99 100 rev->d[1] = (token != NULL) ? 1 : 0; 101 102 free(s); 103 return 0; 104 } 105 106 ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 107 ipmi_request_t request, ipmi_response_t response, 108 ipmi_data_len_t data_len, ipmi_context_t context) 109 { 110 ipmi_ret_t rc = IPMI_CC_OK; 111 const char *objname = "/org/openbmc/inventory/system/chassis/motherboard/bmc"; 112 const char *iface = "org.openbmc.InventoryItem"; 113 char *ver = NULL; 114 char *busname = NULL; 115 int r; 116 rev_t rev = {0}; 117 ipmi_device_id_t dev_id{}; 118 119 // Data length 120 *data_len = sizeof(dev_id); 121 122 // From IPMI spec, controller that have different application commands, or different 123 // definitions of OEM fields, are expected to have different Device ID values. 124 // Set to 0 now. 125 126 // Device Revision is set to 0 now. 127 // Bit7 identifies if device provide Device SDRs, obmc don't have SDR,we use ipmi to 128 // simulate SDR, hence the value: 129 dev_id.revision = 0x80; 130 131 // Firmware revision is already implemented, so get it from appropriate position. 132 r = mapper_get_service(bus, objname, &busname); 133 if (r < 0) { 134 fprintf(stderr, "Failed to get %s bus name: %s\n", 135 objname, strerror(-r)); 136 goto finish; 137 } 138 r = sd_bus_get_property_string(bus,busname,objname,iface,"version", NULL, &ver); 139 if ( r < 0 ) { 140 fprintf(stderr, "Failed to obtain version property: %s\n", strerror(-r)); 141 } else { 142 r = convert_version(ver, &rev); 143 if( r >= 0 ) { 144 // bit7 identifies if the device is available, 0=normal operation, 145 // 1=device firmware, SDR update or self-initialization in progress. 146 // our SDR is normal working condition, so mask: 147 dev_id.fw[0] = 0x7F & rev.major; 148 149 rev.minor = (rev.minor > 99 ? 99 : rev.minor); 150 dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16; 151 memcpy(&dev_id.aux, rev.d, 4); 152 } 153 } 154 155 // IPMI Spec verison 2.0 156 dev_id.ipmi_ver = 2; 157 158 // Additional device Support. 159 // List the 'logical device' commands and functions that the controller supports 160 // that are in addition to the mandatory IPM and Application commands. 161 // [7] Chassis Device (device functions as chassis device per ICMB spec.) 162 // [6] Bridge (device responds to Bridge NetFn commands) 163 // [5] IPMB Event Generator 164 // [4] IPMB Event Receiver 165 // [3] FRU Inventory Device 166 // [2] SEL Device 167 // [1] SDR Repository Device 168 // [0] Sensor Device 169 // We support FRU/SEL/Sensor now: 170 dev_id.addn_dev_support = 0x8D; 171 172 // This value is the IANA number assigned to "IBM Platform Firmware 173 // Division", which is also used by our service processor. We may want 174 // a different number or at least a different version? 175 dev_id.manuf_id[0] = 0x41; 176 dev_id.manuf_id[1] = 0xA7; 177 dev_id.manuf_id[2] = 0x00; 178 179 // Witherspoon's product ID is hardcoded to 4F42(ASCII 'OB'). 180 // TODO: openbmc/openbmc#495 181 dev_id.prod_id[0] = 0x4F; 182 dev_id.prod_id[1] = 0x42; 183 184 // Pack the actual response 185 memcpy(response, &dev_id, *data_len); 186 finish: 187 free(busname); 188 return rc; 189 } 190 191 ipmi_ret_t ipmi_app_get_self_test_results(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 192 ipmi_request_t request, ipmi_response_t response, 193 ipmi_data_len_t data_len, ipmi_context_t context) 194 { 195 ipmi_ret_t rc = IPMI_CC_OK; 196 197 // Byte 2: 198 // 55h - No error. 199 // 56h - Self Test funciton not implemented in this controller. 200 // 57h - Corrupted or inaccesssible data or devices. 201 // 58h - Fatal hardware error. 202 // FFh - reserved. 203 // all other: Device-specific 'internal failure'. 204 // Byte 3: 205 // For byte 2 = 55h, 56h, FFh: 00h 206 // For byte 2 = 58h, all other: Device-specific 207 // For byte 2 = 57h: self-test error bitfield. 208 // Note: returning 57h does not imply that all test were run. 209 // [7] 1b = Cannot access SEL device. 210 // [6] 1b = Cannot access SDR Repository. 211 // [5] 1b = Cannot access BMC FRU device. 212 // [4] 1b = IPMB signal lines do not respond. 213 // [3] 1b = SDR Repository empty. 214 // [2] 1b = Internal Use Area of BMC FRU corrupted. 215 // [1] 1b = controller update 'boot block' firmware corrupted. 216 // [0] 1b = controller operational firmware corrupted. 217 218 char selftestresults[2] = {0}; 219 220 *data_len = 2; 221 222 selftestresults[0] = 0x56; 223 selftestresults[1] = 0; 224 225 memcpy(response, selftestresults, *data_len); 226 227 return rc; 228 } 229 230 ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 231 ipmi_request_t request, ipmi_response_t response, 232 ipmi_data_len_t data_len, ipmi_context_t context) 233 { 234 const char *objname = "/org/openbmc/control/chassis0"; 235 const char *iface = "org.freedesktop.DBus.Properties"; 236 const char *chassis_iface = "org.openbmc.control.Chassis"; 237 sd_bus_message *reply = NULL; 238 sd_bus_error error = SD_BUS_ERROR_NULL; 239 int r = 0; 240 char *uuid = NULL; 241 char *busname = NULL; 242 243 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 244 // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte order 245 // Ex: 0x2332fc2c40e66298e511f2782395a361 246 247 const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec 248 uint8_t resp_uuid[resp_size]; // Array to hold the formatted response 249 int resp_loc = resp_size-1; // Point resp end of array to save in reverse order 250 int i = 0; 251 char *tokptr = NULL; 252 char *id_octet = NULL; 253 254 // Status code. 255 ipmi_ret_t rc = IPMI_CC_OK; 256 *data_len = 0; 257 258 printf("IPMI GET DEVICE GUID\n"); 259 260 // Call Get properties method with the interface and property name 261 r = mapper_get_service(bus, objname, &busname); 262 if (r < 0) { 263 fprintf(stderr, "Failed to get %s bus name: %s\n", 264 objname, strerror(-r)); 265 goto finish; 266 } 267 r = sd_bus_call_method(bus,busname,objname,iface, 268 "Get",&error, &reply, "ss", 269 chassis_iface, "uuid"); 270 if (r < 0) 271 { 272 fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); 273 rc = IPMI_CC_UNSPECIFIED_ERROR; 274 goto finish; 275 } 276 277 r = sd_bus_message_read(reply, "v", "s", &uuid); 278 if (r < 0 || uuid == NULL) 279 { 280 fprintf(stderr, "Failed to get a response: %s", strerror(-r)); 281 rc = IPMI_CC_RESPONSE_ERROR; 282 goto finish; 283 } 284 285 // Traverse the UUID 286 id_octet = strtok_r(uuid, "-", &tokptr); // Get the UUID octects separated by dash 287 288 if (id_octet == NULL) 289 { 290 // Error 291 fprintf(stderr, "Unexpected UUID format: %s", uuid); 292 rc = IPMI_CC_RESPONSE_ERROR; 293 goto finish; 294 } 295 296 while (id_octet != NULL) 297 { 298 // Calculate the octet string size since it varies 299 // Divide it by 2 for the array size since 1 byte is built from 2 chars 300 int tmp_size = strlen(id_octet)/2; 301 302 for(i = 0; i < tmp_size; i++) 303 { 304 char tmp_array[3] = {0}; // Holder of the 2 chars that will become a byte 305 strncpy(tmp_array, id_octet, 2); // 2 chars at a time 306 307 int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte 308 memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1); // Copy end to first 309 resp_loc--; 310 id_octet+=2; // Finished with the 2 chars, advance 311 } 312 id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet 313 } 314 315 // Data length 316 *data_len = resp_size; 317 318 // Pack the actual response 319 memcpy(response, &resp_uuid, *data_len); 320 321 finish: 322 sd_bus_error_free(&error); 323 reply = sd_bus_message_unref(reply); 324 free(busname); 325 326 return rc; 327 } 328 329 ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 330 ipmi_request_t request, ipmi_response_t response, 331 ipmi_data_len_t data_len, ipmi_context_t context) 332 { 333 printf("Handling Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd); 334 335 // Status code. 336 ipmi_ret_t rc = IPMI_CC_OK; 337 338 // Per IPMI 2.0 spec, the input and output buffer size must be the max 339 // buffer size minus one byte to allocate space for the length byte. 340 uint8_t str[] = {0x01, MAX_IPMI_BUFFER-1, MAX_IPMI_BUFFER-1, 0x0A, 0x01}; 341 342 // Data length 343 *data_len = sizeof(str); 344 345 // Pack the actual response 346 memcpy(response, &str, *data_len); 347 348 return rc; 349 } 350 351 352 struct set_wd_data_t { 353 uint8_t t_use; 354 uint8_t t_action; 355 uint8_t preset; 356 uint8_t flags; 357 uint8_t ls; 358 uint8_t ms; 359 } __attribute__ ((packed)); 360 361 362 363 ipmi_ret_t ipmi_app_set_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 364 ipmi_request_t request, ipmi_response_t response, 365 ipmi_data_len_t data_len, ipmi_context_t context) 366 { 367 const char *objname = "/org/openbmc/watchdog/host0"; 368 const char *iface = "org.openbmc.Watchdog"; 369 sd_bus_message *reply = NULL; 370 sd_bus_error error = SD_BUS_ERROR_NULL; 371 int r = 0; 372 373 set_wd_data_t *reqptr = (set_wd_data_t*) request; 374 uint16_t timer = 0; 375 uint32_t timer_ms = 0; 376 char *busname = NULL; 377 *data_len = 0; 378 379 // Get number of 100ms intervals 380 timer = (((uint16_t)reqptr->ms) << 8) + reqptr->ls; 381 // Get timer value in ms 382 timer_ms = timer * 100; 383 384 printf("WATCHDOG SET Timer:[0x%X] 100ms intervals\n",timer); 385 386 // Get bus name 387 r = mapper_get_service(bus, objname, &busname); 388 if (r < 0) { 389 fprintf(stderr, "Failed to get %s bus name: %s\n", 390 objname, strerror(-r)); 391 goto finish; 392 } 393 // Set watchdog timer 394 r = sd_bus_call_method(bus, busname, objname, iface, 395 "set", &error, &reply, "i", timer_ms); 396 if(r < 0) 397 { 398 fprintf(stderr, "Failed to call the SET method: %s\n", strerror(-r)); 399 goto finish; 400 } 401 402 sd_bus_error_free(&error); 403 reply = sd_bus_message_unref(reply); 404 405 // Stop the current watchdog if any 406 r = sd_bus_call_method(bus, busname, objname, iface, 407 "stop", &error, &reply, NULL); 408 if(r < 0) 409 { 410 fprintf(stderr, "Failed to call the STOP method: %s\n", strerror(-r)); 411 goto finish; 412 } 413 414 if (reqptr->t_use & 0x40) 415 { 416 sd_bus_error_free(&error); 417 reply = sd_bus_message_unref(reply); 418 419 // Start the watchdog if requested 420 r = sd_bus_call_method(bus, busname, objname, iface, 421 "start", &error, &reply, NULL); 422 if(r < 0) 423 { 424 fprintf(stderr, "Failed to call the START method: %s\n", strerror(-r)); 425 } 426 } 427 428 finish: 429 sd_bus_error_free(&error); 430 reply = sd_bus_message_unref(reply); 431 free(busname); 432 433 return (r < 0) ? -1 : IPMI_CC_OK; 434 } 435 436 437 ipmi_ret_t ipmi_app_reset_watchdog(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 438 ipmi_request_t request, ipmi_response_t response, 439 ipmi_data_len_t data_len, ipmi_context_t context) 440 { 441 const char *objname = "/org/openbmc/watchdog/host0"; 442 const char *iface = "org.openbmc.Watchdog"; 443 sd_bus_message *reply = NULL; 444 sd_bus_error error = SD_BUS_ERROR_NULL; 445 int r = 0; 446 char *busname = NULL; 447 448 // Status code. 449 ipmi_ret_t rc = IPMI_CC_OK; 450 *data_len = 0; 451 452 printf("WATCHDOG RESET\n"); 453 // Get bus name 454 r = mapper_get_service(bus, objname, &busname); 455 if (r < 0) { 456 fprintf(stderr, "Failed to get %s bus name: %s\n", 457 objname, strerror(-r)); 458 goto finish; 459 } 460 // Refresh watchdog 461 r = sd_bus_call_method(bus, busname, objname, iface, 462 "poke", &error, &reply, NULL); 463 if (r < 0) { 464 fprintf(stderr, "Failed to add reset watchdog: %s\n", strerror(-r)); 465 rc = -1; 466 } 467 468 finish: 469 sd_bus_error_free(&error); 470 reply = sd_bus_message_unref(reply); 471 free(busname); 472 473 return rc; 474 } 475 476 extern struct channel_config_t channel_config; 477 478 ipmi_ret_t ipmi_set_channel_access(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 479 ipmi_request_t request, ipmi_response_t response, 480 ipmi_data_len_t data_len, ipmi_context_t context) 481 { 482 ipmi_ret_t rc = IPMI_CC_OK; 483 484 sd_bus *bus = ipmid_get_sd_bus_connection(); 485 sd_bus_message *reply = nullptr; 486 sd_bus_error error = SD_BUS_ERROR_NULL; 487 int r = 0; 488 char *app = nullptr; 489 int family = 0; 490 unsigned char prefixlen = 0; 491 char* ipaddr = nullptr; 492 uint32_t mask = 0xFFFFFFFF; 493 char* gateway = nullptr; 494 char tmp_netmask[INET_ADDRSTRLEN]; 495 496 // Todo: parse the request data if needed. 497 498 // Using Set Channel cmd to apply changes of Set Lan Cmd. 499 500 r = mapper_get_service(bus, app_obj, &app); 501 if (r < 0) { 502 fprintf(stderr, "Failed to get %s bus name: %s\n", 503 app_obj, strerror(-r)); 504 rc = IPMI_CC_UNSPECIFIED_ERROR; 505 goto finish; 506 } 507 508 r = sd_bus_call_method(bus, app, app_obj, app_ifc, "GetAddress4", &error, 509 &reply, "s", app_nwinterface); 510 if (r < 0) { 511 fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r)); 512 rc = IPMI_CC_UNSPECIFIED_ERROR; 513 goto finish; 514 } 515 516 r = sd_bus_message_read(reply, "iyss", 517 &family, &prefixlen, &ipaddr, &gateway); 518 if (r < 0) { 519 fprintf(stderr, "Failed to get a response: %s\n", strerror(-r)); 520 rc = IPMI_CC_RESPONSE_ERROR; 521 goto finish; 522 } 523 524 printf("N/W data from Cache: %s:%s:%s\n", 525 channel_config.new_ipaddr.c_str(), 526 channel_config.new_netmask.c_str(), 527 channel_config.new_gateway.c_str()); 528 529 if(channel_config.new_ipaddr.empty()) { 530 channel_config.new_ipaddr.assign(ipaddr); 531 } 532 533 if(channel_config.new_netmask.empty()) { 534 mask = htonl(mask<<(32-prefixlen)); 535 uint8_t* p = (uint8_t*)&mask; 536 537 snprintf(tmp_netmask, INET_ADDRSTRLEN, "%d.%d.%d.%d", 538 *p, *(p+1), *(p+2), *(p+3)); 539 channel_config.new_netmask.assign(tmp_netmask); 540 } 541 542 if(channel_config.new_gateway.empty()) { 543 channel_config.new_gateway.assign(gateway); 544 } 545 546 printf("N/W data from HW %s:%d:%s:%s\n", 547 family==AF_INET?"IPv4":"IPv6", prefixlen, ipaddr,gateway); 548 printf("N/W data from Cache: %s:%s:%s\n", 549 channel_config.new_ipaddr.c_str(), 550 channel_config.new_netmask.c_str(), 551 channel_config.new_gateway.c_str()); 552 553 r = sd_bus_call_method(bus, // On the System Bus 554 app, // Service to contact 555 app_obj, // Object path 556 app_ifc, // Interface name 557 "SetAddress4", // Method to be called 558 &error, // object to return error 559 &reply, // Response message on success 560 "ssss", // input message (Interface, 561 // IP Address, Netmask, Gateway) 562 app_nwinterface, // eth0 563 channel_config.new_ipaddr.c_str(), 564 channel_config.new_netmask.c_str(), 565 channel_config.new_gateway.c_str()); 566 if(r < 0) { 567 fprintf(stderr, "Failed to set network data %s:%s:%s %s\n", 568 channel_config.new_ipaddr.c_str(), 569 channel_config.new_netmask.c_str(), 570 channel_config.new_gateway.c_str(), 571 error.message); 572 rc = IPMI_CC_UNSPECIFIED_ERROR; 573 } 574 575 channel_config.new_ipaddr.clear(); 576 channel_config.new_netmask.clear(); 577 channel_config.new_gateway.clear(); 578 579 finish: 580 sd_bus_error_free(&error); 581 reply = sd_bus_message_unref(reply); 582 free(app); 583 584 return rc; 585 } 586 587 // ATTENTION: This ipmi function is very hardcoded on purpose 588 // OpenBMC does not fully support IPMI. This command is useful 589 // to have around because it enables testing of interfaces with 590 // the IPMI tool. 591 #define GET_CHANNEL_INFO_CHANNEL_OFFSET 0 592 // IPMI Table 6-2 593 #define IPMI_CHANNEL_TYPE_IPMB 1 594 // IPMI Table 6-3 595 #define IPMI_CHANNEL_MEDIUM_TYPE_OTHER 6 596 597 ipmi_ret_t ipmi_app_channel_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 598 ipmi_request_t request, ipmi_response_t response, 599 ipmi_data_len_t data_len, ipmi_context_t context) 600 { 601 ipmi_ret_t rc = IPMI_CC_OK; 602 uint8_t resp[] = { 603 1, 604 IPMI_CHANNEL_MEDIUM_TYPE_OTHER, 605 IPMI_CHANNEL_TYPE_IPMB, 606 1,0x41,0xA7,0x00,0,0}; 607 uint8_t *p = (uint8_t*) request; 608 609 printf("IPMI APP GET CHANNEL INFO\n"); 610 611 // The supported channels numbers are 1 and 8. 612 // Channel Number E is used as way to identify the current channel 613 // that the command is being is received from. 614 if (*p == 0xe || *p == 1 || *p == 8) { 615 616 *data_len = sizeof(resp); 617 memcpy(response, resp, *data_len); 618 619 } else { 620 rc = IPMI_CC_PARM_OUT_OF_RANGE; 621 *data_len = 0; 622 } 623 624 return rc; 625 } 626 627 ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 628 ipmi_request_t request, ipmi_response_t response, 629 ipmi_data_len_t data_len, ipmi_context_t context) 630 { 631 printf("Handling WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd); 632 633 // Status code. 634 ipmi_ret_t rc = IPMI_CC_INVALID; 635 636 *data_len = strlen("THIS IS WILDCARD"); 637 638 // Now pack actual response 639 memcpy(response, "THIS IS WILDCARD", *data_len); 640 641 return rc; 642 } 643 644 void register_netfn_app_functions() 645 { 646 // <Get BT Interface Capabilities> 647 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CAP_BIT); 648 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL, ipmi_app_get_bt_capabilities, 649 PRIVILEGE_USER); 650 651 // <Wildcard Command> 652 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_WILDCARD); 653 ipmi_register_callback(NETFUN_APP, IPMI_CMD_WILDCARD, NULL, ipmi_app_wildcard_handler, 654 PRIVILEGE_USER); 655 656 // <Reset Watchdog Timer> 657 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_RESET_WD); 658 ipmi_register_callback(NETFUN_APP, IPMI_CMD_RESET_WD, NULL, ipmi_app_reset_watchdog, 659 PRIVILEGE_OPERATOR); 660 661 // <Set Watchdog Timer> 662 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_WD); 663 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_WD, NULL, ipmi_app_set_watchdog, 664 PRIVILEGE_OPERATOR); 665 666 // <Get Device ID> 667 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_DEVICE_ID); 668 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_ID, NULL, ipmi_app_get_device_id, 669 PRIVILEGE_USER); 670 671 // <Get Self Test Results> 672 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_SELF_TEST_RESULTS); 673 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SELF_TEST_RESULTS, NULL, 674 ipmi_app_get_self_test_results, PRIVILEGE_USER); 675 676 // <Get Device GUID> 677 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID); 678 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL, ipmi_app_get_device_guid, 679 PRIVILEGE_USER); 680 681 // <Set ACPI Power State> 682 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_SET_ACPI); 683 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_ACPI, NULL, ipmi_app_set_acpi_power_state, 684 PRIVILEGE_ADMIN); 685 686 // <Set Channel Access> 687 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, 688 IPMI_CMD_SET_CHAN_ACCESS); 689 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL, 690 ipmi_set_channel_access, PRIVILEGE_ADMIN); 691 692 // <Get Channel Info Command> 693 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",NETFUN_APP, IPMI_CMD_GET_CHAN_INFO); 694 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL, ipmi_app_channel_info, 695 PRIVILEGE_USER); 696 697 return; 698 } 699 700 701