blob: ac29456bf81e8e22665237cbd79104ed691f3a0e [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
150 printf("IPMI SET ACPI STATE Ignoring for now\n");
151 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
401 printf("IPMI GET DEVICE GUID\n");
402
403 // Call Get properties method with the interface and property name
Sergey Solomineb9b8142016-08-23 09:07:28 -0500404 r = mapper_get_service(bus, objname, &busname);
405 if (r < 0) {
Brad Bishop819ddd42016-10-05 21:19:19 -0400406 fprintf(stderr, "Failed to get %s bus name: %s\n",
407 objname, strerror(-r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500408 goto finish;
409 }
vishwa1eaea4f2016-02-26 11:57:40 -0600410 r = sd_bus_call_method(bus,busname,objname,iface,
411 "Get",&error, &reply, "ss",
412 chassis_iface, "uuid");
413 if (r < 0)
414 {
415 fprintf(stderr, "Failed to call Get Method: %s\n", strerror(-r));
416 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 {
423 fprintf(stderr, "Failed to get a response: %s", strerror(-r));
424 rc = IPMI_CC_RESPONSE_ERROR;
425 goto finish;
426 }
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500427
428 // Traverse the UUID
Patrick Ventured2117022018-02-06 08:54:37 -0800429 // Get the UUID octects separated by dash
430 id_octet = strtok_r(uuid, "-", &tokptr);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500431
432 if (id_octet == NULL)
vishwa1eaea4f2016-02-26 11:57:40 -0600433 {
434 // Error
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500435 fprintf(stderr, "Unexpected UUID format: %s", uuid);
vishwa1eaea4f2016-02-26 11:57:40 -0600436 rc = IPMI_CC_RESPONSE_ERROR;
437 goto finish;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500438 }
439
440 while (id_octet != NULL)
441 {
442 // Calculate the octet string size since it varies
443 // Divide it by 2 for the array size since 1 byte is built from 2 chars
444 int tmp_size = strlen(id_octet)/2;
445
446 for(i = 0; i < tmp_size; i++)
447 {
Patrick Ventured2117022018-02-06 08:54:37 -0800448 // Holder of the 2 chars that will become a byte
449 char tmp_array[3] = {0};
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500450 strncpy(tmp_array, id_octet, 2); // 2 chars at a time
451
452 int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte
Patrick Ventured2117022018-02-06 08:54:37 -0800453 // Copy end to first
454 memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500455 resp_loc--;
456 id_octet+=2; // Finished with the 2 chars, advance
457 }
458 id_octet=strtok_r(NULL, "-", &tokptr); // Get next octet
459 }
460
461 // Data length
462 *data_len = resp_size;
463
464 // Pack the actual response
465 memcpy(response, &resp_uuid, *data_len);
466
vishwa1eaea4f2016-02-26 11:57:40 -0600467finish:
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500468 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600469 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500470 free(busname);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500471
472 return rc;
473}
Chris Austen6caf28b2015-10-13 12:40:40 -0500474
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500475ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
476 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530477 ipmi_data_len_t data_len, ipmi_context_t context)
478{
479 printf("Handling Netfn:[0x%X], Cmd:[0x%X]\n",netfn,cmd);
480
481 // Status code.
482 ipmi_ret_t rc = IPMI_CC_OK;
483
Adriana Kobylak88ad8152016-12-13 10:09:08 -0600484 // Per IPMI 2.0 spec, the input and output buffer size must be the max
485 // buffer size minus one byte to allocate space for the length byte.
486 uint8_t str[] = {0x01, MAX_IPMI_BUFFER-1, MAX_IPMI_BUFFER-1, 0x0A, 0x01};
vishwabmcba0bd5f2015-09-30 16:50:23 +0530487
488 // Data length
489 *data_len = sizeof(str);
490
491 // Pack the actual response
492 memcpy(response, &str, *data_len);
493
494 return rc;
495}
496
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500497ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
498 ipmi_request_t request, ipmi_response_t response,
vishwabmcba0bd5f2015-09-30 16:50:23 +0530499 ipmi_data_len_t data_len, ipmi_context_t context)
500{
501 printf("Handling WILDCARD Netfn:[0x%X], Cmd:[0x%X]\n",netfn, cmd);
502
503 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800504 ipmi_ret_t rc = IPMI_CC_INVALID;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530505
506 *data_len = strlen("THIS IS WILDCARD");
507
508 // Now pack actual response
509 memcpy(response, "THIS IS WILDCARD", *data_len);
510
511 return rc;
512}
513
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600514ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
515 ipmi_request_t request, ipmi_response_t response,
516 ipmi_data_len_t data_len, ipmi_context_t context)
517
518{
519 ipmi_ret_t rc = IPMI_CC_OK;
520 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
521
522 try
523 {
524 // Get the Inventory object implementing BMC interface
525 ipmi::DbusObjectInfo bmcObject =
526 ipmi::getDbusObject(bus, bmc_interface);
527
528 // Read UUID property value from bmcObject
529 // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
530 auto variant = ipmi::getDbusProperty(
531 bus, bmcObject.second, bmcObject.first, bmc_guid_interface,
532 bmc_guid_property);
533 std::string guidProp = variant.get<std::string>();
534
535 // Erase "-" characters from the property value
536 guidProp.erase(std::remove(guidProp.begin(), guidProp.end(), '-'),
537 guidProp.end());
538
539 auto guidPropLen = guidProp.length();
540 // Validate UUID data
541 // Divide by 2 as 1 byte is built from 2 chars
542 if ( (guidPropLen <=0) || ((guidPropLen/2) != bmc_guid_len) )
543
544 {
545 log<level::ERR>("Invalid UUID property value",
546 entry("UUID_LENGTH=%d", guidPropLen));
547 return IPMI_CC_RESPONSE_ERROR;
548 }
549
550 // Convert data in RFC4122(MSB) format to LSB format
551 // Get 2 characters at a time as 1 byte is built from 2 chars and
552 // convert to hex byte
553 // TODO: Data printed for GUID command is not as per the
554 // GUID format defined in IPMI specification 2.0 section 20.8
555 // Ticket raised: https://sourceforge.net/p/ipmitool/bugs/501/
556 uint8_t respGuid[bmc_guid_len];
557 for (size_t i = 0, respLoc = (bmc_guid_len - 1);
558 i < guidPropLen && respLoc >= 0; i += 2, respLoc--)
559 {
560 auto value = static_cast<uint8_t>(
561 std::stoi(guidProp.substr(i, 2).c_str(), NULL, 16));
562 respGuid[respLoc] = value;
563 }
564
565 *data_len = bmc_guid_len;
566 memcpy(response, &respGuid, bmc_guid_len);
567 }
568 catch (const InternalFailure& e)
569 {
570 log<level::ERR>("Failed in reading BMC UUID property",
571 entry("INTERFACE=%s", bmc_interface),
572 entry("PROPERTY_INTERFACE=%s", bmc_guid_interface),
573 entry("PROPERTY=%s", bmc_guid_property));
574 return IPMI_CC_UNSPECIFIED_ERROR;
575 }
576 return rc;
577}
578
Chris Austen6caf28b2015-10-13 12:40:40 -0500579void register_netfn_app_functions()
vishwabmcba0bd5f2015-09-30 16:50:23 +0530580{
Tom05732372016-09-06 17:21:23 +0530581 // <Get BT Interface Capabilities>
Patrick Ventured2117022018-02-06 08:54:37 -0800582 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
583 NETFUN_APP,
584 IPMI_CMD_GET_CAP_BIT);
585 ipmi_register_callback(NETFUN_APP,
586 IPMI_CMD_GET_CAP_BIT,
587 NULL,
588 ipmi_app_get_bt_capabilities,
Tom05732372016-09-06 17:21:23 +0530589 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500590
Tom05732372016-09-06 17:21:23 +0530591 // <Wildcard Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800592 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
593 NETFUN_APP,
594 IPMI_CMD_WILDCARD);
595 ipmi_register_callback(NETFUN_APP,
596 IPMI_CMD_WILDCARD,
597 NULL,
598 ipmi_app_wildcard_handler,
Tom05732372016-09-06 17:21:23 +0530599 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500600
Tom05732372016-09-06 17:21:23 +0530601 // <Reset Watchdog Timer>
Patrick Ventured2117022018-02-06 08:54:37 -0800602 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
603 NETFUN_APP,
604 IPMI_CMD_RESET_WD);
605 ipmi_register_callback(NETFUN_APP,
606 IPMI_CMD_RESET_WD,
607 NULL,
William A. Kennington III61d5f7b2018-02-09 15:23:53 -0800608 ipmi_app_watchdog_reset,
Tom05732372016-09-06 17:21:23 +0530609 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500610
Tom05732372016-09-06 17:21:23 +0530611 // <Set Watchdog Timer>
Patrick Ventured2117022018-02-06 08:54:37 -0800612 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
613 NETFUN_APP,
614 IPMI_CMD_SET_WD);
615 ipmi_register_callback(NETFUN_APP,
616 IPMI_CMD_SET_WD,
617 NULL,
William A. Kennington III61d5f7b2018-02-09 15:23:53 -0800618 ipmi_app_watchdog_set,
Tom05732372016-09-06 17:21:23 +0530619 PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500620
William A. Kennington III73f44512018-02-09 15:28:46 -0800621 // <Get Watchdog Timer>
622 ipmi_register_callback(NETFUN_APP,
623 IPMI_CMD_GET_WD,
624 NULL,
625 ipmi_app_watchdog_get,
626 PRIVILEGE_OPERATOR);
627
Tom05732372016-09-06 17:21:23 +0530628 // <Get Device ID>
Patrick Ventured2117022018-02-06 08:54:37 -0800629 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
630 NETFUN_APP,
631 IPMI_CMD_GET_DEVICE_ID);
632 ipmi_register_callback(NETFUN_APP,
633 IPMI_CMD_GET_DEVICE_ID,
634 NULL,
635 ipmi_app_get_device_id,
Tom05732372016-09-06 17:21:23 +0530636 PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500637
Tom05732372016-09-06 17:21:23 +0530638 // <Get Self Test Results>
Patrick Ventured2117022018-02-06 08:54:37 -0800639 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
640 NETFUN_APP,
641 IPMI_CMD_GET_SELF_TEST_RESULTS);
642 ipmi_register_callback(NETFUN_APP,
643 IPMI_CMD_GET_SELF_TEST_RESULTS,
644 NULL,
645 ipmi_app_get_self_test_results,
646 PRIVILEGE_USER);
Nan Li41fa24a2016-11-10 20:12:37 +0800647
Tom05732372016-09-06 17:21:23 +0530648 // <Get Device GUID>
Patrick Ventured2117022018-02-06 08:54:37 -0800649 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
650 NETFUN_APP,
651 IPMI_CMD_GET_DEVICE_GUID);
652 ipmi_register_callback(NETFUN_APP,
653 IPMI_CMD_GET_DEVICE_GUID,
654 NULL,
655 ipmi_app_get_device_guid,
Tom05732372016-09-06 17:21:23 +0530656 PRIVILEGE_USER);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500657
Tom05732372016-09-06 17:21:23 +0530658 // <Set ACPI Power State>
Patrick Ventured2117022018-02-06 08:54:37 -0800659 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
660 NETFUN_APP,
661 IPMI_CMD_SET_ACPI);
662 ipmi_register_callback(NETFUN_APP,
663 IPMI_CMD_SET_ACPI,
664 NULL,
665 ipmi_app_set_acpi_power_state,
Tom05732372016-09-06 17:21:23 +0530666 PRIVILEGE_ADMIN);
Chris Austen6caf28b2015-10-13 12:40:40 -0500667
Tom Joseph69fabfe2017-08-04 10:15:01 +0530668 // <Get Channel Access>
Patrick Ventured2117022018-02-06 08:54:37 -0800669 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
670 NETFUN_APP,
671 IPMI_CMD_GET_CHANNEL_ACCESS);
672 ipmi_register_callback(NETFUN_APP,
673 IPMI_CMD_GET_CHANNEL_ACCESS,
674 NULL,
675 ipmi_get_channel_access,
676 PRIVILEGE_USER);
Tom Joseph69fabfe2017-08-04 10:15:01 +0530677
Tom05732372016-09-06 17:21:23 +0530678 // <Get Channel Info Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800679 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
680 NETFUN_APP,
681 IPMI_CMD_GET_CHAN_INFO);
682 ipmi_register_callback(NETFUN_APP,
683 IPMI_CMD_GET_CHAN_INFO,
684 NULL,
685 ipmi_app_channel_info,
Tom05732372016-09-06 17:21:23 +0530686 PRIVILEGE_USER);
Chris Austenc2cd29d2016-02-05 20:02:29 -0600687
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600688 // <Get System GUID Command>
Patrick Ventured2117022018-02-06 08:54:37 -0800689 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n",
690 NETFUN_APP,
691 IPMI_CMD_GET_SYS_GUID);
692 ipmi_register_callback(NETFUN_APP,
693 IPMI_CMD_GET_SYS_GUID,
694 NULL,
695 ipmi_app_get_sys_guid,
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600696 PRIVILEGE_USER);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530697 return;
698}
699