| #pragma once |
| |
| #include "cper.hpp" |
| |
| #include <chrono> |
| |
| namespace uefi::cper |
| { |
| |
| /** |
| * @brief Helper function to create a UTC UEFI CPER timestamp from a |
| * std::chrono time point. |
| * https://uefi.org/specs/UEFI/2.10/Apx_N_Common_Platform_Error_Record.html#record-header |
| * |
| * @param[in] timeOfCollection - A std::chrono time_point representing the time |
| * the fault was detected by the system software. |
| * @param[in] isPrecise - Bool which indicates if the time is precise. |
| * |
| * @param[out] A uefi cper timestamp as uint64_t. |
| */ |
| uint64_t createCperTimestamp( |
| const std::chrono::time_point<std::chrono::system_clock> timeOfCollection, |
| const bool isPrecise = true) |
| { |
| // Number of years in a century. |
| constexpr int kCentury = 100; |
| |
| // The tm_year counts the number of years since 1900. |
| // https://en.cppreference.com/w/c/chrono/tm |
| constexpr int kTmYearOffset = 1900; |
| |
| // UEFI expects the isPrecise byte bits [1:7] to be zero. |
| const uint8_t isPreciseBit = 0 | (isPrecise & 0x1); |
| |
| const time_t tt = std::chrono::system_clock::to_time_t(timeOfCollection); |
| const tm utcTime = *gmtime(&tt); |
| |
| // The uefi timestamp breaks the calendar year into two bytes |
| // representing the number of centuries and number of years. |
| const int calendarYear = utcTime.tm_year + kTmYearOffset; |
| const uint8_t year = calendarYear % kCentury; |
| const uint8_t century = calendarYear / kCentury; |
| |
| const Timestamp timestamp(utcTime.tm_sec, utcTime.tm_min, utcTime.tm_hour, |
| isPreciseBit, utcTime.tm_mday, utcTime.tm_mon, |
| year, century); |
| |
| uint64_t ret; |
| memcpy(&ret, ×tamp, sizeof(ret)); |
| return ret; |
| } |
| } // namespace uefi::cper |