blob: ac06f5086803041856c54d556808a56ae96a59b8 [file] [log] [blame]
Patrick Venture46470a32018-09-07 19:26:25 -07001#include "apphandler.hpp"
Patrick Venture0b02be92018-08-31 11:55:55 -07002
Xo Wangf542e8b2017-08-09 15:34:16 -07003#include "app/channel.hpp"
4#include "app/watchdog.hpp"
5#include "ipmid.hpp"
Xo Wangf542e8b2017-08-09 15:34:16 -07006#include "sys_info_param.hpp"
7#include "transporthandler.hpp"
8#include "types.hpp"
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +05309#include "user_channel/usercommands.hpp"
Xo Wangf542e8b2017-08-09 15:34:16 -070010#include "utils.hpp"
11
Patrick Venture0b02be92018-08-31 11:55:55 -070012#include <arpa/inet.h>
Patrick Venture46470a32018-09-07 19:26:25 -070013#include <host-ipmid/ipmid-api.h>
Xo Wang87651332017-08-11 10:17:59 -070014#include <limits.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070015#include <mapper.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070016#include <systemd/sd-bus.h>
Xo Wang87651332017-08-11 10:17:59 -070017#include <unistd.h>
Patrick Venture0b02be92018-08-31 11:55:55 -070018
Patrick Venture3a5071a2018-09-12 13:27:42 -070019#include <algorithm>
20#include <array>
21#include <cstddef>
22#include <fstream>
23#include <memory>
Patrick Venture46470a32018-09-07 19:26:25 -070024#include <nlohmann/json.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070025#include <phosphor-logging/elog-errors.hpp>
26#include <phosphor-logging/log.hpp>
William A. Kennington III4c008022018-10-12 17:18:14 -070027#include <sdbusplus/message/types.hpp>
Patrick Venture3a5071a2018-09-12 13:27:42 -070028#include <string>
29#include <tuple>
30#include <vector>
31#include <xyz/openbmc_project/Common/error.hpp>
32#include <xyz/openbmc_project/Software/Activation/server.hpp>
33#include <xyz/openbmc_project/Software/Version/server.hpp>
34#include <xyz/openbmc_project/State/BMC/server.hpp>
Ratan Guptab8e99552017-07-27 07:07:48 +053035
Vernon Mauery185b9f82018-07-20 10:52:36 -070036#if __has_include(<filesystem>)
37#include <filesystem>
38#elif __has_include(<experimental/filesystem>)
39#include <experimental/filesystem>
Patrick Venture0b02be92018-08-31 11:55:55 -070040namespace std
41{
42// splice experimental::filesystem into std
43namespace filesystem = std::experimental::filesystem;
44} // namespace std
Vernon Mauery185b9f82018-07-20 10:52:36 -070045#else
Patrick Venture0b02be92018-08-31 11:55:55 -070046#error filesystem not available
Vernon Mauery185b9f82018-07-20 10:52:36 -070047#endif
Ratan Gupta62736ec2017-09-02 12:02:47 +053048
Patrick Venture0b02be92018-08-31 11:55:55 -070049extern sd_bus* bus;
vishwabmcba0bd5f2015-09-30 16:50:23 +053050
Alexander Amelkinba19c182018-09-04 15:49:36 +030051constexpr auto bmc_state_interface = "xyz.openbmc_project.State.BMC";
52constexpr auto bmc_state_property = "CurrentBMCState";
Marri Devender Rao5e007a52018-01-08 06:18:36 -060053constexpr auto bmc_interface = "xyz.openbmc_project.Inventory.Item.Bmc";
54constexpr auto bmc_guid_interface = "xyz.openbmc_project.Common.UUID";
55constexpr auto bmc_guid_property = "UUID";
56constexpr auto bmc_guid_len = 16;
57
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060058static constexpr auto redundancyIntf =
59 "xyz.openbmc_project.Software.RedundancyPriority";
Patrick Venture0b02be92018-08-31 11:55:55 -070060static constexpr auto versionIntf = "xyz.openbmc_project.Software.Version";
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060061static constexpr auto activationIntf =
62 "xyz.openbmc_project.Software.Activation";
63static constexpr auto softwareRoot = "/xyz/openbmc_project/software";
64
Chris Austen6caf28b2015-10-13 12:40:40 -050065void register_netfn_app_functions() __attribute__((constructor));
vishwabmcba0bd5f2015-09-30 16:50:23 +053066
Ratan Guptab8e99552017-07-27 07:07:48 +053067using namespace phosphor::logging;
68using namespace sdbusplus::xyz::openbmc_project::Common::Error;
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060069using Version = sdbusplus::xyz::openbmc_project::Software::server::Version;
70using Activation =
71 sdbusplus::xyz::openbmc_project::Software::server::Activation;
Alexander Amelkinba19c182018-09-04 15:49:36 +030072using BMC = sdbusplus::xyz::openbmc_project::State::server::BMC;
Vernon Mauery185b9f82018-07-20 10:52:36 -070073namespace fs = std::filesystem;
William A. Kennington III4c008022018-10-12 17:18:14 -070074namespace variant_ns = sdbusplus::message::variant_ns;
Ratan Guptab8e99552017-07-27 07:07:48 +053075
Nan Liee0cb902016-07-11 15:38:03 +080076// Offset in get device id command.
77typedef struct
78{
Patrick Venture0b02be92018-08-31 11:55:55 -070079 uint8_t id;
80 uint8_t revision;
81 uint8_t fw[2];
82 uint8_t ipmi_ver;
83 uint8_t addn_dev_support;
84 uint8_t manuf_id[3];
85 uint8_t prod_id[2];
86 uint8_t aux[4];
87} __attribute__((packed)) ipmi_device_id_t;
Chris Austen7303bdc2016-04-17 11:50:54 -050088
Nagaraju Goruganti744398d2018-02-20 09:52:00 -060089/**
90 * @brief Returns the Version info from primary s/w object
91 *
92 * Get the Version info from the active s/w object which is having high
93 * "Priority" value(a smaller number is a higher priority) and "Purpose"
94 * is "BMC" from the list of all s/w objects those are implementing
95 * RedundancyPriority interface from the given softwareRoot path.
96 *
97 * @return On success returns the Version info from primary s/w object.
98 *
99 */
100std::string getActiveSoftwareVersionInfo()
101{
102 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
103
104 std::string revision{};
Patrick Venture0b02be92018-08-31 11:55:55 -0700105 auto objectTree =
106 ipmi::getAllDbusObjects(bus, softwareRoot, redundancyIntf, "");
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600107 if (objectTree.empty())
108 {
109 log<level::ERR>("No Obj has implemented the s/w redundancy interface",
110 entry("INTERFACE=%s", redundancyIntf));
111 elog<InternalFailure>();
112 }
113
114 auto objectFound = false;
115 for (auto& softObject : objectTree)
116 {
117 auto service = ipmi::getService(bus, redundancyIntf, softObject.first);
118 auto objValueTree = ipmi::getManagedObjects(bus, service, softwareRoot);
119
120 auto minPriority = 0xFF;
121 for (const auto& objIter : objValueTree)
122 {
123 try
124 {
125 auto& intfMap = objIter.second;
126 auto& redundancyPriorityProps = intfMap.at(redundancyIntf);
127 auto& versionProps = intfMap.at(versionIntf);
128 auto& activationProps = intfMap.at(activationIntf);
William A. Kennington III4c008022018-10-12 17:18:14 -0700129 auto priority = variant_ns::get<uint8_t>(
130 redundancyPriorityProps.at("Priority"));
131 auto purpose =
132 variant_ns::get<std::string>(versionProps.at("Purpose"));
133 auto activation = variant_ns::get<std::string>(
134 activationProps.at("Activation"));
135 auto version =
136 variant_ns::get<std::string>(versionProps.at("Version"));
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600137 if ((Version::convertVersionPurposeFromString(purpose) ==
138 Version::VersionPurpose::BMC) &&
139 (Activation::convertActivationsFromString(activation) ==
140 Activation::Activations::Active))
141 {
142 if (priority < minPriority)
143 {
144 minPriority = priority;
145 objectFound = true;
146 revision = std::move(version);
147 }
148 }
149 }
150 catch (const std::exception& e)
151 {
152 log<level::ERR>(e.what());
153 }
154 }
155 }
156
157 if (!objectFound)
158 {
159 log<level::ERR>("Could not found an BMC software Object");
160 elog<InternalFailure>();
161 }
162
163 return revision;
164}
165
Alexander Amelkinba19c182018-09-04 15:49:36 +0300166bool getCurrentBmcState()
167{
168 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
169
170 // Get the Inventory object implementing the BMC interface
171 ipmi::DbusObjectInfo bmcObject =
172 ipmi::getDbusObject(bus, bmc_state_interface);
173 auto variant =
174 ipmi::getDbusProperty(bus, bmcObject.second, bmcObject.first,
175 bmc_state_interface, bmc_state_property);
176
William A. Kennington III4c008022018-10-12 17:18:14 -0700177 return variant_ns::holds_alternative<std::string>(variant) &&
178 BMC::convertBMCStateFromString(
179 variant_ns::get<std::string>(variant)) == BMC::BMCState::Ready;
Alexander Amelkinba19c182018-09-04 15:49:36 +0300180}
181
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500182ipmi_ret_t ipmi_app_set_acpi_power_state(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700183 ipmi_request_t request,
184 ipmi_response_t response,
185 ipmi_data_len_t data_len,
186 ipmi_context_t context)
Chris Austen6caf28b2015-10-13 12:40:40 -0500187{
188 ipmi_ret_t rc = IPMI_CC_OK;
189 *data_len = 0;
190
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530191 log<level::DEBUG>("IPMI SET ACPI STATE Ignoring for now\n");
Chris Austen6caf28b2015-10-13 12:40:40 -0500192 return rc;
193}
194
Chris Austen7303bdc2016-04-17 11:50:54 -0500195typedef struct
196{
197 char major;
198 char minor;
Chris Austen176c9652016-04-30 16:32:17 -0500199 uint16_t d[2];
Chris Austen7303bdc2016-04-17 11:50:54 -0500200} rev_t;
201
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600202/* Currently supports the vx.x-x-[-x] and v1.x.x-x-[-x] format. It will */
203/* return -1 if not in those formats, this routine knows how to parse */
Chris Austen7303bdc2016-04-17 11:50:54 -0500204/* version = v0.6-19-gf363f61-dirty */
205/* ^ ^ ^^ ^ */
206/* | | |----------|-- additional details */
207/* | |---------------- Minor */
208/* |------------------ Major */
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600209/* and version = v1.99.10-113-g65edf7d-r3-0-g9e4f715 */
210/* ^ ^ ^^ ^ */
211/* | | |--|---------- additional details */
212/* | |---------------- Minor */
213/* |------------------ Major */
Chris Austen7303bdc2016-04-17 11:50:54 -0500214/* Additional details : If the option group exists it will force Auxiliary */
215/* Firmware Revision Information 4th byte to 1 indicating the build was */
216/* derived with additional edits */
Patrick Venture0b02be92018-08-31 11:55:55 -0700217int convert_version(const char* p, rev_t* rev)
Chris Austen7303bdc2016-04-17 11:50:54 -0500218{
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600219 std::string s(p);
220 std::string token;
Chris Austen176c9652016-04-30 16:32:17 -0500221 uint16_t commits;
Chris Austen7303bdc2016-04-17 11:50:54 -0500222
Patrick Venture0b02be92018-08-31 11:55:55 -0700223 auto location = s.find_first_of('v');
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600224 if (location != std::string::npos)
225 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700226 s = s.substr(location + 1);
Chris Austen176c9652016-04-30 16:32:17 -0500227 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500228
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600229 if (!s.empty())
230 {
231 location = s.find_first_of(".");
232 if (location != std::string::npos)
233 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700234 rev->major =
235 static_cast<char>(std::stoi(s.substr(0, location), 0, 16));
236 token = s.substr(location + 1);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600237 }
Chris Austen176c9652016-04-30 16:32:17 -0500238
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600239 if (!token.empty())
240 {
241 location = token.find_first_of(".-");
242 if (location != std::string::npos)
243 {
Patrick Ventured2117022018-02-06 08:54:37 -0800244 rev->minor = static_cast<char>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700245 std::stoi(token.substr(0, location), 0, 16));
246 token = token.substr(location + 1);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600247 }
248 }
Chris Austen7303bdc2016-04-17 11:50:54 -0500249
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600250 // Capture the number of commits on top of the minor tag.
251 // I'm using BE format like the ipmi spec asked for
252 location = token.find_first_of(".-");
253 if (!token.empty())
254 {
255 commits = std::stoi(token.substr(0, location), 0, 16);
Patrick Venture0b02be92018-08-31 11:55:55 -0700256 rev->d[0] = (commits >> 8) | (commits << 8);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600257
258 // commit number we skip
259 location = token.find_first_of(".-");
260 if (location != std::string::npos)
261 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700262 token = token.substr(location + 1);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600263 }
264 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700265 else
266 {
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600267 rev->d[0] = 0;
268 }
269
270 if (location != std::string::npos)
271 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700272 token = token.substr(location + 1);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600273 }
274
275 // Any value of the optional parameter forces it to 1
276 location = token.find_first_of(".-");
277 if (location != std::string::npos)
278 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700279 token = token.substr(location + 1);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600280 }
281 commits = (!token.empty()) ? 1 : 0;
282
Patrick Venture0b02be92018-08-31 11:55:55 -0700283 // We do this operation to get this displayed in least significant bytes
284 // of ipmitool device id command.
285 rev->d[1] = (commits >> 8) | (commits << 8);
Dinesh Chinari2b7e07d2017-11-08 15:38:50 -0600286 }
287
Chris Austen7303bdc2016-04-17 11:50:54 -0500288 return 0;
289}
290
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500291ipmi_ret_t ipmi_app_get_device_id(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700292 ipmi_request_t request,
293 ipmi_response_t response,
294 ipmi_data_len_t data_len,
295 ipmi_context_t context)
Chris Austen6caf28b2015-10-13 12:40:40 -0500296{
297 ipmi_ret_t rc = IPMI_CC_OK;
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600298 int r = -1;
Chris Austen7303bdc2016-04-17 11:50:54 -0500299 rev_t rev = {0};
David Cobbleya1adb072017-11-21 15:58:13 -0800300 static ipmi_device_id_t dev_id{};
301 static bool dev_id_initialized = false;
302 const char* filename = "/usr/share/ipmi-providers/dev_id.json";
Alexander Amelkinba19c182018-09-04 15:49:36 +0300303 constexpr auto ipmiDevIdStateShift = 7;
304 constexpr auto ipmiDevIdFw1Mask = ~(1 << ipmiDevIdStateShift);
Chris Austen6caf28b2015-10-13 12:40:40 -0500305
306 // Data length
Chris Austen7303bdc2016-04-17 11:50:54 -0500307 *data_len = sizeof(dev_id);
308
David Cobbleya1adb072017-11-21 15:58:13 -0800309 if (!dev_id_initialized)
310 {
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600311 try
312 {
313 auto version = getActiveSoftwareVersionInfo();
314 r = convert_version(version.c_str(), &rev);
David Cobbleya1adb072017-11-21 15:58:13 -0800315 }
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600316 catch (const std::exception& e)
317 {
318 log<level::ERR>(e.what());
319 }
Nan Liee0cb902016-07-11 15:38:03 +0800320
Patrick Venture0b02be92018-08-31 11:55:55 -0700321 if (r >= 0)
322 {
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600323 // bit7 identifies if the device is available
324 // 0=normal operation
325 // 1=device firmware, SDR update,
326 // or self-initialization in progress.
Alexander Amelkinba19c182018-09-04 15:49:36 +0300327 // The availability may change in run time, so mask here
328 // and initialize later.
329 dev_id.fw[0] = rev.major & ipmiDevIdFw1Mask;
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600330
331 rev.minor = (rev.minor > 99 ? 99 : rev.minor);
332 dev_id.fw[1] = rev.minor % 10 + (rev.minor / 10) * 16;
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700333 std::memcpy(&dev_id.aux, rev.d, 4);
David Cobbleya1adb072017-11-21 15:58:13 -0800334 }
Nan Liee0cb902016-07-11 15:38:03 +0800335
David Cobbleya1adb072017-11-21 15:58:13 -0800336 // IPMI Spec version 2.0
337 dev_id.ipmi_ver = 2;
Adriana Kobylak0e912642016-06-22 16:54:39 -0500338
David Cobbleya1adb072017-11-21 15:58:13 -0800339 std::ifstream dev_id_file(filename);
340 if (dev_id_file.is_open())
341 {
342 auto data = nlohmann::json::parse(dev_id_file, nullptr, false);
343 if (!data.is_discarded())
344 {
345 dev_id.id = data.value("id", 0);
346 dev_id.revision = data.value("revision", 0);
347 dev_id.addn_dev_support = data.value("addn_dev_support", 0);
348 dev_id.manuf_id[2] = data.value("manuf_id", 0) >> 16;
349 dev_id.manuf_id[1] = data.value("manuf_id", 0) >> 8;
350 dev_id.manuf_id[0] = data.value("manuf_id", 0);
351 dev_id.prod_id[1] = data.value("prod_id", 0) >> 8;
352 dev_id.prod_id[0] = data.value("prod_id", 0);
Tom Josephaf8a0982018-03-09 07:54:02 -0600353 dev_id.aux[3] = data.value("aux", 0);
354 dev_id.aux[2] = data.value("aux", 0) >> 8;
355 dev_id.aux[1] = data.value("aux", 0) >> 16;
356 dev_id.aux[0] = data.value("aux", 0) >> 24;
David Cobbleya1adb072017-11-21 15:58:13 -0800357
Patrick Venture0b02be92018-08-31 11:55:55 -0700358 // Don't read the file every time if successful
David Cobbleya1adb072017-11-21 15:58:13 -0800359 dev_id_initialized = true;
360 }
361 else
362 {
363 log<level::ERR>("Device ID JSON parser failure");
364 rc = IPMI_CC_UNSPECIFIED_ERROR;
365 }
366 }
367 else
368 {
369 log<level::ERR>("Device ID file not found");
370 rc = IPMI_CC_UNSPECIFIED_ERROR;
Chris Austen7303bdc2016-04-17 11:50:54 -0500371 }
372 }
Chris Austen6caf28b2015-10-13 12:40:40 -0500373
Alexander Amelkinba19c182018-09-04 15:49:36 +0300374 // Set availability to the actual current BMC state
375 dev_id.fw[0] &= ipmiDevIdFw1Mask;
376 if (!getCurrentBmcState())
377 {
378 dev_id.fw[0] |= (1 << ipmiDevIdStateShift);
379 }
380
Chris Austen6caf28b2015-10-13 12:40:40 -0500381 // Pack the actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700382 std::memcpy(response, &dev_id, *data_len);
Nagaraju Goruganti744398d2018-02-20 09:52:00 -0600383
Chris Austen6caf28b2015-10-13 12:40:40 -0500384 return rc;
385}
386
Nan Li41fa24a2016-11-10 20:12:37 +0800387ipmi_ret_t ipmi_app_get_self_test_results(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700388 ipmi_request_t request,
389 ipmi_response_t response,
390 ipmi_data_len_t data_len,
391 ipmi_context_t context)
Nan Li41fa24a2016-11-10 20:12:37 +0800392{
393 ipmi_ret_t rc = IPMI_CC_OK;
394
395 // Byte 2:
396 // 55h - No error.
Gunnar Mills8991dd62017-10-25 17:11:29 -0500397 // 56h - Self Test function not implemented in this controller.
Nan Li41fa24a2016-11-10 20:12:37 +0800398 // 57h - Corrupted or inaccesssible data or devices.
399 // 58h - Fatal hardware error.
400 // FFh - reserved.
401 // all other: Device-specific 'internal failure'.
402 // Byte 3:
403 // For byte 2 = 55h, 56h, FFh: 00h
404 // For byte 2 = 58h, all other: Device-specific
405 // For byte 2 = 57h: self-test error bitfield.
406 // Note: returning 57h does not imply that all test were run.
407 // [7] 1b = Cannot access SEL device.
408 // [6] 1b = Cannot access SDR Repository.
409 // [5] 1b = Cannot access BMC FRU device.
410 // [4] 1b = IPMB signal lines do not respond.
411 // [3] 1b = SDR Repository empty.
412 // [2] 1b = Internal Use Area of BMC FRU corrupted.
413 // [1] 1b = controller update 'boot block' firmware corrupted.
414 // [0] 1b = controller operational firmware corrupted.
415
416 char selftestresults[2] = {0};
417
418 *data_len = 2;
419
420 selftestresults[0] = 0x56;
421 selftestresults[1] = 0;
422
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700423 std::memcpy(response, selftestresults, *data_len);
Nan Li41fa24a2016-11-10 20:12:37 +0800424
425 return rc;
426}
427
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500428ipmi_ret_t ipmi_app_get_device_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700429 ipmi_request_t request,
430 ipmi_response_t response,
431 ipmi_data_len_t data_len,
432 ipmi_context_t context)
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500433{
Patrick Venture0b02be92018-08-31 11:55:55 -0700434 const char* objname = "/org/openbmc/control/chassis0";
435 const char* iface = "org.freedesktop.DBus.Properties";
436 const char* chassis_iface = "org.openbmc.control.Chassis";
437 sd_bus_message* reply = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500438 sd_bus_error error = SD_BUS_ERROR_NULL;
439 int r = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700440 char* uuid = NULL;
441 char* busname = NULL;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500442
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500443 // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
Patrick Ventured2117022018-02-06 08:54:37 -0800444 // Per IPMI Spec 2.0 need to convert to 16 hex bytes and reverse the byte
445 // order
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500446 // Ex: 0x2332fc2c40e66298e511f2782395a361
447
Patrick Venture0b02be92018-08-31 11:55:55 -0700448 const int resp_size = 16; // Response is 16 hex bytes per IPMI Spec
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500449 uint8_t resp_uuid[resp_size]; // Array to hold the formatted response
Patrick Ventured2117022018-02-06 08:54:37 -0800450 // Point resp end of array to save in reverse order
Patrick Venture0b02be92018-08-31 11:55:55 -0700451 int resp_loc = resp_size - 1;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500452 int i = 0;
Patrick Venture0b02be92018-08-31 11:55:55 -0700453 char* tokptr = NULL;
454 char* id_octet = NULL;
Emily Shafferedb8bb02018-09-27 14:50:15 -0700455 size_t total_uuid_size = 0;
456 // 1 byte of resp is built from 2 chars of uuid.
457 constexpr size_t max_uuid_size = 2 * resp_size;
vishwa1eaea4f2016-02-26 11:57:40 -0600458
459 // Status code.
460 ipmi_ret_t rc = IPMI_CC_OK;
461 *data_len = 0;
462
vishwa1eaea4f2016-02-26 11:57:40 -0600463 // Call Get properties method with the interface and property name
Sergey Solomineb9b8142016-08-23 09:07:28 -0500464 r = mapper_get_service(bus, objname, &busname);
Patrick Venture0b02be92018-08-31 11:55:55 -0700465 if (r < 0)
466 {
467 log<level::ERR>("Failed to get bus name", entry("BUS=%s", objname),
Aditya Saripalli5fb14602017-11-09 14:46:27 +0530468 entry("ERRNO=0x%X", -r));
Sergey Solomineb9b8142016-08-23 09:07:28 -0500469 goto finish;
470 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700471 r = sd_bus_call_method(bus, busname, objname, iface, "Get", &error, &reply,
472 "ss", chassis_iface, "uuid");
vishwa1eaea4f2016-02-26 11:57:40 -0600473 if (r < 0)
474 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700475 log<level::ERR>("Failed to call Get Method", entry("ERRNO=0x%X", -r));
vishwa1eaea4f2016-02-26 11:57:40 -0600476 rc = IPMI_CC_UNSPECIFIED_ERROR;
477 goto finish;
478 }
479
480 r = sd_bus_message_read(reply, "v", "s", &uuid);
481 if (r < 0 || uuid == NULL)
482 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700483 log<level::ERR>("Failed to get a response", entry("ERRNO=0x%X", -r));
vishwa1eaea4f2016-02-26 11:57:40 -0600484 rc = IPMI_CC_RESPONSE_ERROR;
485 goto finish;
486 }
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500487
488 // Traverse the UUID
Patrick Ventured2117022018-02-06 08:54:37 -0800489 // Get the UUID octects separated by dash
490 id_octet = strtok_r(uuid, "-", &tokptr);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500491
492 if (id_octet == NULL)
vishwa1eaea4f2016-02-26 11:57:40 -0600493 {
494 // Error
Patrick Venture0b02be92018-08-31 11:55:55 -0700495 log<level::ERR>("Unexpected UUID format", entry("UUID=%s", uuid));
vishwa1eaea4f2016-02-26 11:57:40 -0600496 rc = IPMI_CC_RESPONSE_ERROR;
497 goto finish;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500498 }
499
500 while (id_octet != NULL)
501 {
502 // Calculate the octet string size since it varies
503 // Divide it by 2 for the array size since 1 byte is built from 2 chars
Patrick Venture0b02be92018-08-31 11:55:55 -0700504 int tmp_size = strlen(id_octet) / 2;
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500505
Emily Shafferedb8bb02018-09-27 14:50:15 -0700506 // Check if total UUID size has been exceeded
507 if ((total_uuid_size += strlen(id_octet)) > max_uuid_size)
508 {
509 // Error - UUID too long to store
510 log<level::ERR>("UUID too long", entry("UUID=%s", uuid));
511 rc = IPMI_CC_RESPONSE_ERROR;
512 goto finish;
513 }
514
Patrick Venture0b02be92018-08-31 11:55:55 -0700515 for (i = 0; i < tmp_size; i++)
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500516 {
Patrick Ventured2117022018-02-06 08:54:37 -0800517 // Holder of the 2 chars that will become a byte
518 char tmp_array[3] = {0};
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500519 strncpy(tmp_array, id_octet, 2); // 2 chars at a time
520
521 int resp_byte = strtoul(tmp_array, NULL, 16); // Convert to hex byte
Patrick Ventured2117022018-02-06 08:54:37 -0800522 // Copy end to first
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700523 std::memcpy((void*)&resp_uuid[resp_loc], &resp_byte, 1);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500524 resp_loc--;
Patrick Venture0b02be92018-08-31 11:55:55 -0700525 id_octet += 2; // Finished with the 2 chars, advance
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500526 }
Patrick Venture0b02be92018-08-31 11:55:55 -0700527 id_octet = strtok_r(NULL, "-", &tokptr); // Get next octet
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500528 }
529
530 // Data length
531 *data_len = resp_size;
532
533 // Pack the actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700534 std::memcpy(response, &resp_uuid, *data_len);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500535
vishwa1eaea4f2016-02-26 11:57:40 -0600536finish:
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500537 sd_bus_error_free(&error);
vishwa1eaea4f2016-02-26 11:57:40 -0600538 reply = sd_bus_message_unref(reply);
Sergey Solomineb9b8142016-08-23 09:07:28 -0500539 free(busname);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500540
541 return rc;
542}
Chris Austen6caf28b2015-10-13 12:40:40 -0500543
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500544ipmi_ret_t ipmi_app_get_bt_capabilities(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700545 ipmi_request_t request,
546 ipmi_response_t response,
547 ipmi_data_len_t data_len,
548 ipmi_context_t context)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530549{
vishwabmcba0bd5f2015-09-30 16:50:23 +0530550
551 // Status code.
552 ipmi_ret_t rc = IPMI_CC_OK;
553
Adriana Kobylak88ad8152016-12-13 10:09:08 -0600554 // Per IPMI 2.0 spec, the input and output buffer size must be the max
555 // buffer size minus one byte to allocate space for the length byte.
Patrick Venture0b02be92018-08-31 11:55:55 -0700556 uint8_t str[] = {0x01, MAX_IPMI_BUFFER - 1, MAX_IPMI_BUFFER - 1, 0x0A,
557 0x01};
vishwabmcba0bd5f2015-09-30 16:50:23 +0530558
559 // Data length
560 *data_len = sizeof(str);
561
562 // Pack the actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700563 std::memcpy(response, &str, *data_len);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530564
565 return rc;
566}
567
Adriana Kobylak3a552e12015-10-19 16:11:00 -0500568ipmi_ret_t ipmi_app_wildcard_handler(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700569 ipmi_request_t request,
570 ipmi_response_t response,
571 ipmi_data_len_t data_len,
572 ipmi_context_t context)
vishwabmcba0bd5f2015-09-30 16:50:23 +0530573{
vishwabmcba0bd5f2015-09-30 16:50:23 +0530574 // Status code.
Nan Li70aa8d92016-08-29 00:11:10 +0800575 ipmi_ret_t rc = IPMI_CC_INVALID;
vishwabmcba0bd5f2015-09-30 16:50:23 +0530576
577 *data_len = strlen("THIS IS WILDCARD");
578
579 // Now pack actual response
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700580 std::memcpy(response, "THIS IS WILDCARD", *data_len);
vishwabmcba0bd5f2015-09-30 16:50:23 +0530581
582 return rc;
583}
584
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600585ipmi_ret_t ipmi_app_get_sys_guid(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
Patrick Venture0b02be92018-08-31 11:55:55 -0700586 ipmi_request_t request,
587 ipmi_response_t response,
588 ipmi_data_len_t data_len,
589 ipmi_context_t context)
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600590
591{
592 ipmi_ret_t rc = IPMI_CC_OK;
593 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
594
595 try
596 {
597 // Get the Inventory object implementing BMC interface
598 ipmi::DbusObjectInfo bmcObject =
599 ipmi::getDbusObject(bus, bmc_interface);
600
601 // Read UUID property value from bmcObject
602 // UUID is in RFC4122 format Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
Patrick Venture0b02be92018-08-31 11:55:55 -0700603 auto variant =
604 ipmi::getDbusProperty(bus, bmcObject.second, bmcObject.first,
605 bmc_guid_interface, bmc_guid_property);
William A. Kennington III4c008022018-10-12 17:18:14 -0700606 std::string guidProp = variant_ns::get<std::string>(variant);
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600607
608 // Erase "-" characters from the property value
609 guidProp.erase(std::remove(guidProp.begin(), guidProp.end(), '-'),
Patrick Venture0b02be92018-08-31 11:55:55 -0700610 guidProp.end());
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600611
612 auto guidPropLen = guidProp.length();
613 // Validate UUID data
614 // Divide by 2 as 1 byte is built from 2 chars
Patrick Venture0b02be92018-08-31 11:55:55 -0700615 if ((guidPropLen <= 0) || ((guidPropLen / 2) != bmc_guid_len))
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600616
617 {
618 log<level::ERR>("Invalid UUID property value",
Patrick Venture0b02be92018-08-31 11:55:55 -0700619 entry("UUID_LENGTH=%d", guidPropLen));
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600620 return IPMI_CC_RESPONSE_ERROR;
621 }
622
623 // Convert data in RFC4122(MSB) format to LSB format
624 // Get 2 characters at a time as 1 byte is built from 2 chars and
625 // convert to hex byte
626 // TODO: Data printed for GUID command is not as per the
627 // GUID format defined in IPMI specification 2.0 section 20.8
628 // Ticket raised: https://sourceforge.net/p/ipmitool/bugs/501/
629 uint8_t respGuid[bmc_guid_len];
630 for (size_t i = 0, respLoc = (bmc_guid_len - 1);
Patrick Venture0b02be92018-08-31 11:55:55 -0700631 i < guidPropLen && respLoc >= 0; i += 2, respLoc--)
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600632 {
633 auto value = static_cast<uint8_t>(
Patrick Venture0b02be92018-08-31 11:55:55 -0700634 std::stoi(guidProp.substr(i, 2).c_str(), NULL, 16));
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600635 respGuid[respLoc] = value;
636 }
637
638 *data_len = bmc_guid_len;
Patrick Ventureb51bf9c2018-09-10 15:53:14 -0700639 std::memcpy(response, &respGuid, bmc_guid_len);
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600640 }
641 catch (const InternalFailure& e)
642 {
643 log<level::ERR>("Failed in reading BMC UUID property",
644 entry("INTERFACE=%s", bmc_interface),
645 entry("PROPERTY_INTERFACE=%s", bmc_guid_interface),
646 entry("PROPERTY=%s", bmc_guid_property));
647 return IPMI_CC_UNSPECIFIED_ERROR;
648 }
649 return rc;
650}
651
Xo Wangf542e8b2017-08-09 15:34:16 -0700652static std::unique_ptr<SysInfoParamStore> sysInfoParamStore;
653
Xo Wang87651332017-08-11 10:17:59 -0700654static std::string sysInfoReadSystemName()
655{
656 // Use the BMC hostname as the "System Name."
657 char hostname[HOST_NAME_MAX + 1] = {};
658 if (gethostname(hostname, HOST_NAME_MAX) != 0)
659 {
660 perror("System info parameter: system name");
661 }
662 return hostname;
663}
664
Xo Wangf542e8b2017-08-09 15:34:16 -0700665struct IpmiSysInfoResp
666{
667 uint8_t paramRevision;
668 uint8_t setSelector;
669 union
670 {
671 struct
672 {
673 uint8_t encoding;
674 uint8_t stringLen;
675 uint8_t stringData0[14];
676 } __attribute__((packed));
677 uint8_t stringDataN[16];
678 uint8_t byteData;
679 };
680} __attribute__((packed));
681
682/**
683 * Split a string into (up to) 16-byte chunks as expected in response for get
684 * system info parameter.
685 *
686 * @param[in] fullString: Input string to be split
687 * @param[in] chunkIndex: Index of the chunk to be written out
688 * @param[in,out] chunk: Output data buffer; must have 14 byte capacity if
689 * chunk_index = 0 and 16-byte capacity otherwise
690 * @return the number of bytes written into the output buffer, or -EINVAL for
691 * invalid arguments.
692 */
693static int splitStringParam(const std::string& fullString, int chunkIndex,
694 uint8_t* chunk)
695{
696 constexpr int maxChunk = 255;
697 constexpr int smallChunk = 14;
698 constexpr int chunkSize = 16;
699 if (chunkIndex > maxChunk || chunk == nullptr)
700 {
701 return -EINVAL;
702 }
703 try
704 {
705 std::string output;
706 if (chunkIndex == 0)
707 {
708 // Output must have 14 byte capacity.
709 output = fullString.substr(0, smallChunk);
710 }
711 else
712 {
713 // Output must have 16 byte capacity.
714 output = fullString.substr((chunkIndex * chunkSize) - 2, chunkSize);
715 }
716
717 std::memcpy(chunk, output.c_str(), output.length());
718 return output.length();
719 }
720 catch (const std::out_of_range& e)
721 {
722 // The position was beyond the end.
723 return -EINVAL;
724 }
725}
726
727/**
728 * Packs the Get Sys Info Request Item into the response.
729 *
730 * @param[in] paramString - the parameter.
731 * @param[in] setSelector - the selector
732 * @param[in,out] resp - the System info response.
733 * @return The number of bytes packed or failure from splitStringParam().
734 */
735static int packGetSysInfoResp(const std::string& paramString,
736 uint8_t setSelector, IpmiSysInfoResp* resp)
737{
738 uint8_t* dataBuffer = resp->stringDataN;
739 resp->setSelector = setSelector;
740 if (resp->setSelector == 0) // First chunk has only 14 bytes.
741 {
742 resp->encoding = 0;
743 resp->stringLen = paramString.length();
744 dataBuffer = resp->stringData0;
745 }
746 return splitStringParam(paramString, resp->setSelector, dataBuffer);
747}
748
749ipmi_ret_t ipmi_app_get_system_info(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
750 ipmi_request_t request,
751 ipmi_response_t response,
752 ipmi_data_len_t dataLen,
753 ipmi_context_t context)
754{
755 IpmiSysInfoResp resp = {};
756 size_t respLen = 0;
757 uint8_t* const reqData = static_cast<uint8_t*>(request);
758 std::string paramString;
759 bool found;
760 std::tuple<bool, std::string> ret;
761 constexpr int minRequestSize = 4;
762 constexpr int paramSelector = 1;
763 constexpr uint8_t revisionOnly = 0x80;
764 const uint8_t paramRequested = reqData[paramSelector];
765 int rc;
766
767 if (*dataLen < minRequestSize)
768 {
769 return IPMI_CC_REQ_DATA_LEN_INVALID;
770 }
771
772 *dataLen = 0; // default to 0.
773
774 // Parameters revision as of IPMI spec v2.0 rev. 1.1 (Feb 11, 2014 E6)
775 resp.paramRevision = 0x11;
776 if (reqData[0] & revisionOnly) // Get parameter revision only
777 {
778 respLen = 1;
779 goto writeResponse;
780 }
781
782 // The "Set In Progress" parameter can be used for rollback of parameter
783 // data and is not implemented.
784 if (paramRequested == 0)
785 {
786 resp.byteData = 0;
787 respLen = 2;
788 goto writeResponse;
789 }
790
791 if (sysInfoParamStore == nullptr)
792 {
793 sysInfoParamStore = std::make_unique<SysInfoParamStore>();
Xo Wang87651332017-08-11 10:17:59 -0700794 sysInfoParamStore->update(IPMI_SYSINFO_SYSTEM_NAME,
795 sysInfoReadSystemName);
Xo Wangf542e8b2017-08-09 15:34:16 -0700796 }
797
798 // Parameters other than Set In Progress are assumed to be strings.
799 ret = sysInfoParamStore->lookup(paramRequested);
800 found = std::get<0>(ret);
801 paramString = std::get<1>(ret);
802 if (!found)
803 {
804 return IPMI_CC_SYSTEM_INFO_PARAMETER_NOT_SUPPORTED;
805 }
806 // TODO: Cache each parameter across multiple calls, until the whole string
807 // has been read out. Otherwise, it's possible for a parameter to change
808 // between requests for its chunks, returning chunks incoherent with each
809 // other. For now, the parameter store is simply required to have only
810 // idempotent callbacks.
811 rc = packGetSysInfoResp(paramString, reqData[2], &resp);
812 if (rc == -EINVAL)
813 {
814 return IPMI_CC_RESPONSE_ERROR;
815 }
816
817 respLen = sizeof(resp); // Write entire string data chunk in response.
818
819writeResponse:
820 std::memcpy(response, &resp, sizeof(resp));
821 *dataLen = respLen;
822 return IPMI_CC_OK;
823}
824
Chris Austen6caf28b2015-10-13 12:40:40 -0500825void register_netfn_app_functions()
vishwabmcba0bd5f2015-09-30 16:50:23 +0530826{
Tom05732372016-09-06 17:21:23 +0530827 // <Get BT Interface Capabilities>
Patrick Venture0b02be92018-08-31 11:55:55 -0700828 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CAP_BIT, NULL,
829 ipmi_app_get_bt_capabilities, PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500830
Tom05732372016-09-06 17:21:23 +0530831 // <Wildcard Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700832 ipmi_register_callback(NETFUN_APP, IPMI_CMD_WILDCARD, NULL,
833 ipmi_app_wildcard_handler, PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500834
Tom05732372016-09-06 17:21:23 +0530835 // <Reset Watchdog Timer>
Patrick Venture0b02be92018-08-31 11:55:55 -0700836 ipmi_register_callback(NETFUN_APP, IPMI_CMD_RESET_WD, NULL,
837 ipmi_app_watchdog_reset, PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500838
Tom05732372016-09-06 17:21:23 +0530839 // <Set Watchdog Timer>
Patrick Venture0b02be92018-08-31 11:55:55 -0700840 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_WD, NULL,
841 ipmi_app_watchdog_set, PRIVILEGE_OPERATOR);
Chris Austen6caf28b2015-10-13 12:40:40 -0500842
William A. Kennington III73f44512018-02-09 15:28:46 -0800843 // <Get Watchdog Timer>
Patrick Venture0b02be92018-08-31 11:55:55 -0700844 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_WD, NULL,
845 ipmi_app_watchdog_get, PRIVILEGE_OPERATOR);
William A. Kennington III73f44512018-02-09 15:28:46 -0800846
Tom05732372016-09-06 17:21:23 +0530847 // <Get Device ID>
Patrick Venture0b02be92018-08-31 11:55:55 -0700848 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_ID, NULL,
849 ipmi_app_get_device_id, PRIVILEGE_USER);
Chris Austen6caf28b2015-10-13 12:40:40 -0500850
Tom05732372016-09-06 17:21:23 +0530851 // <Get Self Test Results>
Patrick Venture0b02be92018-08-31 11:55:55 -0700852 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SELF_TEST_RESULTS, NULL,
853 ipmi_app_get_self_test_results, PRIVILEGE_USER);
Nan Li41fa24a2016-11-10 20:12:37 +0800854
Tom05732372016-09-06 17:21:23 +0530855 // <Get Device GUID>
Patrick Venture0b02be92018-08-31 11:55:55 -0700856 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_DEVICE_GUID, NULL,
857 ipmi_app_get_device_guid, PRIVILEGE_USER);
Adriana Kobylakd100ee52015-10-20 17:02:37 -0500858
Tom05732372016-09-06 17:21:23 +0530859 // <Set ACPI Power State>
Patrick Venture0b02be92018-08-31 11:55:55 -0700860 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_ACPI, NULL,
861 ipmi_app_set_acpi_power_state, PRIVILEGE_ADMIN);
Chris Austen6caf28b2015-10-13 12:40:40 -0500862
Tom Joseph69fabfe2017-08-04 10:15:01 +0530863 // <Get Channel Access>
Patrick Venture0b02be92018-08-31 11:55:55 -0700864 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHANNEL_ACCESS, NULL,
865 ipmi_get_channel_access, PRIVILEGE_USER);
Tom Joseph69fabfe2017-08-04 10:15:01 +0530866
Tom05732372016-09-06 17:21:23 +0530867 // <Get Channel Info Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700868 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_INFO, NULL,
869 ipmi_app_channel_info, PRIVILEGE_USER);
Chris Austenc2cd29d2016-02-05 20:02:29 -0600870
Marri Devender Rao5e007a52018-01-08 06:18:36 -0600871 // <Get System GUID Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700872 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYS_GUID, NULL,
873 ipmi_app_get_sys_guid, PRIVILEGE_USER);
Tom Joseph7cbe2282018-03-21 21:17:33 +0530874
875 // <Get Channel Cipher Suites Command>
Patrick Venture0b02be92018-08-31 11:55:55 -0700876 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_CHAN_CIPHER_SUITES, NULL,
877 getChannelCipherSuites, PRIVILEGE_CALLBACK);
Tom Joseph13227682018-08-10 01:05:21 +0530878 // <Set Channel Access Command>
879 ipmi_register_callback(NETFUN_APP, IPMI_CMD_SET_CHAN_ACCESS, NULL,
880 ipmi_set_channel_access, PRIVILEGE_ADMIN);
Xo Wangf542e8b2017-08-09 15:34:16 -0700881
882 // <Get System Info Command>
883 ipmi_register_callback(NETFUN_APP, IPMI_CMD_GET_SYSTEM_INFO, NULL,
884 ipmi_app_get_system_info, PRIVILEGE_USER);
Richard Marian Thomaiyar5a6b6362018-03-12 23:42:34 +0530885 ipmi::registerUserIpmiFunctions();
vishwabmcba0bd5f2015-09-30 16:50:23 +0530886 return;
887}