xref: /openbmc/phosphor-host-ipmid/oem/nvidia/bootstrap-credentials-oem-cmds.cpp (revision 529d31c7b9ce70a1747b1f50b24b7ddcfaf8bc25)
1 /*
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>
11 #include <ipmid/utils.hpp>
12 #include <phosphor-logging/lg2.hpp>
13 
14 #include <cstdint>
15 
16 void registerBootstrapCredentialsOemCommands() __attribute__((constructor));
17 
18 namespace ipmi
19 {
20 ipmi::RspType<uint8_t, uint8_t> ipmiGetUsbVendorIdProductId(uint8_t type)
21 {
22     constexpr uint8_t descriptorVendorId = 1;
23     constexpr uint8_t descriptorProductId = 2;
24 
25     // IPMI OEM USB Linux Gadget info
26     constexpr uint16_t usbVendorId = 0x0525;
27     constexpr uint16_t usbProductId = 0xA4A2;
28 
29     if (type == descriptorVendorId)
30     {
31         return ipmi::responseSuccess(static_cast<uint8_t>(usbVendorId >> 8),
32                                      static_cast<uint8_t>(usbVendorId & 0xFF));
33     }
34     else if (type == descriptorProductId)
35     {
36         return ipmi::responseSuccess(static_cast<uint8_t>(usbProductId >> 8),
37                                      static_cast<uint8_t>(usbProductId & 0xFF));
38     }
39     return ipmi::responseInvalidFieldRequest();
40 }
41 
42 ipmi::RspType<ipmi::message::Payload> ipmiGetUsbSerialNumber()
43 {
44     static constexpr uint8_t usbSerialNumber = 0x00;
45     ipmi::message::Payload usbSerialNumberPayload;
46     usbSerialNumberPayload.pack(usbSerialNumber);
47     return ipmi::responseSuccess(usbSerialNumberPayload);
48 }
49 
50 ipmi::RspType<ipmi::message::Payload> ipmiGetRedfishHostName(
51     ipmi::Context::ptr ctx)
52 {
53     std::string service{};
54     constexpr auto networkConfigObj = "/xyz/openbmc_project/network/config";
55     constexpr auto networkConfigIface =
56         "xyz.openbmc_project.Network.SystemConfiguration";
57     boost::system::error_code ec =
58         ipmi::getService(ctx, networkConfigIface, networkConfigObj, service);
59     if (ec)
60     {
61         lg2::error("ipmiGetRedfishHostName failed to get Network SystemConfig "
62                    "object: {STATUS}",
63                    "STATUS", ec.message());
64         return ipmi::responseResponseError();
65     }
66 
67     std::string hostName{};
68     ec = ipmi::getDbusProperty<std::string>(
69         ctx, service, networkConfigObj, networkConfigIface, "HostName",
70         hostName);
71     if (ec)
72     {
73         lg2::error("ipmiGetRedfishHostName failed to get HostName from Network "
74                    "SystemConfig service: {STATUS}",
75                    "STATUS", ec.message());
76         return ipmi::responseResponseError();
77     }
78     ipmi::message::Payload hostNamePayload;
79     hostNamePayload.pack(
80         std::vector<uint8_t>(hostName.begin(), hostName.end()));
81     return ipmi::responseSuccess(hostNamePayload);
82 }
83 
84 ipmi::RspType<uint8_t> ipmiGetIpmiChannelRfHi()
85 {
86     constexpr auto redfishHostInterfaceChannel = "usb0";
87     uint8_t chNum = ipmi::getChannelByName(redfishHostInterfaceChannel);
88     ChannelInfo chInfo{};
89     Cc compCode = ipmi::getChannelInfo(chNum, chInfo);
90     if (compCode != ipmi::ccSuccess)
91     {
92         lg2::error(
93             "ipmiGetIpmiChannelRfHi failed for channel {CHANNEL} with error {ERROR}",
94             "CHANNEL", chNum, "ERROR", compCode);
95         return ipmi::responseUnspecifiedError();
96     }
97 
98     if (chInfo.mediumType !=
99             static_cast<uint8_t>(EChannelMediumType::lan8032) ||
100         chInfo.protocolType !=
101             static_cast<uint8_t>(EChannelProtocolType::ipmbV10) ||
102         chInfo.sessionSupported !=
103             static_cast<uint8_t>(EChannelSessSupported::multi) ||
104         chInfo.isIpmi != true)
105     {
106         lg2::error(
107             "ipmiGetIpmiChannelRfHi: channel {CHANNEL} lacks required config",
108             "CHANNEL", chNum);
109         return responseSensorInvalid();
110     }
111     return ipmi::responseSuccess(static_cast<uint8_t>(chNum));
112 }
113 
114 } // namespace ipmi
115 
116 void registerBootstrapCredentialsOemCommands()
117 {
118     ipmi::registerHandler(
119         ipmi::prioOemBase, ipmi::groupNvidia,
120         ipmi::bootstrap_credentials_oem::cmdGetUsbVendorIdProductId,
121         ipmi::Privilege::Admin, ipmi::ipmiGetUsbVendorIdProductId);
122 
123     ipmi::registerHandler(
124         ipmi::prioOemBase, ipmi::groupNvidia,
125         ipmi::bootstrap_credentials_oem::cmdGetUsbSerialNumber,
126         ipmi::Privilege::Admin, ipmi::ipmiGetUsbSerialNumber);
127 
128     ipmi::registerHandler(
129         ipmi::prioOemBase, ipmi::groupNvidia,
130         ipmi::bootstrap_credentials_oem::cmdGetRedfishHostName,
131         ipmi::Privilege::Admin, ipmi::ipmiGetRedfishHostName);
132 
133     ipmi::registerHandler(
134         ipmi::prioOemBase, ipmi::groupNvidia,
135         ipmi::bootstrap_credentials_oem::cmdGetIpmiChannelRfHi,
136         ipmi::Privilege::Admin, ipmi::ipmiGetIpmiChannelRfHi);
137 }
138