blob: 42fedab436d2c4d35344c18d1647a23b2771acb8 [file] [log] [blame]
Vishwanatha Subbanna07655062017-07-14 20:31:57 +05301#include "config.h"
Patrick Venture02261c02018-10-31 15:16:23 -07002
3#include "oemhandler.hpp"
4
Tom Joseph246bc0d2017-10-17 16:08:38 +05305#include "elog-errors.hpp"
Patrick Venture02261c02018-10-31 15:16:23 -07006
7#include <endian.h>
William A. Kennington III822eaf62019-02-12 15:20:06 -08008#include <ipmid/api.h>
Chris Austen4d98c1e2015-10-13 14:33:50 -05009#include <stdio.h>
10#include <string.h>
Vishwanatha Subbanna07655062017-07-14 20:31:57 +053011#include <systemd/sd-bus.h>
Patrick Venture02261c02018-10-31 15:16:23 -070012
Vishwanatha Subbanna07655062017-07-14 20:31:57 +053013#include <host-interface.hpp>
William A. Kennington III822eaf62019-02-12 15:20:06 -080014#include <ipmid-host/cmd.hpp>
George Liu23395f52025-04-03 10:33:54 +080015#include <ipmid/api-types.hpp>
Tom Joseph3503fdc2019-01-10 11:25:27 +053016#include <org/open_power/Host/error.hpp>
Tom Joseph246bc0d2017-10-17 16:08:38 +053017#include <org/open_power/OCC/Metrics/error.hpp>
Patrick Venture02261c02018-10-31 15:16:23 -070018#include <sdbusplus/bus.hpp>
Adriana Kobylak81c34df2018-11-01 11:44:16 -050019#include <sdbusplus/exception.hpp>
Chris Austen4d98c1e2015-10-13 14:33:50 -050020
Patrick Williams490126f2023-05-10 07:50:22 -050021#include <fstream>
22#include <functional>
23#include <memory>
24
Andrew Jeffery8fb3f032018-07-27 16:45:44 +093025void register_netfn_ibm_oem_commands() __attribute__((constructor));
Chris Austen4d98c1e2015-10-13 14:33:50 -050026
Patrick Venture02261c02018-10-31 15:16:23 -070027const char* g_esel_path = "/tmp/esel";
Chris Austen29a8e0f2015-10-30 11:44:38 -050028uint16_t g_record_id = 0x0001;
Tom Joseph246bc0d2017-10-17 16:08:38 +053029using namespace phosphor::logging;
30constexpr auto occMetricsType = 0xDD;
31
Tom Josephb61b1072019-01-28 12:32:52 +053032extern const ObjectIDMap invSensors;
33const std::map<uint8_t, Entry::Level> severityMap{
34 {0x10, Entry::Level::Warning}, // Recoverable error
35 {0x20, Entry::Level::Warning}, // Predictive error
36 {0x40, Entry::Level::Error}, // Unrecoverable error
37 {0x50, Entry::Level::Error}, // Critical error
38 {0x60, Entry::Level::Error}, // Error from a diagnostic test
39 {0x70, Entry::Level::Warning}, // Recoverable symptom
40 {0xFF, Entry::Level::Error}, // Unknown error
41};
42
43Entry::Level mapSeverity(const std::string& eSELData)
44{
45 constexpr size_t severityOffset = 0x4A;
46
47 if (eSELData.size() > severityOffset)
48 {
49 // Dive in to the IBM log to find the severity
50 uint8_t sev = 0xF0 & eSELData[severityOffset];
51
52 auto find = severityMap.find(sev);
53 if (find != severityMap.end())
54 {
55 return find->second;
56 }
57 }
58
59 // Default to Entry::Level::Error if a matching is not found.
60 return Entry::Level::Error;
61}
62
63std::string mapCalloutAssociation(const std::string& eSELData)
64{
65 auto rec = reinterpret_cast<const SELEventRecord*>(&eSELData[0]);
66 uint8_t sensor = rec->sensorNum;
67
68 /*
69 * Search the sensor number to inventory path mapping to figure out the
70 * inventory associated with the ESEL.
71 */
72 auto found = std::find_if(invSensors.begin(), invSensors.end(),
73 [&sensor](const auto& iter) {
Patrick Williamsd9c74ac2024-08-16 15:20:03 -040074 return (iter.second.sensorID == sensor);
75 });
Tom Josephb61b1072019-01-28 12:32:52 +053076 if (found != invSensors.end())
77 {
78 return found->first;
79 }
80
81 return {};
82}
83
Patrick Williamsa0a221f2022-07-22 19:26:53 -050084std::string getService(sdbusplus::bus_t& bus, const std::string& path,
Adriana Kobylak81c34df2018-11-01 11:44:16 -050085 const std::string& interface)
86{
Andrew Geissler7f25db72025-03-09 19:09:58 -050087 auto method =
88 bus.new_method_call("xyz.openbmc_project.ObjectMapper",
89 "/xyz/openbmc_project/object_mapper",
90 "xyz.openbmc_project.ObjectMapper", "GetObject");
Adriana Kobylak81c34df2018-11-01 11:44:16 -050091
92 method.append(path);
93 method.append(std::vector<std::string>({interface}));
94
95 std::map<std::string, std::vector<std::string>> response;
96
97 try
98 {
99 auto reply = bus.call(method);
100
101 reply.read(response);
102 if (response.empty())
103 {
104 log<level::ERR>("Error in mapper response for getting service name",
105 entry("PATH=%s", path.c_str()),
106 entry("INTERFACE=%s", interface.c_str()));
107 return std::string{};
108 }
109 }
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500110 catch (const sdbusplus::exception_t& e)
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500111 {
112 log<level::ERR>("Error in mapper method call",
113 entry("ERROR=%s", e.what()));
114 return std::string{};
115 }
116
117 return response.begin()->first;
118}
119
Tom Joseph246bc0d2017-10-17 16:08:38 +0530120std::string readESEL(const char* fileName)
121{
Patrick Venture02261c02018-10-31 15:16:23 -0700122 std::string content{};
Tom Joseph246bc0d2017-10-17 16:08:38 +0530123
124 std::ifstream handle(fileName);
125
126 if (handle.fail())
127 {
Patrick Venture02261c02018-10-31 15:16:23 -0700128 log<level::ERR>("Failed to open eSEL", entry("FILENAME=%s", fileName));
Tom Joseph246bc0d2017-10-17 16:08:38 +0530129 return content;
130 }
131
132 handle.seekg(0, std::ios::end);
133 content.resize(handle.tellg());
134 handle.seekg(0, std::ios::beg);
135 handle.read(&content[0], content.size());
136 handle.close();
137
138 return content;
139}
140
141void createOCCLogEntry(const std::string& eSELData)
142{
143 // Each byte in eSEL is formatted as %02x with a space between bytes and
144 // insert '/0' at the end of the character array.
145 constexpr auto byteSeperator = 3;
146
Patrick Venture02261c02018-10-31 15:16:23 -0700147 std::unique_ptr<char[]> data(
148 new char[(eSELData.size() * byteSeperator) + 1]());
Tom Joseph246bc0d2017-10-17 16:08:38 +0530149
150 for (size_t i = 0; i < eSELData.size(); i++)
151 {
152 sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
153 }
154 data[eSELData.size() * byteSeperator] = '\0';
155
Patrick Venture02261c02018-10-31 15:16:23 -0700156 using error = sdbusplus::org::open_power::OCC::Metrics::Error::Event;
Tom Joseph246bc0d2017-10-17 16:08:38 +0530157 using metadata = org::open_power::OCC::Metrics::Event;
158
159 report<error>(metadata::ESEL(data.get()));
160}
161
Tom Joseph3503fdc2019-01-10 11:25:27 +0530162void createHostEntry(const std::string& eSELData)
163{
164 // Each byte in eSEL is formatted as %02x with a space between bytes and
165 // insert '/0' at the end of the character array.
Tom Joseph3503fdc2019-01-10 11:25:27 +0530166 constexpr auto byteSeperator = 3;
167
Tom Josephb61b1072019-01-28 12:32:52 +0530168 auto sev = mapSeverity(eSELData);
169 auto inventoryPath = mapCalloutAssociation(eSELData);
Tom Joseph3503fdc2019-01-10 11:25:27 +0530170
Tom Josephb61b1072019-01-28 12:32:52 +0530171 if (!inventoryPath.empty())
Tom Joseph3503fdc2019-01-10 11:25:27 +0530172 {
Tom Josephb61b1072019-01-28 12:32:52 +0530173 std::unique_ptr<char[]> data(
174 new char[(eSELData.size() * byteSeperator) + 1]());
175
176 for (size_t i = 0; i < eSELData.size(); i++)
177 {
178 sprintf(&data[i * byteSeperator], "%02x ", eSELData[i]);
179 }
180 data[eSELData.size() * byteSeperator] = '\0';
181
182 using hosterror = sdbusplus::org::open_power::Host::Error::Event;
183 using hostmetadata = org::open_power::Host::Event;
184
185 report<hosterror>(
186 sev, hostmetadata::ESEL(data.get()),
187 hostmetadata::CALLOUT_INVENTORY_PATH(inventoryPath.c_str()));
Tom Joseph3503fdc2019-01-10 11:25:27 +0530188 }
Tom Joseph3503fdc2019-01-10 11:25:27 +0530189}
190
Adriana Kobylak080503e2023-01-05 13:44:25 -0600191/** @brief Helper function to do a graceful restart (reboot) of the BMC.
192 @return 0 on success, -1 on error
193 */
194int rebootBMC()
195{
Patrick Williams505492c2023-02-02 02:57:25 -0600196 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Adriana Kobylak080503e2023-01-05 13:44:25 -0600197 auto service = getService(bus, stateBmcPath, stateBmcIntf);
198 if (service.empty())
199 {
200 log<level::ERR>("Error getting the service name to reboot the BMC.");
201 return -1;
202 }
203 std::variant<std::string> reboot =
204 "xyz.openbmc_project.State.BMC.Transition.Reboot";
205 auto method = bus.new_method_call(service.c_str(), stateBmcPath,
206 propertiesIntf, "Set");
207 method.append(stateBmcIntf, "RequestedBMCTransition", reboot);
208 try
209 {
210 bus.call_noreply(method);
211 }
212 catch (const sdbusplus::exception_t& e)
213 {
214 log<level::ERR>("Error calling to reboot the BMC.",
215 entry("ERROR=%s", e.what()));
216 return -1;
217 }
218 return 0;
219}
220
Chris Austen4d98c1e2015-10-13 14:33:50 -0500221///////////////////////////////////////////////////////////////////////////////
Patrick Williams24fa5a92015-10-30 14:53:57 -0500222// For the First partial add eSEL the SEL Record ID and offset
223// value should be 0x0000. The extended data needs to be in
224// the form of an IPMI SEL Event Record, with Event sensor type
225// of 0xDF and Event Message format of 0x04. The returned
Chris Austen4d98c1e2015-10-13 14:33:50 -0500226// Record ID should be used for all partial eSEL adds.
227//
Chris Austenba54afb2016-02-19 23:18:42 -0600228// This function creates a /tmp/esel file to store the
Chris Austen4d98c1e2015-10-13 14:33:50 -0500229// incoming partial esel. It is the role of some other
Patrick Williams24fa5a92015-10-30 14:53:57 -0500230// function to commit the error log in to long term
231// storage. Likely via the ipmi add_sel command.
Chris Austen4d98c1e2015-10-13 14:33:50 -0500232///////////////////////////////////////////////////////////////////////////////
Patrick Williamsd9c74ac2024-08-16 15:20:03 -0400233ipmi_ret_t ipmi_ibm_oem_partial_esel(
Andrew Geissler7f25db72025-03-09 19:09:58 -0500234 [[maybe_unused]] ipmi_netfn_t netfn, [[maybe_unused]] ipmi_cmd_t cmd,
235 [[maybe_unused]] ipmi_request_t request,
236 [[maybe_unused]] ipmi_response_t response, ipmi_data_len_t data_len,
237 [[maybe_unused]] ipmi_context_t context)
Chris Austen4d98c1e2015-10-13 14:33:50 -0500238{
Patrick Venture02261c02018-10-31 15:16:23 -0700239 uint8_t* reqptr = (uint8_t*)request;
240 esel_request_t esel_req;
241 FILE* fp;
242 int r = 0;
243 uint8_t rlen;
244 ipmi_ret_t rc = IPMI_CC_OK;
245 const char* pio;
Chris Austen4d98c1e2015-10-13 14:33:50 -0500246
Patrick Venture02261c02018-10-31 15:16:23 -0700247 esel_req.resid = le16toh((((uint16_t)reqptr[1]) << 8) + reqptr[0]);
248 esel_req.selrecord = le16toh((((uint16_t)reqptr[3]) << 8) + reqptr[2]);
249 esel_req.offset = le16toh((((uint16_t)reqptr[5]) << 8) + reqptr[4]);
250 esel_req.progress = reqptr[6];
Nan Lib6c4c562016-03-30 17:06:13 +0800251
Patrick Venture02261c02018-10-31 15:16:23 -0700252 // According to IPMI spec, Reservation ID must be checked.
253 if (!checkSELReservation(esel_req.resid))
254 {
255 // 0xc5 means Reservation Cancelled or Invalid Reservation ID.
256 printf("Used Reservation ID = %d\n", esel_req.resid);
257 rc = IPMI_CC_INVALID_RESERVATION_ID;
Nan Lib6c4c562016-03-30 17:06:13 +0800258
Patrick Venture02261c02018-10-31 15:16:23 -0700259 // clean g_esel_path.
260 r = remove(g_esel_path);
261 if (r < 0)
262 fprintf(stderr, "Error deleting %s\n", g_esel_path);
Nan Lib6c4c562016-03-30 17:06:13 +0800263
Patrick Venture02261c02018-10-31 15:16:23 -0700264 return rc;
265 }
Nan Lib6c4c562016-03-30 17:06:13 +0800266
267 // OpenPOWER Host Interface spec says if RecordID and Offset are
Patrick Venture02261c02018-10-31 15:16:23 -0700268 // 0 then then this is a new request
269 if (!esel_req.selrecord && !esel_req.offset)
270 pio = "wb";
271 else
272 pio = "rb+";
Chris Austen4d98c1e2015-10-13 14:33:50 -0500273
Patrick Venture02261c02018-10-31 15:16:23 -0700274 rlen = (*data_len) - (uint8_t)(sizeof(esel_request_t));
Chris Austen4d98c1e2015-10-13 14:33:50 -0500275
Patrick Venture02261c02018-10-31 15:16:23 -0700276 if ((fp = fopen(g_esel_path, pio)) != NULL)
Tom Joseph246bc0d2017-10-17 16:08:38 +0530277 {
Patrick Venture02261c02018-10-31 15:16:23 -0700278 fseek(fp, esel_req.offset, SEEK_SET);
279 fwrite(reqptr + (uint8_t)(sizeof(esel_request_t)), rlen, 1, fp);
280 fclose(fp);
Chris Austen4d98c1e2015-10-13 14:33:50 -0500281
Patrick Venture02261c02018-10-31 15:16:23 -0700282 *data_len = sizeof(g_record_id);
283 memcpy(response, &g_record_id, *data_len);
284 }
285 else
286 {
287 fprintf(stderr, "Error trying to perform %s for esel%s\n", pio,
288 g_esel_path);
289 rc = IPMI_CC_INVALID;
290 *data_len = 0;
291 }
Tom Joseph246bc0d2017-10-17 16:08:38 +0530292
Patrick Venture02261c02018-10-31 15:16:23 -0700293 // The first bit presents that this is the last partial packet
294 // coming down. If that is the case advance the record id so we
295 // don't overlap logs. This allows anyone to establish a log
296 // directory system.
297 if (esel_req.progress & 1)
298 {
299 g_record_id++;
Tom Joseph246bc0d2017-10-17 16:08:38 +0530300
Patrick Venture02261c02018-10-31 15:16:23 -0700301 auto eSELData = readESEL(g_esel_path);
302
303 if (eSELData.empty())
304 {
305 return IPMI_CC_UNSPECIFIED_ERROR;
306 }
307
308 // If the eSEL record type is OCC metrics, then create the OCC log
309 // entry.
310 if (eSELData[2] == occMetricsType)
311 {
312 createOCCLogEntry(eSELData);
313 }
Tom Joseph3503fdc2019-01-10 11:25:27 +0530314 else
315 {
316 createHostEntry(eSELData);
317 }
Tom Joseph246bc0d2017-10-17 16:08:38 +0530318 }
319
320 return rc;
Chris Austen4d98c1e2015-10-13 14:33:50 -0500321}
322
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600323// Prepare for FW Update.
324// Execute needed commands to prepare the system for a fw update from the host.
Patrick Williamsd9c74ac2024-08-16 15:20:03 -0400325ipmi_ret_t ipmi_ibm_oem_prep_fw_update(
Andrew Geissler7f25db72025-03-09 19:09:58 -0500326 [[maybe_unused]] ipmi_netfn_t netfn, [[maybe_unused]] ipmi_cmd_t cmd,
327 [[maybe_unused]] ipmi_request_t request,
328 [[maybe_unused]] ipmi_response_t response, ipmi_data_len_t data_len,
329 [[maybe_unused]] ipmi_context_t context)
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600330{
331 ipmi_ret_t ipmi_rc = IPMI_CC_OK;
332 *data_len = 0;
333
334 int rc = 0;
335 std::ofstream rwfs_file;
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600336
337 // Set one time flag
Patrick Venture02261c02018-10-31 15:16:23 -0700338 rc = system(
339 "fw_setenv openbmconce copy-files-to-ram copy-base-filesystem-to-ram");
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600340 rc = WEXITSTATUS(rc);
Patrick Venture02261c02018-10-31 15:16:23 -0700341 if (rc != 0)
342 {
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600343 fprintf(stderr, "fw_setenv openbmconce failed with rc=%d\n", rc);
Andrew Geisslerd9296052017-06-15 14:57:25 -0500344 return IPMI_CC_UNSPECIFIED_ERROR;
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600345 }
346
347 // Touch the image-rwfs file to perform an empty update to force the save
Patrick Venture02261c02018-10-31 15:16:23 -0700348 // in case we're already in ram and the flash is the same causing the ram
349 // files to not be copied back to flash
350 rwfs_file.open("/run/initramfs/image-rwfs",
351 std::ofstream::out | std::ofstream::app);
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600352 rwfs_file.close();
353
354 // Reboot the BMC for settings to take effect
Adriana Kobylak080503e2023-01-05 13:44:25 -0600355 rc = rebootBMC();
356 if (rc < 0)
Patrick Venture02261c02018-10-31 15:16:23 -0700357 {
Adriana Kobylak080503e2023-01-05 13:44:25 -0600358 fprintf(stderr, "Failed to reset BMC: %s\n", strerror(-rc));
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600359 return -1;
360 }
361 printf("Warning: BMC is going down for reboot!\n");
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600362
363 return ipmi_rc;
364}
Chris Austen4d98c1e2015-10-13 14:33:50 -0500365
Patrick Williamsd9c74ac2024-08-16 15:20:03 -0400366ipmi_ret_t ipmi_ibm_oem_bmc_factory_reset(
Andrew Geissler7f25db72025-03-09 19:09:58 -0500367 [[maybe_unused]] ipmi_netfn_t netfn, [[maybe_unused]] ipmi_cmd_t cmd,
368 [[maybe_unused]] ipmi_request_t request,
369 [[maybe_unused]] ipmi_response_t response,
370 [[maybe_unused]] ipmi_data_len_t data_len,
371 [[maybe_unused]] ipmi_context_t context)
Adriana Kobylak81e23102018-08-09 14:44:19 -0500372{
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500373 sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
Andrew Geissler64354b62019-09-20 13:39:24 -0500374
375 // Since this is a one way command (i.e. the host is requesting a power
376 // off of itself and a reboot of the BMC) we can exceed the 5 second
377 // IPMI timeout. Testing has shown that the power off can take up to
378 // 10 seconds so give it at least 15
379 constexpr auto powerOffWait = std::chrono::seconds(15);
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500380 constexpr auto setFactoryWait = std::chrono::seconds(3);
Matt Spinler34aca012018-09-25 11:21:06 -0500381
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500382 // Power Off Chassis
383 auto service = getService(bus, stateChassisPath, stateChassisIntf);
384 if (service.empty())
385 {
386 return IPMI_CC_UNSPECIFIED_ERROR;
387 }
Patrick Williams61950102020-05-13 17:49:58 -0500388 std::variant<std::string> off =
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500389 "xyz.openbmc_project.State.Chassis.Transition.Off";
390 auto method = bus.new_method_call(service.c_str(), stateChassisPath,
391 propertiesIntf, "Set");
392 method.append(stateChassisIntf, "RequestedPowerTransition", off);
393 try
394 {
395 bus.call_noreply(method);
396 }
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500397 catch (const sdbusplus::exception_t& e)
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500398 {
399 log<level::ERR>("Error powering off the chassis",
400 entry("ERROR=%s", e.what()));
401 return IPMI_CC_UNSPECIFIED_ERROR;
402 }
Matt Spinler34aca012018-09-25 11:21:06 -0500403
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500404 // Wait a few seconds for the chassis to power off
405 std::this_thread::sleep_for(powerOffWait);
406
407 // Set Factory Reset
408 method = bus.new_method_call(bmcUpdaterServiceName, softwarePath,
409 factoryResetIntf, "Reset");
410 try
411 {
412 bus.call_noreply(method);
413 }
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500414 catch (const sdbusplus::exception_t& e)
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500415 {
416 log<level::ERR>("Error setting factory reset",
417 entry("ERROR=%s", e.what()));
418 return IPMI_CC_UNSPECIFIED_ERROR;
419 }
420
421 // Wait a few seconds for service that sets the reset env variable to
422 // complete before the BMC is rebooted
423 std::this_thread::sleep_for(setFactoryWait);
424
425 // Reboot BMC
Adriana Kobylak080503e2023-01-05 13:44:25 -0600426 auto rc = rebootBMC();
427 if (rc < 0)
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500428 {
Adriana Kobylak080503e2023-01-05 13:44:25 -0600429 log<level::ALERT>("The BMC needs to be manually rebooted to complete "
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500430 "the factory reset.");
431 return IPMI_CC_UNSPECIFIED_ERROR;
432 }
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500433
434 return IPMI_CC_OK;
Adriana Kobylak81e23102018-08-09 14:44:19 -0500435}
436
Patrick Venture02261c02018-10-31 15:16:23 -0700437namespace
438{
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530439// Storage to keep the object alive during process life
440std::unique_ptr<open_power::host::command::Host> opHost
Patrick Venture02261c02018-10-31 15:16:23 -0700441 __attribute__((init_priority(101)));
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500442std::unique_ptr<sdbusplus::server::manager_t> objManager
Patrick Venture02261c02018-10-31 15:16:23 -0700443 __attribute__((init_priority(101)));
444} // namespace
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530445
Andrew Jeffery8fb3f032018-07-27 16:45:44 +0930446void register_netfn_ibm_oem_commands()
Chris Austen4d98c1e2015-10-13 14:33:50 -0500447{
George Liu23395f52025-04-03 10:33:54 +0800448 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", ipmi::netFnOemSix,
Patrick Venture02261c02018-10-31 15:16:23 -0700449 IPMI_CMD_PESEL);
George Liu23395f52025-04-03 10:33:54 +0800450 ipmi_register_callback(ipmi::netFnOemSix, IPMI_CMD_PESEL, NULL,
Patrick Venture02261c02018-10-31 15:16:23 -0700451 ipmi_ibm_oem_partial_esel, SYSTEM_INTERFACE);
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600452
George Liu23395f52025-04-03 10:33:54 +0800453 printf("Registering NetFn:[0x%X], Cmd:[0x%X]\n", ipmi::netFnOemTwo,
Patrick Venture02261c02018-10-31 15:16:23 -0700454 IPMI_CMD_PREP_FW_UPDATE);
George Liu23395f52025-04-03 10:33:54 +0800455 ipmi_register_callback(ipmi::netFnOemTwo, IPMI_CMD_PREP_FW_UPDATE, NULL,
Patrick Venture02261c02018-10-31 15:16:23 -0700456 ipmi_ibm_oem_prep_fw_update, SYSTEM_INTERFACE);
Adriana Kobylak187bfce2016-03-04 11:55:43 -0600457
George Liu23395f52025-04-03 10:33:54 +0800458 ipmi_register_callback(ipmi::netFnOemSix, IPMI_CMD_BMC_FACTORY_RESET, NULL,
Adriana Kobylak81c34df2018-11-01 11:44:16 -0500459 ipmi_ibm_oem_bmc_factory_reset, SYSTEM_INTERFACE);
Adriana Kobylak81e23102018-08-09 14:44:19 -0500460
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530461 // Create new object on the bus
Andrew Geissler7f25db72025-03-09 19:09:58 -0500462 auto objPath = std::string{"/org/open_power/control"} + '/' + HOST_NAME +
463 '0';
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530464
465 // Add sdbusplus ObjectManager.
466 auto& sdbusPlusHandler = ipmid_get_sdbus_plus_handler();
Patrick Williamsa0a221f2022-07-22 19:26:53 -0500467 objManager = std::make_unique<sdbusplus::server::manager_t>(
Andrew Geissler7f25db72025-03-09 19:09:58 -0500468 *sdbusPlusHandler, "/org/open_power/control");
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530469
470 opHost = std::make_unique<open_power::host::command::Host>(
Patrick Venture02261c02018-10-31 15:16:23 -0700471 *sdbusPlusHandler, objPath.c_str());
Vishwanatha Subbanna07655062017-07-14 20:31:57 +0530472
473 // Service for this is provided by phosphor layer systemcmdintf
474 // and this will be as part of that.
Tomcbfd6ec2016-09-14 17:45:55 +0530475 return;
Chris Austen4d98c1e2015-10-13 14:33:50 -0500476}