blob: d1b5ae5faf206a2e015692f672b6c8ba905dfd94 [file] [log] [blame]
#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, &timestamp, sizeof(ret));
return ret;
}
} // namespace uefi::cper