1 #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
13 namespace phosphor
14 {
15 namespace smbios
16 {
17 namespace utils
18 {
getExistingVersionPaths(sdbusplus::bus_t & bus)19 std::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
getFirmwareInventoryData(uint8_t * & dataIn,int inventoryIndex)46 bool 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
firmwareInfoUpdate(uint8_t * smbiosTableStorage)70 void 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
checkAndCreateFirmwarePath(uint8_t * dataIn,int inventoryIndex,std::vector<std::string> & existingVersionPaths)94 std::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
firmwareComponentName(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)178 void 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
firmwareVersion(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)185 void 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
firmwareId(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)192 void 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
firmwareReleaseDate(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)199 void FirmwareInventory::firmwareReleaseDate(
200 const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
201 {
202 std::string result = positionToString(positionNum, structLen, dataIn);
203 releaseDate(result);
204 }
205
firmwareManufacturer(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)206 void 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
214