This commit is contained in:
Tyler Murphy 2023-07-16 19:56:56 -04:00
parent fbf131b5c0
commit 8ad6ef551e
18 changed files with 362 additions and 50 deletions

2
.env
View file

@ -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

2
.gitignore vendored
View file

@ -1,4 +1,4 @@
/boot
/iso
/os.iso
/kernel/bin
/libk/bin

View file

@ -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:

View file

@ -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 $@

30
kernel/include/time.h Normal file
View file

@ -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);

View file

@ -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;

View file

@ -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
};

View file

@ -9,7 +9,7 @@ fpu_init:
cmp word [test], 0
jne no_fpu
xor eax, 0
mov eax, 0
ret
no_fpu:

138
kernel/src/drivers/cmos.c Normal file
View file

@ -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;
}

0
kernel/src/drivers/vga.c Normal file
View file

0
kernel/src/drivers/vga.h Normal file
View file

View file

@ -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));

View file

@ -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);
}

View file

@ -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();
}
}

146
kernel/src/print/time.c Normal file
View file

@ -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';
}

View file

@ -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();
}

View file

@ -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);