blob: 30053d5c4435df2dc2a7d1e94ac58df86f5c49b7 [file] [log] [blame]
#include "firmware_inventory.hpp"
#include "mdrv2.hpp"
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <regex>
#include <sstream>
namespace phosphor
{
namespace smbios
{
namespace utils
{
std::vector<std::string> getExistingVersionPaths(sdbusplus::bus_t& bus)
{
std::vector<std::string> existingVersionPaths;
auto getVersionPaths = bus.new_method_call(
phosphor::smbios::mapperBusName, phosphor::smbios::mapperPath,
phosphor::smbios::mapperInterface, "GetSubTreePaths");
getVersionPaths.append(firmwarePath);
getVersionPaths.append(0);
getVersionPaths.append(
std::array<std::string, 1>({phosphor::smbios::versionInterface}));
try
{
auto reply = bus.call(getVersionPaths);
reply.read(existingVersionPaths);
}
catch (const sdbusplus::exception_t& e)
{
lg2::error("Failed to query version objects. ERROR={E}", "E", e.what());
existingVersionPaths.clear();
}
return existingVersionPaths;
}
} // namespace utils
bool FirmwareInventory::getFirmwareInventoryData(uint8_t*& dataIn,
int inventoryIndex)
{
dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
if (dataIn == nullptr)
{
return false;
}
for (uint8_t index = 0; index < inventoryIndex; index++)
{
dataIn = smbiosNextPtr(dataIn);
if (dataIn == nullptr)
{
return false;
}
dataIn = getSMBIOSTypePtr(dataIn, firmwareInventoryInformationType);
if (dataIn == nullptr)
{
return false;
}
}
return true;
}
void FirmwareInventory::firmwareInfoUpdate(uint8_t* smbiosTableStorage)
{
uint8_t* dataIn = smbiosTableStorage;
if (!getFirmwareInventoryData(dataIn, firmwareInventoryIndex))
{
lg2::info("Failed to get data for firmware inventory index {I}", "I",
firmwareInventoryIndex);
return;
}
auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
firmwareComponentName(firmwareInfo->componentName, firmwareInfo->length,
dataIn);
firmwareVersion(firmwareInfo->version, firmwareInfo->length, dataIn);
firmwareId(firmwareInfo->id, firmwareInfo->length, dataIn);
firmwareReleaseDate(firmwareInfo->releaseDate, firmwareInfo->length,
dataIn);
firmwareManufacturer(firmwareInfo->manufacturer, firmwareInfo->length,
dataIn);
present(true);
purpose(softwareVersion::VersionPurpose::Other);
std::vector<std::tuple<std::string, std::string, std::string>> assocs;
assocs.emplace_back("software_version", "functional",
"/xyz/openbmc_project/software");
association::associations(assocs);
}
std::string FirmwareInventory::checkAndCreateFirmwarePath(
uint8_t* dataIn, int inventoryIndex,
std::vector<std::string>& existingVersionPaths)
{
if (!getFirmwareInventoryData(dataIn, inventoryIndex))
{
lg2::info("Failed to get data for firmware inventory index {I}", "I",
inventoryIndex);
return "";
}
auto firmwareInfo = reinterpret_cast<struct FirmwareInfo*>(dataIn);
std::string firmwareId =
positionToString(firmwareInfo->id, firmwareInfo->length, dataIn);
auto firmwareName = positionToString(firmwareInfo->componentName,
firmwareInfo->length, dataIn);
std::string firmwareObjPath = "";
#ifdef EXPOSE_FW_COMPONENT_NAME
firmwareObjPath = firmwareName;
#else
firmwareObjPath = firmwareId;
#endif
if (firmwareInfo->numOfAssociatedComponents > 0)
{
for (int i = 0; i < firmwareInfo->numOfAssociatedComponents; i++)
{
auto component = smbiosHandlePtr(
dataIn, firmwareInfo->associatedComponentHandles[i]);
if (component == nullptr)
{
continue;
}
auto header = reinterpret_cast<struct StructureHeader*>(component);
switch (header->type)
{
case processorsType:
case systemSlots:
case onboardDevicesExtended:
{
auto designation = positionToString(
component[4], header->length, component);
if (!designation.empty())
{
firmwareObjPath.append("_").append(designation);
}
break;
}
case systemPowerSupply:
{
auto location = positionToString(component[5],
header->length, component);
if (!location.empty())
{
firmwareObjPath.append("_").append(location);
}
break;
}
default:
break;
}
}
}
if (firmwareObjPath.empty())
{
firmwareObjPath = "firmware" + std::to_string(inventoryIndex);
}
boost::algorithm::trim_right(firmwareObjPath);
firmwareObjPath =
std::regex_replace(firmwareObjPath, std::regex("[^a-zA-Z0-9_/]+"), "_");
auto eqObjName = [firmwareObjPath](std::string s) {
std::filesystem::path p(s);
return p.filename().compare(firmwareObjPath) == 0;
};
if (std::find_if(existingVersionPaths.begin(), existingVersionPaths.end(),
std::move(eqObjName)) != existingVersionPaths.end())
{
return "";
}
std::string path = firmwarePath;
path.append("/").append(firmwareObjPath);
return path;
}
void FirmwareInventory::firmwareComponentName(
const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
prettyName(result);
}
void FirmwareInventory::firmwareVersion(
const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
version(result);
}
void FirmwareInventory::firmwareId(const uint8_t positionNum,
const uint8_t structLen, uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
extendedVersion(result);
}
void FirmwareInventory::firmwareReleaseDate(
const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
buildDate(result);
}
void FirmwareInventory::firmwareManufacturer(
const uint8_t positionNum, const uint8_t structLen, uint8_t* dataIn)
{
std::string result = positionToString(positionNum, structLen, dataIn);
manufacturer(result);
}
} // namespace smbios
} // namespace phosphor