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/CMakeLists.txt b/CMakeLists.txt
index 90837f6..1095c8a 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -40,7 +40,7 @@
add_definitions (-DBOOST_ASIO_DISABLE_THREADS)
set (SRC_FILES src/mdrv2.cpp src/mdrv2_main.cpp src/cpu.cpp src/dimm.cpp
- src/system.cpp)
+ src/system.cpp src/pcieslot.cpp)
include_directories (${CMAKE_CURRENT_BINARY_DIR})
diff --git a/include/mdrv2.hpp b/include/mdrv2.hpp
index 8f03579..baacd0c 100644
--- a/include/mdrv2.hpp
+++ b/include/mdrv2.hpp
@@ -17,6 +17,7 @@
#pragma once
#include "cpu.hpp"
#include "dimm.hpp"
+#include "pcieslot.hpp"
#include "smbios_mdrv2.hpp"
#include "system.hpp"
@@ -135,8 +136,10 @@
int getTotalCpuSlot(void);
int getTotalDimmSlot(void);
+ int getTotalPcieSlot(void);
std::vector<std::unique_ptr<Cpu>> cpus;
std::vector<std::unique_ptr<Dimm>> dimms;
+ std::vector<std::unique_ptr<Pcie>> pcies;
std::unique_ptr<System> system;
std::shared_ptr<sdbusplus::asio::dbus_interface> smbiosInterface;
};
diff --git a/include/pcieslot.hpp b/include/pcieslot.hpp
new file mode 100644
index 0000000..d16d75e
--- /dev/null
+++ b/include/pcieslot.hpp
@@ -0,0 +1,156 @@
+#pragma once
+#include "smbios_mdrv2.hpp"
+
+#include <xyz/openbmc_project/Inventory/Connector/Embedded/server.hpp>
+#include <xyz/openbmc_project/Inventory/Decorator/LocationCode/server.hpp>
+#include <xyz/openbmc_project/Inventory/Item/PCIeSlot/server.hpp>
+#include <xyz/openbmc_project/Inventory/Item/server.hpp>
+
+#include <cstdint>
+#include <map>
+#include <unordered_set>
+
+namespace phosphor
+{
+
+namespace smbios
+{
+
+using PCIeSlot =
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::PCIeSlot;
+using PCIeGeneration = sdbusplus::xyz::openbmc_project::Inventory::Item::
+ server::PCIeSlot::Generations;
+using PCIeType = sdbusplus::xyz::openbmc_project::Inventory::Item::server::
+ PCIeSlot::SlotTypes;
+using embedded =
+ sdbusplus::xyz::openbmc_project::Inventory::Connector::server::Embedded;
+using location =
+ sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::LocationCode;
+using item = sdbusplus::xyz::openbmc_project::Inventory::server::Item;
+
+class Pcie : sdbusplus::server::object_t<PCIeSlot, location, embedded, item>
+{
+ public:
+ Pcie() = delete;
+ Pcie(const Pcie&) = delete;
+ Pcie& operator=(const Pcie&) = delete;
+ Pcie(Pcie&&) = delete;
+ Pcie& operator=(Pcie&&) = delete;
+ ~Pcie() = default;
+
+ Pcie(sdbusplus::bus::bus& bus, const std::string& objPath,
+ const uint8_t& pcieId, uint8_t* smbiosTableStorage) :
+ sdbusplus::server::object_t<PCIeSlot, location, embedded, item>(
+ bus, objPath.c_str()),
+ pcieNum(pcieId), storage(smbiosTableStorage)
+ {
+ pcieInfoUpdate();
+ }
+
+ void pcieInfoUpdate();
+
+ private:
+ uint8_t pcieNum;
+ uint8_t* storage;
+
+ struct SystemSlotInfo
+ {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+ uint8_t slotDesignation;
+ uint8_t slotType;
+ uint8_t slotDataBusWidth;
+ uint8_t currUsage;
+ uint8_t slotLength;
+ uint16_t slotID;
+ uint8_t characteristics1;
+ uint8_t characteristics2;
+ uint16_t segGroupNum;
+ uint8_t busNum;
+ uint8_t deviceNum;
+ } __attribute__((packed));
+
+ void pcieGeneration(const uint8_t type);
+ void pcieType(const uint8_t type);
+ void pcieLaneSize(const uint8_t width);
+ void pcieIsHotPluggable(const uint8_t characteristics);
+ void pcieLocation(const uint8_t slotDesignation, const uint8_t structLen,
+ uint8_t* dataIn);
+};
+
+static const std::unordered_set<uint8_t> pcieSmbiosType = {
+ 0x09, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1c,
+ 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1,
+ 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd,
+ 0xbe, 0xbf, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6};
+
+// Definition follow smbios spec DSP0134 3.4.0
+static const std::map<uint8_t, PCIeGeneration> pcieGenerationTable = {
+ {0x09, PCIeGeneration::Unknown}, {0x14, PCIeGeneration::Gen3},
+ {0x15, PCIeGeneration::Gen3}, {0x16, PCIeGeneration::Gen3},
+ {0x17, PCIeGeneration::Gen3}, {0x18, PCIeGeneration::Gen1},
+ {0x19, PCIeGeneration::Gen1}, {0x1a, PCIeGeneration::Gen1},
+ {0x1b, PCIeGeneration::Gen1}, {0x1c, PCIeGeneration::Gen1},
+ {0x1d, PCIeGeneration::Gen3}, {0x1e, PCIeGeneration::Gen3},
+ {0x1f, PCIeGeneration::Gen2}, {0x20, PCIeGeneration::Gen3},
+ {0x21, PCIeGeneration::Gen1}, {0x22, PCIeGeneration::Gen1},
+ {0x23, PCIeGeneration::Gen1}, {0x24, PCIeGeneration::Gen4},
+ {0x25, PCIeGeneration::Gen5}, {0x26, PCIeGeneration::Unknown},
+ {0x27, PCIeGeneration::Unknown}, {0x28, PCIeGeneration::Unknown},
+ {0x29, PCIeGeneration::Unknown}, {0xa5, PCIeGeneration::Gen1},
+ {0xa6, PCIeGeneration::Gen1}, {0xa7, PCIeGeneration::Gen1},
+ {0xa8, PCIeGeneration::Gen1}, {0xa9, PCIeGeneration::Gen1},
+ {0xaa, PCIeGeneration::Gen1}, {0xab, PCIeGeneration::Gen2},
+ {0xac, PCIeGeneration::Gen2}, {0xad, PCIeGeneration::Gen2},
+ {0xae, PCIeGeneration::Gen2}, {0xaf, PCIeGeneration::Gen2},
+ {0xb0, PCIeGeneration::Gen2}, {0xb1, PCIeGeneration::Gen3},
+ {0xb2, PCIeGeneration::Gen3}, {0xb3, PCIeGeneration::Gen3},
+ {0xb4, PCIeGeneration::Gen3}, {0xb5, PCIeGeneration::Gen3},
+ {0xb6, PCIeGeneration::Gen3}, {0xb8, PCIeGeneration::Gen4},
+ {0xb9, PCIeGeneration::Gen4}, {0xba, PCIeGeneration::Gen4},
+ {0xbb, PCIeGeneration::Gen4}, {0xbc, PCIeGeneration::Gen4},
+ {0xbd, PCIeGeneration::Gen4}, {0xbe, PCIeGeneration::Gen5},
+ {0xbf, PCIeGeneration::Gen5}, {0xc0, PCIeGeneration::Gen5},
+ {0xc1, PCIeGeneration::Gen5}, {0xc2, PCIeGeneration::Gen5},
+ {0xc3, PCIeGeneration::Gen5}, {0xc4, PCIeGeneration::Unknown},
+ {0xc5, PCIeGeneration::Unknown}, {0xc6, PCIeGeneration::Unknown}};
+
+static const std::map<uint8_t, PCIeType> pcieTypeTable = {
+ {0x09, PCIeType::OEM}, {0x14, PCIeType::M_2},
+ {0x15, PCIeType::M_2}, {0x16, PCIeType::M_2},
+ {0x17, PCIeType::M_2}, {0x18, PCIeType::Unknown},
+ {0x19, PCIeType::Unknown}, {0x1a, PCIeType::Unknown},
+ {0x1b, PCIeType::Unknown}, {0x1c, PCIeType::Unknown},
+ {0x1d, PCIeType::Unknown}, {0x1e, PCIeType::Unknown},
+ {0xa8, PCIeType::Unknown}, {0xa9, PCIeType::Unknown},
+ {0x1F, PCIeType::U_2}, {0x20, PCIeType::U_2},
+ {0x21, PCIeType::Mini}, {0x22, PCIeType::Mini},
+ {0x23, PCIeType::Mini}, {0x24, PCIeType::U_2},
+ {0x25, PCIeType::U_2}, {0x26, PCIeType::OCP3Small},
+ {0x27, PCIeType::OCP3Large}, {0x28, PCIeType::Unknown},
+ {0x29, PCIeType::Unknown}, {0xa5, PCIeType::Unknown},
+ {0xa6, PCIeType::Unknown}, {0xa7, PCIeType::Unknown},
+ {0xa8, PCIeType::Unknown}, {0xa9, PCIeType::Unknown},
+ {0xaa, PCIeType::Unknown}, {0xab, PCIeType::Unknown},
+ {0xac, PCIeType::Unknown}, {0xad, PCIeType::Unknown},
+ {0xae, PCIeType::Unknown}, {0xaf, PCIeType::Unknown},
+ {0xb0, PCIeType::Unknown}, {0xb1, PCIeType::Unknown},
+ {0xb2, PCIeType::Unknown}, {0xb3, PCIeType::Unknown},
+ {0xb4, PCIeType::Unknown}, {0xb5, PCIeType::Unknown},
+ {0xb6, PCIeType::Unknown}, {0xb8, PCIeType::Unknown},
+ {0xb9, PCIeType::Unknown}, {0xba, PCIeType::Unknown},
+ {0xbb, PCIeType::Unknown}, {0xbc, PCIeType::Unknown},
+ {0xbd, PCIeType::Unknown}, {0xbe, PCIeType::Unknown},
+ {0xbf, PCIeType::Unknown}, {0xc0, PCIeType::Unknown},
+ {0xc1, PCIeType::Unknown}, {0xc2, PCIeType::Unknown},
+ {0xc3, PCIeType::Unknown}, {0xc4, PCIeType::Unknown},
+ {0xc5, PCIeType::Unknown}, {0xc6, PCIeType::Unknown}};
+
+const std::map<uint8_t, size_t> pcieLanesTable = {
+ {0x08, 1}, {0x09, 2}, {0xa, 4}, {0xb, 8}, {0xc, 12}, {0xd, 16}, {0xe, 32}};
+
+}; // namespace smbios
+
+}; // namespace phosphor
diff --git a/include/smbios_mdrv2.hpp b/include/smbios_mdrv2.hpp
index a307332..0d8ec30 100644
--- a/include/smbios_mdrv2.hpp
+++ b/include/smbios_mdrv2.hpp
@@ -125,6 +125,9 @@
static constexpr const char* dimmPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm";
+static constexpr const char* pciePath =
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/pcieslot";
+
static constexpr const char* systemPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard/bios";
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