Calculate the boot timestamp in UNIX time for further usage

This commit is contained in:
apio 2022-11-20 18:30:40 +01:00
parent 459e1ed653
commit 43e26e583c

View File

@ -1,8 +1,58 @@
#include "arch/Timer.h" #include "arch/Timer.h"
#include "arch/Serial.h"
#include "boot/bootboot.h"
#include <Result.h>
static u64 timer_ticks = 0; static u64 timer_ticks = 0;
static u64 boot_timestamp; static u64 boot_timestamp;
static int isleap(int year)
{
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
static int make_yday(int year, int month)
{
static const short int upto[12] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
int yd;
yd = upto[month - 1];
if (month > 2 && isleap(year)) yd++;
return yd;
}
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_16
static u64 broken_down_to_unix(u64 year, u64 yday, u64 hour, u64 min, u64 sec)
{
return sec + min * 60 + hour * 3600 + yday * 86400 + (year - 70) * 31536000 + ((year - 69) / 4) * 86400 -
((year - 1) / 100) * 86400 + ((year + 299) / 400) * 86400;
}
// The bootloader encodes the date and time in Binary-Coded Decimal (BCD), which represents decimal digits using
// hexadecimal digits. For example, BCD 0x22 is 22 in decimal.
// https://gitlab.com/bztsrc/bootboot/-/blob/master/bootboot_spec_1st_ed.pdf, page 15.
static int bcd_number_to_decimal(int num)
{
return ((num >> 4) * 10) + (num & 0xf);
}
static u64 bootloader_time_to_unix(u8 boottime[8])
{
int year = bcd_number_to_decimal(boottime[0]) * 100 + bcd_number_to_decimal(boottime[1]);
int month = bcd_number_to_decimal(boottime[2]);
int day = bcd_number_to_decimal(boottime[3]);
int hour = bcd_number_to_decimal(boottime[4]);
int minute = bcd_number_to_decimal(boottime[5]);
int second = bcd_number_to_decimal(boottime[6]);
// "The last byte can store 1/100th second precision, but in lack of support on most platforms, it is 0x00".
// Therefore, let's not rely on it.
Serial::printf("Current time: %.2d/%.2d/%d %.2d:%.2d:%.2d UTC\n", day, month, year, hour, minute, second)
.release_value();
return broken_down_to_unix(year - 1900, make_yday(year, month) + (day - 1), hour, minute, second);
}
extern BOOTBOOT bootboot;
namespace Timer namespace Timer
{ {
void tick() void tick()
@ -75,6 +125,7 @@ namespace Timer
void init() void init()
{ {
boot_timestamp = bootloader_time_to_unix(bootboot.datetime);
arch_init(); arch_init();
} }
} }