blob: c9360dfffa1ec75ac3e447dbc79e94e61b028199 [file] [log] [blame]
Pavithra Barithayaa410c652021-07-22 01:32:47 -05001#include "fru_oem_ibm.hpp"
2
Pavithra Barithayac8bcefb2021-11-23 07:03:00 -06003#include <com/ibm/VPD/Manager/client.hpp>
Pavithra Barithayaa410c652021-07-22 01:32:47 -05004#include <phosphor-logging/lg2.hpp>
5
Pavithra Barithaya8db5f192024-03-19 09:44:38 -05006#include <format>
Pavithra Barithayaa410c652021-07-22 01:32:47 -05007#include <ranges>
8
9PHOSPHOR_LOG2_USING;
10
11namespace pldm
12{
13namespace responder
14{
15namespace oem_ibm_fru
16{
17
18void pldm::responder::oem_ibm_fru::Handler::setIBMFruHandler(
19 pldm::responder::fru::Handler* handler)
20{
21 fruHandler = handler;
22}
23
24int pldm::responder::oem_ibm_fru::Handler::processOEMFRUTable(
25 const std::vector<uint8_t>& fruData)
26{
27 uint8_t dataSize = 0;
28 const uint8_t* data = fruData.data();
29
30 while (dataSize < fruData.size())
31 {
32 auto record =
33 reinterpret_cast<const pldm_fru_record_data_format*>(data);
34 if (!record)
35 {
36 return PLDM_ERROR_INVALID_DATA;
37 }
38
39 auto& entityAssociationMap = getAssociateEntityMap();
40 uint16_t fruRSI = le16toh(record->record_set_id);
41
42 dataSize += sizeof(pldm_fru_record_data_format) -
43 sizeof(pldm_fru_record_tlv);
44 data += dataSize;
45
46 for ([[maybe_unused]] const auto& i :
47 std::views::iota(0, (int)record->num_fru_fields))
48 {
49 auto tlv = reinterpret_cast<const pldm_fru_record_tlv*>(data);
50 if (!tlv)
51 {
52 return PLDM_ERROR_INVALID_DATA;
53 }
54
55 if (tlv->type == PLDM_OEM_FRU_FIELD_TYPE_PCIE_CONFIG_SPACE_DATA)
56 {
57 auto pcieData =
58 reinterpret_cast<const PcieConfigSpaceData*>(tlv->value);
59
60 if (!pcieData)
61 {
62 return PLDM_ERROR_INVALID_DATA;
63 }
Pavithra Barithayaa410c652021-07-22 01:32:47 -050064
Pavithra Barithaya8db5f192024-03-19 09:44:38 -050065 auto vendorId = std::format("0x{:04x}",
66 htole16(pcieData->vendorId));
67 auto deviceId = std::format("0x{:04x}",
68 htole16(pcieData->deviceId));
69 auto revisionId = std::format("0x{:02x}",
70 htole16(pcieData->revisionId));
Pavithra Barithayaa410c652021-07-22 01:32:47 -050071
Pavithra Barithaya8db5f192024-03-19 09:44:38 -050072 std::string classCode = "0x";
Pavithra Barithayaa410c652021-07-22 01:32:47 -050073 for (const auto& ele : pcieData->classCode)
74 {
Pavithra Barithaya8db5f192024-03-19 09:44:38 -050075 classCode += std::format("{:02x}", ele);
Pavithra Barithayaa410c652021-07-22 01:32:47 -050076 }
Pavithra Barithayaa410c652021-07-22 01:32:47 -050077
Pavithra Barithaya8db5f192024-03-19 09:44:38 -050078 auto subSystemVendorId = std::format(
79 "0x{:04x}", htole16(pcieData->subSystemVendorId));
80 auto subSystemId = std::format("0x{:04x}",
81 htole16(pcieData->subSystemId));
Pavithra Barithayaa410c652021-07-22 01:32:47 -050082
83 updateDBusProperty(fruRSI, entityAssociationMap, vendorId,
84 deviceId, revisionId, classCode,
85 subSystemVendorId, subSystemId);
86 }
Pavithra Barithayac8bcefb2021-11-23 07:03:00 -060087
88 if (tlv->type == PLDM_OEM_IBM_FRU_FIELD_TYPE_FIRMWARE_UAK)
89 {
90 std::vector<uint8_t> value(&tlv->value[0],
91 &tlv->value[tlv->length]);
92 setFirmwareUAK(value);
93 }
Pavithra Barithayaa410c652021-07-22 01:32:47 -050094 // length of tlv is removed from the structure pldm_fru_record_tlv
95 // and the new tlv length is added back.
96 dataSize += sizeof(pldm_fru_record_tlv) - sizeof(uint8_t) +
97 tlv->length;
98 data += dataSize;
99 }
100 }
101
102 return PLDM_SUCCESS;
103}
104
105void Handler::updateDBusProperty(
106 uint16_t fruRSI, const AssociatedEntityMap& fruAssociationMap,
107 const std::string& vendorId, const std::string& deviceId,
108 const std::string& revisionId, const std::string& classCode,
109 const std::string& subSystemVendorId, const std::string& subSystemId)
110{
111 uint16_t entityType{};
112 uint16_t entityInstanceNum{};
113 uint16_t containerId{};
114 uint16_t terminusHandle{};
115 const pldm_pdr_record* record{};
116
117 record = pldm_pdr_fru_record_set_find_by_rsi(
118 pdrRepo, fruRSI, &terminusHandle, &entityType, &entityInstanceNum,
119 &containerId);
120
121 if (record)
122 {
123 for (const auto& [key, value] : fruAssociationMap)
124 {
125 if (entityInstanceNum == value.entity_instance_num &&
126 entityType == value.entity_type &&
127 containerId == value.entity_container_id)
128 {
Pavithra Barithaya5e542be2021-08-13 00:33:31 -0500129 if (!(pldm::responder::utils::checkIfIBMFru(key)))
130 {
131 pldm::utils::setFruPresence(key, true);
132 }
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500133 dbus_map_update(key, "Function0VendorId", vendorId);
134 dbus_map_update(key, "Function0DeviceId", deviceId);
135 dbus_map_update(key, "Function0RevisionId", revisionId);
136 dbus_map_update(key, "Function0ClassCode", classCode);
137 dbus_map_update(key, "Function0SubsystemVendorId",
138 subSystemVendorId);
139 dbus_map_update(key, "Function0SubsystemId", subSystemId);
140 }
141 }
142 }
143}
144
145void Handler::dbus_map_update(const std::string& adapterObjPath,
146 const std::string& propertyName,
147 const std::string& propValue)
148{
149 pldm::utils::PropertyValue value = propValue;
150 pldm::utils::DBusMapping dbusMapping;
151 dbusMapping.objectPath = adapterObjPath;
152 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item.PCIeDevice";
153 dbusMapping.propertyName = propertyName;
154 dbusMapping.propertyType = "string";
155 try
156 {
157 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
158 }
159 catch (const std::exception& e)
160 {
161 error("Failed to set '{PROPERTY}' property: {ERROR}", "PROPERTY",
162 propertyName, "ERROR", e);
163 }
164}
Pavithra Barithayac8bcefb2021-11-23 07:03:00 -0600165
166void Handler::setFirmwareUAK(const std::vector<uint8_t>& data)
167{
168 using VPDManager = sdbusplus::client::com::ibm::vpd::Manager<>;
169
170 static constexpr auto uakObjPath = "/com/ibm/VPD/Manager";
171 static constexpr auto fruPath =
172 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
173
174 auto& bus = pldm::utils::DBusHandler::getBus();
175 try
176 {
177 auto service = pldm::utils::DBusHandler().getService(
178 uakObjPath, VPDManager::interface);
179 auto method = bus.new_method_call(
180 service.c_str(), uakObjPath, VPDManager::interface, "WriteKeyword");
181 method.append(static_cast<sdbusplus::message::object_path>(fruPath),
182 "UTIL", "D8", data);
183 bus.call_noreply(method);
184 }
185 catch (const std::exception& e)
186 {
187 error("Failed to make a DBus call to VPD manager: {ERROR}", "ERROR", e);
188 }
189}
190
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500191} // namespace oem_ibm_fru
192} // namespace responder
193} // namespace pldm