summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTyler Murphy <=>2023-07-16 19:56:56 -0400
committerTyler Murphy <=>2023-07-16 19:56:56 -0400
commit8ad6ef551e9a1c51a77f3662978c7559556897d6 (patch)
treeed07aeae3122a009385d7db8fc98a61b25c38c99
parentinitial (diff)
downloadfinix-8ad6ef551e9a1c51a77f3662978c7559556897d6.tar.gz
finix-8ad6ef551e9a1c51a77f3662978c7559556897d6.tar.bz2
finix-8ad6ef551e9a1c51a77f3662978c7559556897d6.zip
time
-rw-r--r--.env2
-rw-r--r--.gitignore2
-rw-r--r--Makefile14
-rw-r--r--kernel/Makefile4
-rw-r--r--kernel/include/time.h30
-rw-r--r--kernel/src/boot/tag.c10
-rw-r--r--kernel/src/boot/tag.h3
-rw-r--r--kernel/src/cpu/fpu.asm2
-rw-r--r--kernel/src/drivers/cmos.c138
-rw-r--r--kernel/src/drivers/vga.c0
-rw-r--r--kernel/src/drivers/vga.h0
-rw-r--r--kernel/src/graphics/framebuffer.h15
-rw-r--r--kernel/src/interrupt/idt.asm (renamed from kernel/src/interrupt/isr.asm)0
-rw-r--r--kernel/src/interrupt/idt.c24
-rw-r--r--kernel/src/main.c9
-rw-r--r--kernel/src/print/time.c146
-rw-r--r--kernel/src/tty/term.c11
-rw-r--r--kernel/src/tty/term.h2
18 files changed, 362 insertions, 50 deletions
diff --git a/.env b/.env
index ab3cca2..8884d6d 100644
--- a/.env
+++ b/.env
@@ -3,7 +3,7 @@ LD=i386-elf-ld
AS=nasm
AR=ar
-CFLAGS=-ffreestanding -m32 -O2 -Wall -Wextra -pedantic -DKERNEL_LOG
+CFLAGS=-ffreestanding -m32 -O2 -Wall -Wextra -pedantic # -DKERNEL_LOG
LDFLAGS=-nostdlib
QEMU=qemu-system-i386
diff --git a/.gitignore b/.gitignore
index bf6638d..34dd279 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,4 @@
-/boot
+/iso
/os.iso
/kernel/bin
/libk/bin
diff --git a/Makefile b/Makefile
index c684312..c9fd3aa 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
include .env
-.PHONY: all libk kernel
+.PHONY: all libk kernel clean run
all: os.iso
@@ -11,16 +11,16 @@ kernel:
make --directory=kernel
os.iso: libk kernel
- rm -fr os.iso
- mkdir -p boot/grub
- cp grub.cfg boot/grub
- cp kernel/bin/kernel.bin boot
- grub-mkrescue -o os.iso .
+ @rm -fr os.iso
+ @mkdir -p iso/boot/grub
+ cp grub.cfg iso/boot/grub
+ cp kernel/bin/kernel.bin iso/boot
+ grub-mkrescue -o os.iso iso
clean:
make --directory=libk clean
make --directory=kernel clean
- rm -fr boot
+ rm -fr iso
rm -fr os.iso
run:
diff --git a/kernel/Makefile b/kernel/Makefile
index 999498b..d4cbdf4 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -4,7 +4,7 @@ C_SRC = $(shell find src -type f -name "*.c")
C_OBJ = $(patsubst %.c,bin/%.o, $(C_SRC))
ASM_SRC = $(shell find src -type f -name "*.asm")
-ASM_OBJ = $(patsubst %.asm,bin/%.o, $(ASM_SRC))
+ASM_OBJ = $(patsubst %.asm,bin/%.asm.o, $(ASM_SRC))
CFLAGS += -Iinclude -Isrc -I../libk/include -std=gnu17
@@ -16,7 +16,7 @@ $(C_OBJ): bin/%.o : %.c
@mkdir -p $(@D)
$(CC) -c $(CFLAGS) -o $@ $<
-$(ASM_OBJ): bin/%.o : %.asm
+$(ASM_OBJ): bin/%.asm.o : %.asm
@mkdir -p $(@D)
$(AS) $< -f elf -o $@
diff --git a/kernel/include/time.h b/kernel/include/time.h
new file mode 100644
index 0000000..783d96f
--- /dev/null
+++ b/kernel/include/time.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include <stddef.h>
+
+struct Time {
+ int sec; /// Seconds [0,59]
+ int min; /// Minutes [0,59]
+ int hour; /// Hour [0,23]
+ int mday; /// Day of month [1,31]
+ int mon; /// Month of year [0,11]
+ int year; /// Years since 1900
+ int wday; /// Day of week [0,6] (Sunday = 0)
+ int yday; /// Day of year [0,365]
+ int yn; /// Year number [0,99]
+ int cen; /// Century [19,20]
+ int leap; /// If year is a leap year (True == 1)
+};
+
+extern void rtc_update(void);
+extern void rtc_set_timezone(int offset);
+extern struct Time *rtc_utctime(void);
+extern struct Time *rtc_localtime(void);
+
+/**
+ * Converts the time into a string format
+ * @param time the current time
+ * @param format see manpage for date
+ * @param buf the buffer to store it in
+ */
+extern void timetostr(struct Time *time, char *format, char *buf, size_t n);
diff --git a/kernel/src/boot/tag.c b/kernel/src/boot/tag.c
index 22ea758..d4dd0c9 100644
--- a/kernel/src/boot/tag.c
+++ b/kernel/src/boot/tag.c
@@ -4,7 +4,6 @@
#include "print.h"
#include "tag.h"
#include "acpi/acpi.h"
-#include "graphics/framebuffer.h"
#include "memory/memory.h"
static struct BootInfo info;
@@ -18,12 +17,6 @@ static void read_cmdline(struct BootTag *tag, char *data, uint8_t len) {
info.tags[ID_CMDLINE] = *tag;
}
-static void read_framebuffer(struct BootTag *tag, uint32_t *data) {
- debugk("Found framebuffer");
- tag->data.framebuffer = (struct Framebuffer *) data;
- info.tags[ID_FRAMEBUFFER] = *tag;;
-}
-
static void read_memorymap(struct BootTag *tag, uint32_t *data) {
debugk("Found memorymap");
tag->data.memory_map = (struct MemoryMap *) data;
@@ -48,9 +41,6 @@ static uint32_t *read_tag(uint32_t *data) {
case ID_CMDLINE:
read_cmdline(&tag, (char *)(data + 2), data_len);
break;
- case ID_FRAMEBUFFER:
- read_framebuffer(&tag, data + 2);
- break;
case iD_MEMORYMAP:
read_memorymap(&tag, data + 2);
break;
diff --git a/kernel/src/boot/tag.h b/kernel/src/boot/tag.h
index f9853e5..a81e443 100644
--- a/kernel/src/boot/tag.h
+++ b/kernel/src/boot/tag.h
@@ -4,7 +4,6 @@
#include <stdint.h>
#include "acpi/acpi.h"
-#include "graphics/framebuffer.h"
#include "memory/memory.h"
#define CMDLINE_MAX 32
@@ -15,7 +14,6 @@ struct BootTag {
uint32_t size;
union {
char cmdline[CMDLINE_MAX];
- struct Framebuffer *framebuffer;
struct MemoryMap *memory_map;
struct RootSystemDescriptionPointer *rsdp;
} data;
@@ -30,7 +28,6 @@ struct BootInfo {
enum BootTagID {
ID_CMDLINE = 0,
iD_MEMORYMAP = 6,
- ID_FRAMEBUFFER = 8,
ID_RSDP = 14
};
diff --git a/kernel/src/cpu/fpu.asm b/kernel/src/cpu/fpu.asm
index e49ab6f..d03feba 100644
--- a/kernel/src/cpu/fpu.asm
+++ b/kernel/src/cpu/fpu.asm
@@ -9,7 +9,7 @@ fpu_init:
cmp word [test], 0
jne no_fpu
- xor eax, 0
+ mov eax, 0
ret
no_fpu:
diff --git a/kernel/src/drivers/cmos.c b/kernel/src/drivers/cmos.c
new file mode 100644
index 0000000..5ac12c3
--- /dev/null
+++ b/kernel/src/drivers/cmos.c
@@ -0,0 +1,138 @@
+#include "print.h"
+#include <stdint.h>
+#include <sys.h>
+#include <time.h>
+
+#define CMOS_WRITE_PORT 0x70
+#define CMOS_READ_PORT 0x71
+
+#define CMOS_REG_SEC 0x00
+#define CMOS_REG_MIN 0x02
+#define CMOS_REG_HOUR 0x04
+#define CMOS_REG_WDAY 0x06
+#define CMOS_REG_MDAY 0x07
+#define CMOS_REG_MON 0x08
+#define CMOS_REG_YEAR 0x09
+#define CMOS_REG_CEN 0x32
+
+static struct Time time;
+static struct Time localtime;
+static int cur_offset = 0;
+
+static uint8_t cmos_read(uint8_t reg) {
+ uint8_t hex, ret;
+
+ outb(CMOS_WRITE_PORT, reg);
+ hex = inb(CMOS_READ_PORT);
+
+ ret = hex & 0x0F;
+ ret += (hex & 0xF0) / 16 * 10;
+
+ return ret;
+}
+
+static int mday_offset[12] = {
+ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
+};
+
+static int month_days[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+};
+
+static void update_localtime(void) {
+
+ int change, max;
+
+ // set localtime
+ localtime = time;
+
+ // do we acutally need to do anything
+ if (cur_offset == 0) return;
+ localtime.hour += cur_offset;
+
+ // check if day rolled over
+ change = localtime.hour < 0 ? -1 : localtime.hour >= 24 ? 1 : 0;
+ if (!change) return;
+
+ // roll over day
+ localtime.hour = (localtime.hour + 24) % 24;
+ localtime.wday = (localtime.wday + change + 7) % 7;
+ localtime.mday += change;
+ localtime.yday += change;
+
+ // check if month rolled over
+ max = month_days[localtime.mon];
+ if (localtime.leap && localtime.mon == 1) max++;
+ change = localtime.mday < 0 ? -1 : localtime.mday >= max ? 1 : 0;
+ if (!change) return;
+
+ // roll over month
+ localtime.mon = (localtime.mon + change + 12) % 12;
+
+ // check if year rolled over
+ max = localtime.leap ? 366 : 365;
+ change = localtime.yday < 0 ? -1 : localtime.yday >= max ? 1 : 0;
+ if (!change) return;
+
+ // roll over year
+ localtime.yn += change;
+
+ // check if cen rolled over
+ change = localtime.yn < 0 ? -1 : localtime.yn >= 100 ? 1 : 0;
+ if (!change) goto year;
+
+ // roll over cen
+ localtime.cen += change;
+
+
+year:
+
+ localtime.year = localtime.yn + localtime.cen * 100;
+ localtime.leap = localtime.year % 4 == 0 && localtime.year % 100 != 0;
+
+ if (localtime.leap && localtime.yday == -1)
+ localtime.yday = 365;
+ else if (localtime.yday == -1)
+ localtime.yday = 364;
+ else
+ localtime.yday = 0;
+
+ localtime.year -= 1900;
+
+}
+
+void rtc_set_timezone(int offset) {
+ cur_offset = offset;
+}
+
+void rtc_update(void) {
+ time.sec = cmos_read(CMOS_REG_SEC);
+ time.min = cmos_read(CMOS_REG_MIN);
+ time.hour = cmos_read(CMOS_REG_HOUR);
+ time.wday = cmos_read(CMOS_REG_WDAY) - 1;
+ time.mday = cmos_read(CMOS_REG_MDAY);
+ time.mon = cmos_read(CMOS_REG_MON) - 1;
+ time.yn = cmos_read(CMOS_REG_YEAR);
+ time.cen = 20;
+
+ time.year = time.yn + time.cen * 100;
+
+ time.leap = time.year % 4 == 0 && time.year % 100 != 0;
+
+ time.yday = mday_offset[time.mon] + time.mday;
+
+ if (time.leap && time.mon > 2)
+ time.yday++;
+
+ time.year -= 1900;
+
+ update_localtime();
+}
+
+struct Time *rtc_utctime(void) {
+ return &time;
+}
+
+struct Time *rtc_localtime(void) {
+ return &localtime;
+}
diff --git a/kernel/src/drivers/vga.c b/kernel/src/drivers/vga.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kernel/src/drivers/vga.c
diff --git a/kernel/src/drivers/vga.h b/kernel/src/drivers/vga.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/kernel/src/drivers/vga.h
diff --git a/kernel/src/graphics/framebuffer.h b/kernel/src/graphics/framebuffer.h
deleted file mode 100644
index c3b0dc6..0000000
--- a/kernel/src/graphics/framebuffer.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-struct Framebuffer {
- uint64_t addr;
- uint32_t pitch;
- uint32_t width;
- uint32_t height;
- uint8_t depth;
- uint8_t type;
- uint8_t reserved;
- // struct FramebufferPallete palettes[];
-
-} __attribute__ ((packed));
diff --git a/kernel/src/interrupt/isr.asm b/kernel/src/interrupt/idt.asm
index 6cccdc6..6cccdc6 100644
--- a/kernel/src/interrupt/isr.asm
+++ b/kernel/src/interrupt/idt.asm
diff --git a/kernel/src/interrupt/idt.c b/kernel/src/interrupt/idt.c
index 6df3793..aaa7034 100644
--- a/kernel/src/interrupt/idt.c
+++ b/kernel/src/interrupt/idt.c
@@ -9,25 +9,35 @@
#include "acpi/acpi.h"
#include "drivers/ps2kb.h"
#include "drivers/ps2mouse.h"
+#include "time.h"
#include "tty/color.h"
#include "idt.h"
#include "pic.h"
#include "tty/term.h"
-static int timer = 0;
+#define WIDTH 30
+static char buf[WIDTH];
+static int timer = -1;
void idt_pic_eoi(uint8_t exception) {
pic_eoi(exception - PIC_REMAP_OFFSET);
}
void idt_pic_timer(void) {
- uint32_t state = term_save();
- term_setfg(VGA_LIGHT_GREEN);
- term_setpos(60, 0);
- puts(" ");
- term_setpos(60, 0);
- printk("%d", timer);
+
timer += 1;
+ if (timer % 20 != 0) return;
+
+ uint32_t state = term_save();
+
+ term_setfg(VGA_LIGHT_GREEN);
+ term_setpos(TERM_W - WIDTH - 1, 0);
+ for (size_t i = 0; i < WIDTH; i++) putchar(' ');
+ term_setpos(TERM_W - WIDTH - 1, 0);
+
+ timetostr(rtc_localtime(), "%a %b %d %Y %H:%M:%S", buf, WIDTH);
+ printk("%s", buf);
+
term_load(state);
}
diff --git a/kernel/src/main.c b/kernel/src/main.c
index 2a04c24..7c0f221 100644
--- a/kernel/src/main.c
+++ b/kernel/src/main.c
@@ -6,6 +6,7 @@
#include "drivers/ps2mouse.h"
#include "interrupt/idt.h"
#include "interrupt/pic.h"
+#include "time.h"
#include "tty/cursor.h"
#include "tty/term.h"
@@ -21,6 +22,9 @@ void kernel_main(void* boot_info) {
term_init();
cursor_enable();
+ rtc_set_timezone(-4);
+ rtc_update();
+
idt_init();
pic_remap(PIC_REMAP_OFFSET);
@@ -64,5 +68,8 @@ void kernel_main(void* boot_info) {
y = fclamp(y, 0, TERM_H);
printk(" x%d y%d\n", (int)x, (int)y);
}
- }
+
+ term_flush();
+ rtc_update();
+ }
}
diff --git a/kernel/src/print/time.c b/kernel/src/print/time.c
new file mode 100644
index 0000000..7f52a98
--- /dev/null
+++ b/kernel/src/print/time.c
@@ -0,0 +1,146 @@
+#include <stdbool.h>
+#include <string.h>
+#include <time.h>
+#include <stddef.h>
+
+static char* ABB_WEEKDAY[7] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
+static char* FULL_WEEKDAY[7] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturady"
+};
+
+static char* ABB_MONTH[12] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+
+static char* FULL_MONTH[12] = {
+ "January", "Feburary", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
+};
+
+static char *write_num(unsigned int num, unsigned int pad, char *buf, size_t n) {
+ size_t digits = 1;
+ unsigned int x = num;
+
+ while (x /= 10, x > 0) digits++;
+ if (pad == 0) pad = digits;
+
+ for (size_t i = 0; i < pad; i++) {
+
+ size_t digit;
+ if (i >= digits) {
+ digit = 0;
+ } else {
+ digit = num % 10;
+ num /= 10;
+ }
+
+ if (pad - i - 1 >= n) continue;
+ buf[pad - i - 1] = '0' + digit;
+
+ }
+
+ if (pad > n) pad = n;
+
+ return buf + pad;
+}
+
+void timetostr(struct Time *time, char *format, char *buf, size_t n) {
+ char *index = buf;
+ char c;
+ int space;
+
+ while (
+ c = *format++,
+ space = (buf + n) - index,
+ c != '\0' && space > 0
+ ) {
+ if (c != '%') {
+ *index++ = c;
+ continue;
+ } else {
+ c = *format++;
+ }
+
+ switch (c) {
+ case '%':
+ *index++ = '%';
+ break;
+ case 'a':
+ index = strncpy(index, ABB_WEEKDAY[time->wday], space);
+ break;
+ case 'A':
+ index = strncpy(index, FULL_WEEKDAY[time->wday], space);
+ break;
+ case 'b':
+ case 'h':
+ index = strncpy(index, ABB_MONTH[time->mon], space);
+ break;
+ case 'B':
+ index = strncpy(index, FULL_MONTH[time->mon], space);
+ break;
+ case 'C':
+ index = write_num(time->cen, 0, index, space);
+ break;
+ case 'd':
+ index = write_num(time->mday, 2, index, space);
+ break;
+ case 'H':
+ index = write_num(time->hour, 2, index, space);
+ break;
+ case 'I':
+ index = write_num((time->hour + 12) % 12 + 1, 2, index, space);
+ break;
+ case 'j':
+ index = write_num(time->yday, 3, index, space);
+ break;
+ case 'm':
+ index = write_num(time->mon + 1, 2, index, space);
+ break;
+ case 'M':
+ index = write_num(time->min, 2, index, space);
+ break;
+ case 'n':
+ *index++ = '\n';
+ break;
+ case 'p':
+ index = strncpy(index, time->hour > 11 ? "PM" : "AM", space);
+ break;
+ case 'P':
+ index = strncpy(index, time->hour > 11 ? "pm" : "am", space);
+ break;
+ case 'q':
+ index = write_num((time->mon + 3) / 3, 0, index, space);
+ break;
+ case 'S':
+ index = write_num(time->sec, 2, index, space);
+ break;
+ case 't':
+ *index++ = '\t';
+ break;
+ case 'u':
+ index = write_num(((time->wday + 1 )% 7) + 1, 0, index, space);
+ break;
+ case 'w':
+ index = write_num(time->wday, 0, index, space);
+ break;
+ case 'y':
+ index = write_num(time->yn, 2, index, space);
+ break;
+ case 'Y':
+ index = write_num(time->year + 1900, 0, index, space);
+ break;
+ default: {
+ char b[3] = {'%', c, '\0'};
+ index = strncpy(index, b, space);
+ break;
+ }
+ }
+ }
+
+ if (space < 1)
+ buf[n - 1] = '\0';
+ else
+ *index = '\0';
+}
diff --git a/kernel/src/tty/term.c b/kernel/src/tty/term.c
index 4f75788..231d38b 100644
--- a/kernel/src/tty/term.c
+++ b/kernel/src/tty/term.c
@@ -9,7 +9,8 @@
#include "color.h"
#include "cursor.h"
-uint16_t *buffer;
+uint16_t buffer[TERM_W * TERM_H * sizeof(uint16_t)];
+uint16_t *front;
uint8_t x, y;
uint8_t color;
@@ -27,7 +28,7 @@ static void term_clear_line(int y) {
void term_init (void) {
x = 0;
y = 0;
- buffer = (uint16_t*) 0xb8000;
+ front = (uint16_t*) 0xb8000;
term_setfg(VGA_WHITE);
term_setbg(VGA_BLACK);
term_clear();
@@ -129,3 +130,9 @@ void putchar(int c) {
bool term_newline(void) {
return x == 0;
}
+
+void term_flush(void) {
+ int_disable();
+ memcpy(front, buffer, TERM_W * TERM_H * sizeof(uint16_t));
+ int_enable();
+}
diff --git a/kernel/src/tty/term.h b/kernel/src/tty/term.h
index f6eb555..ceda255 100644
--- a/kernel/src/tty/term.h
+++ b/kernel/src/tty/term.h
@@ -25,3 +25,5 @@ uint16_t term_save_col(void);
void term_load_col(uint16_t color);
bool term_newline(void);
+
+void term_flush(void);