From 243c130a919c7037b5edd3a8097317340796ce85 Mon Sep 17 00:00:00 2001 From: "Jason M. Bills" Date: Thu, 5 Dec 2019 13:29:56 -0800 Subject: Update to internal 2019-12-05 Signed-off-by: Jason M. Bills --- .../recipes-phosphor/datetime/pch-time-sync.bb | 26 ++ .../datetime/pch-time-sync/.clang-format | 98 ++++++++ .../datetime/pch-time-sync/CMakeLists.txt | 40 ++++ .../datetime/pch-time-sync/cmake-format.json | 12 + .../datetime/pch-time-sync/pch-time-sync.cpp | 265 +++++++++++++++++++++ .../datetime/pch-time-sync/pch-time-sync.service | 13 + 6 files changed, 454 insertions(+) create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp create mode 100644 meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/datetime') diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb new file mode 100644 index 000000000..089aaf59f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync.bb @@ -0,0 +1,26 @@ + +SUMMARY = "PCH BMC time service" +DESCRIPTION = "This service will read date/time from PCH device periodically, and set the BMC system time accordingly" + +SRC_URI = "\ + file://CMakeLists.txt \ + file://pch-time-sync.cpp \ + " +PV = "0.1" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${INTELBASE}/COPYING.apache-2.0;md5=34400b68072d710fecd0a2940a0d1658" + +S = "${WORKDIR}" + +SYSTEMD_SERVICE_${PN} = "pch-time-sync.service" + +inherit cmake +inherit obmc-phosphor-systemd + +DEPENDS += " \ + sdbusplus \ + phosphor-logging \ + boost \ + i2c-tools \ + " diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format new file mode 100644 index 000000000..dd2770837 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/.clang-format @@ -0,0 +1,98 @@ +--- +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 ] +IncludeBlocks: Regroup +IncludeCategories: + - Regex: '^[<"](gtest|gmock)' + Priority: 5 + - Regex: '^"config.h"' + Priority: -1 + - Regex: '^".*\.hpp"' + Priority: 1 + - Regex: '^<.*\.h>' + Priority: 2 + - Regex: '^<.*' + Priority: 3 + - Regex: '.*' + Priority: 4 +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: true +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/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt new file mode 100644 index 000000000..a4cf8155f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required (VERSION 3.5 FATAL_ERROR) +project (pch-time-sync CXX) +set (CMAKE_CXX_STANDARD 17) +set (CMAKE_CXX_STANDARD_REQUIRED ON) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti") +set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-rtti") + +include_directories (${CMAKE_CURRENT_SOURCE_DIR}) + +# boost support +find_package (Boost REQUIRED) +# pkg_check_modules(Boost boost REQUIRED) +include_directories (${Boost_INCLUDE_DIRS}) +add_definitions (-DBOOST_ERROR_CODE_HEADER_ONLY) +add_definitions (-DBOOST_SYSTEM_NO_DEPRECATED) +add_definitions (-DBOOST_ALL_NO_LIB) +add_definitions (-DBOOST_NO_RTTI) +add_definitions (-DBOOST_NO_TYPEID) +add_definitions (-DBOOST_ASIO_DISABLE_THREADS) + +# import sdbusplus +find_package (PkgConfig REQUIRED) +pkg_check_modules (SDBUSPLUSPLUS sdbusplus REQUIRED) +include_directories (${SDBUSPLUSPLUS_INCLUDE_DIRS}) +link_directories (${SDBUSPLUSPLUS_LIBRARY_DIRS}) + +# import phosphor-logging +find_package (PkgConfig REQUIRED) +pkg_check_modules (LOGGING phosphor-logging REQUIRED) +include_directories (${LOGGING_INCLUDE_DIRS}) +link_directories (${LOGGING_LIBRARY_DIRS}) + +add_executable (pch-time-sync pch-time-sync.cpp) + +target_link_libraries (${PROJECT_NAME} ${Boost_LIBRARIES}) +target_link_libraries (${PROJECT_NAME} ${SDBUSPLUSPLUS_LIBRARIES} + phosphor_logging) +target_link_libraries (${PROJECT_NAME} i2c) + +install (TARGETS pch-time-sync DESTINATION bin) diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/cmake-format.json new file mode 100644 index 000000000..583c255a3 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/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 +} \ No newline at end of file diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp new file mode 100644 index 000000000..0c1014589 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.cpp @@ -0,0 +1,265 @@ +/* Copyright 2019 Intel + * + * 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 + +#include +#include +#include +#include +#include +extern "C" { +#include +#include +} + +static constexpr uint32_t syncIntervalNormalMS = 60000; +static constexpr uint32_t syncIntervalFastMS = (syncIntervalNormalMS / 2); + +static uint32_t syncIntervalMS = syncIntervalNormalMS; + +// will update bmc time if the time difference beyond this value +static constexpr uint8_t timeDiffAllowedSecond = 1; + +static inline uint8_t bcd2Decimal(uint8_t hex) +{ + uint8_t dec = ((hex & 0xF0) >> 4) * 10 + (hex & 0x0F); + return dec; +} + +class I2CFile +{ + private: + int fd = -1; + + public: + I2CFile(const int& i2cBus, const int& slaveAddr, const int& flags) + { + std::string i2cDev = "/dev/i2c-" + std::to_string(i2cBus); + + fd = open(i2cDev.c_str(), flags); + if (fd < 0) + { + throw std::runtime_error("Unable to open i2c device."); + } + + if (ioctl(fd, I2C_SLAVE_FORCE, slaveAddr) < 0) + { + close(fd); + fd = -1; + throw std::runtime_error("Unable to set i2c slave address."); + } + } + + uint8_t i2cReadByteData(const uint8_t& offset) + { + int ret = i2c_smbus_read_byte_data(fd, offset); + + if (ret < 0) + { + throw std::runtime_error("i2c read failed"); + } + return static_cast(ret); + } + + ~I2CFile() + { + if (!(fd < 0)) + { + close(fd); + } + } +}; + +class PCHSync +{ + private: + bool getPCHDate(uint8_t& year, uint8_t& month, uint8_t& day, uint8_t& hour, + uint8_t& minute, uint8_t& second) + { + try + { + constexpr uint8_t pchDevI2CBusNumber = 0x03; + constexpr uint8_t pchDevI2CSlaveAddress = 0x44; + constexpr uint8_t pchDevRegRTCYear = 0x0f; + constexpr uint8_t pchDevRegRTCMonth = 0x0e; + constexpr uint8_t pchDevRegRTCDay = 0x0d; + constexpr uint8_t pchDevRegRTCHour = 0x0b; + constexpr uint8_t pchDevRegRTCMinute = 0x0a; + constexpr uint8_t pchDevRegRTCSecond = 0x09; + I2CFile pchDev(pchDevI2CBusNumber, pchDevI2CSlaveAddress, + O_RDWR | O_CLOEXEC); + year = pchDev.i2cReadByteData(pchDevRegRTCYear); + year = bcd2Decimal(year); + if (year > 99) + { + return false; + } + + month = pchDev.i2cReadByteData(pchDevRegRTCMonth); + month = bcd2Decimal(month); + if ((month < 1) || (month > 12)) + { + return false; + } + + day = pchDev.i2cReadByteData(pchDevRegRTCDay); + day = bcd2Decimal(day); + if ((day < 1) || (day > 31)) + { + return false; + } + + hour = pchDev.i2cReadByteData(pchDevRegRTCHour); + hour = bcd2Decimal(hour); + if (hour >= 24) + { + return false; + } + + minute = pchDev.i2cReadByteData(pchDevRegRTCMinute); + minute = bcd2Decimal(minute); + if (minute >= 60) + { + return false; + } + + second = pchDev.i2cReadByteData(pchDevRegRTCSecond); + second = bcd2Decimal(second); + if (second >= 60) + { + return false; + } + } + catch (const std::exception& e) + { + return false; + } + + return true; + } + + bool getSystemTime(time_t& timeSeconds) + { + struct timespec sTime = {0}; + int ret = 0; + + ret = clock_gettime(CLOCK_REALTIME, &sTime); + + if (ret != 0) + { + return false; + } + timeSeconds = sTime.tv_sec; + return true; + } + + bool setSystemTime(uint32_t timeSeconds) + { + struct timespec sTime = {0}; + int ret = 0; + + sTime.tv_sec = timeSeconds; + sTime.tv_nsec = 0; + + ret = clock_settime(CLOCK_REALTIME, &sTime); + + return (ret == 0); + } + + bool updateBMCTime() + { + int ret = 0; + time_t BMCTimeSeconds = 0; + time_t PCHTimeSeconds = 0; + struct tm tm = {0}; + + // get PCH and system time + if (!getPCHDate(year, month, day, hour, minute, second)) + { + return false; + }; + + if (!getSystemTime(BMCTimeSeconds)) + { + return false; + } + + std::string dateString = + "20" + std::to_string(year) + "-" + std::to_string(month) + "-" + + std::to_string(day) + " " + std::to_string(hour) + ":" + + std::to_string(minute) + ":" + std::to_string(second); + + strptime(dateString.c_str(), "%Y-%m-%d %H:%M:%S", &tm); + + PCHTimeSeconds = mktime(&tm); + if (PCHTimeSeconds == -1) + { + return false; + } + + if (std::abs(PCHTimeSeconds - BMCTimeSeconds) > timeDiffAllowedSecond) + { + if (!setSystemTime(PCHTimeSeconds)) + { + return false; + } + std::cout << "Update BMC time to " << dateString << std::endl; + } + + return true; + } + + void startSyncTimer() + { + if (updateBMCTime()) + { + syncIntervalMS = syncIntervalNormalMS; + } + else + { + std::cout << "Update BMC time Fail" << std::endl; + syncIntervalMS = syncIntervalFastMS; + } + + syncTimer->expires_after(std::chrono::milliseconds(syncIntervalMS)); + syncTimer->async_wait( + [this](const boost::system::error_code& ec) { startSyncTimer(); }); + } + + std::unique_ptr syncTimer; + uint8_t year, month, day, hour, minute, second; + + public: + PCHSync(boost::asio::io_service& io) + { + syncTimer = std::make_unique(io); + startSyncTimer(); + } + + ~PCHSync() = default; +}; + +int main(int argc, char** argv) +{ + boost::asio::io_service io; + PCHSync pchSyncer(io); + + phosphor::logging::log( + "Starting PCH time sync service"); + + io.run(); + return 0; +} diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service new file mode 100644 index 000000000..cf9c3053f --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/datetime/pch-time-sync/pch-time-sync.service @@ -0,0 +1,13 @@ +[Unit] +Description=PCH BMC time sync service +Conflicts=systemd-timesyncd.service + +[Service] +Restart=always +RestartSec=10 +ExecStart=/usr/bin/pch-time-sync +StartLimitInterval=0 +Type=simple + +[Install] +WantedBy=sysinit.target -- cgit v1.2.3