Set system boot time properly, fix gettimeofday
This commit is contained in:
+2
-1
@@ -74,7 +74,8 @@ OBJS+=$(O)/sys/debug.o \
|
||||
$(O)/sys/random.o \
|
||||
$(O)/sys/init.o \
|
||||
$(O)/sys/vfs/vfs_ops.o \
|
||||
$(O)/sys/vfs/vfs_access.o
|
||||
$(O)/sys/vfs/vfs_access.o \
|
||||
$(O)/sys/time.o
|
||||
|
||||
# \
|
||||
$(O)/sys/vfs/pty.o \
|
||||
|
||||
@@ -1,16 +1,6 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
struct rtc_time {
|
||||
uint8_t second;
|
||||
uint8_t minute;
|
||||
uint8_t hour;
|
||||
uint8_t weekday;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint16_t year;
|
||||
};
|
||||
|
||||
void rtc_read(struct rtc_time *time);
|
||||
void rtc_read(struct tm *time);
|
||||
void rtc_set_century(uint8_t c);
|
||||
void rtc_init(void);
|
||||
|
||||
@@ -19,5 +19,12 @@ struct timespec {
|
||||
typedef uint64_t time_t;
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
struct tm;
|
||||
|
||||
// Nanoseconds since boot
|
||||
extern uint64_t system_time;
|
||||
// Seconds since epoch
|
||||
extern time_t system_boot_time;
|
||||
|
||||
time_t mktime(struct tm *tm);
|
||||
#endif
|
||||
|
||||
@@ -5,6 +5,20 @@
|
||||
#define NULL ((void *) 0)
|
||||
#endif
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
struct tm {
|
||||
int tm_sec;
|
||||
int tm_min;
|
||||
int tm_hour;
|
||||
int tm_mday;
|
||||
int tm_mon;
|
||||
int tm_year;
|
||||
int tm_wday;
|
||||
int tm_yday;
|
||||
int tm_isdst;
|
||||
};
|
||||
#endif
|
||||
|
||||
typedef uint64_t uintptr_t;
|
||||
typedef int64_t intptr_t;
|
||||
|
||||
|
||||
+8
-26
@@ -50,16 +50,16 @@ static inline uint8_t cmos_read_time(uint8_t reg, uint8_t reg_b) {
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_read(struct rtc_time *time) {
|
||||
void rtc_read(struct tm *time) {
|
||||
uint8_t reg_b = cmos_inb(RTC_REGB_STATUS);
|
||||
|
||||
time->second = cmos_read_time(RTC_REG_SECOND, reg_b);
|
||||
time->minute = cmos_read_time(RTC_REG_MINUTE, reg_b);
|
||||
time->hour = cmos_read_time(RTC_REG_HOUR, reg_b);
|
||||
time->weekday = cmos_read_time(RTC_REG_WEEKDAY, reg_b);
|
||||
time->day = cmos_read_time(RTC_REG_DAY, reg_b);
|
||||
time->month = cmos_read_time(RTC_REG_MONTH, reg_b);
|
||||
time->year = cmos_read_time(RTC_REG_YEAR, reg_b) + 100 * rtc_century;
|
||||
time->tm_sec = cmos_read_time(RTC_REG_SECOND, reg_b);
|
||||
time->tm_min = cmos_read_time(RTC_REG_MINUTE, reg_b);
|
||||
time->tm_hour = cmos_read_time(RTC_REG_HOUR, reg_b);
|
||||
//time->tm_wday = cmos_read_time(RTC_REG_WEEKDAY, reg_b);
|
||||
time->tm_mday = cmos_read_time(RTC_REG_DAY, reg_b);
|
||||
time->tm_mon = cmos_read_time(RTC_REG_MONTH, reg_b);
|
||||
time->tm_year = cmos_read_time(RTC_REG_YEAR, reg_b) + 100 * rtc_century;
|
||||
}
|
||||
|
||||
static uint32_t rtc_irq(void *ctx) {
|
||||
@@ -94,25 +94,7 @@ void rtc_set_century(uint8_t century) {
|
||||
}
|
||||
|
||||
void rtc_init(void) {
|
||||
static const char *day_names[] = {
|
||||
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
|
||||
};
|
||||
static const char *month_names[] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
|
||||
"Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
|
||||
struct rtc_time time;
|
||||
|
||||
cmos_inb(RTC_REGC_STATUS);
|
||||
irq_add_leg_handler(8, rtc_irq, NULL);
|
||||
rtc_enable_irq();
|
||||
|
||||
rtc_read(&time);
|
||||
kdebug("%s %02u %s %04u %02u:%02u:%02u\n",
|
||||
day_names[(time.weekday - 1) % 7],
|
||||
time.day,
|
||||
month_names[(time.month - 1) % 12],
|
||||
time.year,
|
||||
time.hour, time.minute, time.second);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
#define PIT_CMD 0x43
|
||||
|
||||
uint64_t int_timer_ticks = 0;
|
||||
uint64_t system_time = 0;
|
||||
|
||||
static uint32_t timer_tick(void *arg) {
|
||||
switch ((uint64_t) arg) {
|
||||
|
||||
+9
-6
@@ -28,12 +28,7 @@
|
||||
static multiboot_info_t *multiboot_info;
|
||||
|
||||
static void amd64_make_random_seed(void) {
|
||||
struct rtc_time t;
|
||||
rtc_read(&t);
|
||||
|
||||
uint64_t s = 137831;
|
||||
s += t.second + t.minute * 60 + t.hour * 3600 + t.day * 86400;
|
||||
random_init(s + system_time);
|
||||
random_init(15267 + system_time);
|
||||
}
|
||||
|
||||
void kernel_main(struct amd64_loader_data *data) {
|
||||
@@ -64,6 +59,14 @@ void kernel_main(struct amd64_loader_data *data) {
|
||||
|
||||
amd64_apic_init();
|
||||
rtc_init();
|
||||
// Setup system time
|
||||
struct tm t;
|
||||
rtc_read(&t);
|
||||
system_boot_time = mktime(&t);
|
||||
kinfo("Boot time: %04u-%02u-%02u %02u:%02u:%02u\n",
|
||||
t.tm_year, t.tm_mon, t.tm_mday,
|
||||
t.tm_hour, t.tm_min, t.tm_sec);
|
||||
|
||||
pci_init();
|
||||
|
||||
vfs_init();
|
||||
|
||||
+1
-7
@@ -62,14 +62,8 @@ int sys_gettimeofday(struct timeval *tv, struct timezone *tz) {
|
||||
tz->tz_minuteswest = 0;
|
||||
}
|
||||
|
||||
uint64_t secs = system_time / 1000000000ULL;
|
||||
|
||||
struct rtc_time time_rtc;
|
||||
rtc_read(&time_rtc);
|
||||
secs += time_rtc.second + time_rtc.minute * 60 + time_rtc.hour * 3600;
|
||||
|
||||
uint64_t secs = system_time / 1000000000ULL + system_boot_time;
|
||||
// System time is in nanos
|
||||
// TODO: use RTC-provided time for full system time
|
||||
tv->tv_usec = (system_time / 1000) % 1000000;
|
||||
tv->tv_sec = secs;
|
||||
|
||||
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
#include "sys/time.h"
|
||||
#include "sys/types.h"
|
||||
|
||||
#define leap_days_to_1970 477
|
||||
|
||||
uint64_t system_time = 0;
|
||||
time_t system_boot_time = 0;
|
||||
|
||||
static const int days_to_month365[] = {
|
||||
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
|
||||
};
|
||||
|
||||
static const int days_to_month366[] = {
|
||||
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
|
||||
};
|
||||
|
||||
static inline int is_leap(int year) {
|
||||
return (year % 4 == 0 && ((year % 100 != 0) || (year % 400 == 0)));
|
||||
}
|
||||
|
||||
static int tm_check(const struct tm *tm) {
|
||||
return tm->tm_mday < 0 || tm->tm_mday > 31 ||
|
||||
tm->tm_mon < 0 || tm->tm_mon > 12 ||
|
||||
tm->tm_year < 1970 || tm->tm_year > 2500 ||
|
||||
tm->tm_hour < 0 || tm->tm_hour > 23 ||
|
||||
tm->tm_min < 0 || tm->tm_min > 59 ||
|
||||
tm->tm_sec < 0 || tm->tm_sec > 59;
|
||||
}
|
||||
|
||||
time_t mktime(struct tm *tm) {
|
||||
if (tm_check(tm) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculate year day when month starts
|
||||
int month_startd = (is_leap(tm->tm_year) ? days_to_month366 : days_to_month365)[tm->tm_mon - 1];
|
||||
|
||||
// Calculate number of days from epoch to year start
|
||||
int prev_year = tm->tm_year;
|
||||
int days_before = ((prev_year - 1970) * 365) + (prev_year) / 4 - (prev_year) / 100 + (prev_year / 400) - leap_days_to_1970;
|
||||
|
||||
// Add number of seconds in epoch days
|
||||
time_t result = days_before + month_startd + tm->tm_mday - 2;
|
||||
result *= 86400;
|
||||
|
||||
result += tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
|
||||
|
||||
return result;
|
||||
}
|
||||
Reference in New Issue
Block a user