blob: a55a5171296c5a74dc27a6373b7e148c62e0d1db [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);
Prithvi Pai6f9e7a72025-03-14 13:05:02 +053092}
93
94std::string FirmwareInventory::checkAndCreateFirmwarePath(
95 uint8_t* dataIn, int inventoryIndex,
96 std::vector<std::string>& existingVersionPaths)
97{
98 if (!getFirmwareInventoryData(dataIn, inventoryIndex))
99 {
100 lg2::info("Failed to get data for firmware inventory index {I}", "I",
101 inventoryIndex);
102 return "";
103 }
104 auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
105 std::string firmwareId =
106 positionToString(firmwareInfo->id, firmwareInfo->length, dataIn);
107 auto firmwareName = positionToString(firmwareInfo->componentName,
108 firmwareInfo->length, dataIn);
109 std::string firmwareObjPath = "";
110#ifdef EXPOSE_FW_COMPONENT_NAME
111 firmwareObjPath = firmwareName;
112#else
113 firmwareObjPath = firmwareId;
114#endif
115 if (firmwareInfo->numOfAssociatedComponents > 0)
116 {
117 for (int i = 0; i < firmwareInfo->numOfAssociatedComponents; i++)
118 {
119 auto component = smbiosHandlePtr(
120 dataIn, firmwareInfo->associatedComponentHandles[i]);
121 if (component == nullptr)
122 {
123 continue;
124 }
125
126 auto header = reinterpret_cast<struct StructureHeader*>(component);
127 switch (header->type)
128 {
129 case processorsType:
130 case systemSlots:
131 case onboardDevicesExtended:
132 {
133 auto designation = positionToString(
134 component[4], header->length, component);
135 if (!designation.empty())
136 {
137 firmwareObjPath.append("_").append(designation);
138 }
139 break;
140 }
141 case systemPowerSupply:
142 {
143 auto location = positionToString(component[5],
144 header->length, component);
145 if (!location.empty())
146 {
147 firmwareObjPath.append("_").append(location);
148 }
149 break;
150 }
151 default:
152 break;
153 }
154 }
155 }
156 if (firmwareObjPath.empty())
157 {
158 firmwareObjPath = "firmware" + std::to_string(inventoryIndex);
159 }
160 boost::algorithm::trim_right(firmwareObjPath);
161 firmwareObjPath =
162 std::regex_replace(firmwareObjPath, std::regex("[^a-zA-Z0-9_/]+"), "_");
163
164 auto eqObjName = [firmwareObjPath](std::string s) {
165 std::filesystem::path p(s);
166 return p.filename().compare(firmwareObjPath) == 0;
167 };
168 if (std::find_if(existingVersionPaths.begin(), existingVersionPaths.end(),
169 std::move(eqObjName)) != existingVersionPaths.end())
170 {
171 return "";
172 }
173 std::string path = firmwarePath;
174 path.append("/").append(firmwareObjPath);
175 return path;
176}
177
178void FirmwareInventory::firmwareComponentName(
179 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
180{
181 std::string result = positionToString(positionNum, structLen, dataIn);
182 prettyName(result);
183}
184
185void FirmwareInventory::firmwareVersion(
186 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
187{
188 std::string result = positionToString(positionNum, structLen, dataIn);
189 version(result);
190}
191
192void FirmwareInventory::firmwareId(const uint8_t positionNum,
193 const uint8_t structLen, uint8_t* dataIn)
194{
195 std::string result = positionToString(positionNum, structLen, dataIn);
196 extendedVersion(result);
197}
198
199void FirmwareInventory::firmwareReleaseDate(
200 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
201{
202 std::string result = positionToString(positionNum, structLen, dataIn);
Prithvi Paiac4cb322025-06-10 10:45:55 +0530203 releaseDate(result);
Prithvi Pai6f9e7a72025-03-14 13:05:02 +0530204}
205
206void FirmwareInventory::firmwareManufacturer(
207 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
208{
209 std::string result = positionToString(positionNum, structLen, dataIn);
210 manufacturer(result);
211}
212} // namespace smbios
213} // namespace phosphor