1 /* 2 * Copyright (c) 2018 Intel Corporation. 3 * Copyright (c) 2018-present Facebook. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include "xyz/openbmc_project/Common/error.hpp" 19 #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp> 20 #include <xyz/openbmc_project/Control/Boot/Source/server.hpp> 21 22 #include <ipmid/api.hpp> 23 #include <ipmid/utils.hpp> 24 #include <commandutils.hpp> 25 #include <nlohmann/json.hpp> 26 #include <oemcommands.hpp> 27 #include <phosphor-logging/log.hpp> 28 #include <sdbusplus/bus.hpp> 29 30 #include <ipmid/api.hpp> 31 #include <ipmid/api-types.hpp> 32 33 #include <array> 34 #include <cstring> 35 #include <fstream> 36 #include <iomanip> 37 #include <iostream> 38 #include <sstream> 39 #include <string> 40 #include <vector> 41 42 #define SIZE_IANA_ID 3 43 44 namespace ipmi 45 { 46 47 using namespace phosphor::logging; 48 49 static void registerOEMFunctions() __attribute__((constructor)); 50 sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h 51 static constexpr size_t maxFRUStringLength = 0x3F; 52 constexpr uint8_t cmdSetSystemGuid = 0xEF; 53 54 int plat_udbg_get_post_desc(uint8_t, uint8_t*, uint8_t, uint8_t*, uint8_t*, 55 uint8_t*); 56 int plat_udbg_get_gpio_desc(uint8_t, uint8_t*, uint8_t*, uint8_t*, uint8_t*, 57 uint8_t*); 58 ipmi_ret_t plat_udbg_get_frame_data(uint8_t, uint8_t, uint8_t*, uint8_t*, 59 uint8_t*); 60 ipmi_ret_t plat_udbg_control_panel(uint8_t, uint8_t, uint8_t, uint8_t*, 61 uint8_t*); 62 int sendMeCmd(uint8_t, uint8_t, std::vector<uint8_t>&, std::vector<uint8_t>&); 63 64 int sendBicCmd(uint8_t, uint8_t, uint8_t, std::vector<uint8_t>&, 65 std::vector<uint8_t>&); 66 67 nlohmann::json oemData __attribute__((init_priority(101))); 68 69 static constexpr size_t GUID_SIZE = 16; 70 // TODO Make offset and location runtime configurable to ensure we 71 // can make each define their own locations. 72 static constexpr off_t OFFSET_SYS_GUID = 0x17F0; 73 static constexpr const char* FRU_EEPROM = "/sys/bus/i2c/devices/6-0054/eeprom"; 74 75 enum class LanParam : uint8_t 76 { 77 INPROGRESS = 0, 78 AUTHSUPPORT = 1, 79 AUTHENABLES = 2, 80 IP = 3, 81 IPSRC = 4, 82 MAC = 5, 83 SUBNET = 6, 84 GATEWAY = 12, 85 VLAN = 20, 86 CIPHER_SUITE_COUNT = 22, 87 CIPHER_SUITE_ENTRIES = 23, 88 IPV6 = 59, 89 }; 90 91 namespace network 92 { 93 94 constexpr auto ROOT = "/xyz/openbmc_project/network"; 95 constexpr auto SERVICE = "xyz.openbmc_project.Network"; 96 constexpr auto IPV4_TYPE = "ipv4"; 97 constexpr auto IPV6_TYPE = "ipv6"; 98 constexpr auto IPV4_PREFIX = "169.254"; 99 constexpr auto IPV6_PREFIX = "fe80"; 100 constexpr auto IP_INTERFACE = "xyz.openbmc_project.Network.IP"; 101 constexpr auto MAC_INTERFACE = "xyz.openbmc_project.Network.MACAddress"; 102 103 bool isLinkLocalIP(const std::string& address) 104 { 105 return address.find(IPV4_PREFIX) == 0 || address.find(IPV6_PREFIX) == 0; 106 } 107 108 DbusObjectInfo getIPObject(sdbusplus::bus::bus& bus, 109 const std::string& interface, 110 const std::string& serviceRoot, 111 const std::string& match) 112 { 113 auto objectTree = getAllDbusObjects(bus, serviceRoot, interface, match); 114 115 if (objectTree.empty()) 116 { 117 log<level::ERR>("No Object has implemented the IP interface", 118 entry("INTERFACE=%s", interface.c_str())); 119 } 120 121 DbusObjectInfo objectInfo; 122 123 for (auto& object : objectTree) 124 { 125 auto variant = 126 ipmi::getDbusProperty(bus, object.second.begin()->first, 127 object.first, IP_INTERFACE, "Address"); 128 129 objectInfo = std::make_pair(object.first, object.second.begin()->first); 130 131 // if LinkLocalIP found look for Non-LinkLocalIP 132 if (isLinkLocalIP(std::get<std::string>(variant))) 133 { 134 continue; 135 } 136 else 137 { 138 break; 139 } 140 } 141 return objectInfo; 142 } 143 144 } // namespace network 145 146 namespace boot 147 { 148 149 using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server; 150 using IpmiValue = uint8_t; 151 152 std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = { 153 {0x0f, Source::Sources::Default}, 154 {0x00, Source::Sources::RemovableMedia}, 155 {0x01, Source::Sources::Network}, 156 {0x02, Source::Sources::Disk}, 157 {0x03, Source::Sources::ExternalMedia}, 158 {0x09, Source::Sources::Network}}; 159 160 std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = { 161 {0x06, Mode::Modes::Setup}, {0x00, Mode::Modes::Regular}}; 162 163 std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = { 164 {Source::Sources::Default, 0x0f}, 165 {Source::Sources::RemovableMedia, 0x00}, 166 {Source::Sources::Network, 0x01}, 167 {Source::Sources::Disk, 0x02}, 168 {Source::Sources::ExternalMedia, 0x03}}; 169 170 std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = { 171 {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, 0x00}}; 172 173 static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode"; 174 static constexpr auto bootSourceIntf = 175 "xyz.openbmc_project.Control.Boot.Source"; 176 static constexpr auto bootSourceProp = "BootSource"; 177 static constexpr auto bootModeProp = "BootMode"; 178 179 auto instances(std::string s) 180 { 181 std::string delimiter = " "; 182 size_t pos = 0; 183 std::string token; 184 std::vector<std::string> host; 185 186 while ((pos = s.find(delimiter)) != std::string::npos) 187 { 188 token = s.substr(0, pos); 189 host.push_back(token); 190 s.erase(0, pos + delimiter.length()); 191 } 192 host.push_back(s); 193 194 return host; 195 } 196 197 std::optional<size_t> findHost(size_t id) 198 { 199 std::string str = INSTANCES; 200 size_t hostId; 201 202 if (INSTANCES == "0") 203 { 204 hostId = id; 205 } 206 else 207 { 208 static const auto hosts = instances(str); 209 std::string num = std::to_string(id + 1); 210 auto instance = std::lower_bound(hosts.begin(), hosts.end(), num); 211 212 if ((instance == hosts.end()) || (*instance != num)) 213 { 214 return std::nullopt; 215 } 216 hostId = id + 1; 217 } 218 219 return hostId; 220 } 221 222 std::tuple<std::string, std::string> objPath(size_t id) 223 { 224 std::string hostName = "host" + std::to_string(id); 225 std::string bootObjPath = 226 "/xyz/openbmc_project/control/" + hostName + "/boot"; 227 return std::make_tuple(std::move(bootObjPath), std::move(hostName)); 228 } 229 230 } // namespace boot 231 232 //---------------------------------------------------------------------- 233 // Helper functions for storing oem data 234 //---------------------------------------------------------------------- 235 236 void flushOemData() 237 { 238 std::ofstream file(JSON_OEM_DATA_FILE); 239 file << oemData; 240 file.close(); 241 return; 242 } 243 244 std::string bytesToStr(uint8_t* byte, int len) 245 { 246 std::stringstream ss; 247 int i; 248 249 ss << std::hex; 250 for (i = 0; i < len; i++) 251 { 252 ss << std::setw(2) << std::setfill('0') << (int)byte[i]; 253 } 254 255 return ss.str(); 256 } 257 258 int strToBytes(std::string& str, uint8_t* data) 259 { 260 std::string sstr; 261 int i; 262 263 for (i = 0; i < (str.length()) / 2; i++) 264 { 265 sstr = str.substr(i * 2, 2); 266 data[i] = (uint8_t)std::strtol(sstr.c_str(), NULL, 16); 267 } 268 return i; 269 } 270 271 ipmi_ret_t getNetworkData(uint8_t lan_param, char* data) 272 { 273 ipmi_ret_t rc = IPMI_CC_OK; 274 sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection()); 275 276 const std::string ethdevice = "eth0"; 277 278 switch (static_cast<LanParam>(lan_param)) 279 { 280 case LanParam::IP: 281 { 282 auto ethIP = ethdevice + "/" + ipmi::network::IPV4_TYPE; 283 std::string ipaddress; 284 auto ipObjectInfo = ipmi::network::getIPObject( 285 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP); 286 287 auto properties = ipmi::getAllDbusProperties( 288 bus, ipObjectInfo.second, ipObjectInfo.first, 289 ipmi::network::IP_INTERFACE); 290 291 ipaddress = std::get<std::string>(properties["Address"]); 292 293 std::strcpy(data, ipaddress.c_str()); 294 } 295 break; 296 297 case LanParam::IPV6: 298 { 299 auto ethIP = ethdevice + "/" + ipmi::network::IPV6_TYPE; 300 std::string ipaddress; 301 auto ipObjectInfo = ipmi::network::getIPObject( 302 bus, ipmi::network::IP_INTERFACE, ipmi::network::ROOT, ethIP); 303 304 auto properties = ipmi::getAllDbusProperties( 305 bus, ipObjectInfo.second, ipObjectInfo.first, 306 ipmi::network::IP_INTERFACE); 307 308 ipaddress = std::get<std::string>(properties["Address"]); 309 310 std::strcpy(data, ipaddress.c_str()); 311 } 312 break; 313 314 case LanParam::MAC: 315 { 316 std::string macAddress; 317 auto macObjectInfo = 318 ipmi::getDbusObject(bus, ipmi::network::MAC_INTERFACE, 319 ipmi::network::ROOT, ethdevice); 320 321 auto variant = ipmi::getDbusProperty( 322 bus, macObjectInfo.second, macObjectInfo.first, 323 ipmi::network::MAC_INTERFACE, "MACAddress"); 324 325 macAddress = std::get<std::string>(variant); 326 327 sscanf(macAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT, 328 (data), (data + 1), (data + 2), (data + 3), (data + 4), 329 (data + 5)); 330 std::strcpy(data, macAddress.c_str()); 331 } 332 break; 333 334 default: 335 rc = IPMI_CC_PARM_OUT_OF_RANGE; 336 } 337 return rc; 338 } 339 340 // return code: 0 successful 341 int8_t getFruData(std::string& data, std::string& name) 342 { 343 std::string objpath = "/xyz/openbmc_project/FruDevice"; 344 std::string intf = "xyz.openbmc_project.FruDeviceManager"; 345 std::string service = getService(dbus, intf, objpath); 346 ObjectValueTree valueTree = getManagedObjects(dbus, service, "/"); 347 if (valueTree.empty()) 348 { 349 phosphor::logging::log<phosphor::logging::level::ERR>( 350 "No object implements interface", 351 phosphor::logging::entry("INTF=%s", intf.c_str())); 352 return -1; 353 } 354 355 for (const auto& item : valueTree) 356 { 357 auto interface = item.second.find("xyz.openbmc_project.FruDevice"); 358 if (interface == item.second.end()) 359 { 360 continue; 361 } 362 363 auto property = interface->second.find(name.c_str()); 364 if (property == interface->second.end()) 365 { 366 continue; 367 } 368 369 try 370 { 371 Value variant = property->second; 372 std::string& result = std::get<std::string>(variant); 373 if (result.size() > maxFRUStringLength) 374 { 375 phosphor::logging::log<phosphor::logging::level::ERR>( 376 "FRU serial number exceed maximum length"); 377 return -1; 378 } 379 data = result; 380 return 0; 381 } 382 catch (const std::bad_variant_access& e) 383 { 384 phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 385 return -1; 386 } 387 } 388 return -1; 389 } 390 391 typedef struct 392 { 393 uint8_t cur_power_state; 394 uint8_t last_power_event; 395 uint8_t misc_power_state; 396 uint8_t front_panel_button_cap_status; 397 } ipmi_get_chassis_status_t; 398 399 //---------------------------------------------------------------------- 400 // Get Debug Frame Info 401 //---------------------------------------------------------------------- 402 ipmi_ret_t ipmiOemDbgGetFrameInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 403 ipmi_request_t request, 404 ipmi_response_t response, 405 ipmi_data_len_t data_len, 406 ipmi_context_t context) 407 { 408 uint8_t* req = reinterpret_cast<uint8_t*>(request); 409 uint8_t* res = reinterpret_cast<uint8_t*>(response); 410 uint8_t num_frames = 3; 411 412 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID 413 res[SIZE_IANA_ID] = num_frames; 414 *data_len = SIZE_IANA_ID + 1; 415 416 return IPMI_CC_OK; 417 } 418 419 //---------------------------------------------------------------------- 420 // Get Debug Updated Frames 421 //---------------------------------------------------------------------- 422 ipmi_ret_t ipmiOemDbgGetUpdFrames(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 423 ipmi_request_t request, 424 ipmi_response_t response, 425 ipmi_data_len_t data_len, 426 ipmi_context_t context) 427 { 428 uint8_t* req = reinterpret_cast<uint8_t*>(request); 429 uint8_t* res = reinterpret_cast<uint8_t*>(response); 430 uint8_t num_updates = 3; 431 *data_len = 4; 432 433 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID 434 res[SIZE_IANA_ID] = num_updates; 435 *data_len = SIZE_IANA_ID + num_updates + 1; 436 res[SIZE_IANA_ID + 1] = 1; // info page update 437 res[SIZE_IANA_ID + 2] = 2; // cri sel update 438 res[SIZE_IANA_ID + 3] = 3; // cri sensor update 439 440 return IPMI_CC_OK; 441 } 442 443 //---------------------------------------------------------------------- 444 // Get Debug POST Description 445 //---------------------------------------------------------------------- 446 ipmi_ret_t ipmiOemDbgGetPostDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 447 ipmi_request_t request, 448 ipmi_response_t response, 449 ipmi_data_len_t data_len, 450 ipmi_context_t context) 451 { 452 uint8_t* req = reinterpret_cast<uint8_t*>(request); 453 uint8_t* res = reinterpret_cast<uint8_t*>(response); 454 uint8_t index = 0; 455 uint8_t next = 0; 456 uint8_t end = 0; 457 uint8_t phase = 0; 458 uint8_t descLen = 0; 459 int ret; 460 461 index = req[3]; 462 phase = req[4]; 463 464 ret = plat_udbg_get_post_desc(index, &next, phase, &end, &descLen, &res[8]); 465 if (ret) 466 { 467 memcpy(res, req, SIZE_IANA_ID); // IANA ID 468 *data_len = SIZE_IANA_ID; 469 return IPMI_CC_UNSPECIFIED_ERROR; 470 } 471 472 memcpy(res, req, SIZE_IANA_ID); // IANA ID 473 res[3] = index; 474 res[4] = next; 475 res[5] = phase; 476 res[6] = end; 477 res[7] = descLen; 478 *data_len = SIZE_IANA_ID + 5 + descLen; 479 480 return IPMI_CC_OK; 481 } 482 483 //---------------------------------------------------------------------- 484 // Get Debug GPIO Description 485 //---------------------------------------------------------------------- 486 ipmi_ret_t ipmiOemDbgGetGpioDesc(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 487 ipmi_request_t request, 488 ipmi_response_t response, 489 ipmi_data_len_t data_len, 490 ipmi_context_t context) 491 { 492 uint8_t* req = reinterpret_cast<uint8_t*>(request); 493 uint8_t* res = reinterpret_cast<uint8_t*>(response); 494 495 uint8_t index = 0; 496 uint8_t next = 0; 497 uint8_t level = 0; 498 uint8_t pinDef = 0; 499 uint8_t descLen = 0; 500 int ret; 501 502 index = req[3]; 503 504 ret = plat_udbg_get_gpio_desc(index, &next, &level, &pinDef, &descLen, 505 &res[8]); 506 if (ret) 507 { 508 memcpy(res, req, SIZE_IANA_ID); // IANA ID 509 *data_len = SIZE_IANA_ID; 510 return IPMI_CC_UNSPECIFIED_ERROR; 511 } 512 513 memcpy(res, req, SIZE_IANA_ID); // IANA ID 514 res[3] = index; 515 res[4] = next; 516 res[5] = level; 517 res[6] = pinDef; 518 res[7] = descLen; 519 *data_len = SIZE_IANA_ID + 5 + descLen; 520 521 return IPMI_CC_OK; 522 } 523 524 //---------------------------------------------------------------------- 525 // Get Debug Frame Data 526 //---------------------------------------------------------------------- 527 ipmi_ret_t ipmiOemDbgGetFrameData(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 528 ipmi_request_t request, 529 ipmi_response_t response, 530 ipmi_data_len_t data_len, 531 ipmi_context_t context) 532 { 533 uint8_t* req = reinterpret_cast<uint8_t*>(request); 534 uint8_t* res = reinterpret_cast<uint8_t*>(response); 535 uint8_t frame; 536 uint8_t page; 537 uint8_t next; 538 uint8_t count; 539 int ret; 540 541 frame = req[3]; 542 page = req[4]; 543 int fr = frame; 544 int pg = page; 545 546 ret = plat_udbg_get_frame_data(frame, page, &next, &count, &res[7]); 547 if (ret) 548 { 549 memcpy(res, req, SIZE_IANA_ID); // IANA ID 550 *data_len = SIZE_IANA_ID; 551 return IPMI_CC_UNSPECIFIED_ERROR; 552 } 553 554 memcpy(res, req, SIZE_IANA_ID); // IANA ID 555 res[3] = frame; 556 res[4] = page; 557 res[5] = next; 558 res[6] = count; 559 *data_len = SIZE_IANA_ID + 4 + count; 560 561 return IPMI_CC_OK; 562 } 563 564 //---------------------------------------------------------------------- 565 // Get Debug Control Panel 566 //---------------------------------------------------------------------- 567 ipmi_ret_t ipmiOemDbgGetCtrlPanel(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 568 ipmi_request_t request, 569 ipmi_response_t response, 570 ipmi_data_len_t data_len, 571 ipmi_context_t context) 572 { 573 uint8_t* req = reinterpret_cast<uint8_t*>(request); 574 uint8_t* res = reinterpret_cast<uint8_t*>(response); 575 576 uint8_t panel; 577 uint8_t operation; 578 uint8_t item; 579 uint8_t count; 580 ipmi_ret_t ret; 581 582 panel = req[3]; 583 operation = req[4]; 584 item = req[5]; 585 586 ret = plat_udbg_control_panel(panel, operation, item, &count, &res[3]); 587 588 std::memcpy(res, req, SIZE_IANA_ID); // IANA ID 589 *data_len = SIZE_IANA_ID + count; 590 591 return ret; 592 } 593 594 //---------------------------------------------------------------------- 595 // Set Dimm Info (CMD_OEM_SET_DIMM_INFO) 596 //---------------------------------------------------------------------- 597 ipmi_ret_t ipmiOemSetDimmInfo(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 uint8_t* req = reinterpret_cast<uint8_t*>(request); 602 603 uint8_t index = req[0]; 604 uint8_t type = req[1]; 605 uint16_t speed; 606 uint32_t size; 607 608 memcpy(&speed, &req[2], 2); 609 memcpy(&size, &req[4], 4); 610 611 std::stringstream ss; 612 ss << std::hex; 613 ss << std::setw(2) << std::setfill('0') << (int)index; 614 615 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_INDEX] = index; 616 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_TYPE] = type; 617 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SPEED] = speed; 618 oemData[KEY_SYS_CONFIG][ss.str()][KEY_DIMM_SIZE] = size; 619 620 flushOemData(); 621 622 *data_len = 0; 623 624 return IPMI_CC_OK; 625 } 626 627 //---------------------------------------------------------------------- 628 // Get Board ID (CMD_OEM_GET_BOARD_ID) 629 //---------------------------------------------------------------------- 630 ipmi_ret_t ipmiOemGetBoardID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 631 ipmi_request_t request, ipmi_response_t response, 632 ipmi_data_len_t data_len, ipmi_context_t context) 633 { 634 uint8_t* req = reinterpret_cast<uint8_t*>(request); 635 uint8_t* res = reinterpret_cast<uint8_t*>(response); 636 637 /* TODO: Needs to implement this after GPIO implementation */ 638 *data_len = 0; 639 640 return IPMI_CC_OK; 641 } 642 643 /* Helper functions to set boot order */ 644 void setBootOrder(std::string bootObjPath, uint8_t* data, 645 std::string bootOrderKey) 646 { 647 648 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 649 650 // SETTING BOOT MODE PROPERTY 651 auto bootValue = ipmi::boot::modeIpmiToDbus.find((data[0])); 652 std::string bootOption = 653 ipmi::boot::Mode::convertModesToString((bootValue->second)); 654 655 std::string service = 656 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath); 657 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf, 658 ipmi::boot::bootModeProp, bootOption); 659 660 // SETTING BOOT SOURCE PROPERTY 661 auto bootOrder = ipmi::boot::sourceIpmiToDbus.find((data[1])); 662 std::string bootSource = 663 ipmi::boot::Source::convertSourcesToString((bootOrder->second)); 664 665 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath); 666 setDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf, 667 ipmi::boot::bootSourceProp, bootSource); 668 669 nlohmann::json bootMode; 670 uint8_t mode = data[0]; 671 int i; 672 673 bootMode["UEFI"] = (mode & BOOT_MODE_UEFI ? true : false); 674 bootMode["CMOS_CLR"] = (mode & BOOT_MODE_CMOS_CLR ? true : false); 675 bootMode["FORCE_BOOT"] = (mode & BOOT_MODE_FORCE_BOOT ? true : false); 676 bootMode["BOOT_FLAG"] = (mode & BOOT_MODE_BOOT_FLAG ? true : false); 677 oemData[bootOrderKey][KEY_BOOT_MODE] = bootMode; 678 679 /* Initialize boot sequence array */ 680 oemData[bootOrderKey][KEY_BOOT_SEQ] = {}; 681 for (i = 1; i < SIZE_BOOT_ORDER; i++) 682 { 683 if (data[i] >= BOOT_SEQ_ARRAY_SIZE) 684 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = "NA"; 685 else 686 oemData[bootOrderKey][KEY_BOOT_SEQ][i - 1] = bootSeq[data[i]]; 687 } 688 689 flushOemData(); 690 } 691 692 //---------------------------------------------------------------------- 693 // Set Boot Order (CMD_OEM_SET_BOOT_ORDER) 694 //---------------------------------------------------------------------- 695 ipmi::RspType<std::vector<uint8_t>> 696 ipmiOemSetBootOrder(ipmi::Context::ptr ctx, std::vector<uint8_t> data) 697 { 698 699 uint8_t bootSeq[SIZE_BOOT_ORDER]; 700 size_t len = data.size(); 701 702 if (len != SIZE_BOOT_ORDER) 703 { 704 phosphor::logging::log<phosphor::logging::level::ERR>( 705 "Invalid Boot order length received"); 706 return ipmi::responseReqDataLenInvalid(); 707 } 708 709 std::copy(std::begin(data), std::end(data), bootSeq); 710 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx); 711 712 if (!hostId) 713 { 714 phosphor::logging::log<phosphor::logging::level::ERR>( 715 "Invalid Host Id received"); 716 return ipmi::responseInvalidCommand(); 717 } 718 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId); 719 720 setBootOrder(bootObjPath, bootSeq, hostName); 721 722 return ipmi::responseSuccess(data); 723 } 724 725 //---------------------------------------------------------------------- 726 // Get Boot Order (CMD_OEM_GET_BOOT_ORDER) 727 //---------------------------------------------------------------------- 728 ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t> 729 ipmiOemGetBootOrder(ipmi::Context::ptr ctx) 730 { 731 uint8_t bootOption, bootOrder; 732 uint8_t bootSeq[SIZE_BOOT_ORDER]; 733 uint8_t mode = 0; 734 735 std::optional<size_t> hostId = ipmi::boot::findHost(ctx->hostIdx); 736 737 if (!hostId) 738 { 739 phosphor::logging::log<phosphor::logging::level::ERR>( 740 "Invalid Host Id received"); 741 return ipmi::responseInvalidCommand(); 742 } 743 auto [bootObjPath, hostName] = ipmi::boot::objPath(*hostId); 744 745 // GETTING PROPERTY OF MODE INTERFACE 746 747 std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 748 749 std::string service = 750 getService(*dbus, ipmi::boot::bootModeIntf, bootObjPath); 751 Value variant = 752 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootModeIntf, 753 ipmi::boot::bootModeProp); 754 755 auto bootMode = ipmi::boot::Mode::convertModesFromString( 756 std::get<std::string>(variant)); 757 758 bootOption = ipmi::boot::modeDbusToIpmi.at(bootMode); 759 760 // GETTING PROPERTY OF SOURCE INTERFACE 761 762 service = getService(*dbus, ipmi::boot::bootSourceIntf, bootObjPath); 763 variant = 764 getDbusProperty(*dbus, service, bootObjPath, ipmi::boot::bootSourceIntf, 765 ipmi::boot::bootSourceProp); 766 auto bootSource = ipmi::boot::Source::convertSourcesFromString( 767 std::get<std::string>(variant)); 768 769 bootOrder = ipmi::boot::sourceDbusToIpmi.at(bootSource); 770 771 if (oemData.find(hostName) == oemData.end()) 772 { 773 /* Return default boot order 0100090203ff */ 774 uint8_t defaultBoot[SIZE_BOOT_ORDER] = { 775 BOOT_MODE_UEFI, bootMap["USB_DEV"], bootMap["NET_IPV6"], 776 bootMap["SATA_HDD"], bootMap["SATA_CD"], 0xff}; 777 778 memcpy(bootSeq, defaultBoot, SIZE_BOOT_ORDER); 779 phosphor::logging::log<phosphor::logging::level::INFO>( 780 "Set default boot order"); 781 setBootOrder(bootObjPath, defaultBoot, hostName); 782 } 783 else 784 { 785 nlohmann::json bootMode = oemData[hostName][KEY_BOOT_MODE]; 786 if (bootMode["UEFI"]) 787 mode |= BOOT_MODE_UEFI; 788 if (bootMode["CMOS_CLR"]) 789 mode |= BOOT_MODE_CMOS_CLR; 790 if (bootMode["BOOT_FLAG"]) 791 mode |= BOOT_MODE_BOOT_FLAG; 792 793 bootSeq[0] = mode; 794 795 for (int i = 1; i < SIZE_BOOT_ORDER; i++) 796 { 797 std::string seqStr = oemData[hostName][KEY_BOOT_SEQ][i - 1]; 798 if (bootMap.find(seqStr) != bootMap.end()) 799 bootSeq[i] = bootMap[seqStr]; 800 else 801 bootSeq[i] = 0xff; 802 } 803 } 804 805 return ipmi::responseSuccess(bootOption, bootOrder, bootSeq[2], bootSeq[3], 806 bootSeq[4], bootSeq[5]); 807 } 808 // Set Machine Config Info (CMD_OEM_SET_MACHINE_CONFIG_INFO) 809 //---------------------------------------------------------------------- 810 ipmi_ret_t ipmiOemSetMachineCfgInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 811 ipmi_request_t request, 812 ipmi_response_t response, 813 ipmi_data_len_t data_len, 814 ipmi_context_t context) 815 { 816 machineConfigInfo_t* req = reinterpret_cast<machineConfigInfo_t*>(request); 817 uint8_t len = *data_len; 818 819 *data_len = 0; 820 821 if (len < sizeof(machineConfigInfo_t)) 822 { 823 phosphor::logging::log<phosphor::logging::level::ERR>( 824 "Invalid machine configuration length received"); 825 return IPMI_CC_REQ_DATA_LEN_INVALID; 826 } 827 828 if (req->chassis_type >= sizeof(chassisType) / sizeof(uint8_t*)) 829 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = "UNKNOWN"; 830 else 831 oemData[KEY_MC_CONFIG][KEY_MC_CHAS_TYPE] = 832 chassisType[req->chassis_type]; 833 834 if (req->mb_type >= sizeof(mbType) / sizeof(uint8_t*)) 835 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = "UNKNOWN"; 836 else 837 oemData[KEY_MC_CONFIG][KEY_MC_MB_TYPE] = mbType[req->mb_type]; 838 839 oemData[KEY_MC_CONFIG][KEY_MC_PROC_CNT] = req->proc_cnt; 840 oemData[KEY_MC_CONFIG][KEY_MC_MEM_CNT] = req->mem_cnt; 841 oemData[KEY_MC_CONFIG][KEY_MC_HDD35_CNT] = req->hdd35_cnt; 842 oemData[KEY_MC_CONFIG][KEY_MC_HDD25_CNT] = req->hdd25_cnt; 843 844 if (req->riser_type >= sizeof(riserType) / sizeof(uint8_t*)) 845 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = "UNKNOWN"; 846 else 847 oemData[KEY_MC_CONFIG][KEY_MC_RSR_TYPE] = riserType[req->riser_type]; 848 849 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC] = {}; 850 int i = 0; 851 if (req->pcie_card_loc & BIT_0) 852 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT1"; 853 if (req->pcie_card_loc & BIT_1) 854 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT2"; 855 if (req->pcie_card_loc & BIT_2) 856 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT3"; 857 if (req->pcie_card_loc & BIT_3) 858 oemData[KEY_MC_CONFIG][KEY_MC_PCIE_LOC][i++] = "SLOT4"; 859 860 if (req->slot1_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*)) 861 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = "UNKNOWN"; 862 else 863 oemData[KEY_MC_CONFIG][KEY_MC_SLOT1_TYPE] = 864 pcieType[req->slot1_pcie_type]; 865 866 if (req->slot2_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*)) 867 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = "UNKNOWN"; 868 else 869 oemData[KEY_MC_CONFIG][KEY_MC_SLOT2_TYPE] = 870 pcieType[req->slot2_pcie_type]; 871 872 if (req->slot3_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*)) 873 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = "UNKNOWN"; 874 else 875 oemData[KEY_MC_CONFIG][KEY_MC_SLOT3_TYPE] = 876 pcieType[req->slot3_pcie_type]; 877 878 if (req->slot4_pcie_type >= sizeof(pcieType) / sizeof(uint8_t*)) 879 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = "UNKNOWN"; 880 else 881 oemData[KEY_MC_CONFIG][KEY_MC_SLOT4_TYPE] = 882 pcieType[req->slot4_pcie_type]; 883 884 oemData[KEY_MC_CONFIG][KEY_MC_AEP_CNT] = req->aep_mem_cnt; 885 886 flushOemData(); 887 888 return IPMI_CC_OK; 889 } 890 891 //---------------------------------------------------------------------- 892 // Set POST start (CMD_OEM_SET_POST_START) 893 //---------------------------------------------------------------------- 894 ipmi_ret_t ipmiOemSetPostStart(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 895 ipmi_request_t request, ipmi_response_t response, 896 ipmi_data_len_t data_len, ipmi_context_t context) 897 { 898 phosphor::logging::log<phosphor::logging::level::INFO>("POST Start Event"); 899 900 /* Do nothing, return success */ 901 *data_len = 0; 902 return IPMI_CC_OK; 903 } 904 905 //---------------------------------------------------------------------- 906 // Set POST End (CMD_OEM_SET_POST_END) 907 //---------------------------------------------------------------------- 908 ipmi_ret_t ipmiOemSetPostEnd(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 909 ipmi_request_t request, ipmi_response_t response, 910 ipmi_data_len_t data_len, ipmi_context_t context) 911 { 912 struct timespec ts; 913 914 phosphor::logging::log<phosphor::logging::level::INFO>("POST End Event"); 915 916 *data_len = 0; 917 918 // Timestamp post end time. 919 clock_gettime(CLOCK_REALTIME, &ts); 920 oemData[KEY_TS_SLED] = ts.tv_sec; 921 flushOemData(); 922 923 // Sync time with system 924 // TODO: Add code for syncing time 925 926 return IPMI_CC_OK; 927 } 928 929 //---------------------------------------------------------------------- 930 // Set PPIN Info (CMD_OEM_SET_PPIN_INFO) 931 //---------------------------------------------------------------------- 932 // Inform BMC about PPIN data of 8 bytes for each CPU 933 // 934 // Request: 935 // Byte 1:8 – CPU0 PPIN data 936 // Optional: 937 // Byte 9:16 – CPU1 PPIN data 938 // 939 // Response: 940 // Byte 1 – Completion Code 941 ipmi_ret_t ipmiOemSetPPINInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 942 ipmi_request_t request, ipmi_response_t response, 943 ipmi_data_len_t data_len, ipmi_context_t context) 944 { 945 uint8_t* req = reinterpret_cast<uint8_t*>(request); 946 std::string ppinStr; 947 int len; 948 949 if (*data_len > SIZE_CPU_PPIN * 2) 950 len = SIZE_CPU_PPIN * 2; 951 else 952 len = *data_len; 953 *data_len = 0; 954 955 ppinStr = bytesToStr(req, len); 956 oemData[KEY_PPIN_INFO] = ppinStr.c_str(); 957 flushOemData(); 958 959 return IPMI_CC_OK; 960 } 961 962 //---------------------------------------------------------------------- 963 // Set ADR Trigger (CMD_OEM_SET_ADR_TRIGGER) 964 //---------------------------------------------------------------------- 965 ipmi_ret_t ipmiOemSetAdrTrigger(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 966 ipmi_request_t request, 967 ipmi_response_t response, 968 ipmi_data_len_t data_len, 969 ipmi_context_t context) 970 { 971 /* Do nothing, return success */ 972 *data_len = 0; 973 return IPMI_CC_OK; 974 } 975 976 // Helper function to set guid at offset in EEPROM 977 static int setGUID(off_t offset, uint8_t* guid) 978 { 979 int fd = -1; 980 ssize_t len; 981 int ret = 0; 982 983 errno = 0; 984 985 // Check if file is present 986 if (access(FRU_EEPROM, F_OK) == -1) 987 { 988 std::cerr << "Unable to access: " << FRU_EEPROM << std::endl; 989 return errno; 990 } 991 992 // Open the file 993 fd = open(FRU_EEPROM, O_WRONLY); 994 if (fd == -1) 995 { 996 std::cerr << "Unable to open: " << FRU_EEPROM << std::endl; 997 return errno; 998 } 999 1000 // seek to the offset 1001 lseek(fd, offset, SEEK_SET); 1002 1003 // Write bytes to location 1004 len = write(fd, guid, GUID_SIZE); 1005 if (len != GUID_SIZE) 1006 { 1007 phosphor::logging::log<phosphor::logging::level::ERR>( 1008 "GUID write data to EEPROM failed"); 1009 ret = errno; 1010 } 1011 1012 close(fd); 1013 return ret; 1014 } 1015 1016 //---------------------------------------------------------------------- 1017 // Set System GUID (CMD_OEM_SET_SYSTEM_GUID) 1018 //---------------------------------------------------------------------- 1019 #if BIC_ENABLED 1020 ipmi::RspType<> ipmiOemSetSystemGuid(ipmi::Context::ptr ctx, uint8_t cmdReq, 1021 std::vector<uint8_t> reqData) 1022 { 1023 std::vector<uint8_t> respData; 1024 1025 if (reqData.size() != GUID_SIZE) // 16bytes 1026 { 1027 1028 return ipmi::responseReqDataLenInvalid(); 1029 } 1030 1031 auto ptrReqData = reqData.insert(reqData.begin(), reqData.size()); 1032 1033 uint8_t bicAddr = (uint8_t)ctx->hostIdx << 2; 1034 1035 if (sendBicCmd(ctx->netFn, ctx->cmd, bicAddr, reqData, respData)) 1036 return ipmi::responseUnspecifiedError(); 1037 1038 return ipmi::responseSuccess(); 1039 } 1040 1041 #else 1042 ipmi_ret_t ipmiOemSetSystemGuid(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1043 ipmi_request_t request, 1044 ipmi_response_t response, 1045 ipmi_data_len_t data_len, 1046 ipmi_context_t context) 1047 { 1048 uint8_t* req = reinterpret_cast<uint8_t*>(request); 1049 1050 if (*data_len != GUID_SIZE) // 16bytes 1051 { 1052 *data_len = 0; 1053 return IPMI_CC_REQ_DATA_LEN_INVALID; 1054 } 1055 1056 *data_len = 0; 1057 1058 if (setGUID(OFFSET_SYS_GUID, req)) 1059 { 1060 return IPMI_CC_UNSPECIFIED_ERROR; 1061 } 1062 return IPMI_CC_OK; 1063 } 1064 #endif 1065 1066 //---------------------------------------------------------------------- 1067 // Set Bios Flash Info (CMD_OEM_SET_BIOS_FLASH_INFO) 1068 //---------------------------------------------------------------------- 1069 ipmi_ret_t ipmiOemSetBiosFlashInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1070 ipmi_request_t request, 1071 ipmi_response_t response, 1072 ipmi_data_len_t data_len, 1073 ipmi_context_t context) 1074 { 1075 /* Do nothing, return success */ 1076 *data_len = 0; 1077 return IPMI_CC_OK; 1078 } 1079 1080 //---------------------------------------------------------------------- 1081 // Set PPR (CMD_OEM_SET_PPR) 1082 //---------------------------------------------------------------------- 1083 ipmi_ret_t ipmiOemSetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1084 ipmi_request_t request, ipmi_response_t response, 1085 ipmi_data_len_t data_len, ipmi_context_t context) 1086 { 1087 uint8_t* req = reinterpret_cast<uint8_t*>(request); 1088 uint8_t pprCnt, pprAct, pprIndex; 1089 uint8_t selParam = req[0]; 1090 uint8_t len = *data_len; 1091 std::stringstream ss; 1092 std::string str; 1093 1094 *data_len = 0; 1095 1096 switch (selParam) 1097 { 1098 case PPR_ACTION: 1099 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) == 1100 oemData[KEY_PPR].end()) 1101 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1102 1103 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT]; 1104 if (pprCnt == 0) 1105 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1106 1107 pprAct = req[1]; 1108 /* Check if ppr is enabled or disabled */ 1109 if (!(pprAct & 0x80)) 1110 pprAct = 0; 1111 1112 oemData[KEY_PPR][KEY_PPR_ACTION] = pprAct; 1113 break; 1114 case PPR_ROW_COUNT: 1115 if (req[1] > 100) 1116 return IPMI_CC_PARM_OUT_OF_RANGE; 1117 1118 oemData[KEY_PPR][KEY_PPR_ROW_COUNT] = req[1]; 1119 break; 1120 case PPR_ROW_ADDR: 1121 pprIndex = req[1]; 1122 if (pprIndex > 100) 1123 return IPMI_CC_PARM_OUT_OF_RANGE; 1124 1125 if (len < PPR_ROW_ADDR_LEN + 1) 1126 { 1127 phosphor::logging::log<phosphor::logging::level::ERR>( 1128 "Invalid PPR Row Address length received"); 1129 return IPMI_CC_REQ_DATA_LEN_INVALID; 1130 } 1131 1132 ss << std::hex; 1133 ss << std::setw(2) << std::setfill('0') << (int)pprIndex; 1134 1135 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex; 1136 1137 str = bytesToStr(&req[1], PPR_ROW_ADDR_LEN); 1138 oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR] = str.c_str(); 1139 break; 1140 case PPR_HISTORY_DATA: 1141 pprIndex = req[1]; 1142 if (pprIndex > 100) 1143 return IPMI_CC_PARM_OUT_OF_RANGE; 1144 1145 if (len < PPR_HST_DATA_LEN + 1) 1146 { 1147 phosphor::logging::log<phosphor::logging::level::ERR>( 1148 "Invalid PPR history data length received"); 1149 return IPMI_CC_REQ_DATA_LEN_INVALID; 1150 } 1151 1152 ss << std::hex; 1153 ss << std::setw(2) << std::setfill('0') << (int)pprIndex; 1154 1155 oemData[KEY_PPR][ss.str()][KEY_PPR_INDEX] = pprIndex; 1156 1157 str = bytesToStr(&req[1], PPR_HST_DATA_LEN); 1158 oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA] = str.c_str(); 1159 break; 1160 default: 1161 return IPMI_CC_PARM_OUT_OF_RANGE; 1162 break; 1163 } 1164 1165 flushOemData(); 1166 1167 return IPMI_CC_OK; 1168 } 1169 1170 //---------------------------------------------------------------------- 1171 // Get PPR (CMD_OEM_GET_PPR) 1172 //---------------------------------------------------------------------- 1173 ipmi_ret_t ipmiOemGetPpr(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1174 ipmi_request_t request, ipmi_response_t response, 1175 ipmi_data_len_t data_len, ipmi_context_t context) 1176 { 1177 uint8_t* req = reinterpret_cast<uint8_t*>(request); 1178 uint8_t* res = reinterpret_cast<uint8_t*>(response); 1179 uint8_t pprCnt, pprIndex; 1180 uint8_t selParam = req[0]; 1181 std::stringstream ss; 1182 std::string str; 1183 1184 /* Any failure will return zero length data */ 1185 *data_len = 0; 1186 1187 switch (selParam) 1188 { 1189 case PPR_ACTION: 1190 res[0] = 0; 1191 *data_len = 1; 1192 1193 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) != 1194 oemData[KEY_PPR].end()) 1195 { 1196 pprCnt = oemData[KEY_PPR][KEY_PPR_ROW_COUNT]; 1197 if (pprCnt != 0) 1198 { 1199 if (oemData[KEY_PPR].find(KEY_PPR_ACTION) != 1200 oemData[KEY_PPR].end()) 1201 { 1202 res[0] = oemData[KEY_PPR][KEY_PPR_ACTION]; 1203 } 1204 } 1205 } 1206 break; 1207 case PPR_ROW_COUNT: 1208 res[0] = 0; 1209 *data_len = 1; 1210 if (oemData[KEY_PPR].find(KEY_PPR_ROW_COUNT) != 1211 oemData[KEY_PPR].end()) 1212 res[0] = oemData[KEY_PPR][KEY_PPR_ROW_COUNT]; 1213 break; 1214 case PPR_ROW_ADDR: 1215 pprIndex = req[1]; 1216 if (pprIndex > 100) 1217 return IPMI_CC_PARM_OUT_OF_RANGE; 1218 1219 ss << std::hex; 1220 ss << std::setw(2) << std::setfill('0') << (int)pprIndex; 1221 1222 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end()) 1223 return IPMI_CC_PARM_OUT_OF_RANGE; 1224 1225 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_ROW_ADDR) == 1226 oemData[KEY_PPR][ss.str()].end()) 1227 return IPMI_CC_PARM_OUT_OF_RANGE; 1228 1229 str = oemData[KEY_PPR][ss.str()][KEY_PPR_ROW_ADDR]; 1230 *data_len = strToBytes(str, res); 1231 break; 1232 case PPR_HISTORY_DATA: 1233 pprIndex = req[1]; 1234 if (pprIndex > 100) 1235 return IPMI_CC_PARM_OUT_OF_RANGE; 1236 1237 ss << std::hex; 1238 ss << std::setw(2) << std::setfill('0') << (int)pprIndex; 1239 1240 if (oemData[KEY_PPR].find(ss.str()) == oemData[KEY_PPR].end()) 1241 return IPMI_CC_PARM_OUT_OF_RANGE; 1242 1243 if (oemData[KEY_PPR][ss.str()].find(KEY_PPR_HST_DATA) == 1244 oemData[KEY_PPR][ss.str()].end()) 1245 return IPMI_CC_PARM_OUT_OF_RANGE; 1246 1247 str = oemData[KEY_PPR][ss.str()][KEY_PPR_HST_DATA]; 1248 *data_len = strToBytes(str, res); 1249 break; 1250 default: 1251 return IPMI_CC_PARM_OUT_OF_RANGE; 1252 break; 1253 } 1254 1255 return IPMI_CC_OK; 1256 } 1257 1258 /* FB OEM QC Commands */ 1259 1260 //---------------------------------------------------------------------- 1261 // Set Proc Info (CMD_OEM_Q_SET_PROC_INFO) 1262 //---------------------------------------------------------------------- 1263 //"Request: 1264 // Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first 1265 // Byte 4 – Processor Index, 0 base 1266 // Byte 5 – Parameter Selector 1267 // Byte 6..N – Configuration parameter data (see below for Parameters 1268 // of Processor Information) 1269 // Response: 1270 // Byte 1 – Completion code 1271 // 1272 // Parameter#1: (Processor Product Name) 1273 // 1274 // Byte 1..48 –Product name(ASCII code) 1275 // Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz 1276 // 1277 // Param#2: Processor Basic Information 1278 // Byte 1 – Core Number 1279 // Byte 2 – Thread Number (LSB) 1280 // Byte 3 – Thread Number (MSB) 1281 // Byte 4 – Processor frequency in MHz (LSB) 1282 // Byte 5 – Processor frequency in MHz (MSB) 1283 // Byte 6..7 – Revision 1284 // 1285 ipmi_ret_t ipmiOemQSetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1286 ipmi_request_t request, ipmi_response_t response, 1287 ipmi_data_len_t data_len, ipmi_context_t context) 1288 { 1289 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request); 1290 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*); 1291 std::stringstream ss; 1292 std::string str; 1293 uint8_t len = *data_len; 1294 1295 *data_len = 0; 1296 1297 /* check for requested data params */ 1298 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam) 1299 { 1300 phosphor::logging::log<phosphor::logging::level::ERR>( 1301 "Invalid parameter received"); 1302 return IPMI_CC_PARM_OUT_OF_RANGE; 1303 } 1304 1305 len = len - 5; // Get Actual data length 1306 1307 ss << std::hex; 1308 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex; 1309 oemData[KEY_Q_PROC_INFO][ss.str()][KEY_PROC_INDEX] = req->procIndex; 1310 1311 str = bytesToStr(req->data, len); 1312 oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]] = str.c_str(); 1313 flushOemData(); 1314 1315 return IPMI_CC_OK; 1316 } 1317 1318 //---------------------------------------------------------------------- 1319 // Get Proc Info (CMD_OEM_Q_GET_PROC_INFO) 1320 //---------------------------------------------------------------------- 1321 // Request: 1322 // Byte 1:3 – Manufacturer ID – XXYYZZ h, LSB first 1323 // Byte 4 – Processor Index, 0 base 1324 // Byte 5 – Parameter Selector 1325 // Response: 1326 // Byte 1 – Completion code 1327 // Byte 2..N – Configuration Parameter Data (see below for Parameters 1328 // of Processor Information) 1329 // 1330 // Parameter#1: (Processor Product Name) 1331 // 1332 // Byte 1..48 –Product name(ASCII code) 1333 // Ex. Intel(R) Xeon(R) CPU E5-2685 v3 @ 2.60GHz 1334 // 1335 // Param#2: Processor Basic Information 1336 // Byte 1 – Core Number 1337 // Byte 2 – Thread Number (LSB) 1338 // Byte 3 – Thread Number (MSB) 1339 // Byte 4 – Processor frequency in MHz (LSB) 1340 // Byte 5 – Processor frequency in MHz (MSB) 1341 // Byte 6..7 – Revision 1342 // 1343 ipmi_ret_t ipmiOemQGetProcInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1344 ipmi_request_t request, ipmi_response_t response, 1345 ipmi_data_len_t data_len, ipmi_context_t context) 1346 { 1347 qProcInfo_t* req = reinterpret_cast<qProcInfo_t*>(request); 1348 uint8_t numParam = sizeof(cpuInfoKey) / sizeof(uint8_t*); 1349 uint8_t* res = reinterpret_cast<uint8_t*>(response); 1350 std::stringstream ss; 1351 std::string str; 1352 1353 *data_len = 0; 1354 1355 /* check for requested data params */ 1356 if (req->paramSel < 1 || req->paramSel >= numParam) 1357 { 1358 phosphor::logging::log<phosphor::logging::level::ERR>( 1359 "Invalid parameter received"); 1360 return IPMI_CC_PARM_OUT_OF_RANGE; 1361 } 1362 1363 ss << std::hex; 1364 ss << std::setw(2) << std::setfill('0') << (int)req->procIndex; 1365 1366 if (oemData[KEY_Q_PROC_INFO].find(ss.str()) == 1367 oemData[KEY_Q_PROC_INFO].end()) 1368 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1369 1370 if (oemData[KEY_Q_PROC_INFO][ss.str()].find(cpuInfoKey[req->paramSel]) == 1371 oemData[KEY_Q_PROC_INFO][ss.str()].end()) 1372 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1373 1374 str = oemData[KEY_Q_PROC_INFO][ss.str()][cpuInfoKey[req->paramSel]]; 1375 *data_len = strToBytes(str, res); 1376 1377 return IPMI_CC_OK; 1378 } 1379 1380 //---------------------------------------------------------------------- 1381 // Set Dimm Info (CMD_OEM_Q_SET_DIMM_INFO) 1382 //---------------------------------------------------------------------- 1383 // Request: 1384 // Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first 1385 // Byte 4 – DIMM Index, 0 base 1386 // Byte 5 – Parameter Selector 1387 // Byte 6..N – Configuration parameter data (see below for Parameters 1388 // of DIMM Information) 1389 // Response: 1390 // Byte 1 – Completion code 1391 // 1392 // Param#1 (DIMM Location): 1393 // Byte 1 – DIMM Present 1394 // Byte 1 – DIMM Present 1395 // 01h – Present 1396 // FFh – Not Present 1397 // Byte 2 – Node Number, 0 base 1398 // Byte 3 – Channel Number , 0 base 1399 // Byte 4 – DIMM Number , 0 base 1400 // 1401 // Param#2 (DIMM Type): 1402 // Byte 1 – DIMM Type 1403 // Bit [7:6] 1404 // For DDR3 1405 // 00 – Normal Voltage (1.5V) 1406 // 01 – Ultra Low Voltage (1.25V) 1407 // 10 – Low Voltage (1.35V) 1408 // 11 – Reserved 1409 // For DDR4 1410 // 00 – Reserved 1411 // 01 – Reserved 1412 // 10 – Reserved 1413 // 11 – Normal Voltage (1.2V) 1414 // Bit [5:0] 1415 // 0x00 – SDRAM 1416 // 0x01 – DDR-1 RAM 1417 // 0x02 – Rambus 1418 // 0x03 – DDR-2 RAM 1419 // 0x04 – FBDIMM 1420 // 0x05 – DDR-3 RAM 1421 // 0x06 – DDR-4 RAM 1422 // 1423 // Param#3 (DIMM Speed): 1424 // Byte 1..2 – DIMM speed in MHz, LSB 1425 // Byte 3..6 – DIMM size in Mbytes, LSB 1426 // 1427 // Param#4 (Module Part Number): 1428 // Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C) 1429 // 1430 // Param#5 (Module Serial Number): 1431 // Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C) 1432 // 1433 // Param#6 (Module Manufacturer ID): 1434 // Byte 1 - Module Manufacturer ID, LSB 1435 // Byte 2 - Module Manufacturer ID, MSB 1436 // 1437 ipmi_ret_t ipmiOemQSetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1438 ipmi_request_t request, ipmi_response_t response, 1439 ipmi_data_len_t data_len, ipmi_context_t context) 1440 { 1441 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request); 1442 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*); 1443 std::stringstream ss; 1444 std::string str; 1445 uint8_t len = *data_len; 1446 1447 *data_len = 0; 1448 1449 /* check for requested data params */ 1450 if (len < 5 || req->paramSel < 1 || req->paramSel >= numParam) 1451 { 1452 phosphor::logging::log<phosphor::logging::level::ERR>( 1453 "Invalid parameter received"); 1454 return IPMI_CC_PARM_OUT_OF_RANGE; 1455 } 1456 1457 len = len - 5; // Get Actual data length 1458 1459 ss << std::hex; 1460 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex; 1461 oemData[KEY_Q_DIMM_INFO][ss.str()][KEY_DIMM_INDEX] = req->dimmIndex; 1462 1463 str = bytesToStr(req->data, len); 1464 oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]] = 1465 str.c_str(); 1466 flushOemData(); 1467 1468 return IPMI_CC_OK; 1469 } 1470 1471 //---------------------------------------------------------------------- 1472 // Get Dimm Info (CMD_OEM_Q_GET_DIMM_INFO) 1473 //---------------------------------------------------------------------- 1474 // Request: 1475 // Byte 1:3 – Manufacturer ID – XXYYZZh, LSB first 1476 // Byte 4 – DIMM Index, 0 base 1477 // Byte 5 – Parameter Selector 1478 // Byte 6..N – Configuration parameter data (see below for Parameters 1479 // of DIMM Information) 1480 // Response: 1481 // Byte 1 – Completion code 1482 // Byte 2..N – Configuration Parameter Data (see Table_1213h Parameters 1483 // of DIMM Information) 1484 // 1485 // Param#1 (DIMM Location): 1486 // Byte 1 – DIMM Present 1487 // Byte 1 – DIMM Present 1488 // 01h – Present 1489 // FFh – Not Present 1490 // Byte 2 – Node Number, 0 base 1491 // Byte 3 – Channel Number , 0 base 1492 // Byte 4 – DIMM Number , 0 base 1493 // 1494 // Param#2 (DIMM Type): 1495 // Byte 1 – DIMM Type 1496 // Bit [7:6] 1497 // For DDR3 1498 // 00 – Normal Voltage (1.5V) 1499 // 01 – Ultra Low Voltage (1.25V) 1500 // 10 – Low Voltage (1.35V) 1501 // 11 – Reserved 1502 // For DDR4 1503 // 00 – Reserved 1504 // 01 – Reserved 1505 // 10 – Reserved 1506 // 11 – Normal Voltage (1.2V) 1507 // Bit [5:0] 1508 // 0x00 – SDRAM 1509 // 0x01 – DDR-1 RAM 1510 // 0x02 – Rambus 1511 // 0x03 – DDR-2 RAM 1512 // 0x04 – FBDIMM 1513 // 0x05 – DDR-3 RAM 1514 // 0x06 – DDR-4 RAM 1515 // 1516 // Param#3 (DIMM Speed): 1517 // Byte 1..2 – DIMM speed in MHz, LSB 1518 // Byte 3..6 – DIMM size in Mbytes, LSB 1519 // 1520 // Param#4 (Module Part Number): 1521 // Byte 1..20 –Module Part Number (JEDEC Standard No. 21-C) 1522 // 1523 // Param#5 (Module Serial Number): 1524 // Byte 1..4 –Module Serial Number (JEDEC Standard No. 21-C) 1525 // 1526 // Param#6 (Module Manufacturer ID): 1527 // Byte 1 - Module Manufacturer ID, LSB 1528 // Byte 2 - Module Manufacturer ID, MSB 1529 // 1530 ipmi_ret_t ipmiOemQGetDimmInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1531 ipmi_request_t request, ipmi_response_t response, 1532 ipmi_data_len_t data_len, ipmi_context_t context) 1533 { 1534 qDimmInfo_t* req = reinterpret_cast<qDimmInfo_t*>(request); 1535 uint8_t numParam = sizeof(dimmInfoKey) / sizeof(uint8_t*); 1536 uint8_t* res = reinterpret_cast<uint8_t*>(response); 1537 std::stringstream ss; 1538 std::string str; 1539 1540 *data_len = 0; 1541 1542 /* check for requested data params */ 1543 if (req->paramSel < 1 || req->paramSel >= numParam) 1544 { 1545 phosphor::logging::log<phosphor::logging::level::ERR>( 1546 "Invalid parameter received"); 1547 return IPMI_CC_PARM_OUT_OF_RANGE; 1548 } 1549 1550 ss << std::hex; 1551 ss << std::setw(2) << std::setfill('0') << (int)req->dimmIndex; 1552 1553 if (oemData[KEY_Q_DIMM_INFO].find(ss.str()) == 1554 oemData[KEY_Q_DIMM_INFO].end()) 1555 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1556 1557 if (oemData[KEY_Q_DIMM_INFO][ss.str()].find(dimmInfoKey[req->paramSel]) == 1558 oemData[KEY_Q_DIMM_INFO][ss.str()].end()) 1559 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1560 1561 str = oemData[KEY_Q_DIMM_INFO][ss.str()][dimmInfoKey[req->paramSel]]; 1562 *data_len = strToBytes(str, res); 1563 1564 return IPMI_CC_OK; 1565 } 1566 1567 //---------------------------------------------------------------------- 1568 // Set Drive Info (CMD_OEM_Q_SET_DRIVE_INFO) 1569 //---------------------------------------------------------------------- 1570 // BIOS issue this command to provide HDD information to BMC. 1571 // 1572 // BIOS just can get information by standard ATA / SMART command for 1573 // OB SATA controller. 1574 // BIOS can get 1575 // 1. Serial Number 1576 // 2. Model Name 1577 // 3. HDD FW Version 1578 // 4. HDD Capacity 1579 // 5. HDD WWN 1580 // 1581 // Use Get HDD info Param #5 to know the MAX HDD info index. 1582 // 1583 // Request: 1584 // Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first 1585 // Byte 4 – 1586 // [7:4] Reserved 1587 // [3:0] HDD Controller Type 1588 // 0x00 – BIOS 1589 // 0x01 – Expander 1590 // 0x02 – LSI 1591 // Byte 5 – HDD Info Index, 0 base 1592 // Byte 6 – Parameter Selector 1593 // Byte 7..N – Configuration parameter data (see Table_1415h Parameters of HDD 1594 // Information) 1595 // 1596 // Response: 1597 // Byte 1 – Completion Code 1598 // 1599 // Param#0 (HDD Location): 1600 // Byte 1 – Controller 1601 // [7:3] Device Number 1602 // [2:0] Function Number 1603 // For Intel C610 series (Wellsburg) 1604 // D31:F2 (0xFA) – SATA control 1 1605 // D31:F5 (0xFD) – SATA control 2 1606 // D17:F4 (0x8C) – sSata control 1607 // Byte 2 – Port Number 1608 // Byte 3 – Location (0xFF: No HDD Present) 1609 // BIOS default set Byte 3 to 0xFF, if No HDD Present. And then skip send param 1610 // #1~4, #6, #7 to BMC (still send param #5) BIOS default set Byte 3 to 0, if 1611 // the HDD present. BMC or other people who know the HDD location has 1612 // responsibility for update Location info 1613 // 1614 // Param#1 (Serial Number): 1615 // Bytes 1..33: HDD Serial Number 1616 // 1617 // Param#2 (Model Name): 1618 // Byte 1..33 – HDD Model Name 1619 // 1620 // Param#3 (HDD FW Version): 1621 // Byte 1..17 –HDD FW version 1622 // 1623 // Param#4 (Capacity): 1624 // Byte 1..4 –HDD Block Size, LSB 1625 // Byte 5..12 - HDD Block Number, LSB 1626 // HDD Capacity = HDD Block size * HDD BLock number (Unit Byte) 1627 // 1628 // Param#5 (Max HDD Quantity): 1629 // Byte 1 - Max HDD Quantity 1630 // Max supported port numbers in this PCH 1631 // 1632 // Param#6 (HDD Type) 1633 // Byte 1 – HDD Type 1634 // 0h – Reserved 1635 // 1h – SAS 1636 // 2h – SATA 1637 // 3h – PCIE SSD (NVME) 1638 // 1639 // Param#7 (HDD WWN) 1640 // Data 1...8: HDD World Wide Name, LSB 1641 // 1642 ipmi_ret_t ipmiOemQSetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1643 ipmi_request_t request, 1644 ipmi_response_t response, 1645 ipmi_data_len_t data_len, 1646 ipmi_context_t context) 1647 { 1648 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request); 1649 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*); 1650 uint8_t ctrlType = req->hddCtrlType & 0x0f; 1651 std::stringstream ss; 1652 std::string str; 1653 uint8_t len = *data_len; 1654 1655 *data_len = 0; 1656 1657 /* check for requested data params */ 1658 if (len < 6 || req->paramSel < 1 || req->paramSel >= numParam || 1659 ctrlType > 2) 1660 { 1661 phosphor::logging::log<phosphor::logging::level::ERR>( 1662 "Invalid parameter received"); 1663 return IPMI_CC_PARM_OUT_OF_RANGE; 1664 } 1665 1666 len = len - 6; // Get Actual data length 1667 1668 ss << std::hex; 1669 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex; 1670 oemData[KEY_Q_DRIVE_INFO][KEY_HDD_CTRL_TYPE] = req->hddCtrlType; 1671 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()][KEY_HDD_INDEX] = 1672 req->hddIndex; 1673 1674 str = bytesToStr(req->data, len); 1675 oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()] 1676 [driveInfoKey[req->paramSel]] = str.c_str(); 1677 flushOemData(); 1678 1679 return IPMI_CC_OK; 1680 } 1681 1682 //---------------------------------------------------------------------- 1683 // Get Drive Info (CMD_OEM_Q_GET_DRIVE_INFO) 1684 //---------------------------------------------------------------------- 1685 // BMC needs to check HDD presented or not first. If NOT presented, return 1686 // completion code 0xD5. 1687 // 1688 // Request: 1689 // Byte 1:3 – Quanta Manufacturer ID – 001C4Ch, LSB first 1690 // Byte 4 – 1691 //[7:4] Reserved 1692 //[3:0] HDD Controller Type 1693 // 0x00 – BIOS 1694 // 0x01 – Expander 1695 // 0x02 – LSI 1696 // Byte 5 – HDD Index, 0 base 1697 // Byte 6 – Parameter Selector (See Above Set HDD Information) 1698 // Response: 1699 // Byte 1 – Completion Code 1700 // 0xD5 – Not support in current status (HDD Not Present) 1701 // Byte 2..N – Configuration parameter data (see Table_1415h Parameters of HDD 1702 // Information) 1703 // 1704 ipmi_ret_t ipmiOemQGetDriveInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 1705 ipmi_request_t request, 1706 ipmi_response_t response, 1707 ipmi_data_len_t data_len, 1708 ipmi_context_t context) 1709 { 1710 qDriveInfo_t* req = reinterpret_cast<qDriveInfo_t*>(request); 1711 uint8_t numParam = sizeof(driveInfoKey) / sizeof(uint8_t*); 1712 uint8_t* res = reinterpret_cast<uint8_t*>(response); 1713 uint8_t ctrlType = req->hddCtrlType & 0x0f; 1714 std::stringstream ss; 1715 std::string str; 1716 1717 *data_len = 0; 1718 1719 /* check for requested data params */ 1720 if (req->paramSel < 1 || req->paramSel >= numParam || ctrlType > 2) 1721 { 1722 phosphor::logging::log<phosphor::logging::level::ERR>( 1723 "Invalid parameter received"); 1724 return IPMI_CC_PARM_OUT_OF_RANGE; 1725 } 1726 1727 if (oemData[KEY_Q_DRIVE_INFO].find(ctrlTypeKey[ctrlType]) == 1728 oemData[KEY_Q_DRIVE_INFO].end()) 1729 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1730 1731 ss << std::hex; 1732 ss << std::setw(2) << std::setfill('0') << (int)req->hddIndex; 1733 1734 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]].find(ss.str()) == 1735 oemData[KEY_Q_DRIVE_INFO].end()) 1736 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1737 1738 if (oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()].find( 1739 dimmInfoKey[req->paramSel]) == 1740 oemData[KEY_Q_DRIVE_INFO][ss.str()].end()) 1741 return CC_PARAM_NOT_SUPP_IN_CURR_STATE; 1742 1743 str = oemData[KEY_Q_DRIVE_INFO][ctrlTypeKey[ctrlType]][ss.str()] 1744 [dimmInfoKey[req->paramSel]]; 1745 *data_len = strToBytes(str, res); 1746 1747 return IPMI_CC_OK; 1748 } 1749 1750 /* Helper function for sending DCMI commands to ME and getting response back */ 1751 ipmi::RspType<std::vector<uint8_t>> sendDCMICmd(uint8_t cmd, 1752 std::vector<uint8_t>& cmdData) 1753 { 1754 std::vector<uint8_t> respData; 1755 1756 /* Add group id as first byte to request for ME command */ 1757 cmdData.insert(cmdData.begin(), groupDCMI); 1758 1759 if (sendMeCmd(ipmi::netFnGroup, cmd, cmdData, respData)) 1760 return ipmi::responseUnspecifiedError(); 1761 1762 /* Remove group id as first byte as it will be added by IPMID */ 1763 respData.erase(respData.begin()); 1764 1765 return ipmi::responseSuccess(std::move(respData)); 1766 } 1767 1768 /* DCMI Command handellers. */ 1769 1770 ipmi::RspType<std::vector<uint8_t>> 1771 ipmiOemDCMIGetPowerReading(std::vector<uint8_t> reqData) 1772 { 1773 return sendDCMICmd(ipmi::dcmi::cmdGetPowerReading, reqData); 1774 } 1775 1776 ipmi::RspType<std::vector<uint8_t>> 1777 ipmiOemDCMIGetPowerLimit(std::vector<uint8_t> reqData) 1778 { 1779 return sendDCMICmd(ipmi::dcmi::cmdGetPowerLimit, reqData); 1780 } 1781 1782 ipmi::RspType<std::vector<uint8_t>> 1783 ipmiOemDCMISetPowerLimit(std::vector<uint8_t> reqData) 1784 { 1785 return sendDCMICmd(ipmi::dcmi::cmdSetPowerLimit, reqData); 1786 } 1787 1788 ipmi::RspType<std::vector<uint8_t>> 1789 ipmiOemDCMIApplyPowerLimit(std::vector<uint8_t> reqData) 1790 { 1791 return sendDCMICmd(ipmi::dcmi::cmdActDeactivatePwrLimit, reqData); 1792 } 1793 1794 static void registerOEMFunctions(void) 1795 { 1796 /* Get OEM data from json file */ 1797 std::ifstream file(JSON_OEM_DATA_FILE); 1798 if (file) 1799 { 1800 file >> oemData; 1801 file.close(); 1802 } 1803 1804 phosphor::logging::log<phosphor::logging::level::INFO>( 1805 "Registering OEM commands"); 1806 1807 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_INFO, 1808 NULL, ipmiOemDbgGetFrameInfo, 1809 PRIVILEGE_USER); // get debug frame info 1810 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, 1811 CMD_OEM_USB_DBG_GET_UPDATED_FRAMES, NULL, 1812 ipmiOemDbgGetUpdFrames, 1813 PRIVILEGE_USER); // get debug updated frames 1814 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_POST_DESC, 1815 NULL, ipmiOemDbgGetPostDesc, 1816 PRIVILEGE_USER); // get debug post description 1817 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_GPIO_DESC, 1818 NULL, ipmiOemDbgGetGpioDesc, 1819 PRIVILEGE_USER); // get debug gpio description 1820 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_GET_FRAME_DATA, 1821 NULL, ipmiOemDbgGetFrameData, 1822 PRIVILEGE_USER); // get debug frame data 1823 ipmiPrintAndRegister(NETFN_OEM_USB_DBG_REQ, CMD_OEM_USB_DBG_CTRL_PANEL, 1824 NULL, ipmiOemDbgGetCtrlPanel, 1825 PRIVILEGE_USER); // get debug control panel 1826 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_DIMM_INFO, NULL, 1827 ipmiOemSetDimmInfo, 1828 PRIVILEGE_USER); // Set Dimm Info 1829 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_BOARD_ID, NULL, 1830 ipmiOemGetBoardID, 1831 PRIVILEGE_USER); // Get Board ID 1832 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_MACHINE_CONFIG_INFO, NULL, 1833 ipmiOemSetMachineCfgInfo, 1834 PRIVILEGE_USER); // Set Machine Config Info 1835 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_START, NULL, 1836 ipmiOemSetPostStart, 1837 PRIVILEGE_USER); // Set POST start 1838 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_POST_END, NULL, 1839 ipmiOemSetPostEnd, 1840 PRIVILEGE_USER); // Set POST End 1841 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPIN_INFO, NULL, 1842 ipmiOemSetPPINInfo, 1843 PRIVILEGE_USER); // Set PPIN Info 1844 #if BIC_ENABLED 1845 1846 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne, 1847 ipmi::cmdSetSystemGuid, ipmi::Privilege::User, 1848 ipmiOemSetSystemGuid); 1849 #else 1850 1851 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_SYSTEM_GUID, NULL, 1852 ipmiOemSetSystemGuid, 1853 PRIVILEGE_USER); // Set System GUID 1854 #endif 1855 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_ADR_TRIGGER, NULL, 1856 ipmiOemSetAdrTrigger, 1857 PRIVILEGE_USER); // Set ADR Trigger 1858 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_BIOS_FLASH_INFO, NULL, 1859 ipmiOemSetBiosFlashInfo, 1860 PRIVILEGE_USER); // Set Bios Flash Info 1861 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_SET_PPR, NULL, ipmiOemSetPpr, 1862 PRIVILEGE_USER); // Set PPR 1863 ipmiPrintAndRegister(NETFUN_NONE, CMD_OEM_GET_PPR, NULL, ipmiOemGetPpr, 1864 PRIVILEGE_USER); // Get PPR 1865 /* FB OEM QC Commands */ 1866 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_PROC_INFO, NULL, 1867 ipmiOemQSetProcInfo, 1868 PRIVILEGE_USER); // Set Proc Info 1869 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_PROC_INFO, NULL, 1870 ipmiOemQGetProcInfo, 1871 PRIVILEGE_USER); // Get Proc Info 1872 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DIMM_INFO, NULL, 1873 ipmiOemQSetDimmInfo, 1874 PRIVILEGE_USER); // Set Dimm Info 1875 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DIMM_INFO, NULL, 1876 ipmiOemQGetDimmInfo, 1877 PRIVILEGE_USER); // Get Dimm Info 1878 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_SET_DRIVE_INFO, NULL, 1879 ipmiOemQSetDriveInfo, 1880 PRIVILEGE_USER); // Set Drive Info 1881 ipmiPrintAndRegister(NETFUN_FB_OEM_QC, CMD_OEM_Q_GET_DRIVE_INFO, NULL, 1882 ipmiOemQGetDriveInfo, 1883 PRIVILEGE_USER); // Get Drive Info 1884 1885 /* FB OEM DCMI Commands as per DCMI spec 1.5 Section 6 */ 1886 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI, 1887 ipmi::dcmi::cmdGetPowerReading, 1888 ipmi::Privilege::User, 1889 ipmiOemDCMIGetPowerReading); // Get Power Reading 1890 1891 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI, 1892 ipmi::dcmi::cmdGetPowerLimit, 1893 ipmi::Privilege::User, 1894 ipmiOemDCMIGetPowerLimit); // Get Power Limit 1895 1896 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI, 1897 ipmi::dcmi::cmdSetPowerLimit, 1898 ipmi::Privilege::Operator, 1899 ipmiOemDCMISetPowerLimit); // Set Power Limit 1900 1901 ipmi::registerGroupHandler(ipmi::prioOpenBmcBase, groupDCMI, 1902 ipmi::dcmi::cmdActDeactivatePwrLimit, 1903 ipmi::Privilege::Operator, 1904 ipmiOemDCMIApplyPowerLimit); // Apply Power Limit 1905 1906 /* FB OEM BOOT ORDER COMMANDS */ 1907 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne, 1908 CMD_OEM_GET_BOOT_ORDER, ipmi::Privilege::User, 1909 ipmiOemGetBootOrder); // Get Boot Order 1910 1911 ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnOemOne, 1912 CMD_OEM_SET_BOOT_ORDER, ipmi::Privilege::User, 1913 ipmiOemSetBootOrder); // Set Boot Order 1914 1915 return; 1916 } 1917 1918 } // namespace ipmi 1919