blob: b7d1bec5625fe967554a7b17e6bf405526213072 [file] [log] [blame]
Prithvi Paibffaa112025-07-19 13:57:19 +05301/*
2 * SPDX-FileCopyrightText: Copyright (c) 2024-2025 NVIDIA CORPORATION &
3 * AFFILIATES. All rights reserved.
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#include "oemcommands.hpp"
8
9#include <ipmid/api.hpp>
10#include <ipmid/types.hpp>
Prithvi Pai6823fd42025-08-05 08:35:21 +053011#include <ipmid/utils.hpp>
Prithvi Paic1e7b5c2025-09-01 13:13:15 +053012#include <nlohmann/json.hpp>
Prithvi Pai6823fd42025-08-05 08:35:21 +053013#include <phosphor-logging/lg2.hpp>
Prithvi Paibffaa112025-07-19 13:57:19 +053014
Prithvi Paic1e7b5c2025-09-01 13:13:15 +053015#include <array>
Prithvi Paibffaa112025-07-19 13:57:19 +053016#include <cstdint>
Prithvi Paic1e7b5c2025-09-01 13:13:15 +053017#include <fstream>
Prithvi Paibffaa112025-07-19 13:57:19 +053018
19void registerBootstrapCredentialsOemCommands() __attribute__((constructor));
20
21namespace ipmi
22{
23ipmi::RspType<uint8_t, uint8_t> ipmiGetUsbVendorIdProductId(uint8_t type)
24{
25 constexpr uint8_t descriptorVendorId = 1;
26 constexpr uint8_t descriptorProductId = 2;
27
28 // IPMI OEM USB Linux Gadget info
29 constexpr uint16_t usbVendorId = 0x0525;
30 constexpr uint16_t usbProductId = 0xA4A2;
31
32 if (type == descriptorVendorId)
33 {
34 return ipmi::responseSuccess(static_cast<uint8_t>(usbVendorId >> 8),
35 static_cast<uint8_t>(usbVendorId & 0xFF));
36 }
37 else if (type == descriptorProductId)
38 {
39 return ipmi::responseSuccess(static_cast<uint8_t>(usbProductId >> 8),
40 static_cast<uint8_t>(usbProductId & 0xFF));
41 }
42 return ipmi::responseInvalidFieldRequest();
43}
44
Prithvi Pai6bf35ee2025-07-24 12:05:10 +053045ipmi::RspType<ipmi::message::Payload> ipmiGetUsbSerialNumber()
46{
47 static constexpr uint8_t usbSerialNumber = 0x00;
48 ipmi::message::Payload usbSerialNumberPayload;
49 usbSerialNumberPayload.pack(usbSerialNumber);
50 return ipmi::responseSuccess(usbSerialNumberPayload);
51}
52
Prithvi Pai6823fd42025-08-05 08:35:21 +053053ipmi::RspType<ipmi::message::Payload> ipmiGetRedfishHostName(
54 ipmi::Context::ptr ctx)
55{
56 std::string service{};
57 constexpr auto networkConfigObj = "/xyz/openbmc_project/network/config";
58 constexpr auto networkConfigIface =
59 "xyz.openbmc_project.Network.SystemConfiguration";
60 boost::system::error_code ec =
61 ipmi::getService(ctx, networkConfigIface, networkConfigObj, service);
62 if (ec)
63 {
64 lg2::error("ipmiGetRedfishHostName failed to get Network SystemConfig "
65 "object: {STATUS}",
66 "STATUS", ec.message());
67 return ipmi::responseResponseError();
68 }
69
70 std::string hostName{};
71 ec = ipmi::getDbusProperty<std::string>(
72 ctx, service, networkConfigObj, networkConfigIface, "HostName",
73 hostName);
74 if (ec)
75 {
76 lg2::error("ipmiGetRedfishHostName failed to get HostName from Network "
77 "SystemConfig service: {STATUS}",
78 "STATUS", ec.message());
79 return ipmi::responseResponseError();
80 }
81 ipmi::message::Payload hostNamePayload;
82 hostNamePayload.pack(
83 std::vector<uint8_t>(hostName.begin(), hostName.end()));
84 return ipmi::responseSuccess(hostNamePayload);
85}
Prithvi Pai529d31c2025-08-14 20:44:59 +053086
87ipmi::RspType<uint8_t> ipmiGetIpmiChannelRfHi()
88{
89 constexpr auto redfishHostInterfaceChannel = "usb0";
90 uint8_t chNum = ipmi::getChannelByName(redfishHostInterfaceChannel);
91 ChannelInfo chInfo{};
92 Cc compCode = ipmi::getChannelInfo(chNum, chInfo);
93 if (compCode != ipmi::ccSuccess)
94 {
95 lg2::error(
96 "ipmiGetIpmiChannelRfHi failed for channel {CHANNEL} with error {ERROR}",
97 "CHANNEL", chNum, "ERROR", compCode);
98 return ipmi::responseUnspecifiedError();
99 }
100
101 if (chInfo.mediumType !=
102 static_cast<uint8_t>(EChannelMediumType::lan8032) ||
103 chInfo.protocolType !=
104 static_cast<uint8_t>(EChannelProtocolType::ipmbV10) ||
105 chInfo.sessionSupported !=
106 static_cast<uint8_t>(EChannelSessSupported::multi) ||
107 chInfo.isIpmi != true)
108 {
109 lg2::error(
110 "ipmiGetIpmiChannelRfHi: channel {CHANNEL} lacks required config",
111 "CHANNEL", chNum);
112 return responseSensorInvalid();
113 }
114 return ipmi::responseSuccess(static_cast<uint8_t>(chNum));
115}
116
Prithvi Paic1e7b5c2025-09-01 13:13:15 +0530117bool getRfUuid(std::string& rfUuid)
118{
119 constexpr const char* bmcwebPersistentDataFile =
120 "/home/root/bmcweb_persistent_data.json";
121 std::ifstream f(bmcwebPersistentDataFile);
122 if (!f.is_open())
123 {
124 lg2::error("Failed to open {FILE}", "FILE", bmcwebPersistentDataFile);
125 return false;
126 }
127 auto data = nlohmann::json::parse(f, nullptr, false);
128 if (data.is_discarded())
129 {
130 lg2::error("Failed to parse {FILE}", "FILE", bmcwebPersistentDataFile);
131 return false;
132 }
133
134 if (auto it = data.find("system_uuid"); it != data.end() && it->is_string())
135 {
136 rfUuid = *it;
137 return true;
138 }
139
140 lg2::error("system_uuid missing in {FILE}", "FILE",
141 bmcwebPersistentDataFile);
142 return false;
143}
144
145ipmi::RspType<std::vector<uint8_t>> ipmiGetRedfishServiceUUID()
146{
147 std::string rfUuid;
148 bool ret = getRfUuid(rfUuid);
149 if (!ret)
150 {
151 lg2::error(
152 "ipmiGetRedfishServiceUUID: Error reading Redfish Service UUID File.");
153 return ipmi::responseResponseError();
154 }
155
156 // As per Redfish Host Interface Spec v1.3.0
157 // The Redfish UUID is 16byte and should be represented as below:
158 // Ex: {00112233-4455-6677-8899-AABBCCDDEEFF}
159 // 0x33 0x22 0x11 0x00 0x55 0x44 0x77 0x66 0x88 0x99 0xAA 0xBB 0xCC 0xDD
160 // 0xEE 0xFF
161
162 std::vector<uint8_t> resBuf;
163 std::vector<std::string> groups = ipmi::split(rfUuid, '-');
164
165 for (size_t i = 0; i < groups.size(); ++i)
166 {
167 auto group = groups[i];
168 if (i < 3)
169 {
170 std::reverse(group.begin(), group.end());
171 }
172
173 for (size_t j = 0; j < group.size(); j += 2)
174 {
175 if (i < 3)
176 {
177 std::swap(group[j], group[j + 1]);
178 }
179 resBuf.push_back(static_cast<uint8_t>(
180 std::stoi(group.substr(j, 2), nullptr, 16)));
181 }
182 }
183 return ipmi::responseSuccess(resBuf);
184}
185
Prithvi Paibffaa112025-07-19 13:57:19 +0530186} // namespace ipmi
187
188void registerBootstrapCredentialsOemCommands()
189{
190 ipmi::registerHandler(
191 ipmi::prioOemBase, ipmi::groupNvidia,
192 ipmi::bootstrap_credentials_oem::cmdGetUsbVendorIdProductId,
193 ipmi::Privilege::Admin, ipmi::ipmiGetUsbVendorIdProductId);
Prithvi Pai6bf35ee2025-07-24 12:05:10 +0530194
195 ipmi::registerHandler(
196 ipmi::prioOemBase, ipmi::groupNvidia,
197 ipmi::bootstrap_credentials_oem::cmdGetUsbSerialNumber,
198 ipmi::Privilege::Admin, ipmi::ipmiGetUsbSerialNumber);
Prithvi Pai6823fd42025-08-05 08:35:21 +0530199
200 ipmi::registerHandler(
201 ipmi::prioOemBase, ipmi::groupNvidia,
202 ipmi::bootstrap_credentials_oem::cmdGetRedfishHostName,
203 ipmi::Privilege::Admin, ipmi::ipmiGetRedfishHostName);
Prithvi Pai529d31c2025-08-14 20:44:59 +0530204
205 ipmi::registerHandler(
206 ipmi::prioOemBase, ipmi::groupNvidia,
207 ipmi::bootstrap_credentials_oem::cmdGetIpmiChannelRfHi,
208 ipmi::Privilege::Admin, ipmi::ipmiGetIpmiChannelRfHi);
Prithvi Paic1e7b5c2025-09-01 13:13:15 +0530209
210 ipmi::registerHandler(
211 ipmi::prioOemBase, ipmi::groupNvidia,
212 ipmi::bootstrap_credentials_oem::cmdGetRedfishServiceUUID,
213 ipmi::Privilege::Admin, ipmi::ipmiGetRedfishServiceUUID);
Prithvi Paibffaa112025-07-19 13:57:19 +0530214}