1*fd0f1cf9SJaghathiswari Rankappagounder Natarajan /* 2*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * Copyright 2018 Google Inc. 3*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * 4*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * Licensed under the Apache License, Version 2.0 (the "License"); 5*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * you may not use this file except in compliance with the License. 6*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * You may obtain a copy of the License at 7*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * 8*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * http://www.apache.org/licenses/LICENSE-2.0 9*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * 10*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * Unless required by applicable law or agreed to in writing, software 11*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * distributed under the License is distributed on an "AS IS" BASIS, 12*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * See the License for the specific language governing permissions and 14*fd0f1cf9SJaghathiswari Rankappagounder Natarajan * limitations under the License. 15*fd0f1cf9SJaghathiswari Rankappagounder Natarajan */ 16*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 17*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include "entity_name.hpp" 18*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 19*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include "main.hpp" 20*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 21*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <cstdint> 22*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <cstring> 23*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <experimental/filesystem> 24*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <fstream> 25*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <nlohmann/json.hpp> 26*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <phosphor-logging/elog-errors.hpp> 27*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <phosphor-logging/log.hpp> 28*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <regex> 29*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <sstream> 30*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <string> 31*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <system_error> 32*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <unordered_map> 33*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <vector> 34*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #include <xyz/openbmc_project/Common/error.hpp> 35*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 36*fd0f1cf9SJaghathiswari Rankappagounder Natarajan namespace google 37*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 38*fd0f1cf9SJaghathiswari Rankappagounder Natarajan namespace ipmi 39*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 40*fd0f1cf9SJaghathiswari Rankappagounder Natarajan namespace fs = std::experimental::filesystem; 41*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 42*fd0f1cf9SJaghathiswari Rankappagounder Natarajan namespace 43*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 44*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 45*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // TODO (jaghu) : Add a call to get getChannelMaxTransferSize. 46*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #ifndef MAX_IPMI_BUFFER 47*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #define MAX_IPMI_BUFFER 64 48*fd0f1cf9SJaghathiswari Rankappagounder Natarajan #endif 49*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 50*fd0f1cf9SJaghathiswari Rankappagounder Natarajan using Json = nlohmann::json; 51*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 52*fd0f1cf9SJaghathiswari Rankappagounder Natarajan using namespace phosphor::logging; 53*fd0f1cf9SJaghathiswari Rankappagounder Natarajan using InternalFailure = 54*fd0f1cf9SJaghathiswari Rankappagounder Natarajan sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 55*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 56*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static constexpr auto configFile = 57*fd0f1cf9SJaghathiswari Rankappagounder Natarajan "/usr/share/ipmi-entity-association/entity_association_map.json"; 58*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 59*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static const std::map<uint8_t, std::string> entityIdToName{ 60*fd0f1cf9SJaghathiswari Rankappagounder Natarajan {0x03, "cpu"}, 61*fd0f1cf9SJaghathiswari Rankappagounder Natarajan {0x04, "storage_device"}, 62*fd0f1cf9SJaghathiswari Rankappagounder Natarajan {0x0B, "add_in_card"}, 63*fd0f1cf9SJaghathiswari Rankappagounder Natarajan {0x20, "memory_module"}}; 64*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 65*fd0f1cf9SJaghathiswari Rankappagounder Natarajan Json parse_config() 66*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 67*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::ifstream jsonFile(configFile); 68*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (!jsonFile.is_open()) 69*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 70*fd0f1cf9SJaghathiswari Rankappagounder Natarajan log<level::ERR>("Entity association JSON file not found"); 71*fd0f1cf9SJaghathiswari Rankappagounder Natarajan elog<InternalFailure>(); 72*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 73*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 74*fd0f1cf9SJaghathiswari Rankappagounder Natarajan auto data = Json::parse(jsonFile, nullptr, false); 75*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (data.is_discarded()) 76*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 77*fd0f1cf9SJaghathiswari Rankappagounder Natarajan log<level::ERR>("Entity association JSON parser failure"); 78*fd0f1cf9SJaghathiswari Rankappagounder Natarajan elog<InternalFailure>(); 79*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 80*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 81*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return data; 82*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 83*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 84*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::string read(const std::string& type, uint8_t instance, const Json& config) 85*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 86*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static const std::vector<Json> empty{}; 87*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::vector<Json> readings = config.value(type, empty); 88*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::string name = ""; 89*fd0f1cf9SJaghathiswari Rankappagounder Natarajan for (const auto& j : readings) 90*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 91*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t instanceNum = j.value("instance", 0); 92*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // Not the instance we're interested in 93*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (instanceNum != instance) 94*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 95*fd0f1cf9SJaghathiswari Rankappagounder Natarajan continue; 96*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 97*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 98*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // Found the instance we're interested in 99*fd0f1cf9SJaghathiswari Rankappagounder Natarajan name = j.value("name", ""); 100*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 101*fd0f1cf9SJaghathiswari Rankappagounder Natarajan break; 102*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 103*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return name; 104*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 105*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 106*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } // namespace 107*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 108*fd0f1cf9SJaghathiswari Rankappagounder Natarajan struct GetEntityNameRequest 109*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 110*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t subcommand; 111*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t entity_id; 112*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t entity_instance; 113*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } __attribute__((packed)); 114*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 115*fd0f1cf9SJaghathiswari Rankappagounder Natarajan struct GetEntityNameReply 116*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 117*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t subcommand; 118*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t entity_name_len; 119*fd0f1cf9SJaghathiswari Rankappagounder Natarajan uint8_t entity_name[0]; 120*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } __attribute__((packed)); 121*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 122*fd0f1cf9SJaghathiswari Rankappagounder Natarajan ipmi_ret_t GetEntityName(const uint8_t* reqBuf, uint8_t* replyBuf, 123*fd0f1cf9SJaghathiswari Rankappagounder Natarajan size_t* dataLen) 124*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 125*fd0f1cf9SJaghathiswari Rankappagounder Natarajan struct GetEntityNameRequest request; 126*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 127*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if ((*dataLen) < sizeof(request)) 128*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 129*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::fprintf(stderr, "Invalid command length: %u\n", 130*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static_cast<uint32_t>(*dataLen)); 131*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_REQ_DATA_LEN_INVALID; 132*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 133*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 134*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::memcpy(&request, &reqBuf[0], sizeof(request)); 135*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 136*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // Check if we support this Entity ID. 137*fd0f1cf9SJaghathiswari Rankappagounder Natarajan auto it = entityIdToName.find(request.entity_id); 138*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (it == entityIdToName.end()) 139*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 140*fd0f1cf9SJaghathiswari Rankappagounder Natarajan log<level::ERR>("Unknown Entity ID", 141*fd0f1cf9SJaghathiswari Rankappagounder Natarajan entry("ENTITY_ID=%d", request.entity_id)); 142*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_INVALID_FIELD_REQUEST; 143*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 144*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 145*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static Json config{}; 146*fd0f1cf9SJaghathiswari Rankappagounder Natarajan static bool parsed = false; 147*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 148*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::string entityName; 149*fd0f1cf9SJaghathiswari Rankappagounder Natarajan try 150*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 151*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // Parse the JSON config file. 152*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (!parsed) 153*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 154*fd0f1cf9SJaghathiswari Rankappagounder Natarajan config = parse_config(); 155*fd0f1cf9SJaghathiswari Rankappagounder Natarajan parsed = true; 156*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 157*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 158*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // Find the "entity id:entity instance" mapping to entity name. 159*fd0f1cf9SJaghathiswari Rankappagounder Natarajan entityName = read(it->second, request.entity_instance, config); 160*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (entityName.empty()) 161*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_INVALID_FIELD_REQUEST; 162*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 163*fd0f1cf9SJaghathiswari Rankappagounder Natarajan catch (InternalFailure& e) 164*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 165*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_UNSPECIFIED_ERROR; 166*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 167*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 168*fd0f1cf9SJaghathiswari Rankappagounder Natarajan int length = sizeof(struct GetEntityNameReply) + entityName.length(); 169*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 170*fd0f1cf9SJaghathiswari Rankappagounder Natarajan // TODO (jaghu) : Add a call to get getChannelMaxTransferSize. 171*fd0f1cf9SJaghathiswari Rankappagounder Natarajan if (length > MAX_IPMI_BUFFER) 172*fd0f1cf9SJaghathiswari Rankappagounder Natarajan { 173*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::fprintf(stderr, "Response would overflow response buffer\n"); 174*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_INVALID; 175*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 176*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 177*fd0f1cf9SJaghathiswari Rankappagounder Natarajan auto reply = reinterpret_cast<struct GetEntityNameReply*>(&replyBuf[0]); 178*fd0f1cf9SJaghathiswari Rankappagounder Natarajan reply->subcommand = SysEntityName; 179*fd0f1cf9SJaghathiswari Rankappagounder Natarajan reply->entity_name_len = entityName.length(); 180*fd0f1cf9SJaghathiswari Rankappagounder Natarajan std::memcpy(reply->entity_name, entityName.c_str(), entityName.length()); 181*fd0f1cf9SJaghathiswari Rankappagounder Natarajan 182*fd0f1cf9SJaghathiswari Rankappagounder Natarajan (*dataLen) = length; 183*fd0f1cf9SJaghathiswari Rankappagounder Natarajan return IPMI_CC_OK; 184*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } 185*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } // namespace ipmi 186*fd0f1cf9SJaghathiswari Rankappagounder Natarajan } // namespace google 187