diff options
Diffstat (limited to 'roms/skiboot/core/time-utils.c')
-rw-r--r-- | roms/skiboot/core/time-utils.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/roms/skiboot/core/time-utils.c b/roms/skiboot/core/time-utils.c new file mode 100644 index 000000000..e948654d3 --- /dev/null +++ b/roms/skiboot/core/time-utils.c @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later +/* + * Converts an OPAL formatted datetime into a struct tm. We ignore microseconds + * as Linux doesn't use them anyway. + * + * | year | month | mday | + * +------------------------------------+ + * | hour | minute | secs | reserved | + * +------------------------------------+ + * | microseconds | + * + * Copyright 2013-2014 IBM Corp. + */ + +#include <time-utils.h> + +void datetime_to_tm(uint32_t y_m_d, uint64_t h_m_s_m, struct tm *tm) +{ + uint32_t x; + + tm->tm_year = bcd_byte(y_m_d, 3) * 100 + bcd_byte(y_m_d, 2); + tm->tm_mon = bcd_byte(y_m_d, 1) - 1; + tm->tm_mday = bcd_byte(y_m_d, 0); + + x = h_m_s_m >> 32; + tm->tm_hour = bcd_byte(x, 3); + tm->tm_min = bcd_byte(x, 2); + tm->tm_sec = bcd_byte(x, 1); +} + +/* + * The OPAL API is defined as returned a u64 of a similar + * format to the FSP message; the 32-bit date field is + * in the format: + * + * | year | month | mday | + * + * ... and the 64-bit time field is in the format + * + * | hour | minutes | secs | millisec | + * | ------------------------------------- + * | millisec | reserved | + * + * We simply ignore the microseconds/milliseconds for now + * as I don't quite understand why the OPAL API defines that + * it needs 6 digits for the milliseconds :-) I suspect the + * doc got that wrong and it's supposed to be micro but + * let's ignore it. + * + * Note that Linux doesn't use nor set the ms field anyway. + */ +void tm_to_datetime(struct tm *tm, uint32_t *y_m_d, uint64_t *h_m_s_m) +{ + uint64_t h_m_s; + *y_m_d = int_to_bcd4(tm->tm_year) << 16 | + int_to_bcd2(tm->tm_mon + 1) << 8 | + int_to_bcd2(tm->tm_mday); + + h_m_s = int_to_bcd2(tm->tm_hour) << 24 | + int_to_bcd2(tm->tm_min) << 16 | + int_to_bcd2(tm->tm_sec) << 8; + + *h_m_s_m = h_m_s << 32; +} |