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