smbios-mdr: Parse PCIE slot tables
System slot tables have SMBIOS table type 9. Parse system slot tables
and select all PCIE slots. PCIE slot inventory DBus objects will have
the xyz.openbmc_project.Inventory.Item.PCIeSlot interface defined in
phosphor-dbus-interfaces.
Tested:
Tests on a Intel platform. Some DBus command outputs as follows:
busctl introspect xyz.openbmc_project.Smbios.MDR_V2 \
/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot3
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
org.freedesktop.DBus.Introspectable interface - - -herboard/p
.Introspect method - s -
org.freedesktop.DBus.Peer interface - - -
.GetMachineId method - s -
.Ping method - - -
org.freedesktop.DBus.Properties interface - - -
.Get method ss v -
.GetAll method s a{sv} -
.Set method ssv - -
.PropertiesChanged signal sa{sv}as - -
xyz.openbmc_project.Inventory.Decorator.LocationCode interface - - -
.LocationCode property s "PE3" emits-change writable
xyz.openbmc_project.Inventory.Item interface - - -
.Present property b true emits-change writable
.PrettyName property s "" emits-change writable
xyz.openbmc_project.Inventory.Item.PCIeSlot interface - - -
.Generation property s "xyz.openbmc_project.Inventory.Item.P... emits-change writable
.HotPluggable property b false emits-change writable
.Lanes property u 16 emits-change writable
.SlotType property s "xyz.openbmc_project.Inventory.Item.P... emits-change writable
busctl get-property xyz.openbmc_project.Smbios.MDR_V2 \
/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot3 \
xyz.openbmc_project.Inventory.Item.PCIeSlot Generation
s "xyz.openbmc_project.Inventory.Item.PCIeSlot.Generations.Gen5"
busctl get-property xyz.openbmc_project.Smbios.MDR_V2 \
/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot3 \
xyz.openbmc_project.Inventory.Item.PCIeSlot SlotType
s "xyz.openbmc_project.Inventory.Item.PCIeSlot.SlotTypes.Unknown"
Note that it shows unknown PCIE slot types, as SMBIOS system slot record
does not have the information that a PCIE slot is full-length,
half-length or low-profile.
Signed-off-by: Jie Yang <jjy@google.com>
Change-Id: Ie9179ceb57dea3f659c15939611e873411de7320
diff --git a/src/mdrv2.cpp b/src/mdrv2.cpp
index 1d173c4..39890b3 100644
--- a/src/mdrv2.cpp
+++ b/src/mdrv2.cpp
@@ -16,6 +16,8 @@
#include "mdrv2.hpp"
+#include "pcieslot.hpp"
+
#include <sys/mman.h>
#include <phosphor-logging/elog-errors.hpp>
@@ -411,6 +413,22 @@
#endif
+ pcies.clear();
+ num = getTotalPcieSlot();
+ if (num == -1)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "get pcie total slot failed");
+ return;
+ }
+
+ for (int index = 0; index < num; index++)
+ {
+ std::string path = pciePath + std::to_string(index);
+ pcies.emplace_back(std::make_unique<phosphor::smbios::Pcie>(
+ bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
+ }
+
system.reset();
system = std::make_unique<System>(
bus, systemPath, smbiosDir.dir[smbiosDirIndex].dataStorage);
@@ -484,6 +502,47 @@
return num;
}
+int MDR_V2::getTotalPcieSlot()
+{
+ uint8_t* dataIn = smbiosDir.dir[smbiosDirIndex].dataStorage;
+ int num = 0;
+
+ if (dataIn == nullptr)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "Fail to get total system slot - no storage data");
+ return -1;
+ }
+
+ while (1)
+ {
+ dataIn = getSMBIOSTypePtr(dataIn, systemSlots);
+ if (dataIn == nullptr)
+ {
+ break;
+ }
+
+ /* System slot type offset. Check if the slot is a PCIE slots. All
+ * PCIE slot type are hardcoded in a table.
+ */
+ if (pcieSmbiosType.find(*(dataIn + 5)) != pcieSmbiosType.end())
+ {
+ num++;
+ }
+ dataIn = smbiosNextPtr(dataIn);
+ if (dataIn == nullptr)
+ {
+ break;
+ }
+ if (num >= limitEntryLen)
+ {
+ break;
+ }
+ }
+
+ return num;
+}
+
bool MDR_V2::agentSynchronizeData()
{
struct MDRSMBIOSHeader mdr2SMBIOS;
diff --git a/src/pcieslot.cpp b/src/pcieslot.cpp
new file mode 100644
index 0000000..1b46407
--- /dev/null
+++ b/src/pcieslot.cpp
@@ -0,0 +1,109 @@
+#include "pcieslot.hpp"
+
+#include <cstdint>
+#include <map>
+
+namespace phosphor
+{
+namespace smbios
+{
+
+void Pcie::pcieInfoUpdate()
+{
+ uint8_t* dataIn = getSMBIOSTypePtr(storage, systemSlots);
+
+ if (dataIn == nullptr)
+ {
+ return;
+ }
+
+ /* offset 5 points to the slot type */
+ for (uint8_t index = 0;
+ index < pcieNum ||
+ pcieSmbiosType.find(*(dataIn + 5)) == pcieSmbiosType.end();)
+ {
+ dataIn = smbiosNextPtr(dataIn);
+ if (dataIn == nullptr)
+ {
+ return;
+ }
+ dataIn = getSMBIOSTypePtr(dataIn, systemSlots);
+ if (dataIn == nullptr)
+ {
+ return;
+ }
+ if (pcieSmbiosType.find(*(dataIn + 5)) != pcieSmbiosType.end())
+ {
+ index++;
+ }
+ }
+
+ auto pcieInfo = reinterpret_cast<struct SystemSlotInfo*>(dataIn);
+
+ pcieGeneration(pcieInfo->slotType);
+ pcieType(pcieInfo->slotType);
+ pcieLaneSize(pcieInfo->slotDataBusWidth);
+ pcieIsHotPluggable(pcieInfo->characteristics2);
+ pcieLocation(pcieInfo->slotDesignation, pcieInfo->length, dataIn);
+
+ /* Pcie slot is embedded on the board. Always be true */
+ Item::present(true);
+}
+
+void Pcie::pcieGeneration(const uint8_t type)
+{
+ std::map<uint8_t, PCIeGeneration>::const_iterator it =
+ pcieGenerationTable.find(type);
+ if (it == pcieGenerationTable.end())
+ {
+ PCIeSlot::generation(PCIeGeneration::Unknown);
+ }
+ else
+ {
+ PCIeSlot::generation(it->second);
+ }
+}
+
+void Pcie::pcieType(const uint8_t type)
+{
+ std::map<uint8_t, PCIeType>::const_iterator it = pcieTypeTable.find(type);
+ if (it == pcieTypeTable.end())
+ {
+ PCIeSlot::slotType(PCIeType::Unknown);
+ }
+ else
+ {
+ PCIeSlot::slotType(it->second);
+ }
+}
+
+void Pcie::pcieLaneSize(const uint8_t width)
+{
+ std::map<uint8_t, size_t>::const_iterator it = pcieLanesTable.find(width);
+ if (it == pcieLanesTable.end())
+ {
+ PCIeSlot::lanes(0);
+ }
+ else
+ {
+ PCIeSlot::lanes(it->second);
+ }
+}
+
+void Pcie::pcieIsHotPluggable(const uint8_t characteristics)
+{
+ /* Bit 1 of slot characteristics 2 indicates if slot supports hot-plug
+ * devices
+ */
+ PCIeSlot::hotPluggable(characteristics & 0x2);
+}
+
+void Pcie::pcieLocation(const uint8_t slotDesignation, const uint8_t structLen,
+ uint8_t* dataIn)
+{
+ location::locationCode(
+ positionToString(slotDesignation, structLen, dataIn));
+}
+
+} // namespace smbios
+} // namespace phosphor