Skip to content

Instantly share code, notes, and snippets.

@vathpela
Created January 30, 2020 19:16
Show Gist options
  • Save vathpela/b4fc218f1efd93b01df4715581175cf0 to your computer and use it in GitHub Desktop.
Save vathpela/b4fc218f1efd93b01df4715581175cf0 to your computer and use it in GitHub Desktop.
#include "efi_time.h"
#include <time.h>
char *
efi_strptime(const char *s, const char *format, efi_time_t *time)
{
struct tm tm;
char *end;
if (!s || !format || !time) {
errno = EINVAL;
return NULL;
}
tzset();
memset(&tm, 0, sizeof(tm));
end = strptime(s, format, &tm);
if (end == NULL)
return NULL;
time->pad2 = 0;
time->daylight = tm.tm_isdst ? EFI_TIME_IN_DAYLIGHT : 0;
time->timezone = timezone / 60;
time->nanosecond = 0;
time->pad1 = 0;
time->second = tm.tm_sec;
time->minute = tm.tm_min;
time->hour = tm.tm_hour;
time->day = tm.tm_mday;
time->month = tm.tm_mon + 1;
time->year = tm.tm_year + 1900;
return end;
}
size_t
efi_strftime(char *s, size_t max, const char *format, const efi_time_t *time)
{
size_t ret = 0;
struct tm tm = { 0 };
char *oldtz, *tz = NULL;
if (!s || !format || !time) {
errno = EINVAL;
return ret;
}
oldtz = strdupa(secure_getenv("TZ"));
if (time->timezone == EFI_UNSPECIFIED_TIMEZONE) {
unsetenv("TZ");
} else {
char tzsign = time->timezone >= 0 ? '+' : '-';
int tzabs = tzsign == '+' ? time->timezone : -time->timezone;
int16_t tzhours = tzabs / 60;
int16_t tzminutes = tzabs % 60;
/*
* I have no idea what the right thing to do with DST is
* here, so I'm going to ignore it.
*/
asprintfa(&tz, "UTC%c%"PRId16":%"PRId16":00",
tzsign, tzhours, tzminutes);
setenv("TZ", tz, 1);
}
tzset();
tm.tm_year = time->year - 1900;
tm.tm_mon = time->month - 1;
tm.tm_mday = time->day;
tm.tm_hour = time->hour;
tm.tm_min = time->minute;
tm.tm_sec = time->second;
tm.tm_isdst = (time->daylight & EFI_TIME_IN_DAYLIGHT) ? 1 : 0;
ret = strftime(s, max, format, &tm);
if (oldtz)
setenv("TZ", oldtz, 1);
else
unsetenv("TZ");
return ret;
}
// vim:fenc=utf-8:tw=75:noet
typedef struct {
uint16_t year; // 1900 - 9999
uint8_t month; // 1 - 12
uint8_t day; // 1 - 31
uint8_t hour; // 0 - 23
uint8_t minute; // 0 - 59
uint8_t second; // 0 - 59 // ha ha only serious
uint8_t pad1; // 0
uint32_t nanosecond; // 0 - 999,999,999
int16_t timezone; // minutes from UTC or EFI_UNSPECIFIED_TIMEZONE
uint8_t daylight; // bitfield
uint8_t pad2; // 0
} efi_time_t __attribute__((__aligned__(1)));
#define EFI_TIME_ADJUST_DAYLIGHT ((uint8_t)0x01)
#define EFI_TIME_IN_DAYLIGHT ((uint8_t)0x02)
#define EFI_UNSPECIFIED_TIMEZONE ((uint16_t)0x07ff)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment