smbios-mdr: Add TPM Device Information

Type 43 of SMBIOS records defines the data structure to expose
TPM Device information. Add patch which displays the TPM Device
information on dbus.
Introduced `TPM_DBUS` meson option which will be disabled by default
When enabled, the TPM information is populated on DBUS.

Tested:

TPM information is available under dbus tree of smbios-mdr
```
:~# busctl tree xyz.openbmc_project.Smbios.MDR_V2
`- /xyz
  `- /xyz/openbmc_project
    |- /xyz/openbmc_project/Smbios
    | `- /xyz/openbmc_project/Smbios/MDR_V2
    |- /xyz/openbmc_project/inventory
    | `- /xyz/openbmc_project/inventory/system
    |   `- /xyz/openbmc_project/inventory/system/chassis
    |       |- /xyz/openbmc_project/inventory/system/chassis/motherboard/bios
    |       `- /xyz/openbmc_project/inventory/system/chassis/motherboard/tpm
```

Change-Id: Icd42f4f043bf5a970f4829e5d318568360fe4b59
Signed-off-by: Prithvi Pai <ppai@nvidia.com>
diff --git a/include/mdrv2.hpp b/include/mdrv2.hpp
index d248073..2459a89 100644
--- a/include/mdrv2.hpp
+++ b/include/mdrv2.hpp
@@ -20,6 +20,7 @@
 #include "pcieslot.hpp"
 #include "smbios_mdrv2.hpp"
 #include "system.hpp"
+#include "tpm.hpp"
 
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -188,9 +189,11 @@
     std::optional<size_t> getTotalCpuSlot(void);
     std::optional<size_t> getTotalDimmSlot(void);
     std::optional<size_t> getTotalPcieSlot(void);
+    std::optional<size_t> getTotalTpm(void);
     std::vector<std::unique_ptr<Cpu>> cpus;
     std::vector<std::unique_ptr<Dimm>> dimms;
     std::vector<std::unique_ptr<Pcie>> pcies;
+    std::vector<std::unique_ptr<Tpm>> tpms;
     std::unique_ptr<System> system;
     std::shared_ptr<sdbusplus::asio::dbus_interface> smbiosInterface;
 
diff --git a/include/smbios_mdrv2.hpp b/include/smbios_mdrv2.hpp
index 59680bf..2be6dad 100644
--- a/include/smbios_mdrv2.hpp
+++ b/include/smbios_mdrv2.hpp
@@ -165,6 +165,8 @@
 
 static constexpr const char* systemSuffix = "/chassis/motherboard/bios";
 
+static constexpr const char* tpmSuffix = "/chassis/motherboard/tpm";
+
 constexpr std::array<SMBIOSVersion, 8> supportedSMBIOSVersions{
     SMBIOSVersion{3, 0}, SMBIOSVersion{3, 2}, SMBIOSVersion{3, 3},
     SMBIOSVersion{3, 4}, SMBIOSVersion{3, 5}, SMBIOSVersion{3, 6},
@@ -190,6 +192,7 @@
     systemEventLogType = 15,
     physicalMemoryArrayType = 16,
     memoryDeviceType = 17,
+    tpmDeviceType = 43,
 } SmbiosType;
 
 static constexpr uint8_t separateLen = 2;
diff --git a/include/tpm.hpp b/include/tpm.hpp
new file mode 100644
index 0000000..efa14f0
--- /dev/null
+++ b/include/tpm.hpp
@@ -0,0 +1,95 @@
+#pragma once
+#include "smbios_mdrv2.hpp"
+
+#include <sdbusplus/asio/connection.hpp>
+#include <xyz/openbmc_project/Association/Definitions/server.hpp>
+#include <xyz/openbmc_project/Inventory/Decorator/Asset/server.hpp>
+#include <xyz/openbmc_project/Inventory/Item/Tpm/server.hpp>
+#include <xyz/openbmc_project/Inventory/Item/server.hpp>
+#include <xyz/openbmc_project/Software/Version/server.hpp>
+
+namespace phosphor
+{
+
+namespace smbios
+{
+
+using tpm = sdbusplus::server::xyz::openbmc_project::inventory::item::Tpm;
+using asset =
+    sdbusplus::server::xyz::openbmc_project::inventory::decorator::Asset;
+using Item = sdbusplus::server::xyz::openbmc_project::inventory::Item;
+using softwareversion =
+    sdbusplus::server::xyz::openbmc_project::software::Version;
+using association =
+    sdbusplus::server::xyz::openbmc_project::association::Definitions;
+
+constexpr uint8_t tpmMajorVerion1 = 0x01;
+constexpr uint8_t tpmMajorVerion2 = 0x02;
+
+class Tpm :
+    sdbusplus::server::object_t<tpm, asset, Item, association, softwareversion>
+{
+  public:
+    Tpm() = delete;
+    ~Tpm() = default;
+    Tpm(const Tpm&) = delete;
+    Tpm& operator=(const Tpm&) = delete;
+    Tpm(Tpm&&) = default;
+    Tpm& operator=(Tpm&&) = default;
+
+    Tpm(sdbusplus::bus_t& bus, const std::string& objPath, const uint8_t tpmID,
+        uint8_t* smbiosTableStorage, const std::string& motherboard) :
+        sdbusplus::server::object_t<tpm, asset, Item, association,
+                                    softwareversion>(bus, objPath.c_str()),
+        tpmId(tpmID), storage(smbiosTableStorage), motherboardPath(motherboard)
+    {
+        tpmInfoUpdate(smbiosTableStorage, motherboard);
+    }
+
+    void tpmInfoUpdate(uint8_t* smbiosTableStorage,
+                       const std::string& motherboard);
+
+  private:
+    uint8_t tpmId;
+
+    uint8_t* storage;
+
+    std::string motherboardPath;
+    struct TPMInfo
+    {
+        uint8_t type;
+        uint8_t length;
+        uint16_t handle;
+        char vendor[4];
+        uint8_t specMajor;
+        uint8_t specMinor;
+        uint32_t firmwareVersion1;
+        uint32_t firmwareVersion2;
+        uint8_t description;
+        uint64_t characteristics;
+        uint32_t oem;
+    } __attribute__((packed));
+
+    struct TPMVersionSpec1
+    {
+        uint8_t specMajor;
+        uint8_t specMinor;
+        uint8_t revMajor;
+        uint8_t revMinor;
+    } __attribute__((packed));
+
+    struct TPMVersionSpec2
+    {
+        uint16_t revMinor;
+        uint16_t revMajor;
+    } __attribute__((packed));
+
+    void tpmVendor(const struct TPMInfo* tpmInfo);
+    void tpmFirmwareVersion(const struct TPMInfo* tpmInfo);
+    void tpmDescription(const uint8_t positionNum, const uint8_t structLen,
+                        uint8_t* dataIn);
+};
+
+} // namespace smbios
+
+} // namespace phosphor