From 3690b91e16b0d5828a2eb5d86158ebe2f39a806b Mon Sep 17 00:00:00 2001 From: assada Date: Sat, 25 May 2024 23:17:10 +0300 Subject: [PATCH] rtc time --- Makefile | 2 +- gdt.c | 10 +++---- io.c | 16 ++++++++++- io.h | 3 +++ isr.c | 2 ++ kernel.c | 7 +++-- rtc.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ rtc.h | 29 ++++++++++++++++++++ shell.c | 14 ++++++++++ string.c | 13 +++++++++ string.h | 1 + syscall.c | 4 ++- tty.c | 34 +++++++++++++++++++----- 13 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 rtc.c create mode 100644 rtc.h diff --git a/Makefile b/Makefile index 55bdb48..99eb539 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ GRUB_MKRESCUE = grub-mkrescue KERNEL = deados.bin ISO = deados.iso -SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c +SOURCES_C = kernel.c tty.c idt.c timer.c io.c vga.c gdt.c sys.c irq.c isr.c keyboard.c shell.c string.c user_space.c syscall.c rtc.c SOURCES_ASM = boot.s idt_load.s gdt_flush.s tss_flush.s irq_flush.s isr_flush.s OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o) diff --git a/gdt.c b/gdt.c index 4496f93..a47e4f0 100644 --- a/gdt.c +++ b/gdt.c @@ -35,7 +35,7 @@ static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp) memset(&tss, 0, sizeof(Tss_entry)); tss.ss0 = kernel_ss; - tss.esp0 = kernel_esp; + tss.esp0 = kernel_esp + 0x1000; // SHIT tss.cs = 0x1B; tss.ss = 0x23; @@ -48,10 +48,10 @@ static void tss_install(uint8_t num, uint16_t kernel_ss, uint16_t kernel_esp) void gdt_install() { gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment - gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // Kernel code segment - gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment - gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // User code segment - gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // User data segment + gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // 0x08 Kernel code segment + gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // 0x10 Kernel Data segment + gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // 0x18 User code segment + gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // 0x20 User data segment tss_install(5, 0x10, stack_top); diff --git a/io.c b/io.c index 2311d59..b725abb 100644 --- a/io.c +++ b/io.c @@ -12,9 +12,23 @@ uint8_t inb(uint16_t port) return ret; } -void wait(void) +void io_wait(void) { asm volatile("jmp 1f\n\t" "1:jmp 2f\n\t" "2:"); } + +void outb_wait(uint16_t port, uint8_t val) +{ + outb(port, val); + io_wait(); +} + +uint8_t inb_wait(uint16_t port) +{ + uint8_t ret; + ret = inb(port); + io_wait(); + return ret; +} \ No newline at end of file diff --git a/io.h b/io.h index 1babee8..116cd02 100644 --- a/io.h +++ b/io.h @@ -7,4 +7,7 @@ void outb(uint16_t port, uint8_t val); uint8_t inb(uint16_t port); void io_wait(void); +void outb_wait(uint16_t port, uint8_t val); +uint8_t inb_wait(uint16_t port); + #endif \ No newline at end of file diff --git a/isr.c b/isr.c index bac24fd..5f69724 100644 --- a/isr.c +++ b/isr.c @@ -55,7 +55,9 @@ void isr_call_handler(Stack *registers) void (*handler)(Stack *registers); handler = isr_routines[registers->id]; if (handler) + { handler(registers); + } } void isr_install(void) diff --git a/kernel.c b/kernel.c index aa9ad66..4d6ce0e 100644 --- a/kernel.c +++ b/kernel.c @@ -12,9 +12,11 @@ #include "shell.h" #include "user_space.h" #include "syscall.h" +#include "rtc.h" void kernel_main(void) { + terminal_initialize(); gdt_install(); idt_install(); @@ -24,17 +26,18 @@ void kernel_main(void) timer_install(); keyboard_install(); + rtc_init(); + syscall_init(); enter_user_space(); } void main(void) { - terminal_initialize(); for (int i = 1; i < 4; i++) { terminal_printf("&cTest &7%d\n", i); - delay(500); + delay(200); } terminal_clear(); diff --git a/rtc.c b/rtc.c new file mode 100644 index 0000000..c834cc0 --- /dev/null +++ b/rtc.c @@ -0,0 +1,79 @@ +#include +#include "io.h" +#include "interrupts.h" +#include "rtc.h" + +uint8_t read_cmos(uint16_t reg) +{ + outb_wait(CMOS_ADDRESS, reg); + return inb_wait(CMOS_DATA); +} + +uint8_t get_update_in_progress_flag() +{ + outb_wait(CMOS_ADDRESS, 0x0A); + return inb_wait(CMOS_DATA) & 0x80; +} + +void rtc_handler() +{ + outb_wait(CMOS_ADDRESS, 0x0C); + inb_wait(CMOS_DATA); +} + +uint8_t bcd_to_bin(uint8_t val) +{ + return ((val / 16) * 10) + (val & 0x0F); +} + +struct Rtc_time get_rtc_time() +{ + struct Rtc_time time; + + while (get_update_in_progress_flag()) + ; + + time.sec = read_cmos(REG_SECONDS); + + time.min = read_cmos(REG_MINUTES); + time.hour = read_cmos(REG_HOURS); + + time.mday = read_cmos(REG_DAY); + time.mon = read_cmos(REG_MONTH); + time.year = read_cmos(REG_YEAR); + + uint8_t registerB = read_cmos(0x0B); + + if (!(registerB & 0x04)) + { + time.sec = bcd_to_bin(time.sec); + time.min = bcd_to_bin(time.min); + time.hour = bcd_to_bin(time.hour); + time.mday = bcd_to_bin(time.mday); + time.mon = bcd_to_bin(time.mon); + time.year = bcd_to_bin(time.year); + } + + if (time.year < 70) + { + time.year += 100; + } + else if (time.year >= 100) + { + time.year -= 100; + } + + time.year += 1900; + + return time; +} + +void rtc_init() +{ + outb_wait(CMOS_ADDRESS, 0x8A); + uint8_t prev = inb_wait(CMOS_DATA); + outb_wait(CMOS_ADDRESS, 0x8A); + outb_wait(CMOS_DATA, (prev & 0xF0) | 0x0F); + + irq_install_handler(8, rtc_handler); +} \ No newline at end of file diff --git a/rtc.h b/rtc.h new file mode 100644 index 0000000..4739a06 --- /dev/null +++ b/rtc.h @@ -0,0 +1,29 @@ +#ifndef RTC_H +#define RTC_H + +#include + +#define CMOS_ADDRESS 0x70 +#define CMOS_DATA 0x71 + +#define REG_SECONDS 0x00 +#define REG_MINUTES 0x02 +#define REG_HOURS 0x04 +#define REG_DAY 0x07 +#define REG_MONTH 0x08 +#define REG_YEAR 0x09 + +struct Rtc_time +{ + uint8_t sec; + uint8_t min; + uint8_t hour; + uint8_t mday; + uint8_t mon; + uint16_t year; +}; + +void rtc_init(); +struct Rtc_time get_rtc_time(); + +#endif \ No newline at end of file diff --git a/shell.c b/shell.c index 2a7471e..9872923 100644 --- a/shell.c +++ b/shell.c @@ -3,6 +3,7 @@ #include "shell.h" #include "tty.h" #include "string.h" +#include "rtc.h" void shell_init(void) { @@ -53,6 +54,7 @@ void shell_help_command(void) terminal_printf("exit - Exit the shell.\n"); terminal_printf("echo - Print out the message. &eWITH colors!&7\n"); terminal_printf("clear - Clear the terminal.\n"); + terminal_printf("time - Print out the current time. (UTC)\n"); } void shell_exit_command(void) @@ -63,6 +65,14 @@ void shell_exit_command(void) ; } +void shell_time_command(void) +{ + struct Rtc_time current_time = get_rtc_time(); + terminal_printf("Current time: %02d:%02d:%02d %02d.%02d.%d\n", + current_time.hour, current_time.min, current_time.sec, + current_time.mday, current_time.mon, current_time.year); +} + void shell_echo_command(char *input) { char *message = input; @@ -102,6 +112,10 @@ void shell_parse_input(char *input) { terminal_clear(); } + else if (strcmp(command, "time") == 0) + { + shell_time_command(); + } else { terminal_printf("Unknown command: '"); diff --git a/string.c b/string.c index 4d2089a..d295b18 100644 --- a/string.c +++ b/string.c @@ -21,6 +21,19 @@ void *memset(void *ptr, int value, size_t size) return ptr; } +void memcpy(void *vd, const void *vs, unsigned length) +{ + char *d = vd; + const char *s = vs; + while (length) + { + *d = *s; + d++; + s++; + length--; + } +} + int strcmp(const char *str1, const char *str2) { while (*str1 && (*str1 == *str2)) diff --git a/string.h b/string.h index 67636e4..1b4298e 100644 --- a/string.h +++ b/string.h @@ -10,5 +10,6 @@ size_t strlen(const char *str); void itoa(int value, char *str, int base); void *memset(void *ptr, int value, size_t size); +void memcpy(void *vd, const void *vs, unsigned length); #endif \ No newline at end of file diff --git a/syscall.c b/syscall.c index 8cfdace..1cc0fa2 100644 --- a/syscall.c +++ b/syscall.c @@ -6,11 +6,13 @@ #include "syscall.h" #include "tty.h" #include "timer.h" +#include "rtc.h" -#define NB_SYSCALL 2 +#define NB_SYSCALL 3 void *syscalls[NB_SYSCALL] = { keyboard_getchar, + get_rtc_time, sys_halt}; diff --git a/tty.c b/tty.c index 51a4e33..8a9662f 100644 --- a/tty.c +++ b/tty.c @@ -129,6 +129,21 @@ void terminal_print(const char *data) terminal_write(data, strlen(data)); } +static void print_number(int value, int base, int padding) +{ + char buffer[32]; + itoa(value, buffer, base); + int len = strlen(buffer); + + while (padding > len) + { + terminal_putchar('0'); + padding--; + } + + terminal_print(buffer); +} + void terminal_printf(const char *format, ...) { va_list args; @@ -137,24 +152,29 @@ void terminal_printf(const char *format, ...) const char *p = format; while (*p) { - if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x')) + if (*p == '%' && (*(p + 1) == 's' || *(p + 1) == 'd' || *(p + 1) == 'x' || *(p + 1) == '0')) { p++; + int padding = 0; + + if (*p == '0') + { + p++; + padding = *p - '0'; + p++; + } + if (*p == 's') { terminal_print(va_arg(args, const char *)); } else if (*p == 'd') { - char buffer[12]; - itoa(va_arg(args, int), buffer, 10); - terminal_print(buffer); + print_number(va_arg(args, int), 10, padding); } else if (*p == 'x') { - char buffer[12]; - itoa(va_arg(args, unsigned int), buffer, 16); - terminal_print(buffer); + print_number(va_arg(args, unsigned int), 16, padding); } } else if (*p == '&' && ((*(p + 1) >= '0' && *(p + 1) <= '9') || (*(p + 1) >= 'a' && *(p + 1) <= 'f')))