From 613e5f0e6cc0c6e2a1e2774d81bc581035fd76f9 Mon Sep 17 00:00:00 2001 From: Nikita Kosenkov Date: Thu, 14 Jul 2022 18:12:57 +0300 Subject: Add smbios sources --- .clang-format | 84 ++++ .gitignore | 3 + CMakeLists.txt | 80 ++++ LICENSE | 201 ++++++++++ cmake-format.json | 12 + include/cpu.hpp | 172 ++++++++ include/dimm.hpp | 142 +++++++ include/manager.hpp | 144 +++++++ include/smbios.hpp | 208 ++++++++++ include/timer.hpp | 149 +++++++ src/cpu.cpp | 214 ++++++++++ src/dimm.cpp | 230 +++++++++++ src/manager.cpp | 475 +++++++++++++++++++++++ src/smbios-main.cpp | 96 +++++ src/timer.cpp | 145 +++++++ xyz/openbmc_project/Smbios/MDR_V1.errors.yaml | 6 + xyz/openbmc_project/Smbios/MDR_V1.interface.yaml | 116 ++++++ xyz/openbmc_project/Smbios/README.md | 21 + 18 files changed, 2498 insertions(+) create mode 100644 .clang-format create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 LICENSE create mode 100644 cmake-format.json create mode 100644 include/cpu.hpp create mode 100644 include/dimm.hpp create mode 100644 include/manager.hpp create mode 100644 include/smbios.hpp create mode 100644 include/timer.hpp create mode 100644 src/cpu.cpp create mode 100644 src/dimm.cpp create mode 100644 src/manager.cpp create mode 100644 src/smbios-main.cpp create mode 100644 src/timer.cpp create mode 100644 xyz/openbmc_project/Smbios/MDR_V1.errors.yaml create mode 100644 xyz/openbmc_project/Smbios/MDR_V1.interface.yaml create mode 100644 xyz/openbmc_project/Smbios/README.md diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..37469de --- /dev/null +++ b/.clang-format @@ -0,0 +1,84 @@ +--- +Language: Cpp +# BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlinesLeft: false +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeTernaryOperators: true +BreakConstructorInitializers: AfterColon +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: true +PointerAlignment: Left +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ] +IndentCaseLabels: true +IndentWidth: 4 +IndentWrappedFunctionNames: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Right +ReflowComments: true +SortIncludes: false +SpaceAfterCStyleCast: false +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..817e4b9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +entity-manager/out/* +*.idea +.vscode diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..767aac5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required (VERSION 3.2 FATAL_ERROR) +include (ExternalProject) +set (CMAKE_CXX_STANDARD 17) +set (CMAKE_CXX_STANDARD_REQUIRED ON) +set (CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH}) +set (DBUS_OBJECT_NAME "xyz/openbmc_project/Smbios/MDR_V1") +set (DBUS_INTF_NAME "xyz.openbmc_project.Smbios.MDR_V1") + +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") + +include_directories ( + ${CMAKE_CURRENT_SOURCE_DIR}/include/phosphor-dbus-interfaces +) +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include/GSL/include) +include_directories (${CMAKE_CURRENT_SOURCE_DIR}/include) +link_directories (${DBUSINTERFACE_LIBRARIES}) + +find_package (PkgConfig REQUIRED) +pkg_check_modules (SYSTEMD libsystemd REQUIRED) +include_directories (${SYSTEMD_INCLUDE_DIRS}) +link_directories (${SYSTEMD_LIBRARY_DIRS}) + +# import sdbusplus +find_package (PkgConfig REQUIRED) +pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED) +include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS}) +link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS}) + +# phosphor-dbus-interfaces +find_package (PkgConfig REQUIRED) +pkg_check_modules (DBUSINTERFACE phosphor-dbus-interfaces REQUIRED) +include_directories (${DBUSINTERFACE_INCLUDE_DIRS}) +link_directories (${DBUSINTERFACE_LIBRARY_DIRS}) + +set (SRC_FILES src/manager.cpp src/smbios-main.cpp src/timer.cpp src/cpu.cpp + src/dimm.cpp ${DBUS_OBJECT_NAME}/server.cpp ${DBUS_OBJECT_NAME}/error.cpp) + +include_directories (${CMAKE_CURRENT_BINARY_DIR}) + +find_package (PkgConfig REQUIRED) +pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED) +include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS}) +link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS}) +find_program (SDBUSPLUSPLUS sdbus++) + +add_custom_command (OUTPUT ${DBUS_OBJECT_NAME}/server.hpp + OUTPUT ${DBUS_OBJECT_NAME}/server.cpp + COMMAND mkdir -p ${DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} + interface server-header ${DBUS_INTF_NAME} > + ${DBUS_OBJECT_NAME}/server.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} + interface server-cpp ${DBUS_INTF_NAME} > + ${DBUS_OBJECT_NAME}/server.cpp + DEPENDS ${DBUS_OBJECT_NAME}.interface.yaml) +set_source_files_properties (${DBUS_OBJECT_NAME}/server.hpp + ${DBUS_OBJECT_NAME}/server.cpp PROPERTIES + GENERATED TRUE) + +add_custom_command (OUTPUT ${DBUS_OBJECT_NAME}/error.hpp + OUTPUT ${DBUS_OBJECT_NAME}/error.cpp + COMMAND mkdir -p ${DBUS_OBJECT_NAME} + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} + error exception-header ${DBUS_INTF_NAME} > + ${DBUS_OBJECT_NAME}/error.hpp + COMMAND ${SDBUSPLUSPLUS} -r ${CMAKE_CURRENT_SOURCE_DIR} + error exception-cpp ${DBUS_INTF_NAME} > + ${DBUS_OBJECT_NAME}/error.cpp + DEPENDS ${DBUS_OBJECT_NAME}.errors.yaml) +set_source_files_properties (${DBUS_OBJECT_NAME}/error.hpp + ${DBUS_OBJECT_NAME}/error.cpp PROPERTIES GENERATED + TRUE) + +add_executable (smbiosapp ${SRC_FILES}) +target_link_libraries (smbiosapp ${SYSTEMD_LIBRARIES}) +target_link_libraries (smbiosapp ${DBUSINTERFACE_LIBRARIES}) +target_link_libraries (smbiosapp ${SDBUSPLUSPLUS_LIBRARIES}) +target_link_libraries (smbiosapp phosphor_logging) + +install (TARGETS smbiosapp DESTINATION sbin) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..8dada3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/cmake-format.json b/cmake-format.json new file mode 100644 index 0000000..4a701ae --- /dev/null +++ b/cmake-format.json @@ -0,0 +1,12 @@ +{ + "enum_char": ".", + "line_ending": "unix", + "bullet_char": "*", + "max_subargs_per_line": 99, + "command_case": "lower", + "tab_size": 4, + "line_width": 80, + "separate_fn_name_with_space": true, + "dangle_parens": true, + "separate_ctrl_name_with_space": true +} 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 +#include "smbios.hpp" + +namespace phosphor +{ + +namespace smbios +{ + +// Definition follow smbios spec DSP0134 3.0.0 +static const std::map 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 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 +#include +#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 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 +#include "cpu.hpp" +#include "dimm.hpp" +#include +#include +#include + +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( + 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( + "create folder failed for reading smbios file"); + return; + } + } + for (int index = 0; index < maxMdrIndex - 1; index++) + { + bool status = + readDataFromFlash(reinterpret_cast(®ionS[index]), + regionS[index].flashName); + if (status) + { + restoreRegion = true; + regionComplete(index); + } + else + { + phosphor::logging::log( + "read data from flash failed", + phosphor::logging::entry("REGION ID %d", index)); + } + } + } + + std::vector regionStatus(uint8_t regionId) override; + + void regionComplete(uint8_t regionId) override; + + std::vector regionRead(uint8_t regionId, uint8_t length, + uint16_t offset) override; + + std::string regionWrite(std::vector 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> 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> dimms; + std::vector> 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 + +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(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(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(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 +#include +#include +#include +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; + +/* 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; + +/** @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 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. + * is an integral constant boolean + */ + template 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 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 diff --git a/src/cpu.cpp b/src/cpu.cpp new file mode 100644 index 0000000..a92d9e6 --- /dev/null +++ b/src/cpu.cpp @@ -0,0 +1,214 @@ +/* +// 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. +*/ + +#include "cpu.hpp" +#include "manager.hpp" +#include + +namespace phosphor +{ +namespace smbios +{ + +void Cpu::cpuSocket(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + processorSocket(result); +} + +std::string Cpu::processorSocket(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorSocket(value); +} + +void Cpu::cpuType(uint8_t value) +{ + std::map::const_iterator it = + cpuTypeTable.find(value); + if (it == cpuTypeTable.end()) + { + processorType("Unknown Processor Type"); + } + else + { + processorType(it->second); + } +} + +std::string Cpu::processorType(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorType(value); +} + +void Cpu::cpuFamily(uint8_t value) +{ + std::map::const_iterator it = familyTable.find(value); + if (it == familyTable.end()) + { + processorFamily("Unknown Processor Family"); + } + else + { + processorFamily(it->second); + } +} + +std::string Cpu::processorFamily(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorFamily(value); +} + +void Cpu::cpuManufacturer(uint8_t positionNum, uint8_t structLen, + uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + processorManufacturer(result); +} + +std::string Cpu::processorManufacturer(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorManufacturer(value); +} + +uint32_t Cpu::processorId(uint32_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorId(value); +} + +void Cpu::cpuVersion(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + processorVersion(result); +} + +std::string Cpu::processorVersion(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorVersion(value); +} + +uint16_t Cpu::processorMaxSpeed(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorMaxSpeed(value); +} + +void Cpu::cpuCharacteristics(uint16_t value) +{ + std::string result = ""; + for (uint8_t index = 0; index < (8 * sizeof(value)); index++) + { + if (value & 0x01) + { + result += characterTable[index]; + } + value >>= 1; + } + + processorCharacteristics(result); +} + +std::string Cpu::processorCharacteristics(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorCharacteristics(value); +} + +uint16_t Cpu::processorCoreCount(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorCoreCount(value); +} + +uint16_t Cpu::processorThreadCount(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Cpu:: + processorThreadCount(value); +} + +static constexpr uint8_t maxOldVersionCount = 0xff; +void Cpu::processorInfoUpdate(void) +{ + uint8_t *dataIn = regionS[0].regionData; + + dataIn = smbiosTypePtr(dataIn, processorsType); + if (dataIn == nullptr) + { + return; + } + + for (uint8_t index = 0; index < cpuNum; index++) + { + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + return; + } + dataIn = smbiosTypePtr(dataIn, processorsType); + if (dataIn == nullptr) + { + return; + } + } + + auto cpuInfo = reinterpret_cast(dataIn); + + cpuSocket(cpuInfo->socketDesignation, cpuInfo->length, + dataIn); // offset 4h + cpuType(cpuInfo->processorType); // offset 5h + cpuFamily(cpuInfo->family); // offset 6h + cpuManufacturer(cpuInfo->manufacturer, cpuInfo->length, + dataIn); // offset 7h + processorId(cpuInfo->id); // offset 8h + cpuVersion(cpuInfo->version, cpuInfo->length, dataIn); // offset 10h + processorMaxSpeed(cpuInfo->maxSpeed); // offset 14h + if (cpuInfo->coreCount < maxOldVersionCount) // offset 23h or 2Ah + { + processorCoreCount((uint16_t)cpuInfo->coreCount); + } + else + { + processorCoreCount(cpuInfo->coreCount2); + } + + if (cpuInfo->threadCount < maxOldVersionCount) // offset 25h or 2Eh) + { + processorThreadCount((uint16_t)cpuInfo->threadCount); + } + else + { + processorThreadCount(cpuInfo->threadCount2); + } + + cpuCharacteristics(cpuInfo->characteristics); // offset 26h +} + +} // namespace smbios +} // namespace phosphor diff --git a/src/dimm.cpp b/src/dimm.cpp new file mode 100644 index 0000000..346c701 --- /dev/null +++ b/src/dimm.cpp @@ -0,0 +1,230 @@ +/* +// 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. +*/ + +#include "dimm.hpp" +#include "manager.hpp" + +namespace phosphor +{ +namespace smbios +{ + +using DeviceType = + sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm::DeviceType; + +static constexpr uint16_t maxOldDimmSize = 0x7fff; +void Dimm::memoryInfoUpdate(void) +{ + uint8_t *dataIn = regionS[0].regionData; + + dataIn = smbiosTypePtr(dataIn, memoryDeviceType); + if (dataIn == nullptr) + { + return; + } + + for (uint8_t index = 0; index < dimmNum; index++) + { + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + return; + } + dataIn = smbiosTypePtr(dataIn, memoryDeviceType); + if (dataIn == nullptr) + { + return; + } + } + + auto memoryInfo = reinterpret_cast(dataIn); + + memoryDataWidth(memoryInfo->dataWidth); + + if (memoryInfo->size == maxOldDimmSize) + { + dimmSizeExt(memoryInfo->extendedSize); + } + else + { + dimmSize(memoryInfo->size); + } + + dimmDeviceLocator(memoryInfo->deviceLocator, memoryInfo->length, dataIn); + dimmType(memoryInfo->memoryType); + dimmTypeDetail(memoryInfo->typeDetail); + maxMemorySpeedInMhz(memoryInfo->speed); + dimmManufacturer(memoryInfo->manufacturer, memoryInfo->length, dataIn); + dimmSerialNum(memoryInfo->serialNum, memoryInfo->length, dataIn); + dimmPartNum(memoryInfo->partNum, memoryInfo->length, dataIn); + memoryAttributes(memoryInfo->attributes); + memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed); + + return; +} + +uint16_t Dimm::memoryDataWidth(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryDataWidth(value); +} + +static constexpr uint16_t baseNewVersionDimmSize = 0x8000; +static constexpr uint16_t dimmSizeUnit = 1024; +void Dimm::dimmSize(uint16_t size) +{ + uint32_t result = size & maxOldDimmSize; + if (0 == (size & baseNewVersionDimmSize)) + { + result = result * dimmSizeUnit; + } + memorySizeInKB(result); +} + +void Dimm::dimmSizeExt(uint32_t size) +{ + size = size * dimmSizeUnit; + memorySizeInKB(size); +} + +uint32_t Dimm::memorySizeInKB(uint32_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memorySizeInKB(value); +} + +void Dimm::dimmDeviceLocator(uint8_t positionNum, uint8_t structLen, + uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + memoryDeviceLocator(result); +} + +std::string Dimm::memoryDeviceLocator(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryDeviceLocator(value); +} + +void Dimm::dimmType(uint8_t type) +{ + std::map::const_iterator it = dimmTypeTable.find(type); + if (it == dimmTypeTable.end()) + { + memoryType(DeviceType::Unknown); + } + else + { + memoryType(it->second); + } +} + +DeviceType Dimm::memoryType(DeviceType value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryType(value); +} + +void Dimm::dimmTypeDetail(uint16_t detail) +{ + std::string result; + for (uint8_t index = 0; index < (8 * sizeof(detail)); index++) + { + if (detail & 0x01) + { + result += detailTable[index]; + } + detail >>= 1; + } + memoryTypeDetail(result); +} + +std::string Dimm::memoryTypeDetail(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryTypeDetail(value); +} + +uint16_t Dimm::maxMemorySpeedInMhz(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + maxMemorySpeedInMhz(value); +} + +void Dimm::dimmManufacturer(uint8_t positionNum, uint8_t structLen, + uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + manufacturer(result); +} + +std::string Dimm::manufacturer(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: + Asset::manufacturer(value); +} + +void Dimm::dimmSerialNum(uint8_t positionNum, uint8_t structLen, + uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + serialNumber(result); +} + +std::string Dimm::serialNumber(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: + Asset::serialNumber(value); +} + +void Dimm::dimmPartNum(uint8_t positionNum, uint8_t structLen, uint8_t *dataIn) +{ + std::string result; + + result = positionToString(positionNum, structLen, dataIn); + + partNumber(result); +} + +std::string Dimm::partNumber(std::string value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Decorator::server:: + Asset::partNumber(value); +} + +uint8_t Dimm::memoryAttributes(uint8_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryAttributes(value); +} + +uint16_t Dimm::memoryConfiguredSpeedInMhz(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Inventory::Item::server::Dimm:: + memoryConfiguredSpeedInMhz(value); +} + +} // namespace smbios +} // namespace phosphor diff --git a/src/manager.cpp b/src/manager.cpp new file mode 100644 index 0000000..c3bdf4a --- /dev/null +++ b/src/manager.cpp @@ -0,0 +1,475 @@ +/* +// 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. +*/ + +#include "manager.hpp" +#include +#include +#include "xyz/openbmc_project/Smbios/MDR_V1/error.hpp" +#include +#include +#include +#include + +namespace phosphor +{ +namespace smbios +{ + +void MDR_V1::regionUpdateTimeout(uint8_t u8Data) +{ + uint8_t regionId = u8Data; + if ((regionId == 0) || (regionId >= maxMdrIndex)) + { + phosphor::logging::log( + "timeout callback failure - region Id invalid"); + return; + } + regionId--; + + // TODO: Create a SEL Log + + // unlock the region + if (regionS[regionId].state.lockPolicy != regionLockUnlocked) + { + regionS[regionId].state.valid = false; + regionUpdateCounter(&(regionS[regionId].state.updateCount)); + regionS[regionId].sessionId = 0xFF; + regionS[regionId].state.lockPolicy = regionLockUnlocked; + regionS[regionId].state.regionUsed = 0; + } // If locked +} + +std::vector MDR_V1::regionStatus(uint8_t regionId) +{ + uint8_t *state; + std::vector result; + if (regionId >= maxRegion) + { + phosphor::logging::log( + "region status error - invalid regionId"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return result; + } + state = &(regionS[regionId].state.mdrVersion); + + for (int index = 0; index < sizeof(struct MDRState); index++) + { + result.push_back(state[index]); + } + + return result; +} + +static constexpr int msb = 0x8000; +static constexpr uint32_t polynomial = 0x1070; +uint8_t MDR_V1::calcCRC8(const uint8_t regionId) +{ + uint8_t crc = 0; + + for (int count = 0; count < regionS[regionId].state.regionUsed; count++) + { + int data = ((crc ^ regionS[regionId].regionData[count]) << 8); + for (int index = 0; index < 8; index++) + { + if (data & msb) + { + data = (data ^ (polynomial << 3)); + } + data <<= 1; + } + crc = (data >> 8); + } + + return crc; +} + +uint8_t MDR_V1::getTotalDimmSlot() +{ + uint8_t *dataIn = regionS[0].regionData; + uint8_t num = 0; + + if (dataIn == nullptr) + { + phosphor::logging::log( + "get dimm total slot failed - no region data"); + return 0; + } + + int limit = 0xff; + while (limit > 0) + { + dataIn = smbiosTypePtr(dataIn, memoryDeviceType); + if (dataIn == nullptr) + { + break; + } + num++; + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + break; + } + limit--; + } + + return num; +} + +constexpr int limitEntryLen = 0xff; +uint8_t MDR_V1::getTotalCpuSlot() +{ + uint8_t *dataIn = regionS[0].regionData; + uint8_t num = 0; + + if (dataIn == nullptr) + { + phosphor::logging::log( + "get cpu total slot failed - no region data"); + return 0; + } + + int limit = limitEntryLen; + while (limit > 0) + { + dataIn = smbiosTypePtr(dataIn, processorsType); + if (dataIn == nullptr) + { + break; + } + num++; + dataIn = smbiosNextPtr(dataIn); + if (dataIn == nullptr) + { + break; + } + limit--; + } + + return num; +} + +void MDR_V1::systemInfoUpdate() +{ + uint8_t num = 0; + std::string path; + + num = getTotalDimmSlot(); + + // Clear all dimm cpu interface first + std::vector>().swap(dimms); + std::vector>().swap(cpus); + + for (int index = 0; index < num; index++) + { + path = dimmPath + std::to_string(index); + dimms.emplace_back(std::make_unique( + bus, path, index, ®ionS[0])); + } + + num = 0; + num = getTotalCpuSlot(); + + for (int index = 0; index < num; index++) + { + path = cpuPath + std::to_string(index); + cpus.emplace_back(std::make_unique( + bus, path, index, ®ionS[0])); + } +} + +bool MDR_V1::readDataFromFlash(uint8_t *data, const char *file) +{ + std::ifstream filePtr(file, std::ios_base::binary); + if (!filePtr.good()) + { + phosphor::logging::log( + "Read data from flash error - Open MDRV1 table file failure"); + return false; + } + filePtr.clear(); + filePtr.seekg(0, std::ios_base::beg); + ManagedDataRegion *pRegionS = (ManagedDataRegion *)data; + filePtr.read(reinterpret_cast(&(pRegionS->state)), + sizeof(MDRState)); + filePtr.read(reinterpret_cast(pRegionS->regionData), + (pRegionS->state.regionLength < smbiosTableStorageSize + ? pRegionS->state.regionLength + : smbiosTableStorageSize)); + return true; +} + +bool MDR_V1::storeDataToFlash(uint8_t *data, const char *file) +{ + std::ofstream filePtr(file, std::ios_base::binary); + if (!filePtr.good()) + { + phosphor::logging::log( + "Write data from flash error - Open MDRV1 table file failure"); + return false; + } + + filePtr.clear(); + filePtr.seekp(0, std::ios_base::beg); + ManagedDataRegion *pRegionS = (ManagedDataRegion *)data; + + filePtr.write(reinterpret_cast(&(pRegionS->state)), + sizeof(MDRState)); + filePtr.write(reinterpret_cast(pRegionS->regionData), + pRegionS->state.regionLength); + + return true; +} + +void MDR_V1::regionComplete(uint8_t regionId) +{ + uint8_t tempRegionId = 0; + uint8_t tempUpdateCount = 0; + + if (regionId >= maxRegion) + { + phosphor::logging::log( + "region complete failed - invalid regionId"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return; + } + + regionS[regionId].state.valid = true; + regionS[regionId].state.lockPolicy = regionLockUnlocked; + regionS[regionId].sessionId = 0; + regionS[regionId].state.crc8 = calcCRC8(regionId); + tempRegionId = regionS[regionId].state.regionId; + tempUpdateCount = regionS[regionId].state.updateCount; + + lockPolicy(regionS[regionId].state.lockPolicy); + sessionId(regionS[regionId].sessionId); + + timers[regionId]->setEnabled(); + + // TODO: Create a SEL Log + systemInfoUpdate(); // Update CPU and DIMM information + + // If BMC try to restore region data from BMC flash + // no need to store the data to flash again. + if (restoreRegion) + { + restoreRegion = false; + return; + } + + if (access(smbiosPath, F_OK) == -1) + { + if (0 != mkdir(smbiosPath, S_IRWXU)) + { + phosphor::logging::log( + "create folder failed for writting smbios file"); + return; + } + } + if (!storeDataToFlash(reinterpret_cast(®ionS[regionId]), + regionS[regionId].flashName)) + { + phosphor::logging::log( + "Store data to flash failed"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error::IOError(); + } +} + +std::vector MDR_V1::regionRead(uint8_t regionId, uint8_t length, + uint16_t offset) +{ + std::vector result; + + if (regionId >= maxRegion) + { + phosphor::logging::log( + "region read failed - invalid regionId"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return result; + } + if (regionS[regionId].state.regionUsed < offset + length) + { + phosphor::logging::log( + "region read failed - invalid offset/length"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return result; + } + + result.push_back(length); + result.push_back(regionS[regionId].state.updateCount); + for (uint16_t index = 0; index < length; index++) + { + result.push_back(regionS[regionId].regionData[index + offset]); + } + return result; +} + +std::string MDR_V1::regionWrite(std::vector wData) +{ + uint8_t regionId = wData[0]; + if (regionId >= maxRegion) + { + phosphor::logging::log( + "region write failed - invalid regionId"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return "failed"; + } + uint8_t length = wData[1]; + uint16_t offset = wData[3] << 8 | (wData[2]); + uint8_t *dest; + std::vector::iterator iter; + std::chrono::microseconds usec = + std::chrono::duration_cast( + std::chrono::milliseconds(regionS[regionId].msTimeout)); + + dest = &(regionS[regionId].regionData[offset]); + + iter = wData.begin(); + iter += 4; + std::copy(iter, wData.end(), dest); + regionS[regionId].state.regionUsed = std::max( + regionS[regionId].state.regionUsed, (uint16_t)(offset + length)); + regionUsed(regionS[regionId].state.regionUsed); + timers[regionId]->start(usec); + timers[regionId]->setEnabled(); + + return "Success"; +} + +uint32_t MDR_V1::getOsRunningTime(void) +{ + int s32Result; + struct timespec sTime; + + s32Result = clock_gettime(CLOCK_MONOTONIC, &sTime); + if (s32Result != 0) + { + return 0; + } + + return (sTime.tv_sec); +} + +uint8_t MDR_V1::genMdrSessionId(void) +{ + uint32_t now = 0; + uint8_t id = 0; + + do + { + now = getOsRunningTime(); + id = (uint8_t)(now ^ (now >> 8) ^ (now >> 16) ^ (now >> 24)); + } while ((id == 0x00) || (id == 0xFF)); + + return id; +} + +void MDR_V1::regionUpdateCounter(uint8_t *count) +{ + if (count != nullptr) + { + if (++(*count) == 0) + { + (*count)++; + } + } +} + +uint8_t MDR_V1::regionLock(uint8_t u8SessionId, uint8_t regionId, + uint8_t u8LockPolicy, uint16_t msTimeout) +{ + uint8_t reqSession; + + if (regionId >= maxRegion) + { + phosphor::logging::log( + "region lock failed - invalid regionId"); + throw sdbusplus::xyz::openbmc_project::Smbios::MDR_V1::Error:: + InvalidParameter(); + return 0; + } + + if (u8LockPolicy != regionLockUnlocked) + { + reqSession = genMdrSessionId(); + } + else + { + reqSession = 0; + } + + regionS[regionId].state.valid = false; + regionUpdateCounter(&(regionS[regionId].state.updateCount)); + regionS[regionId].sessionId = reqSession; + regionS[regionId].state.lockPolicy = u8LockPolicy; + regionS[regionId].state.regionUsed = 0; + regionS[regionId].msTimeout = msTimeout; + regionUsed(regionS[regionId].state.regionUsed); + lockPolicy(regionS[regionId].state.lockPolicy); + sessionId(regionS[regionId].sessionId); + + if (regionS[regionId].msTimeout != 0) + { + auto usec = std::chrono::duration_cast( + std::chrono::milliseconds(1000)); + timers[regionId]->start(usec); + timers[regionId]->setEnabled(); + } + + return regionS[regionId].sessionId; +} + +uint8_t MDR_V1::regionId(uint8_t value) +{ + globalRegionId = value; + + sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::lockPolicy( + regionS[value].state.lockPolicy); + + sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::regionUsed( + regionS[value].state.regionUsed); + + sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::sessionId( + regionS[value].sessionId); + + return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::regionId( + value); +} + +uint8_t MDR_V1::lockPolicy(uint8_t value) +{ + return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::lockPolicy( + value); +} + +uint16_t MDR_V1::regionUsed(uint16_t value) +{ + return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::regionUsed( + value); +} + +uint8_t MDR_V1::sessionId(uint8_t value) +{ + return sdbusplus::xyz::openbmc_project::Smbios::server::MDR_V1::sessionId( + value); +} + +} // namespace smbios +} // namespace phosphor diff --git a/src/smbios-main.cpp b/src/smbios-main.cpp new file mode 100644 index 0000000..532163c --- /dev/null +++ b/src/smbios-main.cpp @@ -0,0 +1,96 @@ +/* +// 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. +*/ + +#include "manager.hpp" +#include "smbios.hpp" +#include +#include +#include + +uint8_t mdrSmBiosData[mdrSmbiosSize]; +uint8_t mdrAcpiTable[mdrAcpiTableSize]; +uint8_t mdrMemoryMapping[mdrMemMappingSize]; +uint8_t mdrSCSIBoot[mdrScsiBootSize]; +uint8_t mdrNvmeData[mdrNvmeSize]; + +struct ManagedDataRegion regionS[] = { + // SMBIOS table - matching the regionID order + {mdrType1File, + mdrSmBiosData, + 0, + {mdrVersion, mdrSmbios, false, 0, regionLockUnlocked, mdrSmbiosSize, 0, 0}, + 0}, + + // ACPI tables - matching the regionID order + {mdrAcpiFile, + mdrAcpiTable, + 0, + {mdrVersion, mdrAcpi, false, 0, regionLockUnlocked, 0, mdrAcpiTableSize, + 0}, + 0}, + + // Memory Mapping table - matching the regionID order + {mdrMemMapFile, + mdrMemoryMapping, + 0, + {mdrVersion, mdrMemMap, false, 0, regionLockUnlocked, mdrMemMappingSize, 0, + 0}, + 0}, + + {mdrScsiBootFile, + mdrSCSIBoot, + 0, + {mdrVersion, mdrScsiBoot, false, 0, regionLockUnlocked, mdrScsiBootSize, 0, + 0}, + 0}, + + // NVMe table - matching the regionID order + {mdrNvmeFile, + mdrNvmeData, + 0, + {mdrVersion, mdrNvme, false, 0, regionLockUnlocked, mdrNvmeSize, 0, 0}, + 0}, +}; + +int main(void) +{ + sd_event *events = nullptr; + sd_event_default(&events); + + sdbusplus::bus::bus bus = sdbusplus::bus::new_default(); + sdbusplus::server::manager::manager objManager(bus, "/xyz/openbmc_project"); + phosphor::watchdog::EventPtr eventP{events, + phosphor::watchdog::EventDeleter()}; + bus.attach_event(events, SD_EVENT_PRIORITY_NORMAL); + bus.request_name("xyz.openbmc_project.Smbios.MDR_V1"); + + phosphor::smbios::MDR_V1 mdrV1(bus, phosphor::smbios::mdrV1Path, regionS, + eventP); + + while (true) + { + int r = sd_event_run(events, (uint64_t)-1); + if (r < 0) + { + phosphor::logging::log( + "Failure processing request", + phosphor::logging::entry("errno=0x%X", -r)); + return -1; + } + } + + return 0; +} diff --git a/src/timer.cpp b/src/timer.cpp new file mode 100644 index 0000000..46fa022 --- /dev/null +++ b/src/timer.cpp @@ -0,0 +1,145 @@ +/** + * Copyright © 2017 IBM 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. + */ +#include "timer.hpp" +#include +#include +#include +#include +#include +#include +namespace phosphor +{ +namespace watchdog +{ + +// For throwing exception +using namespace phosphor::logging; +using InternalFailure = + sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; + +// Initializes the timer object +void Timer::initialize() +{ + // This can not be called more than once. + if (eventSource.get()) + { + log("Timer already initialized"); + elog(); + } + + // Add infinite expiration time + decltype(eventSource.get()) sourcePtr = nullptr; + auto r = sd_event_add_time(event.get(), &sourcePtr, + CLOCK_MONOTONIC, // Time base + UINT64_MAX, // Expire time - way long time + 0, // Use default event accuracy + timeoutHandler, // Callback handler on timeout + this); // User data + eventSource.reset(sourcePtr); + + if (r < 0) + { + log("Timer initialization failed"); + elog(); + } + + // Disable the timer for now + setEnabled(); +} + +// callback handler on timeout +int Timer::timeoutHandler(sd_event_source* eventSource, uint64_t usec, + void* userData) +{ + using namespace phosphor::logging; + + auto timer = static_cast(userData); + timer->expire = true; + + // Call an optional callback function + if (timer->userCallBack) + { + timer->userCallBack(timer->regionId); + } + return 0; +} + +// Gets the time from steady_clock +std::chrono::microseconds Timer::getCurrentTime() +{ + using namespace std::chrono; + auto usec = steady_clock::now().time_since_epoch(); + return duration_cast(usec); +} + +// Sets the expiration time and arms the timer +void Timer::start(std::chrono::microseconds usec) +{ + using namespace std::chrono; + + // Get the current MONOTONIC time and add the delta + auto expireTime = getCurrentTime() + usec; + + // Set the time + auto r = sd_event_source_set_time(eventSource.get(), expireTime.count()); + if (r < 0) + { + log( + "Error setting the expiration time", + entry("MSEC=%llu", duration_cast(usec).count())); + elog(); + } +} + +// Returns current timer enablement type +int Timer::getEnabled() const +{ + int enabled{}; + auto r = sd_event_source_get_enabled(eventSource.get(), &enabled); + if (r < 0) + { + log("Error geting current timer type enablement state"); + elog(); + } + return enabled; +} + +// Enables / disables the timer +void Timer::setEnabled(int type) +{ + auto r = sd_event_source_set_enabled(eventSource.get(), type); + if (r < 0) + { + log("Error setting the timer type", entry("TYPE=%d", type)); + elog(); + } +} + +// Returns time remaining before expiration +std::chrono::microseconds Timer::getRemaining() const +{ + uint64_t next = 0; + auto r = sd_event_source_get_time(eventSource.get(), &next); + if (r < 0) + { + log("Error fetching remaining time to expire"); + elog(); + } + return std::chrono::microseconds(next); +} + +} // namespace watchdog +} // namespace phosphor diff --git a/xyz/openbmc_project/Smbios/MDR_V1.errors.yaml b/xyz/openbmc_project/Smbios/MDR_V1.errors.yaml new file mode 100644 index 0000000..5554a10 --- /dev/null +++ b/xyz/openbmc_project/Smbios/MDR_V1.errors.yaml @@ -0,0 +1,6 @@ +- name: InvalidParameter + description: > + An invalid parameter was attempted. +- name: IOError + description: > + An IO Error happened. diff --git a/xyz/openbmc_project/Smbios/MDR_V1.interface.yaml b/xyz/openbmc_project/Smbios/MDR_V1.interface.yaml new file mode 100644 index 0000000..5b46ebf --- /dev/null +++ b/xyz/openbmc_project/Smbios/MDR_V1.interface.yaml @@ -0,0 +1,116 @@ +description: > + smbios MDR V1 service +methods: + - name: RegionStatus + description: > + Get the region status with the given region ID + parameters: + - name: regionId + type: byte + description: > + region ID of Regions. + returns: + - name: status + type: array[byte] + description: > + The result of region status. + errors: + - self.Error.InvalidParameter + + - name: RegionComplete + description: > + Set complete status to region + parameters: + - name: regionId + type: byte + description: + region ID of Regions. + errors: + - self.Error.InvalidParameter + - self.Error.IOError + + - name: RegionRead + description: > + Read Region Data from BMC Memory + parameters: + - name: regionId + type: byte + description: > + region ID of Regions. + - name: length + type: byte + description: > + length of read data + - name: offset + type: uint16 + description: > + offset of read data + returns: + - name: regionData + type: array[byte] + description: > + region data user want to read. + errors: + - self.Error.InvalidParameter + + - name: RegionWrite + description: > + Write Region Data to BMC Memory + parameters: + - name: regionData + type: array[byte] + description: > + Data need to write to memory + returns: + - name: status + type: string + description: > + The status of the write function + errors: + - self.Error.InvalidParameter + + - name: RegionLock + description: > + Lock Region + parameters: + - name: sessionId + type: byte + description: > + Session ID + - name: regionId + type: byte + description: > + Region ID + - name: lockPolicy + type: byte + description: > + The policy to lock region + - name: timeout + type: uint16 + description: > + Timeout when try to lock region + returns: + - name: returnSessionId + type: byte + description: > + return the lock session ID + errors: + - self.Error.InvalidParameter + +properties: + - name: RegionId + type: byte + description: > + ID of Region + - name: SessionId + type: byte + description: > + ID of session + - name: LockPolicy + type: byte + description: > + The policy of the lock + - name: RegionUsed + type: uint16 + description: > + If the region is used or not diff --git a/xyz/openbmc_project/Smbios/README.md b/xyz/openbmc_project/Smbios/README.md new file mode 100644 index 0000000..24c3871 --- /dev/null +++ b/xyz/openbmc_project/Smbios/README.md @@ -0,0 +1,21 @@ +# SMBIOS MDR V1 + +## Overview +SMBIOS MDR V1 service exposes D-Bus methods for SMBIOS Version 1 operations. + +### SMBIOS MDR V1 Interface +SMBIOS MDR V1 interface `xyz.openbmc_project.Smbios.MDR_V1` provides following +methods. +#### methods +* RegionStatus - Get the region status with the given region ID. +* RegionComplete - Set complete status to region. +* RegionRead - Read Region Data from BMC Memory. +* RegionWrite - Write Region Data to BMC Memory. +* RegionLock - Lock Region. + +#### properties +* RegionID - ID of Region, default: 0. +* SessionID - ID of session, default: 0. +* LockPolicy - The policy of the lock, 0 means unlocked, 1 means strict locked, +2 means preemptable locked. +* RegionUsed - If the region is used or not, default: 0. -- cgit v1.2.3