blob: 2ff9a5a74b0e45e8be56a40aed7db424578da772 [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 {
Pavithra Barithaya5e542be2021-08-13 00:33:31 -0500126 if (!(pldm::responder::utils::checkIfIBMFru(key)))
127 {
128 pldm::utils::setFruPresence(key, true);
129 }
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500130 dbus_map_update(key, "Function0VendorId", vendorId);
131 dbus_map_update(key, "Function0DeviceId", deviceId);
132 dbus_map_update(key, "Function0RevisionId", revisionId);
133 dbus_map_update(key, "Function0ClassCode", classCode);
134 dbus_map_update(key, "Function0SubsystemVendorId",
135 subSystemVendorId);
136 dbus_map_update(key, "Function0SubsystemId", subSystemId);
137 }
138 }
139 }
140}
141
142void Handler::dbus_map_update(const std::string& adapterObjPath,
143 const std::string& propertyName,
144 const std::string& propValue)
145{
146 pldm::utils::PropertyValue value = propValue;
147 pldm::utils::DBusMapping dbusMapping;
148 dbusMapping.objectPath = adapterObjPath;
149 dbusMapping.interface = "xyz.openbmc_project.Inventory.Item.PCIeDevice";
150 dbusMapping.propertyName = propertyName;
151 dbusMapping.propertyType = "string";
152 try
153 {
154 pldm::utils::DBusHandler().setDbusProperty(dbusMapping, value);
155 }
156 catch (const std::exception& e)
157 {
158 error("Failed to set '{PROPERTY}' property: {ERROR}", "PROPERTY",
159 propertyName, "ERROR", e);
160 }
161}
Pavithra Barithayac8bcefb2021-11-23 07:03:00 -0600162
163void Handler::setFirmwareUAK(const std::vector<uint8_t>& data)
164{
165 using VPDManager = sdbusplus::client::com::ibm::vpd::Manager<>;
166
167 static constexpr auto uakObjPath = "/com/ibm/VPD/Manager";
168 static constexpr auto fruPath =
169 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
170
171 auto& bus = pldm::utils::DBusHandler::getBus();
172 try
173 {
174 auto service = pldm::utils::DBusHandler().getService(
175 uakObjPath, VPDManager::interface);
176 auto method = bus.new_method_call(
177 service.c_str(), uakObjPath, VPDManager::interface, "WriteKeyword");
178 method.append(static_cast<sdbusplus::message::object_path>(fruPath),
179 "UTIL", "D8", data);
180 bus.call_noreply(method);
181 }
182 catch (const std::exception& e)
183 {
184 error("Failed to make a DBus call to VPD manager: {ERROR}", "ERROR", e);
185 }
186}
187
Pavithra Barithayaa410c652021-07-22 01:32:47 -0500188} // namespace oem_ibm_fru
189} // namespace responder
190} // namespace pldm