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