From 7ebd246403417294fc6fa1914967b6e60a92f062 Mon Sep 17 00:00:00 2001 From: Andres Oportus Date: Mon, 9 Apr 2018 10:35:21 -0700 Subject: Fix FRU BuildDate DBus/IPMI exporting When BMC exports the date into DBUS it translates/expands the 3 bytes FRU format date into an easy to read string as in "2015-11-06 - 22:23:00", when exporting the DBUS date back to IPMI it needs to translate back this date into the 3 bytes FRU format, without this fix we get a build date in 1996 that is the epoch for the FRU date format. This change reconstructs the FRU date from the easy to read string for exporting into IPMI. Tested: Manual check that BuildDate from busctl and ipmitool match Resolves openbmc/openbmc#3013 Change-Id: I0fd1dd8f945f18b53c14bff321c9e233fdb2d742 Signed-off-by: Andres Oportus --- ipmi_fru_info_area.cpp | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/ipmi_fru_info_area.cpp b/ipmi_fru_info_area.cpp index 386b164..1951f8c 100644 --- a/ipmi_fru_info_area.cpp +++ b/ipmi_fru_info_area.cpp @@ -1,6 +1,9 @@ #include #include #include + +#include + #include "ipmi_fru_info_area.hpp" #include namespace ipmi @@ -36,6 +39,9 @@ static constexpr auto areaSizeOffset = 0x1; static constexpr uint8_t typeASCII = 0xC0; static constexpr auto maxRecordAttributeValue = 0x1F; +static constexpr auto secs_from_1970_1996 = 820454400; +static constexpr auto secs_per_min = 60; + /** * @brief Format Beginning of Individual IPMI FRU Data Section * @@ -156,13 +162,28 @@ void appendMfgDate(const PropertyMap& propMap, FruAreaData& data) auto iter = propMap.find(buildDate); if (iter != propMap.end()) { - auto& value = iter->second; - if (value.length() == manufacturingDateSize) + tm time = {}; + strptime(iter->second.c_str(), "%F - %H:%M:%S", &time); + time_t raw = mktime(&time); + + // From FRU Spec: + // "Mfg. Date / Time + // Number of minutes from 0:00 hrs 1/1/96. + // LSbyte first (little endian) + // 00_00_00h = unspecified." + if (raw > secs_from_1970_1996) { - std::copy( - value.begin(), value.end(), std::back_inserter(data)); + raw -= secs_from_1970_1996; + raw /= secs_per_min; + uint8_t fru_raw[3]; + fru_raw[0] = raw & 0xFF; + fru_raw[1] = (raw >> 8) & 0xFF; + fru_raw[2] = (raw >> 16) & 0xFF; + std::copy(fru_raw, fru_raw + 3, std::back_inserter(data)); return; } + fprintf(stderr, "MgfDate invalid date: %u secs since UNIX epoch\n", + static_cast(raw)); } //Blank date data.emplace_back(0); -- cgit v1.2.1