rtc time
This commit is contained in:
parent
ea8f6b4ce0
commit
3690b91e16
2
Makefile
2
Makefile
@ -9,7 +9,7 @@ GRUB_MKRESCUE = grub-mkrescue
|
|||||||
KERNEL = deados.bin
|
KERNEL = deados.bin
|
||||||
ISO = deados.iso
|
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
|
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)
|
OBJECTS = $(SOURCES_ASM:.s=.o) $(SOURCES_C:.c=.o)
|
||||||
|
|
||||||
|
10
gdt.c
10
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));
|
memset(&tss, 0, sizeof(Tss_entry));
|
||||||
|
|
||||||
tss.ss0 = kernel_ss;
|
tss.ss0 = kernel_ss;
|
||||||
tss.esp0 = kernel_esp;
|
tss.esp0 = kernel_esp + 0x1000; // SHIT
|
||||||
|
|
||||||
tss.cs = 0x1B;
|
tss.cs = 0x1B;
|
||||||
tss.ss = 0x23;
|
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()
|
void gdt_install()
|
||||||
{
|
{
|
||||||
gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment
|
gdt_set_gate(0, 0x0, 0x0, 0x0, 0x0); // Null segment
|
||||||
gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // Kernel code segment
|
gdt_set_gate(1, 0x0, 0xFFFFFFFF, 0x9A, 0xCF); // 0x08 Kernel code segment
|
||||||
gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // Data segment
|
gdt_set_gate(2, 0x0, 0xFFFFFFFF, 0x92, 0xCF); // 0x10 Kernel Data segment
|
||||||
gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // User code segment
|
gdt_set_gate(3, 0x0, 0xFFFFFFFF, 0xFA, 0xCF); // 0x18 User code segment
|
||||||
gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // User data segment
|
gdt_set_gate(4, 0x0, 0xFFFFFFFF, 0xF2, 0xCF); // 0x20 User data segment
|
||||||
|
|
||||||
tss_install(5, 0x10, stack_top);
|
tss_install(5, 0x10, stack_top);
|
||||||
|
|
||||||
|
16
io.c
16
io.c
@ -12,9 +12,23 @@ uint8_t inb(uint16_t port)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait(void)
|
void io_wait(void)
|
||||||
{
|
{
|
||||||
asm volatile("jmp 1f\n\t"
|
asm volatile("jmp 1f\n\t"
|
||||||
"1:jmp 2f\n\t"
|
"1:jmp 2f\n\t"
|
||||||
"2:");
|
"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;
|
||||||
|
}
|
3
io.h
3
io.h
@ -7,4 +7,7 @@ void outb(uint16_t port, uint8_t val);
|
|||||||
uint8_t inb(uint16_t port);
|
uint8_t inb(uint16_t port);
|
||||||
void io_wait(void);
|
void io_wait(void);
|
||||||
|
|
||||||
|
void outb_wait(uint16_t port, uint8_t val);
|
||||||
|
uint8_t inb_wait(uint16_t port);
|
||||||
|
|
||||||
#endif
|
#endif
|
2
isr.c
2
isr.c
@ -55,7 +55,9 @@ void isr_call_handler(Stack *registers)
|
|||||||
void (*handler)(Stack *registers);
|
void (*handler)(Stack *registers);
|
||||||
handler = isr_routines[registers->id];
|
handler = isr_routines[registers->id];
|
||||||
if (handler)
|
if (handler)
|
||||||
|
{
|
||||||
handler(registers);
|
handler(registers);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void isr_install(void)
|
void isr_install(void)
|
||||||
|
7
kernel.c
7
kernel.c
@ -12,9 +12,11 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "user_space.h"
|
#include "user_space.h"
|
||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
void kernel_main(void)
|
void kernel_main(void)
|
||||||
{
|
{
|
||||||
|
terminal_initialize();
|
||||||
gdt_install();
|
gdt_install();
|
||||||
|
|
||||||
idt_install();
|
idt_install();
|
||||||
@ -24,17 +26,18 @@ void kernel_main(void)
|
|||||||
timer_install();
|
timer_install();
|
||||||
keyboard_install();
|
keyboard_install();
|
||||||
|
|
||||||
|
rtc_init();
|
||||||
|
|
||||||
syscall_init();
|
syscall_init();
|
||||||
enter_user_space();
|
enter_user_space();
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
terminal_initialize();
|
|
||||||
for (int i = 1; i < 4; i++)
|
for (int i = 1; i < 4; i++)
|
||||||
{
|
{
|
||||||
terminal_printf("&cTest &7%d\n", i);
|
terminal_printf("&cTest &7%d\n", i);
|
||||||
delay(500);
|
delay(200);
|
||||||
}
|
}
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
|
|
||||||
|
79
rtc.c
Normal file
79
rtc.c
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#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);
|
||||||
|
}
|
29
rtc.h
Normal file
29
rtc.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef RTC_H
|
||||||
|
#define RTC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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
|
14
shell.c
14
shell.c
@ -3,6 +3,7 @@
|
|||||||
#include "shell.h"
|
#include "shell.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "string.h"
|
#include "string.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
void shell_init(void)
|
void shell_init(void)
|
||||||
{
|
{
|
||||||
@ -53,6 +54,7 @@ void shell_help_command(void)
|
|||||||
terminal_printf("exit - Exit the shell.\n");
|
terminal_printf("exit - Exit the shell.\n");
|
||||||
terminal_printf("echo - Print out the message. &eWITH colors!&7\n");
|
terminal_printf("echo - Print out the message. &eWITH colors!&7\n");
|
||||||
terminal_printf("clear - Clear the terminal.\n");
|
terminal_printf("clear - Clear the terminal.\n");
|
||||||
|
terminal_printf("time - Print out the current time. (UTC)\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void shell_exit_command(void)
|
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)
|
void shell_echo_command(char *input)
|
||||||
{
|
{
|
||||||
char *message = input;
|
char *message = input;
|
||||||
@ -102,6 +112,10 @@ void shell_parse_input(char *input)
|
|||||||
{
|
{
|
||||||
terminal_clear();
|
terminal_clear();
|
||||||
}
|
}
|
||||||
|
else if (strcmp(command, "time") == 0)
|
||||||
|
{
|
||||||
|
shell_time_command();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
terminal_printf("Unknown command: '");
|
terminal_printf("Unknown command: '");
|
||||||
|
13
string.c
13
string.c
@ -21,6 +21,19 @@ void *memset(void *ptr, int value, size_t size)
|
|||||||
return ptr;
|
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)
|
int strcmp(const char *str1, const char *str2)
|
||||||
{
|
{
|
||||||
while (*str1 && (*str1 == *str2))
|
while (*str1 && (*str1 == *str2))
|
||||||
|
1
string.h
1
string.h
@ -10,5 +10,6 @@ size_t strlen(const char *str);
|
|||||||
void itoa(int value, char *str, int base);
|
void itoa(int value, char *str, int base);
|
||||||
|
|
||||||
void *memset(void *ptr, int value, size_t size);
|
void *memset(void *ptr, int value, size_t size);
|
||||||
|
void memcpy(void *vd, const void *vs, unsigned length);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -6,11 +6,13 @@
|
|||||||
#include "syscall.h"
|
#include "syscall.h"
|
||||||
#include "tty.h"
|
#include "tty.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
#include "rtc.h"
|
||||||
|
|
||||||
#define NB_SYSCALL 2
|
#define NB_SYSCALL 3
|
||||||
|
|
||||||
void *syscalls[NB_SYSCALL] = {
|
void *syscalls[NB_SYSCALL] = {
|
||||||
keyboard_getchar,
|
keyboard_getchar,
|
||||||
|
get_rtc_time,
|
||||||
|
|
||||||
sys_halt};
|
sys_halt};
|
||||||
|
|
||||||
|
34
tty.c
34
tty.c
@ -129,6 +129,21 @@ void terminal_print(const char *data)
|
|||||||
terminal_write(data, strlen(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, ...)
|
void terminal_printf(const char *format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -137,24 +152,29 @@ void terminal_printf(const char *format, ...)
|
|||||||
const char *p = format;
|
const char *p = format;
|
||||||
while (*p)
|
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++;
|
p++;
|
||||||
|
int padding = 0;
|
||||||
|
|
||||||
|
if (*p == '0')
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
padding = *p - '0';
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
if (*p == 's')
|
if (*p == 's')
|
||||||
{
|
{
|
||||||
terminal_print(va_arg(args, const char *));
|
terminal_print(va_arg(args, const char *));
|
||||||
}
|
}
|
||||||
else if (*p == 'd')
|
else if (*p == 'd')
|
||||||
{
|
{
|
||||||
char buffer[12];
|
print_number(va_arg(args, int), 10, padding);
|
||||||
itoa(va_arg(args, int), buffer, 10);
|
|
||||||
terminal_print(buffer);
|
|
||||||
}
|
}
|
||||||
else if (*p == 'x')
|
else if (*p == 'x')
|
||||||
{
|
{
|
||||||
char buffer[12];
|
print_number(va_arg(args, unsigned int), 16, padding);
|
||||||
itoa(va_arg(args, unsigned int), buffer, 16);
|
|
||||||
terminal_print(buffer);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (*p == '&' && ((*(p + 1) >= '0' && *(p + 1) <= '9') || (*(p + 1) >= 'a' && *(p + 1) <= 'f')))
|
else if (*p == '&' && ((*(p + 1) >= '0' && *(p + 1) <= '9') || (*(p + 1) >= 'a' && *(p + 1) <= 'f')))
|
||||||
|
Loading…
Reference in New Issue
Block a user