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