blob: e69829fc7d3c5642021348d287cdd4bf6a150f86 [file] [log] [blame]
vishwabmcba0bd5f2015-09-30 16:50:23 +05301#include "apphandler.h"
Patrick Venture5794fcf2017-10-26 11:11:14 -07002#include "app/channel.hpp"
Patrick Venture5e6ac712017-10-25 12:16:19 -07003#include "app/watchdog.hpp"
Patrick Williams37af7332016-09-02 21:21:42 -05004#include "host-ipmid/ipmid-api.h"
Patrick Williams53a360e2016-08-12 22:01:02 -05005#include "ipmid.hpp"
David Cobbleya1adb072017-11-21 15:58:13 -08006#include "nlohmann/json.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +05307#include "types.hpp"
8#include "utils.hpp"
9
David Cobbleya1adb072017-11-21 15:58:13 -080010#include <fstream>
vishwabmcba0bd5f2015-09-30 16:50:23 +053011#include <stdio.h>
Chris Austen6caf28b2015-10-13 12:40:40 -050012#include <stdint.h>
Adriana Kobylak3a552e12015-10-19 16:11:00 -050013#include <systemd/sd-bus.h>
Sergey Solomineb9b8142016-08-23 09:07:28 -050014#include <mapper.h>
Nan Liee0cb902016-07-11 15:38:03 +080015#include <array>
Tom Joseph69fabfe2017-08-04 10:15:01 +053016#include <vector>
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -060017#include <string>
18#include <cstddef>
Ratan Gupta62736ec2017-09-02 12:02:47 +053019#include <experimental/filesystem>
20
Nan Li3d0df912016-10-18 19:51:41 +080021#include <arpa/inet.h>
Ratan Guptab8e99552017-07-27 07:07:48 +053022#include "transporthandler.hpp"
23
24#include <phosphor-logging/log.hpp>
25#include <phosphor-logging/elog-errors.hpp>
26#include "xyz/openbmc_project/Common/error.hpp"
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060027#include "xyz/openbmc_project/Software/Version/server.hpp"
28#include "xyz/openbmc_project/Software/Activation/server.hpp"
Ratan Guptab8e99552017-07-27 07:07:48 +053029
Adriana Kobylak3a552e12015-10-19 16:11:00 -050030extern sd_bus *bus;
vishwabmcba0bd5f2015-09-30 16:50:23 +053031
Marri Devender Rao5e007a52018-01-08 06:18:36 -060032constexpr auto bmc_interface = "xyz.openbmc_project.Inventory.Item.Bmc";
33constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
34constexpr auto bmc_guid_property = "UUID";
35constexpr auto bmc_guid_len = 16;
36
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060037static constexpr auto redundancyIntf =
38 "xyz.openbmc_project.Software.RedundancyPriority";
39static constexpr auto versionIntf =
40 "xyz.openbmc_project.Software.Version";
41static constexpr auto activationIntf =
42 "xyz.openbmc_project.Software.Activation";
43static constexpr auto softwareRoot = "/xyz/openbmc_project/software";
44
Chris Austen6caf28b2015-10-13 12:40:40 -050045void register_netfn_app_functions() __attribute__((constructor));
vishwabmcba0bd5f2015-09-30 16:50:23 +053046
Ratan Guptab8e99552017-07-27 07:07:48 +053047using namespace phosphor::logging;
48using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060049using Version = sdbusplus::xyz::openbmc_project::Software::server::Version;
50using Activation =
51 sdbusplus::xyz::openbmc_project::Software::server::Activation;
Ratan Gupta62736ec2017-09-02 12:02:47 +053052namespace fs = std::experimental::filesystem;
Ratan Guptab8e99552017-07-27 07:07:48 +053053
Nan Liee0cb902016-07-11 15:38:03 +080054// Offset in get device id command.
55typedef struct
56{
57 uint8_t id;
58 uint8_t revision;
59 uint8_t fw[2];
60 uint8_t ipmi_ver;
61 uint8_t addn_dev_support;
62 uint8_t manuf_id[3];
63 uint8_t prod_id[2];
64 uint8_t aux[4];
65}__attribute__((packed)) ipmi_device_id_t;
Chris Austen7303bdc2016-04-17 11:50:54 -050066
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060067/**
68 * @brief Returns the Version info from primary s/w object
69 *
70 * Get the Version info from the active s/w object which is having high
71 * "Priority" value(a smaller number is a higher priority) and "Purpose"
72 * is "BMC" from the list of all s/w objects those are implementing
73 * RedundancyPriority interface from the given softwareRoot path.
74 *
75 * @return On success returns the Version info from primary s/w object.
76 *
77 */
78std::string getActiveSoftwareVersionInfo()
79{
80 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
81
82 std::string revision{};
83 auto objectTree = ipmi::getAllDbusObjects(bus, softwareRoot, redundancyIntf,
84 "");
85 if (objectTree.empty())
86 {
87 log<level::ERR>("No Obj has implemented the s/w redundancy interface",
88 entry("INTERFACE=%s", redundancyIntf));
89 elog<InternalFailure>();
90 }
91
92 auto objectFound = false;
93 for (auto& softObject : objectTree)
94 {
95 auto service = ipmi::getService(bus, redundancyIntf, softObject.first);
96 auto objValueTree = ipmi::getManagedObjects(bus, service, softwareRoot);
97
98 auto minPriority = 0xFF;
99 for (const auto& objIter : objValueTree)
100 {
101 try
102 {
103 auto& intfMap = objIter.second;
104 auto& redundancyPriorityProps = intfMap.at(redundancyIntf);
105 auto& versionProps = intfMap.at(versionIntf);
106 auto& activationProps = intfMap.at(activationIntf);
107 auto priority =
108 redundancyPriorityProps.at("Priority").get<uint8_t>();
109 auto purpose = versionProps.at("Purpose").get<std::string>();
110 auto activation =
111 activationProps.at("Activation").get<std::string>();
112 auto version = versionProps.at("Version").get<std::string>();
113 if ((Version::convertVersionPurposeFromString(purpose) ==
114 Version::VersionPurpose::BMC) &&
115 (Activation::convertActivationsFromString(activation) ==
116 Activation::Activations::Active))
117 {
118 if (priority < minPriority)
119 {
120 minPriority = priority;
121 objectFound = true;
122 revision = std::move(version);
123 }
124 }
125 }
126 catch (const std::exception& e)
127 {
128 log<level::ERR>(e.what());
129 }
130 }
131 }
132
133 if (!objectFound)
134 {
135 log<level::ERR>("Could not found an BMC software Object");
136 elog<InternalFailure>();
137 }
138
139 return revision;
140}
141
142
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500143ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
144 ipmi_request_t request, ipmi_response_t response,
Chris Austen6caf28b2015-10-13 12:40:40 -0500145 ipmi_data_len_t data_len, ipmi_context_t context)
146{
147 ipmi_ret_t rc = IPMI_CC_OK;
148 *data_len = 0;
149
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530150 log<level::DEBUG>("IPMI SET ACPI STATE Ignoring for now\n");
Chris Austen6caf28b2015-10-13 12:40:40 -0500151 return rc;
152}
153
Chris Austen7303bdc2016-04-17 11:50:54 -0500154typedef struct
155{
156 char major;
157 char minor;
Chris Austen176c9652016-04-30 16:32:17 -0500158 uint16_t d[2];
Chris Austen7303bdc2016-04-17 11:50:54 -0500159} rev_t;
160
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600161/* Currently supports the vx.x-x-[-x] and v1.x.x-x-[-x] format. It will */
162/* return -1 if not in those formats, this routine knows how to parse */
Chris Austen7303bdc2016-04-17 11:50:54 -0500163/* version = v0.6-19-gf363f61-dirty */
164/* ^ ^ ^^ ^ */
165/* | | |----------|-- additional details */
166/* | |---------------- Minor */
167/* |------------------ Major */
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600168/* and version = v1.99.10-113-g65edf7d-r3-0-g9e4f715 */
169/* ^ ^ ^^ ^ */
170/* | | |--|---------- additional details */
171/* | |---------------- Minor */
172/* |------------------ Major */
Chris Austen7303bdc2016-04-17 11:50:54 -0500173/* Additional details : If the option group exists it will force Auxiliary */
174/* Firmware Revision Information 4th byte to 1 indicating the build was */
175/* derived with additional edits */
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600176int convert_version(const char * p, rev_t *rev)
Chris Austen7303bdc2016-04-17 11:50:54 -0500177{
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600178 std::string s(p);
179 std::string token;
Chris Austen176c9652016-04-30 16:32:17 -0500180 uint16_t commits;
Chris Austen7303bdc2016-04-17 11:50:54 -0500181
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600182 auto location = s.find_first_of('v');
183 if (location != std::string::npos)
184 {
185 s = s.substr(location+1);
Chris Austen176c9652016-04-30 16:32:17 -0500186 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500187
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600188 if (!s.empty())
189 {
190 location = s.find_first_of(".");
191 if (location != std::string::npos)
192 {
Patrick Ventured2117022018-02-06 08:54:37 -0800193 rev->major = static_cast<char>(
194 std::stoi(s.substr(0, location), 0, 16));
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600195 token = s.substr(location+1);
196 }
Chris Austen176c9652016-04-30 16:32:17 -0500197
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600198 if (!token.empty())
199 {
200 location = token.find_first_of(".-");
201 if (location != std::string::npos)
202 {
Patrick Ventured2117022018-02-06 08:54:37 -0800203 rev->minor = static_cast<char>(
204 std::stoi(token.substr(0, location), 0, 16));
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600205 token = token.substr(location+1);
206 }
207 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500208
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600209 // Capture the number of commits on top of the minor tag.
210 // I'm using BE format like the ipmi spec asked for
211 location = token.find_first_of(".-");
212 if (!token.empty())
213 {
214 commits = std::stoi(token.substr(0, location), 0, 16);
215 rev->d[0] = (commits>>8) | (commits<<8);
216
217 // commit number we skip
218 location = token.find_first_of(".-");
219 if (location != std::string::npos)
220 {
221 token = token.substr(location+1);
222 }
223 }
224 else {
225 rev->d[0] = 0;
226 }
227
228 if (location != std::string::npos)
229 {
230 token = token.substr(location+1);
231 }
232
233 // Any value of the optional parameter forces it to 1
234 location = token.find_first_of(".-");
235 if (location != std::string::npos)
236 {
237 token = token.substr(location+1);
238 }
239 commits = (!token.empty()) ? 1 : 0;
240
241 //We do this operation to get this displayed in least significant bytes
242 //of ipmitool device id command.
243 rev->d[1] = (commits>>8) | (commits<<8);
244 }
245
Chris Austen7303bdc2016-04-17 11:50:54 -0500246 return 0;
247}
248
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500249ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
250 ipmi_request_t request, ipmi_response_t response,
Chris Austen6caf28b2015-10-13 12:40:40 -0500251 ipmi_data_len_t data_len, ipmi_context_t context)
252{
253 ipmi_ret_t rc = IPMI_CC_OK;
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600254 int r = -1;
Chris Austen7303bdc2016-04-17 11:50:54 -0500255 rev_t rev = {0};
David Cobbleya1adb072017-11-21 15:58:13 -0800256 static ipmi_device_id_t dev_id{};
257 static bool dev_id_initialized = false;
258 const char* filename = "/usr/share/ipmi-providers/dev_id.json";
Chris Austen6caf28b2015-10-13 12:40:40 -0500259
260 // Data length
Chris Austen7303bdc2016-04-17 11:50:54 -0500261 *data_len = sizeof(dev_id);
262
David Cobbleya1adb072017-11-21 15:58:13 -0800263 if (!dev_id_initialized)
264 {
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600265 try
266 {
267 auto version = getActiveSoftwareVersionInfo();
268 r = convert_version(version.c_str(), &rev);
David Cobbleya1adb072017-11-21 15:58:13 -0800269 }
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600270 catch (const std::exception& e)
271 {
272 log<level::ERR>(e.what());
273 }
Nan Liee0cb902016-07-11 15:38:03 +0800274
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600275 if( r >= 0 ) {
276 // bit7 identifies if the device is available
277 // 0=normal operation
278 // 1=device firmware, SDR update,
279 // or self-initialization in progress.
280 // our SDR is normal working condition, so mask:
281 dev_id.fw[0] = 0x7F & rev.major;
282
283 rev.minor = (rev.minor > 99 ? 99 : rev.minor);
284 dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16;
285 memcpy(&dev_id.aux, rev.d, 4);
David Cobbleya1adb072017-11-21 15:58:13 -0800286 }
Nan Liee0cb902016-07-11 15:38:03 +0800287
David Cobbleya1adb072017-11-21 15:58:13 -0800288 // IPMI Spec version 2.0
289 dev_id.ipmi_ver = 2;
Adriana Kobylak0e912642016-06-22 16:54:39 -0500290
David Cobbleya1adb072017-11-21 15:58:13 -0800291 std::ifstream dev_id_file(filename);
292 if (dev_id_file.is_open())
293 {
294 auto data = nlohmann::json::parse(dev_id_file, nullptr, false);
295 if (!data.is_discarded())
296 {
297 dev_id.id = data.value("id", 0);
298 dev_id.revision = data.value("revision", 0);
299 dev_id.addn_dev_support = data.value("addn_dev_support", 0);
300 dev_id.manuf_id[2] = data.value("manuf_id", 0) >> 16;
301 dev_id.manuf_id[1] = data.value("manuf_id", 0) >> 8;
302 dev_id.manuf_id[0] = data.value("manuf_id", 0);
303 dev_id.prod_id[1] = data.value("prod_id", 0) >> 8;
304 dev_id.prod_id[0] = data.value("prod_id", 0);
Tom Josephaf8a0982018-03-09 07:54:02 -0600305 dev_id.aux[3] = data.value("aux", 0);
306 dev_id.aux[2] = data.value("aux", 0) >> 8;
307 dev_id.aux[1] = data.value("aux", 0) >> 16;
308 dev_id.aux[0] = data.value("aux", 0) >> 24;
David Cobbleya1adb072017-11-21 15:58:13 -0800309
310 //Don't read the file every time if successful
311 dev_id_initialized = true;
312 }
313 else
314 {
315 log<level::ERR>("Device ID JSON parser failure");
316 rc = IPMI_CC_UNSPECIFIED_ERROR;
317 }
318 }
319 else
320 {
321 log<level::ERR>("Device ID file not found");
322 rc = IPMI_CC_UNSPECIFIED_ERROR;
Chris Austen7303bdc2016-04-17 11:50:54 -0500323 }
324 }
Chris Austen6caf28b2015-10-13 12:40:40 -0500325
326 // Pack the actual response
Chris Austen7303bdc2016-04-17 11:50:54 -0500327 memcpy(response, &dev_id, *data_len);
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600328
Chris Austen6caf28b2015-10-13 12:40:40 -0500329 return rc;
330}
331
Nan Li41fa24a2016-11-10 20:12:37 +0800332ipmi_ret_t ipmi_app_get_self_test_results(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
333 ipmi_request_t request, ipmi_response_t response,
334 ipmi_data_len_t data_len, ipmi_context_t context)
335{
336 ipmi_ret_t rc = IPMI_CC_OK;
337
338 // Byte 2:
339 // 55h - No error.
Gunnar Mills8991dd62017-10-25 17:11:29 -0500340 // 56h - Self Test function not implemented in this controller.
Nan Li41fa24a2016-11-10 20:12:37 +0800341 // 57h - Corrupted or inaccesssible data or devices.
342 // 58h - Fatal hardware error.
343 // FFh - reserved.
344 // all other: Device-specific 'internal failure'.
345 // Byte 3:
346 // For byte 2 = 55h, 56h, FFh: 00h
347 // For byte 2 = 58h, all other: Device-specific
348 // For byte 2 = 57h: self-test error bitfield.
349 // Note: returning 57h does not imply that all test were run.
350 // [7] 1b = Cannot access SEL device.
351 // [6] 1b = Cannot access SDR Repository.
352 // [5] 1b = Cannot access BMC FRU device.
353 // [4] 1b = IPMB signal lines do not respond.
354 // [3] 1b = SDR Repository empty.
355 // [2] 1b = Internal Use Area of BMC FRU corrupted.
356 // [1] 1b = controller update 'boot block' firmware corrupted.
357 // [0] 1b = controller operational firmware corrupted.
358
359 char selftestresults[2] = {0};
360
361 *data_len = 2;
362
363 selftestresults[0] = 0x56;
364 selftestresults[1] = 0;
365
366 memcpy(response, selftestresults, *data_len);
367
368 return rc;
369}
370
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500371ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
372 ipmi_request_t request, ipmi_response_t response,
373 ipmi_data_len_t data_len, ipmi_context_t context)
374{
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500375 const char *objname = "/org/openbmc/control/chassis0";
Adriana Kobylak31bccae2015-11-05 13:31:06 -0600376 const char *iface = "org.freedesktop.DBus.Properties";
377 const char *chassis_iface = "org.openbmc.control.Chassis";
vishwa1eaea4f2016-02-26 11:57:40 -0600378 sd_bus_message *reply = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500379 sd_bus_error error = SD_BUS_ERROR_NULL;
380 int r = 0;
381 char *uuid = NULL;
Sergey Solomineb9b8142016-08-23 09:07:28 -0500382 char *busname = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500383
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500384 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
Patrick Ventured2117022018-02-06 08:54:37 -0800385 // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte
386 // order
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500387 // Ex: 0x2332fc2c40e66298e511f2782395a361
388
389 const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec
390 uint8_t resp_uuid[resp_size]; // Array to hold the formatted response
Patrick Ventured2117022018-02-06 08:54:37 -0800391 // Point resp end of array to save in reverse order
392 int resp_loc = resp_size-1;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500393 int i = 0;
394 char *tokptr = NULL;
vishwa1eaea4f2016-02-26 11:57:40 -0600395 char *id_octet = NULL;
396
397 // Status code.
398 ipmi_ret_t rc = IPMI_CC_OK;
399 *data_len = 0;
400
vishwa1eaea4f2016-02-26 11:57:40 -0600401 // Call Get properties method with the interface and property name
Sergey Solomineb9b8142016-08-23 09:07:28 -0500402 r = mapper_get_service(bus, objname, &busname);
403 if (r < 0) {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530404 log<level::ERR>("Failed to get bus name",
405 entry("BUS=%s", objname),
406 entry("ERRNO=0x%X", -r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500407 goto finish;
408 }
vishwa1eaea4f2016-02-26 11:57:40 -0600409 r = sd_bus_call_method(bus,busname,objname,iface,
410 "Get",&error, &reply, "ss",
411 chassis_iface, "uuid");
412 if (r < 0)
413 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530414 log<level::ERR>("Failed to call Get Method",
415 entry("ERRNO=0x%X", -r));
vishwa1eaea4f2016-02-26 11:57:40 -0600416 rc = IPMI_CC_UNSPECIFIED_ERROR;
417 goto finish;
418 }
419
420 r = sd_bus_message_read(reply, "v", "s", &uuid);
421 if (r < 0 || uuid == NULL)
422 {
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530423 log<level::ERR>("Failed to get a response",
424 entry("ERRNO=0x%X", -r));
vishwa1eaea4f2016-02-26 11:57:40 -0600425 rc = IPMI_CC_RESPONSE_ERROR;
426 goto finish;
427 }
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500428
429 // Traverse the UUID
Patrick Ventured2117022018-02-06 08:54:37 -0800430 // Get the UUID octects separated by dash
431 id_octet = strtok_r(uuid, "-", &tokptr);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500432
433 if (id_octet == NULL)
vishwa1eaea4f2016-02-26 11:57:40 -0600434 {
435 // Error
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530436 log<level::ERR>("Unexpected UUID format",
437 entry("UUID=%s", uuid));
vishwa1eaea4f2016-02-26 11:57:40 -0600438 rc = IPMI_CC_RESPONSE_ERROR;
439 goto finish;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500440 }
441
442 while (id_octet != NULL)
443 {
444 // Calculate the octet string size since it varies
445 // Divide it by 2 for the array size since 1 byte is built from 2 chars
446 int tmp_size = strlen(id_octet)/2;
447
448 for(i = 0; i < tmp_size; i++)
449 {
Patrick Ventured2117022018-02-06 08:54:37 -0800450 // Holder of the 2 chars that will become a byte
451 char tmp_array[3] = {0};
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500452 strncpy(tmp_array, id_octet, 2); // 2 chars at a time
453
454 int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte
Patrick Ventured2117022018-02-06 08:54:37 -0800455 // Copy end to first
456 memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500457 resp_loc--;
458 id_octet+=2; // Finished with the 2 chars, advance
459 }
460 id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet
461 }
462
463 // Data length
464 *data_len = resp_size;
465
466 // Pack the actual response
467 memcpy(response, &resp_uuid, *data_len);
468
vishwa1eaea4f2016-02-26 11:57:40 -0600469finish:
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500470 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600471 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500472 free(busname);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500473
474 return rc;
475}
Chris Austen6caf28b2015-10-13 12:40:40 -0500476
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500477ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
478 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530479 ipmi_data_len_t data_len, ipmi_context_t context)
480{
vishwabmcba0bd5f2015-09-30 16:50:23 +0530481
482 // Status code.
483 ipmi_ret_t rc = IPMI_CC_OK;
484
Adriana Kobylak88ad8152016-12-13 10:09:08 -0600485 // Per IPMI 2.0 spec, the input and output buffer size must be the max
486 // buffer size minus one byte to allocate space for the length byte.
487 uint8_t str[] = {0x01, MAX_IPMI_BUFFER-1, MAX_IPMI_BUFFER-1, 0x0A, 0x01};
vishwabmcba0bd5f2015-09-30 16:50:23 +0530488
489 // Data length
490 *data_len = sizeof(str);
491
492 // Pack the actual response
493 memcpy(response, &str, *data_len);
494
495 return rc;
496}
497
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500498ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
499 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530500 ipmi_data_len_t data_len, ipmi_context_t context)
501{
vishwabmcba0bd5f2015-09-30 16:50:23 +0530502 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800503 ipmi_ret_t rc = IPMI_CC_INVALID;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530504
505 *data_len = strlen("THIS IS WILDCARD");
506
507 // Now pack actual response
508 memcpy(response, "THIS IS WILDCARD", *data_len);
509
510 return rc;
511}
512
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600513ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
514 ipmi_request_t request, ipmi_response_t response,
515 ipmi_data_len_t data_len, ipmi_context_t context)
516
517{
518 ipmi_ret_t rc = IPMI_CC_OK;
519 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
520
521 try
522 {
523 // Get the Inventory object implementing BMC interface
524 ipmi::DbusObjectInfo bmcObject =
525 ipmi::getDbusObject(bus, bmc_interface);
526
527 // Read UUID property value from bmcObject
528 // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
529 auto variant = ipmi::getDbusProperty(
530 bus, bmcObject.second, bmcObject.first, bmc_guid_interface,
531 bmc_guid_property);
532 std::string guidProp = variant.get<std::string>();
533
534 // Erase "-" characters from the property value
535 guidProp.erase(std::remove(guidProp.begin(), guidProp.end(), '-'),
536 guidProp.end());
537
538 auto guidPropLen = guidProp.length();
539 // Validate UUID data
540 // Divide by 2 as 1 byte is built from 2 chars
541 if ( (guidPropLen <=0) || ((guidPropLen/2) != bmc_guid_len) )
542
543 {
544 log<level::ERR>("Invalid UUID property value",
545 entry("UUID_LENGTH=%d", guidPropLen));
546 return IPMI_CC_RESPONSE_ERROR;
547 }
548
549 // Convert data in RFC4122(MSB) format to LSB format
550 // Get 2 characters at a time as 1 byte is built from 2 chars and
551 // convert to hex byte
552 // TODO: Data printed for GUID command is not as per the
553 // GUID format defined in IPMI specification 2.0 section 20.8
554 // Ticket raised: https://sourceforge.net/p/ipmitool/bugs/501/
555 uint8_t respGuid[bmc_guid_len];
556 for (size_t i = 0, respLoc = (bmc_guid_len - 1);
557 i < guidPropLen && respLoc >= 0; i += 2, respLoc--)
558 {
559 auto value = static_cast<uint8_t>(
560 std::stoi(guidProp.substr(i, 2).c_str(), NULL, 16));
561 respGuid[respLoc] = value;
562 }
563
564 *data_len = bmc_guid_len;
565 memcpy(response, &respGuid, bmc_guid_len);
566 }
567 catch (const InternalFailure& e)
568 {
569 log<level::ERR>("Failed in reading BMC UUID property",
570 entry("INTERFACE=%s", bmc_interface),
571 entry("PROPERTY_INTERFACE=%s", bmc_guid_interface),
572 entry("PROPERTY=%s", bmc_guid_property));
573 return IPMI_CC_UNSPECIFIED_ERROR;
574 }
575 return rc;
576}
577
Chris Austen6caf28b2015-10-13 12:40:40 -0500578void register_netfn_app_functions()
vishwabmcba0bd5f2015-09-30 16:50:23 +0530579{
Tom05732372016-09-06 17:21:23 +0530580 // <Get BT Interface Capabilities>
Patrick Ventured2117022018-02-06 08:54:37 -0800581 ipmi_register_callback(NETFUN_APP,
582 IPMI_CMD_GET_CAP_BIT,
583 NULL,
584 ipmi_app_get_bt_capabilities,
Tom05732372016-09-06 17:21:23 +0530585 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500586
Tom05732372016-09-06 17:21:23 +0530587 // <Wildcard Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800588 ipmi_register_callback(NETFUN_APP,
589 IPMI_CMD_WILDCARD,
590 NULL,
591 ipmi_app_wildcard_handler,
Tom05732372016-09-06 17:21:23 +0530592 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500593
Tom05732372016-09-06 17:21:23 +0530594 // <Reset Watchdog Timer>
Patrick Ventured2117022018-02-06 08:54:37 -0800595 ipmi_register_callback(NETFUN_APP,
596 IPMI_CMD_RESET_WD,
597 NULL,
William A. Kennington III61d5f7b2018-02-09 15:23:53 -0800598 ipmi_app_watchdog_reset,
Tom05732372016-09-06 17:21:23 +0530599 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500600
Tom05732372016-09-06 17:21:23 +0530601 // <Set Watchdog Timer>
Patrick Ventured2117022018-02-06 08:54:37 -0800602 ipmi_register_callback(NETFUN_APP,
603 IPMI_CMD_SET_WD,
604 NULL,
William A. Kennington III61d5f7b2018-02-09 15:23:53 -0800605 ipmi_app_watchdog_set,
Tom05732372016-09-06 17:21:23 +0530606 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500607
William A. Kennington III73f44512018-02-09 15:28:46 -0800608 // <Get Watchdog Timer>
609 ipmi_register_callback(NETFUN_APP,
610 IPMI_CMD_GET_WD,
611 NULL,
612 ipmi_app_watchdog_get,
613 PRIVILEGE_OPERATOR);
614
Tom05732372016-09-06 17:21:23 +0530615 // <Get Device ID>
Patrick Ventured2117022018-02-06 08:54:37 -0800616 ipmi_register_callback(NETFUN_APP,
617 IPMI_CMD_GET_DEVICE_ID,
618 NULL,
619 ipmi_app_get_device_id,
Tom05732372016-09-06 17:21:23 +0530620 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500621
Tom05732372016-09-06 17:21:23 +0530622 // <Get Self Test Results>
Patrick Ventured2117022018-02-06 08:54:37 -0800623 ipmi_register_callback(NETFUN_APP,
624 IPMI_CMD_GET_SELF_TEST_RESULTS,
625 NULL,
626 ipmi_app_get_self_test_results,
627 PRIVILEGE_USER);
Nan Li41fa24a2016-11-10 20:12:37 +0800628
Tom05732372016-09-06 17:21:23 +0530629 // <Get Device GUID>
Patrick Ventured2117022018-02-06 08:54:37 -0800630 ipmi_register_callback(NETFUN_APP,
631 IPMI_CMD_GET_DEVICE_GUID,
632 NULL,
633 ipmi_app_get_device_guid,
Tom05732372016-09-06 17:21:23 +0530634 PRIVILEGE_USER);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500635
Tom05732372016-09-06 17:21:23 +0530636 // <Set ACPI Power State>
Patrick Ventured2117022018-02-06 08:54:37 -0800637 ipmi_register_callback(NETFUN_APP,
638 IPMI_CMD_SET_ACPI,
639 NULL,
640 ipmi_app_set_acpi_power_state,
Tom05732372016-09-06 17:21:23 +0530641 PRIVILEGE_ADMIN);
Chris Austen6caf28b2015-10-13 12:40:40 -0500642
Tom Joseph69fabfe2017-08-04 10:15:01 +0530643 // <Get Channel Access>
Patrick Ventured2117022018-02-06 08:54:37 -0800644 ipmi_register_callback(NETFUN_APP,
645 IPMI_CMD_GET_CHANNEL_ACCESS,
646 NULL,
647 ipmi_get_channel_access,
648 PRIVILEGE_USER);
Tom Joseph69fabfe2017-08-04 10:15:01 +0530649
Tom05732372016-09-06 17:21:23 +0530650 // <Get Channel Info Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800651 ipmi_register_callback(NETFUN_APP,
652 IPMI_CMD_GET_CHAN_INFO,
653 NULL,
654 ipmi_app_channel_info,
Tom05732372016-09-06 17:21:23 +0530655 PRIVILEGE_USER);
Chris Austenc2cd29d2016-02-05 20:02:29 -0600656
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600657 // <Get System GUID Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800658 ipmi_register_callback(NETFUN_APP,
659 IPMI_CMD_GET_SYS_GUID,
660 NULL,
661 ipmi_app_get_sys_guid,
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600662 PRIVILEGE_USER);
Tom Joseph7cbe2282018-03-21 21:17:33 +0530663
664 // <Get Channel Cipher Suites Command>
665 ipmi_register_callback(NETFUN_APP,
666 IPMI_CMD_GET_CHAN_CIPHER_SUITES,
667 NULL,
668 getChannelCipherSuites,
669 PRIVILEGE_CALLBACK);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530670 return;
671}
672