summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/cpu.hpp172
-rw-r--r--include/dimm.hpp142
-rw-r--r--include/manager.hpp144
-rw-r--r--include/smbios.hpp208
-rw-r--r--include/timer.hpp149
5 files changed, 815 insertions, 0 deletions
diff --git a/include/cpu.hpp b/include/cpu.hpp
new file mode 100644
index 0000000..08204da
--- /dev/null
+++ b/include/cpu.hpp
@@ -0,0 +1,172 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <xyz/openbmc_project/Inventory/Item/Cpu/server.hpp>
+#include "smbios.hpp"
+
+namespace phosphor
+{
+
+namespace smbios
+{
+
+// Definition follow smbios spec DSP0134 3.0.0
+static const std::map<uint8_t, std::string> cpuTypeTable = {
+ {0x1, "Other"}, {0x2, "Unknown"}, {0x3, "Central Processor"},
+ {0x4, "Math Processor"}, {0x5, "DSP Processor"}, {0x6, "Vodeo Processor"},
+};
+
+// Definition follow smbios spec DSP0134 3.0.0
+static const std::map<uint8_t, std::string> familyTable = {
+ {0x1, "Other"},
+ {0x2, "Unknown"},
+ {0x10, "Pentium II Xeon processor"},
+ {0xa1, "Quad-Core Intel Xeon processor 3200 Series"},
+ {0xa2, "Dual-Core Intel Xeon processor 3000 Series"},
+ {0xa3, "Quad-Core Intel Xeon processor 5300 Series"},
+ {0xa4, "Dual-Core Intel Xeon processor 5100 Series"},
+ {0xa5, "Dual-Core Intel Xeon processor 5000 Series"},
+ {0xa6, "Dual-Core Intel Xeon processor LV"},
+ {0xa7, "Dual-Core Intel Xeon processor ULV"},
+ {0xa8, "Dual-Core Intel Xeon processor 7100 Series"},
+ {0xa9, "Quad-Core Intel Xeon processor 5400 Series"},
+ {0xaa, "Quad-Core Intel Xeon processor"},
+ {0xab, "Dual-Core Intel Xeon processor 5200 Series"},
+ {0xac, "Dual-Core Intel Xeon processor 7200 Series"},
+ {0xad, "Quad-Core Intel Xeon processor 7300 Series"},
+ {0xae, "Quad-Core Intel Xeon processor 7400 Series"},
+ {0xaf, "Multi-Core Intel Xeon processor 7400 Series"},
+ {0xb0, "Pentium III Xeon processor"},
+ {0xb3, "Intel Xeon processor"},
+ {0xb5, "Intel Xeon processor MP"},
+ {0xd6, "Multi-Core Intel Xeon processor"},
+ {0xd7, "Dual-Core Intel Xeon processor 3xxx Series"},
+ {0xd8, "Quad-Core Intel Xeon processor 3xxx Series"},
+ {0xd9, "VIA Nano Processor Family"},
+ {0xda, "Dual-Core Intel Xeon processor 5xxx Series"},
+ {0xdb, "Quad-Core Intel Xeon processor 5xxx Series"},
+ {0xdd, "Dual-Core Intel Xeon processor 7xxx Series"},
+ {0xde, "Quad-Core Intel Xeon processor 7xxx Series"},
+ {0xdf, "Multi-Core Intel Xeon processor 7xxx Series"},
+ {0xe0, "Multi-Core Intel Xeon processor 3400 Series"}
+
+};
+
+// Definition follow smbios spec DSP0134 3.0.0
+static const std::string characterTable[16]{"Reserved",
+ "Unknown",
+ "64-bit Capable",
+ "Multi-Core",
+ "Hardware Thread",
+ "Execute Protection",
+ "Enhanced Virtualization",
+ "Power/Performance Control",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved",
+ "Reserved"};
+
+class Cpu : sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu>
+{
+ public:
+ Cpu() = delete;
+ Cpu(const Cpu &) = delete;
+ Cpu &operator=(const Cpu &) = delete;
+ Cpu(Cpu &&) = delete;
+ Cpu &operator=(Cpu &&) = delete;
+ ~Cpu() = default;
+
+ Cpu(sdbusplus::bus::bus &bus, const std::string &objPath,
+ const uint8_t &cpuId, struct ManagedDataRegion *region) :
+
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu>(
+ bus, objPath.c_str()),
+ cpuNum(cpuId), regionS(region)
+ {
+ processorInfoUpdate();
+ }
+
+ void processorInfoUpdate(void);
+
+ std::string processorSocket(std::string value) override;
+ std::string processorType(std::string value) override;
+ std::string processorFamily(std::string value) override;
+ std::string processorManufacturer(std::string value) override;
+ uint32_t processorId(uint32_t value) override;
+ std::string processorVersion(std::string value) override;
+ uint16_t processorMaxSpeed(uint16_t value) override;
+ std::string processorCharacteristics(std::string value) override;
+ uint16_t processorCoreCount(uint16_t value) override;
+ uint16_t processorThreadCount(uint16_t value) override;
+
+ private:
+ /** @brief Path of the group instance */
+ uint8_t cpuNum;
+
+ struct ManagedDataRegion *regionS;
+
+ struct ProcessorInfo
+ {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+ uint8_t socketDesignation;
+ uint8_t processorType;
+ uint8_t family;
+ uint8_t manufacturer;
+ uint64_t id;
+ uint8_t version;
+ uint8_t voltage;
+ uint16_t exClock;
+ uint16_t maxSpeed;
+ uint16_t currSpeed;
+ uint8_t status;
+ uint8_t upgrade;
+ uint16_t l1Handle;
+ uint16_t l2Handle;
+ uint16_t l3Handle;
+ uint8_t serialNum;
+ uint8_t assetTag;
+ uint8_t partNum;
+ uint8_t coreCount;
+ uint8_t coreEnable;
+ uint8_t threadCount;
+ uint16_t characteristics;
+ uint16_t family2;
+ uint16_t coreCount2;
+ uint16_t coreEnable2;
+ uint16_t threadCount2;
+ } __attribute__((packed));
+
+ void cpuSocket(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn);
+ void cpuType(uint8_t value);
+ void cpuFamily(uint8_t value);
+ void cpuManufacturer(uint8_t positionNum, uint8_t structLen,
+ uint8_t *dataIn);
+ void cpuVersion(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn);
+ void cpuCharacteristics(uint16_t value);
+};
+
+} // namespace smbios
+
+} // namespace phosphor
diff --git a/include/dimm.hpp b/include/dimm.hpp
new file mode 100644
index 0000000..caac229
--- /dev/null
+++ b/include/dimm.hpp
@@ -0,0 +1,142 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <xyz/openbmc_project/Inventory/Decorator/Asset/server.hpp>
+#include <xyz/openbmc_project/Inventory/Item/Dimm/server.hpp>
+#include "smbios.hpp"
+
+namespace phosphor
+{
+
+namespace smbios
+{
+
+using DeviceType =
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType;
+
+class Dimm
+ : sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm>,
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::Asset>
+
+{
+ public:
+ Dimm() = delete;
+ ~Dimm() = default;
+ Dimm(const Dimm &) = delete;
+ Dimm &operator=(const Dimm &) = delete;
+ Dimm(Dimm &&) = default;
+ Dimm &operator=(Dimm &&) = default;
+
+ Dimm(sdbusplus::bus::bus &bus, const std::string &objPath,
+ const uint8_t &dimmId, struct ManagedDataRegion *region) :
+
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm>(
+ bus, objPath.c_str()),
+ sdbusplus::server::object::object<
+ sdbusplus::xyz::openbmc_project::Inventory::Decorator::server::
+ Asset>(bus, objPath.c_str()),
+ dimmNum(dimmId), regionS(region)
+ {
+ memoryInfoUpdate();
+ }
+
+ void memoryInfoUpdate(void);
+
+ uint16_t memoryDataWidth(uint16_t value) override;
+ uint32_t memorySizeInKB(uint32_t value) override;
+ std::string memoryDeviceLocator(std::string value) override;
+ DeviceType memoryType(DeviceType value) override;
+ std::string memoryTypeDetail(std::string value) override;
+ uint16_t maxMemorySpeedInMhz(uint16_t value) override;
+ std::string manufacturer(std::string value) override;
+ std::string serialNumber(std::string value) override;
+ std::string partNumber(std::string value) override;
+ uint8_t memoryAttributes(uint8_t value) override;
+ uint16_t memoryConfiguredSpeedInMhz(uint16_t value) override;
+
+ private:
+ uint8_t dimmNum;
+
+ struct ManagedDataRegion *regionS;
+
+ void dimmSize(uint16_t size);
+ void dimmSizeExt(uint32_t size);
+ void dimmDeviceLocator(uint8_t positionNum, uint8_t structLen,
+ uint8_t *dataIn);
+ void dimmType(uint8_t type);
+ void dimmTypeDetail(uint16_t detail);
+ void dimmManufacturer(uint8_t positionNum, uint8_t structLen,
+ uint8_t *dataIn);
+ void dimmSerialNum(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn);
+ void dimmPartNum(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn);
+
+ struct MemoryInfo
+ {
+ uint8_t type;
+ uint8_t length;
+ uint16_t handle;
+ uint16_t phyArrayHandle;
+ uint16_t errInfoHandle;
+ uint16_t totalWidth;
+ uint16_t dataWidth;
+ uint16_t size;
+ uint8_t formFactor;
+ uint8_t deviceSet;
+ uint8_t deviceLocator;
+ uint8_t bankLocator;
+ uint8_t memoryType;
+ uint16_t typeDetail;
+ uint16_t speed;
+ uint8_t manufacturer;
+ uint8_t serialNum;
+ uint8_t assetTag;
+ uint8_t partNum;
+ uint8_t attributes;
+ uint32_t extendedSize;
+ uint16_t confClockSpeed;
+ } __attribute__((packed));
+};
+
+const std::map<uint8_t, DeviceType> dimmTypeTable = {
+ {0x1, DeviceType::Other}, {0x2, DeviceType::Unknown},
+ {0x3, DeviceType::DRAM}, {0x4, DeviceType::EDRAM},
+ {0x5, DeviceType::VRAM}, {0x6, DeviceType::SRAM},
+ {0x7, DeviceType::RAM}, {0x8, DeviceType::ROM},
+ {0x9, DeviceType::FLASH}, {0xa, DeviceType::EEPROM},
+ {0xb, DeviceType::FEPROM}, {0xc, DeviceType::EPROM},
+ {0xd, DeviceType::CDRAM}, {0xe, DeviceType::ThreeDRAM},
+ {0xf, DeviceType::SDRAM}, {0x10, DeviceType::DDR_SGRAM},
+ {0x11, DeviceType::RDRAM}, {0x12, DeviceType::DDR},
+ {0x13, DeviceType::DDR2}, {0x14, DeviceType::DDR2_SDRAM_FB_DIMM},
+ {0x18, DeviceType::DDR3}, {0x19, DeviceType::FBD2},
+ {0x1a, DeviceType::DDR4}, {0x1b, DeviceType::LPDDR_SDRAM},
+ {0x1c, DeviceType::LPDDR2_SDRAM}, {0x1d, DeviceType::LPDDR3_SDRAM},
+ {0x1e, DeviceType::LPDDR4_SDRAM}, {0x1f, DeviceType::Logical},
+ {0x20, DeviceType::HBM}, {0x21, DeviceType::HBM2}};
+
+const std::string detailTable[16]{
+ "Reserved", "Other", "Unknown", "Fast-paged",
+ "Static column", "Pseudo-static", "RAMBUS", "Synchronous",
+ "CMOS", "EDO", "Window DRAM", "Cache DRAM",
+ "Non-volatile", "Registered", "Unbuffered", "LRDIMM"};
+
+} // namespace smbios
+
+} // namespace phosphor
diff --git a/include/manager.hpp b/include/manager.hpp
new file mode 100644
index 0000000..2fb5a2f
--- /dev/null
+++ b/include/manager.hpp
@@ -0,0 +1,144 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+
+#include "smbios.hpp"
+#include "timer.hpp"
+#include "xyz/openbmc_project/Smbios/MDR_V1/server.hpp"
+#include <phosphor-logging/elog-errors.hpp>
+#include "cpu.hpp"
+#include "dimm.hpp"
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace phosphor
+{
+namespace smbios
+{
+
+static constexpr const char *mdrV1Path = "/xyz/openbmc_project/Smbios/MDR_V1";
+
+class MDR_V1 : sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1
+{
+ public:
+ MDR_V1() = delete;
+ MDR_V1(const MDR_V1 &) = delete;
+ MDR_V1 &operator=(const MDR_V1 &) = delete;
+ MDR_V1(MDR_V1 &&) = delete;
+ MDR_V1 &operator=(MDR_V1 &&) = delete;
+ ~MDR_V1() = default;
+
+ MDR_V1(sdbusplus::bus::bus &bus, const char *path,
+ struct ManagedDataRegion *region,
+ phosphor::watchdog::EventPtr event) :
+ sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1(bus, path),
+ bus(bus)
+ {
+ for (uint8_t index = 0; index < maxMdrIndex - 1; index++)
+ {
+ timers[index] = std::make_unique<phosphor::watchdog::Timer>(
+ event, index, [&](uint8_t index) {
+ return MDR_V1::regionUpdateTimeout(index);
+ });
+ }
+
+ std::copy(region, region + maxRegion, regionS);
+ if (access(smbiosPath, F_OK) == -1)
+ {
+ int flag = mkdir(smbiosPath, S_IRWXU);
+ if (flag != 0)
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "create folder failed for reading smbios file");
+ return;
+ }
+ }
+ for (int index = 0; index < maxMdrIndex - 1; index++)
+ {
+ bool status =
+ readDataFromFlash(reinterpret_cast<uint8_t *>(&regionS[index]),
+ regionS[index].flashName);
+ if (status)
+ {
+ restoreRegion = true;
+ regionComplete(index);
+ }
+ else
+ {
+ phosphor::logging::log<phosphor::logging::level::ERR>(
+ "read data from flash failed",
+ phosphor::logging::entry("REGION ID %d", index));
+ }
+ }
+ }
+
+ std::vector<uint8_t> regionStatus(uint8_t regionId) override;
+
+ void regionComplete(uint8_t regionId) override;
+
+ std::vector<uint8_t> regionRead(uint8_t regionId, uint8_t length,
+ uint16_t offset) override;
+
+ std::string regionWrite(std::vector<uint8_t> regionData) override;
+
+ uint8_t regionLock(uint8_t sessionId, uint8_t regionId, uint8_t lockPolicy,
+ uint16_t timeout) override;
+
+ void regionUpdateTimeout(uint8_t regionId);
+ uint8_t calcCRC8(const uint8_t regionId);
+
+ std::map<uint8_t, std::unique_ptr<phosphor::watchdog::Timer>> timers;
+
+ uint8_t regionId(uint8_t value) override;
+
+ uint8_t lockPolicy(uint8_t value) override;
+
+ uint8_t sessionId(uint8_t value) override;
+
+ uint16_t regionUsed(uint16_t value) override;
+
+ static constexpr uint8_t maxRegion = maxMdrIndex - 1;
+
+ struct ManagedDataRegion regionS[maxRegion];
+
+ private:
+ sdbusplus::bus::bus &bus;
+
+ bool restoreRegion = false;
+
+ bool storeDataToFlash(uint8_t *data, const char *file);
+ bool readDataFromFlash(uint8_t *data, const char *file);
+
+ uint8_t globalRegionId;
+
+ void regionUpdateCounter(uint8_t *count);
+
+ std::vector<std::unique_ptr<Dimm>> dimms;
+ std::vector<std::unique_ptr<Cpu>> cpus;
+
+ void systemInfoUpdate(void);
+
+ uint8_t getTotalDimmSlot(void);
+ uint8_t getTotalCpuSlot(void);
+
+ uint32_t getOsRunningTime(void);
+ uint8_t genMdrSessionId(void);
+};
+
+} // namespace smbios
+} // namespace phosphor
diff --git a/include/smbios.hpp b/include/smbios.hpp
new file mode 100644
index 0000000..390ac9a
--- /dev/null
+++ b/include/smbios.hpp
@@ -0,0 +1,208 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+
+#pragma once
+#include <map>
+
+static constexpr uint16_t mdrSmbiosSize = 32 * 1024; // 32K
+static constexpr uint16_t mdrAcpiTableSize = 32 * 1024; // 32K
+static constexpr uint16_t mdrMemMappingSize = 8 * 1024; // 8K
+static constexpr uint16_t mdrScsiBootSize = 8 * 1024; // 8K
+static constexpr uint16_t mdrNvmeSize = 1 * 1024; // 1K
+
+static constexpr uint16_t smbiosTableStorageSize = 0xffff;
+
+static constexpr uint8_t mdrVersion = 0x11; // MDR version 1.1
+
+static constexpr const char *smbiosPath = "/etc/smbios";
+static constexpr const char *mdrType1File = "/etc/smbios/smbios1";
+static constexpr const char *mdrType2File = "/etc/smbios/smbios2";
+static constexpr const char *mdrAcpiFile = "/etc/smbios/acpi";
+static constexpr const char *mdrMemMapFile = "/etc/smbios/memmapping";
+static constexpr const char *mdrScsiBootFile = "/etc/smbios/scsiboot";
+static constexpr const char *mdrNvmeFile = "/etc/smbios/nvme";
+
+typedef enum
+{
+ mdrNone = 0,
+ mdrSmbios = 1,
+ mdrAcpi = 2,
+ mdrMemMap = 3,
+ mdrScsiBoot = 4,
+ mdrNvme = 5,
+ maxMdrIndex = 6
+} MDRRegionIndex;
+
+typedef enum
+{
+ regionLockUnlocked = 0,
+ regionLockStrict,
+ regionLockPreemptable
+} MDRLockType;
+
+struct MDRState
+{
+ uint8_t mdrVersion;
+ uint8_t regionId;
+ uint8_t valid;
+ uint8_t updateCount;
+ uint8_t lockPolicy;
+ uint16_t regionLength;
+ uint16_t regionUsed;
+ uint8_t crc8;
+} __attribute__((packed));
+
+struct ManagedDataRegion
+{
+ const char *flashName;
+ uint8_t *regionData;
+ uint16_t msTimeout;
+ struct MDRState state;
+ uint8_t sessionId;
+} __attribute__((packed));
+
+struct BIOSInfo
+{
+ uint8_t biosVersion;
+};
+
+static constexpr const char *dimmPath =
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/dimm";
+
+static constexpr const char *cpuPath =
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu";
+
+static constexpr const char *systemPath =
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard/bios";
+
+typedef enum
+{
+ biosType = 0,
+ systemType = 1,
+ baseboardType = 2,
+ chassisType = 3,
+ processorsType = 4,
+ memoryControllerType = 5,
+ memoryModuleInformationType = 6,
+ cacheType = 7,
+ portConnectorType = 8,
+ systemSlots = 9,
+ onBoardDevicesType = 10,
+ oemStringsType = 11,
+ systemCconfigurationOptionsType = 12,
+ biosLanguageType = 13,
+ groupAssociatonsType = 14,
+ systemEventLogType = 15,
+ physicalMemoryArrayType = 16,
+ memoryDeviceType = 17,
+} SmbiosType;
+
+static constexpr uint8_t separateLen = 2;
+// To get the point of next smbios item
+static inline uint8_t *smbiosNextPtr(uint8_t *smbiosDataIn)
+{
+ if (smbiosDataIn == nullptr)
+ {
+ return nullptr;
+ }
+ uint8_t *smbiosData = smbiosDataIn + *(smbiosDataIn + 1);
+ int len = 0;
+ while ((*smbiosData | *(smbiosData + 1)) != 0)
+ {
+ smbiosData++;
+ len++;
+ if (len >= mdrSmbiosSize) // To avoid endless loop
+ {
+ return nullptr;
+ }
+ }
+ return smbiosData + separateLen;
+}
+
+// When first time run smbiosTypePtr, need to send the RegionS[].regionData
+// to smbiosDataIn
+static inline uint8_t *smbiosTypePtr(uint8_t *smbiosDataIn, uint8_t typeId)
+{
+ if (smbiosDataIn == nullptr)
+ {
+ return nullptr;
+ }
+ char *smbiosData = reinterpret_cast<char *>(smbiosDataIn);
+ while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
+ {
+ if (*smbiosData != typeId)
+ {
+ uint32_t len = *(smbiosData + 1);
+ smbiosData += len;
+ while ((*smbiosData != '\0') || (*(smbiosData + 1) != '\0'))
+ {
+ smbiosData++;
+ len++;
+ if (len >= mdrSmbiosSize) // To avoid endless loop
+ {
+ return nullptr;
+ }
+ }
+ smbiosData += separateLen;
+ continue;
+ }
+ return reinterpret_cast<uint8_t *>(smbiosData);
+ }
+ return nullptr;
+}
+
+static inline std::string positionToString(uint8_t positionNum,
+ uint8_t structLen, uint8_t *dataIn)
+{
+ if (dataIn == nullptr)
+ {
+ return "";
+ }
+ char *target;
+ uint8_t stringLen = 0;
+ uint16_t limit = mdrSmbiosSize; // set a limit to avoid endless loop
+
+ target = reinterpret_cast<char *>(dataIn + structLen);
+ for (uint8_t index = 1; index < positionNum; index++)
+ {
+ for (; *target != '\0'; target++)
+ {
+ limit--;
+ if (limit < 1)
+ {
+ return "";
+ }
+ }
+ target++;
+ if (*target == '\0')
+ {
+ return ""; // 0x00 0x00 means end of the entry.
+ }
+ }
+
+ std::string result = target;
+ return result;
+}
+
+// Find the specific string in smbios item
+static inline std::string seekString(uint8_t *smbiosDataIn, uint8_t stringOrder)
+{
+ if (smbiosDataIn == nullptr)
+ return "";
+ uint8_t len = *(smbiosDataIn + 1);
+
+ return positionToString(stringOrder, len, smbiosDataIn);
+}
diff --git a/include/timer.hpp b/include/timer.hpp
new file mode 100644
index 0000000..30c9879
--- /dev/null
+++ b/include/timer.hpp
@@ -0,0 +1,149 @@
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <chrono>
+#include <systemd/sd-event.h>
+namespace phosphor
+{
+namespace watchdog
+{
+
+/* Need a custom deleter for freeing up sd_event */
+struct EventDeleter
+{
+ void operator()(sd_event* event) const
+ {
+ event = sd_event_unref(event);
+ }
+};
+using EventPtr = std::shared_ptr<sd_event>;
+
+/* Need a custom deleter for freeing up sd_event_source */
+struct EventSourceDeleter
+{
+ void operator()(sd_event_source* eventSource) const
+ {
+ eventSource = sd_event_source_unref(eventSource);
+ }
+};
+using EventSourcePtr = std::unique_ptr<sd_event_source, EventSourceDeleter>;
+
+/** @class Timer
+ * @brief Manages starting timers and handling timeouts
+ */
+class Timer
+{
+ public:
+ Timer() = delete;
+ ~Timer() = default;
+ Timer(const Timer&) = delete;
+ Timer& operator=(const Timer&) = delete;
+ Timer(Timer&&) = delete;
+ Timer& operator=(Timer&&) = delete;
+
+ /** @brief Constructs timer object
+ *
+ * @param[in] event - sd_event unique pointer
+ * @param[in] userCallBack - Optional function callback
+ * for timer expiration
+ */
+ Timer(EventPtr event, uint8_t id,
+ std::function<void(uint8_t)> userCallBack = nullptr) :
+ event(event),
+ regionId(id), userCallBack(userCallBack)
+ {
+ // Initialize the timer
+ initialize();
+ }
+
+ void clearExpired(void)
+ {
+ expire = false;
+ }
+
+ /** @brief Tells whether the timer is expired or not */
+ inline auto expired() const
+ {
+ return expire;
+ }
+
+ /** @brief Returns the current Timer enablement type */
+ int getEnabled() const;
+
+ /** @brief Enables / disables the timer.
+ * <T> is an integral constant boolean
+ */
+ template <typename T> void setEnabled()
+ {
+ constexpr auto type = T::value ? SD_EVENT_ONESHOT : SD_EVENT_OFF;
+ setEnabled(type);
+ }
+
+ /** @brief Returns time remaining in usec before expiration
+ * which is an offset to current steady clock
+ */
+ std::chrono::microseconds getRemaining() const;
+
+ /** @brief Starts the timer with specified expiration value.
+ * std::steady_clock is used for base time.
+ *
+ * @param[in] usec - Microseconds from the current time
+ * before expiration.
+ *
+ * @return None.
+ *
+ * @error Throws exception
+ */
+ void start(std::chrono::microseconds usec);
+
+ /** @brief Gets the current time from steady clock */
+ static std::chrono::microseconds getCurrentTime();
+
+ private:
+ uint8_t regionId;
+
+ /** @brief Reference to sd_event unique pointer */
+ EventPtr event;
+
+ /** @brief event source */
+ EventSourcePtr eventSource;
+
+ /** @brief Set to true when the timeoutHandler is called into */
+ bool expire = false;
+
+ /** @brief Optional function to call on timer expiration
+ * This is called from timeout handler.
+ */
+ std::function<void(uint8_t)> userCallBack;
+
+ /** @brief Initializes the timer object with infinite
+ * expiration time and sets up the callback handler
+ *
+ * @return None.
+ *
+ * @error Throws exception
+ */
+ void initialize();
+
+ /** @brief Callback function when timer goes off
+ *
+ * @param[in] eventSource - Source of the event
+ * @param[in] usec - time in microseconds
+ * @param[in] userData - User data pointer
+ *
+ */
+ static int timeoutHandler(sd_event_source* eventSource, uint64_t usec,
+ void* userData);
+
+ /** @brief Enables / disables the timer
+ *
+ * @param[in] type - Timer type.
+ * This implementation uses only SD_EVENT_OFF
+ * and SD_EVENT_ONESHOT
+ */
+ void setEnabled(int type);
+};
+
+} // namespace watchdog
+} // namespace phosphor