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