diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/cpu.hpp | 172 | ||||
-rw-r--r-- | include/dimm.hpp | 142 | ||||
-rw-r--r-- | include/manager.hpp | 144 | ||||
-rw-r--r-- | include/smbios.hpp | 208 | ||||
-rw-r--r-- | include/timer.hpp | 149 |
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 *>(®ionS[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 |