blob: 30053d5c4435df2dc2a7d1e94ac58df86f5c49b7 [file] [log] [blame]
Prithvi Pai6f9e7a72025-03-14 13:05:02 +05301#include "firmware_inventory.hpp"
2
3#include "mdrv2.hpp"
4
5#include <boost/algorithm/string.hpp>
6
7#include <fstream>
8#include <iomanip>
9#include <iostream>
10#include <regex>
11#include <sstream>
12
13namespace phosphor
14{
15namespace smbios
16{
17namespace utils
18{
19std::vector<std::string> getExistingVersionPaths(sdbusplus::bus_t& bus)
20{
21 std::vector<std::string> existingVersionPaths;
22
23 auto getVersionPaths = bus.new_method_call(
24 phosphor::smbios::mapperBusName, phosphor::smbios::mapperPath,
25 phosphor::smbios::mapperInterface, "GetSubTreePaths");
26 getVersionPaths.append(firmwarePath);
27 getVersionPaths.append(0);
28 getVersionPaths.append(
29 std::array<std::string, 1>({phosphor::smbios::versionInterface}));
30
31 try
32 {
33 auto reply = bus.call(getVersionPaths);
34 reply.read(existingVersionPaths);
35 }
36 catch (const sdbusplus::exception_t& e)
37 {
38 lg2::error("Failed to query version objects. ERROR={E}", "E", e.what());
39 existingVersionPaths.clear();
40 }
41
42 return existingVersionPaths;
43}
44} // namespace utils
45
46bool FirmwareInventory::getFirmwareInventoryData(uint8_t*& dataIn,
47 int inventoryIndex)
48{
49 dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
50 if (dataIn == nullptr)
51 {
52 return false;
53 }
54 for (uint8_t index = 0; index < inventoryIndex; index++)
55 {
56 dataIn = smbiosNextPtr(dataIn);
57 if (dataIn == nullptr)
58 {
59 return false;
60 }
61 dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
62 if (dataIn == nullptr)
63 {
64 return false;
65 }
66 }
67 return true;
68}
69
70void FirmwareInventory::firmwareInfoUpdate(uint8_t* smbiosTableStorage)
71{
72 uint8_t* dataIn = smbiosTableStorage;
73 if (!getFirmwareInventoryData(dataIn, firmwareInventoryIndex))
74 {
75 lg2::info("Failed to get data for firmware inventory index {I}", "I",
76 firmwareInventoryIndex);
77 return;
78 }
79
80 auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
81
82 firmwareComponentName(firmwareInfo->componentName, firmwareInfo->length,
83 dataIn);
84 firmwareVersion(firmwareInfo->version, firmwareInfo->length, dataIn);
85 firmwareId(firmwareInfo->id, firmwareInfo->length, dataIn);
86 firmwareReleaseDate(firmwareInfo->releaseDate, firmwareInfo->length,
87 dataIn);
88 firmwareManufacturer(firmwareInfo->manufacturer, firmwareInfo->length,
89 dataIn);
90 present(true);
91 purpose(softwareVersion::VersionPurpose::Other);
92
93 std::vector<std::tuple<std::string, std::string, std::string>> assocs;
94 assocs.emplace_back("software_version", "functional",
95 "/xyz/openbmc_project/software");
96 association::associations(assocs);
97}
98
99std::string FirmwareInventory::checkAndCreateFirmwarePath(
100 uint8_t* dataIn, int inventoryIndex,
101 std::vector<std::string>& existingVersionPaths)
102{
103 if (!getFirmwareInventoryData(dataIn, inventoryIndex))
104 {
105 lg2::info("Failed to get data for firmware inventory index {I}", "I",
106 inventoryIndex);
107 return "";
108 }
109 auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
110 std::string firmwareId =
111 positionToString(firmwareInfo->id, firmwareInfo->length, dataIn);
112 auto firmwareName = positionToString(firmwareInfo->componentName,
113 firmwareInfo->length, dataIn);
114 std::string firmwareObjPath = "";
115#ifdef EXPOSE_FW_COMPONENT_NAME
116 firmwareObjPath = firmwareName;
117#else
118 firmwareObjPath = firmwareId;
119#endif
120 if (firmwareInfo->numOfAssociatedComponents > 0)
121 {
122 for (int i = 0; i < firmwareInfo->numOfAssociatedComponents; i++)
123 {
124 auto component = smbiosHandlePtr(
125 dataIn, firmwareInfo->associatedComponentHandles[i]);
126 if (component == nullptr)
127 {
128 continue;
129 }
130
131 auto header = reinterpret_cast<struct StructureHeader*>(component);
132 switch (header->type)
133 {
134 case processorsType:
135 case systemSlots:
136 case onboardDevicesExtended:
137 {
138 auto designation = positionToString(
139 component[4], header->length, component);
140 if (!designation.empty())
141 {
142 firmwareObjPath.append("_").append(designation);
143 }
144 break;
145 }
146 case systemPowerSupply:
147 {
148 auto location = positionToString(component[5],
149 header->length, component);
150 if (!location.empty())
151 {
152 firmwareObjPath.append("_").append(location);
153 }
154 break;
155 }
156 default:
157 break;
158 }
159 }
160 }
161 if (firmwareObjPath.empty())
162 {
163 firmwareObjPath = "firmware" + std::to_string(inventoryIndex);
164 }
165 boost::algorithm::trim_right(firmwareObjPath);
166 firmwareObjPath =
167 std::regex_replace(firmwareObjPath, std::regex("[^a-zA-Z0-9_/]+"), "_");
168
169 auto eqObjName = [firmwareObjPath](std::string s) {
170 std::filesystem::path p(s);
171 return p.filename().compare(firmwareObjPath) == 0;
172 };
173 if (std::find_if(existingVersionPaths.begin(), existingVersionPaths.end(),
174 std::move(eqObjName)) != existingVersionPaths.end())
175 {
176 return "";
177 }
178 std::string path = firmwarePath;
179 path.append("/").append(firmwareObjPath);
180 return path;
181}
182
183void FirmwareInventory::firmwareComponentName(
184 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
185{
186 std::string result = positionToString(positionNum, structLen, dataIn);
187 prettyName(result);
188}
189
190void FirmwareInventory::firmwareVersion(
191 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
192{
193 std::string result = positionToString(positionNum, structLen, dataIn);
194 version(result);
195}
196
197void FirmwareInventory::firmwareId(const uint8_t positionNum,
198 const uint8_t structLen, uint8_t* dataIn)
199{
200 std::string result = positionToString(positionNum, structLen, dataIn);
201 extendedVersion(result);
202}
203
204void FirmwareInventory::firmwareReleaseDate(
205 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
206{
207 std::string result = positionToString(positionNum, structLen, dataIn);
208 buildDate(result);
209}
210
211void FirmwareInventory::firmwareManufacturer(
212 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
213{
214 std::string result = positionToString(positionNum, structLen, dataIn);
215 manufacturer(result);
216}
217} // namespace smbios
218} // namespace phosphor