xref: /openbmc/smbios-mdr/src/firmware_inventory.cpp (revision ac4cb328365c7073a54da815c7f2362f1c64bf01)
16f9e7a76SPrithvi Pai #include "firmware_inventory.hpp"
26f9e7a76SPrithvi Pai 
36f9e7a76SPrithvi Pai #include "mdrv2.hpp"
46f9e7a76SPrithvi Pai 
56f9e7a76SPrithvi Pai #include <boost/algorithm/string.hpp>
66f9e7a76SPrithvi Pai 
76f9e7a76SPrithvi Pai #include <fstream>
86f9e7a76SPrithvi Pai #include <iomanip>
96f9e7a76SPrithvi Pai #include <iostream>
106f9e7a76SPrithvi Pai #include <regex>
116f9e7a76SPrithvi Pai #include <sstream>
126f9e7a76SPrithvi Pai 
136f9e7a76SPrithvi Pai namespace phosphor
146f9e7a76SPrithvi Pai {
156f9e7a76SPrithvi Pai namespace smbios
166f9e7a76SPrithvi Pai {
176f9e7a76SPrithvi Pai namespace utils
186f9e7a76SPrithvi Pai {
getExistingVersionPaths(sdbusplus::bus_t & bus)196f9e7a76SPrithvi Pai std::vector<std::string> getExistingVersionPaths(sdbusplus::bus_t& bus)
206f9e7a76SPrithvi Pai {
216f9e7a76SPrithvi Pai     std::vector<std::string> existingVersionPaths;
226f9e7a76SPrithvi Pai 
236f9e7a76SPrithvi Pai     auto getVersionPaths = bus.new_method_call(
246f9e7a76SPrithvi Pai         phosphor::smbios::mapperBusName, phosphor::smbios::mapperPath,
256f9e7a76SPrithvi Pai         phosphor::smbios::mapperInterface, "GetSubTreePaths");
266f9e7a76SPrithvi Pai     getVersionPaths.append(firmwarePath);
276f9e7a76SPrithvi Pai     getVersionPaths.append(0);
286f9e7a76SPrithvi Pai     getVersionPaths.append(
296f9e7a76SPrithvi Pai         std::array<std::string, 1>({phosphor::smbios::versionInterface}));
306f9e7a76SPrithvi Pai 
316f9e7a76SPrithvi Pai     try
326f9e7a76SPrithvi Pai     {
336f9e7a76SPrithvi Pai         auto reply = bus.call(getVersionPaths);
346f9e7a76SPrithvi Pai         reply.read(existingVersionPaths);
356f9e7a76SPrithvi Pai     }
366f9e7a76SPrithvi Pai     catch (const sdbusplus::exception_t& e)
376f9e7a76SPrithvi Pai     {
386f9e7a76SPrithvi Pai         lg2::error("Failed to query version objects. ERROR={E}", "E", e.what());
396f9e7a76SPrithvi Pai         existingVersionPaths.clear();
406f9e7a76SPrithvi Pai     }
416f9e7a76SPrithvi Pai 
426f9e7a76SPrithvi Pai     return existingVersionPaths;
436f9e7a76SPrithvi Pai }
446f9e7a76SPrithvi Pai } // namespace utils
456f9e7a76SPrithvi Pai 
getFirmwareInventoryData(uint8_t * & dataIn,int inventoryIndex)466f9e7a76SPrithvi Pai bool FirmwareInventory::getFirmwareInventoryData(uint8_t*& dataIn,
476f9e7a76SPrithvi Pai                                                  int inventoryIndex)
486f9e7a76SPrithvi Pai {
496f9e7a76SPrithvi Pai     dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
506f9e7a76SPrithvi Pai     if (dataIn == nullptr)
516f9e7a76SPrithvi Pai     {
526f9e7a76SPrithvi Pai         return false;
536f9e7a76SPrithvi Pai     }
546f9e7a76SPrithvi Pai     for (uint8_t index = 0; index < inventoryIndex; index++)
556f9e7a76SPrithvi Pai     {
566f9e7a76SPrithvi Pai         dataIn = smbiosNextPtr(dataIn);
576f9e7a76SPrithvi Pai         if (dataIn == nullptr)
586f9e7a76SPrithvi Pai         {
596f9e7a76SPrithvi Pai             return false;
606f9e7a76SPrithvi Pai         }
616f9e7a76SPrithvi Pai         dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
626f9e7a76SPrithvi Pai         if (dataIn == nullptr)
636f9e7a76SPrithvi Pai         {
646f9e7a76SPrithvi Pai             return false;
656f9e7a76SPrithvi Pai         }
666f9e7a76SPrithvi Pai     }
676f9e7a76SPrithvi Pai     return true;
686f9e7a76SPrithvi Pai }
696f9e7a76SPrithvi Pai 
firmwareInfoUpdate(uint8_t * smbiosTableStorage)706f9e7a76SPrithvi Pai void FirmwareInventory::firmwareInfoUpdate(uint8_t* smbiosTableStorage)
716f9e7a76SPrithvi Pai {
726f9e7a76SPrithvi Pai     uint8_t* dataIn = smbiosTableStorage;
736f9e7a76SPrithvi Pai     if (!getFirmwareInventoryData(dataIn, firmwareInventoryIndex))
746f9e7a76SPrithvi Pai     {
756f9e7a76SPrithvi Pai         lg2::info("Failed to get data for firmware inventory index {I}", "I",
766f9e7a76SPrithvi Pai                   firmwareInventoryIndex);
776f9e7a76SPrithvi Pai         return;
786f9e7a76SPrithvi Pai     }
796f9e7a76SPrithvi Pai 
806f9e7a76SPrithvi Pai     auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
816f9e7a76SPrithvi Pai 
826f9e7a76SPrithvi Pai     firmwareComponentName(firmwareInfo->componentName, firmwareInfo->length,
836f9e7a76SPrithvi Pai                           dataIn);
846f9e7a76SPrithvi Pai     firmwareVersion(firmwareInfo->version, firmwareInfo->length, dataIn);
856f9e7a76SPrithvi Pai     firmwareId(firmwareInfo->id, firmwareInfo->length, dataIn);
866f9e7a76SPrithvi Pai     firmwareReleaseDate(firmwareInfo->releaseDate, firmwareInfo->length,
876f9e7a76SPrithvi Pai                         dataIn);
886f9e7a76SPrithvi Pai     firmwareManufacturer(firmwareInfo->manufacturer, firmwareInfo->length,
896f9e7a76SPrithvi Pai                          dataIn);
906f9e7a76SPrithvi Pai     present(true);
916f9e7a76SPrithvi Pai     purpose(softwareVersion::VersionPurpose::Other);
926f9e7a76SPrithvi Pai }
936f9e7a76SPrithvi Pai 
946f9e7a76SPrithvi Pai std::string FirmwareInventory::checkAndCreateFirmwarePath(
956f9e7a76SPrithvi Pai     uint8_t* dataIn, int inventoryIndex,
966f9e7a76SPrithvi Pai     std::vector<std::string>& existingVersionPaths)
976f9e7a76SPrithvi Pai {
986f9e7a76SPrithvi Pai     if (!getFirmwareInventoryData(dataIn, inventoryIndex))
checkAndCreateFirmwarePath(uint8_t * dataIn,int inventoryIndex,std::vector<std::string> & existingVersionPaths)996f9e7a76SPrithvi Pai     {
1006f9e7a76SPrithvi Pai         lg2::info("Failed to get data for firmware inventory index {I}", "I",
1016f9e7a76SPrithvi Pai                   inventoryIndex);
1026f9e7a76SPrithvi Pai         return "";
1036f9e7a76SPrithvi Pai     }
1046f9e7a76SPrithvi Pai     auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
1056f9e7a76SPrithvi Pai     std::string firmwareId =
1066f9e7a76SPrithvi Pai         positionToString(firmwareInfo->id, firmwareInfo->length, dataIn);
1076f9e7a76SPrithvi Pai     auto firmwareName = positionToString(firmwareInfo->componentName,
1086f9e7a76SPrithvi Pai                                          firmwareInfo->length, dataIn);
1096f9e7a76SPrithvi Pai     std::string firmwareObjPath = "";
1106f9e7a76SPrithvi Pai #ifdef EXPOSE_FW_COMPONENT_NAME
1116f9e7a76SPrithvi Pai     firmwareObjPath = firmwareName;
1126f9e7a76SPrithvi Pai #else
1136f9e7a76SPrithvi Pai     firmwareObjPath = firmwareId;
1146f9e7a76SPrithvi Pai #endif
1156f9e7a76SPrithvi Pai     if (firmwareInfo->numOfAssociatedComponents > 0)
1166f9e7a76SPrithvi Pai     {
1176f9e7a76SPrithvi Pai         for (int i = 0; i < firmwareInfo->numOfAssociatedComponents; i++)
1186f9e7a76SPrithvi Pai         {
1196f9e7a76SPrithvi Pai             auto component = smbiosHandlePtr(
1206f9e7a76SPrithvi Pai                 dataIn, firmwareInfo->associatedComponentHandles[i]);
1216f9e7a76SPrithvi Pai             if (component == nullptr)
1226f9e7a76SPrithvi Pai             {
1236f9e7a76SPrithvi Pai                 continue;
1246f9e7a76SPrithvi Pai             }
1256f9e7a76SPrithvi Pai 
1266f9e7a76SPrithvi Pai             auto header = reinterpret_cast<struct StructureHeader*>(component);
1276f9e7a76SPrithvi Pai             switch (header->type)
1286f9e7a76SPrithvi Pai             {
1296f9e7a76SPrithvi Pai                 case processorsType:
1306f9e7a76SPrithvi Pai                 case systemSlots:
1316f9e7a76SPrithvi Pai                 case onboardDevicesExtended:
1326f9e7a76SPrithvi Pai                 {
1336f9e7a76SPrithvi Pai                     auto designation = positionToString(
1346f9e7a76SPrithvi Pai                         component[4], header->length, component);
1356f9e7a76SPrithvi Pai                     if (!designation.empty())
1366f9e7a76SPrithvi Pai                     {
1376f9e7a76SPrithvi Pai                         firmwareObjPath.append("_").append(designation);
1386f9e7a76SPrithvi Pai                     }
1396f9e7a76SPrithvi Pai                     break;
1406f9e7a76SPrithvi Pai                 }
1416f9e7a76SPrithvi Pai                 case systemPowerSupply:
1426f9e7a76SPrithvi Pai                 {
1436f9e7a76SPrithvi Pai                     auto location = positionToString(component[5],
1446f9e7a76SPrithvi Pai                                                      header->length, component);
1456f9e7a76SPrithvi Pai                     if (!location.empty())
1466f9e7a76SPrithvi Pai                     {
1476f9e7a76SPrithvi Pai                         firmwareObjPath.append("_").append(location);
1486f9e7a76SPrithvi Pai                     }
1496f9e7a76SPrithvi Pai                     break;
1506f9e7a76SPrithvi Pai                 }
1516f9e7a76SPrithvi Pai                 default:
1526f9e7a76SPrithvi Pai                     break;
1536f9e7a76SPrithvi Pai             }
1546f9e7a76SPrithvi Pai         }
1556f9e7a76SPrithvi Pai     }
1566f9e7a76SPrithvi Pai     if (firmwareObjPath.empty())
1576f9e7a76SPrithvi Pai     {
1586f9e7a76SPrithvi Pai         firmwareObjPath = "firmware" + std::to_string(inventoryIndex);
1596f9e7a76SPrithvi Pai     }
1606f9e7a76SPrithvi Pai     boost::algorithm::trim_right(firmwareObjPath);
1616f9e7a76SPrithvi Pai     firmwareObjPath =
1626f9e7a76SPrithvi Pai         std::regex_replace(firmwareObjPath, std::regex("[^a-zA-Z0-9_/]+"), "_");
1636f9e7a76SPrithvi Pai 
1646f9e7a76SPrithvi Pai     auto eqObjName = [firmwareObjPath](std::string s) {
1656f9e7a76SPrithvi Pai         std::filesystem::path p(s);
1666f9e7a76SPrithvi Pai         return p.filename().compare(firmwareObjPath) == 0;
1676f9e7a76SPrithvi Pai     };
1686f9e7a76SPrithvi Pai     if (std::find_if(existingVersionPaths.begin(), existingVersionPaths.end(),
__anonf8ba24900102(std::string s) 1696f9e7a76SPrithvi Pai                      std::move(eqObjName)) != existingVersionPaths.end())
1706f9e7a76SPrithvi Pai     {
1716f9e7a76SPrithvi Pai         return "";
1726f9e7a76SPrithvi Pai     }
1736f9e7a76SPrithvi Pai     std::string path = firmwarePath;
1746f9e7a76SPrithvi Pai     path.append("/").append(firmwareObjPath);
1756f9e7a76SPrithvi Pai     return path;
1766f9e7a76SPrithvi Pai }
1776f9e7a76SPrithvi Pai 
1786f9e7a76SPrithvi Pai void FirmwareInventory::firmwareComponentName(
1796f9e7a76SPrithvi Pai     const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
1806f9e7a76SPrithvi Pai {
1816f9e7a76SPrithvi Pai     std::string result = positionToString(positionNum, structLen, dataIn);
1826f9e7a76SPrithvi Pai     prettyName(result);
firmwareComponentName(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)1836f9e7a76SPrithvi Pai }
1846f9e7a76SPrithvi Pai 
1856f9e7a76SPrithvi Pai void FirmwareInventory::firmwareVersion(
1866f9e7a76SPrithvi Pai     const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
1876f9e7a76SPrithvi Pai {
1886f9e7a76SPrithvi Pai     std::string result = positionToString(positionNum, structLen, dataIn);
1896f9e7a76SPrithvi Pai     version(result);
1906f9e7a76SPrithvi Pai }
1916f9e7a76SPrithvi Pai 
1926f9e7a76SPrithvi Pai void FirmwareInventory::firmwareId(const uint8_t positionNum,
1936f9e7a76SPrithvi Pai                                    const uint8_t structLen, uint8_t* dataIn)
1946f9e7a76SPrithvi Pai {
1956f9e7a76SPrithvi Pai     std::string result = positionToString(positionNum, structLen, dataIn);
1966f9e7a76SPrithvi Pai     extendedVersion(result);
firmwareId(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)1976f9e7a76SPrithvi Pai }
1986f9e7a76SPrithvi Pai 
1996f9e7a76SPrithvi Pai void FirmwareInventory::firmwareReleaseDate(
2006f9e7a76SPrithvi Pai     const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
2016f9e7a76SPrithvi Pai {
2026f9e7a76SPrithvi Pai     std::string result = positionToString(positionNum, structLen, dataIn);
203*ac4cb328SPrithvi Pai     releaseDate(result);
2046f9e7a76SPrithvi Pai }
2056f9e7a76SPrithvi Pai 
2066f9e7a76SPrithvi Pai void FirmwareInventory::firmwareManufacturer(
2076f9e7a76SPrithvi Pai     const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
2086f9e7a76SPrithvi Pai {
2096f9e7a76SPrithvi Pai     std::string result = positionToString(positionNum, structLen, dataIn);
2106f9e7a76SPrithvi Pai     manufacturer(result);
firmwareManufacturer(const uint8_t positionNum,const uint8_t structLen,uint8_t * dataIn)2116f9e7a76SPrithvi Pai }
2126f9e7a76SPrithvi Pai } // namespace smbios
2136f9e7a76SPrithvi Pai } // namespace phosphor
214