diff --git a/include/syscall_defs.h b/include/syscall_defs.h index 35cad7c..4333541 100644 --- a/include/syscall_defs.h +++ b/include/syscall_defs.h @@ -41,5 +41,6 @@ #define SYS_GET_DEVICE_INFO 38 #define SYS_GET_VOLUME_INFO 39 #define SYS_VOLUME_DELETE 40 +#define SYS_DATE_TIME 41 #endif // _M_SYSCALL_DEFS_H diff --git a/include/time.h b/include/time.h new file mode 100644 index 0000000..d3bcb3f --- /dev/null +++ b/include/time.h @@ -0,0 +1,14 @@ +#ifndef _TIME_H +#define _TIME_H + +struct date_time { + int sec; + int min; + int hour; + int day; + int weekday; + int month; + int year; +}; + +#endif // _TIME_H diff --git a/kernel/amd64/bootmain.c b/kernel/amd64/bootmain.c index e0e268e..f338afe 100644 --- a/kernel/amd64/bootmain.c +++ b/kernel/amd64/bootmain.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,7 @@ void bootmain (void) { ioapic_init (); hpet_init (); + rtc_init (); proc_pid_alloc_init (); procgroup_pgid_alloc_init (); diff --git a/kernel/amd64/rtc.c b/kernel/amd64/rtc.c new file mode 100644 index 0000000..a4c8830 --- /dev/null +++ b/kernel/amd64/rtc.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RTC_CMOS_ADDR 0x70 +#define RTC_CMOS_DATA 0x71 + +static uint8_t rtc_century; +#define RTC_SEC 0x00 +#define RTC_SEC_ALARM 0x01 +#define RTC_MIN 0x02 +#define RTC_MIN_ALARM 0x03 +#define RTC_HOUR 0x04 +#define RTC_HOUR_ALARM 0x05 +#define RTC_WEEK_DAY 0x06 +#define RTC_DAY 0x07 +#define RTC_MONTH 0x08 +#define RTC_YEAR 0x09 +#define RTC_REG_A 0x0A +#define RTC_REG_B 0x0B +#define RTC_REG_C 0x0C +#define RTC_REG_D 0x0D + +#define RTC_REG_A_UIP (1 << 7) + +#define RTC_REG_B_HOURFMT (1 << 1) +#define RTC_REG_B_DATAMODE (1 << 2) + +static uint8_t rtc_read (uint8_t addr) { + outb (RTC_CMOS_ADDR, RTC_REG_A); + while (inb (RTC_CMOS_DATA) & RTC_REG_A_UIP) + ; + outb (RTC_CMOS_ADDR, addr); + return inb (RTC_CMOS_DATA); +} + +static void rtc_write (uint8_t addr, uint8_t value) { + outb (RTC_CMOS_ADDR, addr); + outb (RTC_CMOS_DATA, value); +} + +static uint8_t rtc_bcd_to_bin (uint8_t value) { return (value & 0xF) + (value >> 4) * 10; } + +static uint8_t rtc_bin_to_bcd (uint8_t value) { return ((value / 10) << 4) + (value % 10); } + +void rtc_init (void) { + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + struct uacpi_table fadt_table; + uacpi_status status = uacpi_table_find_by_signature (ACPI_FADT_SIGNATURE, &fadt_table); + if (status != UACPI_STATUS_OK) { + DEBUG ("Could not find FADT table!\n"); + spin (); + } + + struct acpi_fadt* fadt = (struct acpi_fadt*)fadt_table.virt_addr; + + rtc_century = fadt->century; +} + +void rtc_date_time (struct date_time* date_time) { + if (rtc_read (RTC_REG_A) & RTC_REG_A_UIP) + stall_ms (1); + + uint8_t sec = rtc_read (RTC_SEC); + uint8_t min = rtc_read (RTC_MIN); + uint8_t hour = rtc_read (RTC_HOUR); + uint8_t weekday = rtc_read (RTC_WEEK_DAY); + uint8_t day = rtc_read (RTC_DAY); + uint8_t month = rtc_read (RTC_MONTH); + uint8_t year = rtc_read (RTC_YEAR); + uint8_t century = rtc_century != 0 ? rtc_read (rtc_century) : 0; + + uint8_t b = rtc_read (RTC_REG_B); + + /* BCD */ + if ((~b) & RTC_REG_B_DATAMODE) { + sec = rtc_bcd_to_bin (sec); + min = rtc_bcd_to_bin (min); + hour = rtc_bcd_to_bin (hour); + day = rtc_bcd_to_bin (day); + month = rtc_bcd_to_bin (month); + year = rtc_bcd_to_bin (year); + if (rtc_century != 0) + century = rtc_bcd_to_bin (century); + } + + weekday--; + + int full_year; + if (rtc_century != 0) + full_year = (century * 100) + year; + else + full_year = (year < 80) ? (2000 + year) : (1900 + year); + + date_time->sec = sec; + date_time->min = min; + date_time->hour = hour; + date_time->day = day; + date_time->weekday = weekday; + date_time->month = month; + date_time->year = full_year; +} diff --git a/kernel/amd64/rtc.h b/kernel/amd64/rtc.h new file mode 100644 index 0000000..03f9a99 --- /dev/null +++ b/kernel/amd64/rtc.h @@ -0,0 +1,10 @@ +#ifndef _KERNEL_AMD64_RTC_H +#define _KERNEL_AMD64_RTC_H + +#include + +void rtc_init (void); + +void rtc_date_time (struct date_time* date_time); + +#endif // _KERNEL_AMD64_RTC_H diff --git a/kernel/amd64/src.mk b/kernel/amd64/src.mk index 8bc059c..2f312e8 100644 --- a/kernel/amd64/src.mk +++ b/kernel/amd64/src.mk @@ -14,7 +14,8 @@ c += amd64/bootmain.c \ amd64/syscall.c \ amd64/gdt.c \ amd64/stall.c \ - amd64/systick.c + amd64/systick.c \ + amd64/rtc.c S += amd64/intr_stub.S \ amd64/spin.S \ @@ -43,4 +44,5 @@ o += amd64/bootmain.o \ amd64/gdt.o \ amd64/sse.o \ amd64/stall.o \ - amd64/systick.o + amd64/systick.o \ + amd64/rtc.o diff --git a/kernel/amd64/time.c b/kernel/amd64/time.c index b1a8038..a8a0709 100644 --- a/kernel/amd64/time.c +++ b/kernel/amd64/time.c @@ -1,6 +1,9 @@ #include +#include #include #include /// Sleep for given amount of microseconds void sleep_micro (size_t us) { hpet_sleep_micro (us); } + +void date_time (struct date_time* date_time) { rtc_date_time (date_time); } diff --git a/kernel/sys/time.h b/kernel/sys/time.h index 85cc074..81148bd 100644 --- a/kernel/sys/time.h +++ b/kernel/sys/time.h @@ -2,8 +2,11 @@ #define _KERNEL_SYS_TIME_H #include +#include /* May take a timer peripheral lock! */ void sleep_micro (size_t us); +void date_time (struct date_time* date_time); + #endif // _KERNEL_SYS_TIME_H diff --git a/kernel/syscall/syscall.c b/kernel/syscall/syscall.c index c30e070..b38c7d7 100644 --- a/kernel/syscall/syscall.c +++ b/kernel/syscall/syscall.c @@ -21,8 +21,10 @@ #include #include #include +#include #include #include +#include #include #include @@ -1149,6 +1151,30 @@ DEFINE_SYSCALL (sys_volume_delete) { return SYSRESULT (ST_OK); } +/* int date_time (struct date_time* dt) */ +DEFINE_SYSCALL (sys_date_time) { + uint64_t fpg, fp; + + uintptr_t uvaddr_dt = a1; + + struct limine_hhdm_response* hhdm = limine_hhdm_request.response; + + uintptr_t out_paddr; + + spin_lock (&proc->lock, &fp); + struct procgroup* procgroup = proc->procgroup; + spin_unlock (&proc->lock, fp); + + struct date_time* dt = sys_get_user_buffer (procgroup, uvaddr_dt, sizeof (struct date_time)); + + if (dt == NULL) + return SYSRESULT (-ST_BAD_ADDRESS_SPACE); + + date_time (dt); + + return ST_OK; +} + static syscall_handler_func_t handler_table[] = { [SYS_QUIT] = &sys_quit, [SYS_TEST] = &sys_test, @@ -1190,6 +1216,7 @@ static syscall_handler_func_t handler_table[] = { [SYS_GET_DEVICE_INFO] = &sys_get_device_info, [SYS_GET_VOLUME_INFO] = &sys_get_volume_info, [SYS_VOLUME_DELETE] = &sys_volume_delete, + [SYS_DATE_TIME] = &sys_date_time, }; syscall_handler_func_t syscall_find_handler (int syscall_num) { diff --git a/libu/Makefile b/libu/Makefile index 7aece48..e6c7c4d 100644 --- a/libu/Makefile +++ b/libu/Makefile @@ -1,8 +1,7 @@ FORMAT = clang-format -i $$(git ls-files '*.c' '*.h' ':!malloc.c' ':!malloc.h' \ ':!\_fat.c' ':!\_fat.h' ':!\_fatctx.h') -DOCS_COLLECT = $$(git ls-files '*.c' '*.h' ':!\_fat.c' ':!\_fat.h' ':!\_fatctx.h' \ - ':!malloc.c' ':!malloc.h') +DOCS_COLLECT = $$(git ls-files '*.c' '*.h' ':!\_fat.c' ':!\_fat.h' ':!\_fatctx.h') cflags += -DPRINTF_INCLUDE_CONFIG_H=1 -D"FAT_PRINTF(a)" diff --git a/libu/system.c b/libu/system.c index 4f24d00..bbed468 100644 --- a/libu/system.c +++ b/libu/system.c @@ -124,3 +124,5 @@ int get_volume_info (struct volume_info* infos, size_t count) { } int volume_delete (const char* key) { return (int)do_syscall (SYS_VOLUME_DELETE, key); } + +int date_time (struct date_time* dt) { return (int)do_syscall (SYS_DATE_TIME, dt); } diff --git a/libu/system.h b/libu/system.h index e651dde..f0a6e6a 100644 --- a/libu/system.h +++ b/libu/system.h @@ -7,6 +7,7 @@ #include #include #include +#include #include /* Quit the current running process */ @@ -129,4 +130,7 @@ int get_volume_info (struct volume_info* infos, size_t count); /* delete a volume */ int volume_delete (const char* key); +/* Get date-time */ +int date_time (struct date_time* dt); + #endif // _LIBMSL_M_SYSTEM_H