uptime command and vga textmode scrolling

This commit is contained in:
rami 2024-08-06 21:12:43 -04:00
parent c60b008e94
commit 6243b46072
15 changed files with 343 additions and 87 deletions

View File

@ -19,7 +19,7 @@ ISO := Hazel.iso
CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib
LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld
QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) -s -m 512M -serial stdio
QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) -s -m 512M -serial stdio -device virtio-gpu
$(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ)
$(CC) $^ -o $@ $(LDFLAGS)

Binary file not shown.

View File

@ -111,8 +111,11 @@ typedef struct {
struct GenericAddressStructure X_GPE1Block;
} fadt_t;
typedef _Bool bool;
rsdp_t *acpi_find_rsdp();
uint8_t acpi_checksum(void *s, int size);
void *acpi_find_sdt(rsdt_t *rsdt, const char *sig);
bool acpi_init();
#endif

View File

@ -4,11 +4,17 @@
#include <kernel/multiboot.h>
#include <kernel/log.h>
#include <kernel/task.h>
#include <kernel/acpi.h>
#define cpu_relax asm volatile ("pause" ::)
#define CHECK_FLAG(x, n) (x & (1<<n))
#define TRUE 1
#define FALSE 0
typedef _Bool bool;
#define KERNEL_VMA 0xC0000000
#define KERNEL_LMA 0x00010000
typedef struct {
multi_mmap_t *multi_mmap;
@ -18,6 +24,7 @@ typedef struct {
log_method_t log_method;
uint64_t ticks;
task_t *current_task;
rsdt_t *rsdt;
} kernel_ctx_t;
#define GDT_NULL 0

21
include/kernel/tty.h Normal file
View File

@ -0,0 +1,21 @@
#ifndef HAZEL_TTY_H_
#define HAZEL_TTY_H_
#include <stdint.h>
typedef enum {
DEV_COM1,
DEV_VGA_TXT,
} dev_t;
typedef struct {
dev_t dev;
uint8_t *output;
uint8_t *input;
uint32_t output_len;
uint32_t input_len;
} tty_t;
#endif

67
include/kernel/vga.h Normal file
View File

@ -0,0 +1,67 @@
#ifndef HAZEL_VGA_H_
#define HAZEL_VGA_H_
#include <stdint.h>
/*
* Location of the linear text buffer
* Used to directly modify text on screen
* 80 columns by 25 rows
*/
#define VGA_MEMORY_ADDR 0xb8000
#define VGA_MAX_COLS 80
#define VGA_MAX_ROWS 25
#define CRTC_ADDR_PORT 0x3d4
#define CRTC_DATA_PORT 0x3d5
#define CRTC_CURSOR_LO_REGISTER 0x0f
#define CRTC_CURSOR_HI_REGISTER 0x0e
enum VGA_COLOR {
VGA_COLOR_BLACK = 0,
VGA_COLOR_BLUE = 1,
VGA_COLOR_GREEN = 2,
VGA_COLOR_CYAN = 3,
VGA_COLOR_RED = 4,
VGA_COLOR_MAGENTA = 5,
VGA_COLOR_BROWN = 6,
VGA_COLOR_LIGHT_GREY = 7,
VGA_COLOR_DARK_GREY = 8,
VGA_COLOR_LIGHT_BLUE = 9,
VGA_COLOR_LIGHT_GREEN = 10,
VGA_COLOR_LIGHT_CYAN = 11,
VGA_COLOR_LIGHT_RED = 12,
VGA_COLOR_LIGHT_MAGENTA = 13,
VGA_COLOR_LIGHT_BROWN = 14,
VGA_COLOR_WHITE = 15
};
/**
* @brief Gets the text-mode cursor's position.
*
* @return The position, not offset, of the cursor. Multiply this by two for the offset.
*/
uint16_t get_cursor_pos();
/**
* @brief Sets the cursor's position in VGA text-mode.
*
* @param pos The position, not offset, of the cursor. Multiply by two for the offset.
*/
void set_cursor_pos(uint16_t pos);
/**
* @brief Clears the screen in VGA text-mode by overwriting every character with a zero, then resets the cursor position.
*/
void clear_screen(void);
void vga_putc(char c);
void popchar();
void set_color(enum VGA_COLOR col);
#endif

View File

@ -1,6 +1,8 @@
#include <kernel/acpi.h>
#include <kernel/kernel.h>
extern kernel_ctx_t ctx;
rsdp_t *acpi_find_rsdp() {
char *ptr = (char *)(KERNEL_VMA + BIOS_START);
const char sig[RSDP_SIG_LEN] = RSDP_SIG;
@ -38,3 +40,38 @@ void *acpi_find_sdt(rsdt_t *rsdt, const char *sig) {
return 0;
}
bool acpi_init() {
rsdp_t *rsdp = acpi_find_rsdp();
if (!rsdp) {
LOG("Invalid RSDP\n");
return FALSE;
}
if (!acpi_checksum(rsdp, sizeof(rsdp_t))) {
LOG("Invalid RSDP checksum\n");
return FALSE;
}
if (rsdp->Revision == 0) LOG("Using ACPI version 1.0\n")
else if (rsdp->Revision == 2) {
LOG("ACPI versions higher than 1.0 are not currently supported!\n");
return FALSE;
}
rsdt_t *rsdt = (rsdt_t *)(rsdp->RsdtAddress);
if (!rsdt) {
LOG("Invalid RSDT\n");
return FALSE;
}
if (!acpi_checksum(rsdt, rsdt->hdr.Length)) {
LOG("Invalid RSDT checksum\n");
return FALSE;
}
ctx.rsdt = rsdt;
LOG("RSDT is valid\n");
void *mcfg = acpi_find_sdt(rsdt, "MCFG");
if (!mcfg) LOG("PCIe not supported\n");
return TRUE;
}

View File

@ -280,11 +280,13 @@ boot_page_tab: times 1024 dd 0
extern syscall_read
extern syscall_write
extern syscall_reboot
extern syscall_uptime
global syscall_table
syscall_table:
dd syscall_read
dd syscall_write
dd syscall_reboot
dd syscall_uptime
section .bss
align 16

View File

@ -10,6 +10,7 @@
#include <kernel/ps2.h>
#include <kernel/acpi.h>
#include <kernel/pci.h>
#include <kernel/vga.h>
#include <stdint.h>
kernel_ctx_t ctx = {0};
@ -34,8 +35,11 @@ extern uint32_t boot_page_tab[1024];
void syscall_write(stack_frame_t r) {
uint32_t fd = r.edi;
uint8_t *buf = (uint8_t *)r.esi;
int len = r.edx;
if (fd == FD_STDOUT) {
LOG("%s", buf);
for (int i = 0; i < len; i++) {
vga_putc(buf[i]);
}
}
}
@ -62,8 +66,10 @@ void syscall_reboot(stack_frame_t r) {
}
void syscall_uptime(stack_frame_t r) {
uint64_t *buf = (uint64_t *)r.esi;
*buf = ctx.ticks;
uint32_t *low = (uint32_t *)r.esi;
uint32_t *high = (uint32_t *)r.edi;
*low = (uint32_t)ctx.ticks;
*high = (uint32_t)(ctx.ticks >> 32);
}
void exception_handler(int_stack_frame_t r) {
@ -76,15 +82,20 @@ void exception_handler(int_stack_frame_t r) {
if (r.int_no == 0xe) {
uint32_t cr2 = 0;
asm volatile ("mov %%cr2, %0" : "=r" (cr2));
LOG("CR2: 0x%08X\n", cr2)
if ((boot_page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000) == 0) {
uint32_t cr3 = 0;
asm volatile ("mov %%cr3, %0" : "=r" (cr3));
uint32_t *page_dir = (uint32_t *)(KERNEL_VMA + cr3);
if ((page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000) == 0) {
LOG("Creating new page table\n");
uint32_t *page_tab = mmap_find_first_free_block();
if (!page_tab) for (;;) {}
page_tab[PAGE_TAB_INDEX(cr2)] = (cr2 & 0xFFFFF000) | 7;
boot_page_dir[PAGE_DIR_INDEX(cr2)] = ((uint32_t)page_tab - KERNEL_VMA) | 7;
page_dir[PAGE_DIR_INDEX(cr2)] = ((uint32_t)page_tab - KERNEL_VMA) | 7;
} else {
uint32_t *page_tab = (uint32_t *)(KERNEL_VMA + (boot_page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000));
uint32_t *page_tab = (uint32_t *)(KERNEL_VMA + (page_dir[PAGE_DIR_INDEX(cr2)] & 0xFFFFF000));
page_tab[PAGE_TAB_INDEX(cr2)] = (cr2 & 0xFFFFF000) | 7;
}
}
@ -100,7 +111,7 @@ void idt_init(void) {
for (int i = 0; i < 32; i++) {
idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
}
idt_encode_entry(idt, 32, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
idt_encode_entry(idt, 0x20, (uint32_t)pit_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
idt_encode_entry(idt, 0x21, (uint32_t)ps2_isr, GDT_SEGMENT_SELECTOR(GDT_KERNEL_CODE, RING0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT);
idt_encode_entry(idt, 0x80, (uint32_t)syscall_isr, GDT_SEGMENT_SELECTOR(GDT_USER_CODE, RING3), TRAP_GATE_32 | INT_RING3 | INT_PRESENT);
@ -110,6 +121,7 @@ void idt_init(void) {
asm volatile ("lidt %0" :: "m"(idtr));
}
void kernel(multiboot_info_t *info) {
if (!CHECK_FLAG(info->flags, 3)) goto halt; // Modules
if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map
@ -125,23 +137,8 @@ void kernel(multiboot_info_t *info) {
if (!mmap_init()) goto halt;
LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, (uint32_t)ctx.mmap);
rsdp_t *rsdp = acpi_find_rsdp();
if (!rsdp) goto halt;
if (!acpi_checksum(rsdp, sizeof(rsdp_t))) goto halt;
if (rsdp->Revision == 0) LOG("Using ACPI version 1.0\n")
else if (rsdp->Revision == 2) {
LOG("ACPI versions higher than 1.0 are not currently supported!\n");
goto halt;
}
rsdt_t *rsdt = (rsdt_t *)(rsdp->RsdtAddress);
if (!rsdt) goto halt;
if (!acpi_checksum(rsdt, rsdt->hdr.Length)) goto halt;
LOG("RSDT is valid\n");
void *mcfg = acpi_find_sdt(rsdt, "MCFG");
if (!mcfg) LOG("PCIe not supported\n");
clear_screen();
acpi_init();
for (int i = 0; i < 256; i++) {
for (int j = 0; j < 32; j++) {
@ -150,7 +147,7 @@ void kernel(multiboot_info_t *info) {
uint8_t class = (uint8_t)(w >> 8);
uint8_t subclass = (uint8_t)w;
if (class == 0xFF) continue;
LOG("Class: %04X | Subclass: %04X\n", class, subclass);
LOG("PCI Class: %04X | Subclass: %04X\n", class, subclass);
}
}
}
@ -180,31 +177,6 @@ void kernel(multiboot_info_t *info) {
tss.ss = tss.ds = tss.es = tss.fs = tss.gs = GDT_SEGMENT_SELECTOR(GDT_USER_DATA, RING3);
flush_tss(GDT_SEGMENT_SELECTOR(5, RING3));
/*
task_t task1 = {0};
task_t task2 = {0};
task1.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA;
task1.next = (uint32_t *)&task2;
ctx.current_task = &task1;
uint32_t *stack = mmap_find_first_free_block();
asm volatile ("mov %%esp, %0" : "=r" (task1.esp));
stack[1023] = 0x207;
stack[1022] = 0x8;
stack[1021] = (uint32_t)test;
stack[1020] = 0xDEADBEEF;
stack[1019] = 0xDEADBEEF;
stack[1018] = 0xDEADBEEF;
stack[1017] = 0xDEADBEEF;
stack[1016] = 0xDEADBEEF;
stack[1015] = 0xDEADBEEF;
stack[1014] = 0xDEADBEEF;
stack[1013] = 0xDEADBEEF;
task2.esp = (uint32_t)stack + (0x1000 - 44);
task2.cr3 = (uint32_t)boot_page_dir - KERNEL_VMA;
task2.next = 0;
*/
multi_mod_t *init = (multi_mod_t *)(info->moduleaddress + KERNEL_VMA);
elf_t *elf = (elf_t *)(init->mod_start+KERNEL_VMA);
task_t task = {0};

View File

@ -1,6 +1,7 @@
#include <kernel/log.h>
#include <kernel/kernel.h>
#include <kernel/serial.h>
#include <kernel/vga.h>
extern kernel_ctx_t ctx;

View File

@ -2,6 +2,7 @@
#include <kernel/io.h>
#include <kernel/pic.h>
#include <kernel/mem.h>
#include <kernel/vga.h>
extern kernel_ctx_t ctx;
char shell_buffer[512] = {0};
@ -52,7 +53,11 @@ void ps2_init() {
void push_stdin(const char c) {
ctx.current_task->stdin[ctx.current_task->stdin_len++] = c;
_putchar(c);
vga_putc(c);
}
void pop_stdin() {
ctx.current_task->stdin[--ctx.current_task->stdin_len] = 0;
}
void ps2_handler() {
@ -100,11 +105,10 @@ void ps2_handler() {
push_stdin('=');
break;
case KBD_BACKSPACE:
/*
if (shell_index > 0) {
//popchar();
shell_buffer[--shell_index] = 0;
}*/
if (ctx.current_task->stdin_len > 0) {
popchar();
pop_stdin();
}
break;
case KBD_TAB:
break;

View File

@ -10,23 +10,8 @@ int task_init(task_t *task, elf_t *elf) {
if (!elf) return 0;
uint8_t *s = (uint8_t *)mmap_find_first_free_block();
/*
memset(s, 0, 0x1000);
int idx = 0;
// Loop section header to find ALLOC sections then allocate them
for (int i = 0; i < elf->e_shnum; i++) {
section_t *sec = (section_t *)((uint32_t)elf + elf->e_shoff + i*elf->e_shentsize);
if (!(sec->sh_flags & 0x2)) continue;
if (!sec->sh_addr) continue;
idx += sec->sh_offset;
memcpy(s + idx, (void *)((uint32_t)elf + sec->sh_offset), sec->sh_offset);
LOG("%d\n", sec->sh_offset);
}
*/
memcpy(s, elf, 0x1000);
//section_t *text = elf_find_section(elf, ".text");
//if (!text) return 0;
task->eip = elf->e_entry;
// Allocate a page for a stack
task->esp = (uint32_t)mmap_find_first_free_block() + 0x1000;
@ -47,16 +32,7 @@ int task_init(task_t *task, elf_t *elf) {
else page_dir[i] = 6;
}
// Map the ELF image to its specified entry
// This will cause problems if the ELF image is larger than 4 MiB so I need to fix this
//page_dir[PAGE_DIR_INDEX(elf->e_entry)] = ((uint32_t)page_tab - KERNEL_VMA) | 7;
page_dir[PAGE_DIR_INDEX(elf->e_entry)] = ((uint32_t)page_tab - KERNEL_VMA) | 7;
/*
uint32_t elf_phys = (uint32_t)s - KERNEL_VMA;
for (int i = 0; i < 1024; i++) {
page_tab[i] = (elf_phys + 0x1000*i) | 7;
}
*/
page_tab[PAGE_TAB_INDEX(elf->e_entry)] = ((uint32_t)s - KERNEL_VMA) | 7;
return 1;

14
kernel/tty.c Normal file
View File

@ -0,0 +1,14 @@
#include <kernel/serial.h>
#include <kernel/tty.h>
void tty_putc(tty_t *tty, char c) {
switch (tty->dev) {
case DEV_COM1:
serial_putc(COM1, c);
break;
case DEV_VGA_TXT:
break;
default:
break;
}
}

98
kernel/vga.c Normal file
View File

@ -0,0 +1,98 @@
/**
* @file vga.c
* @brief Basic functions for interacting with the CRTC controller in VGA text-mode.
* @author rami
* @version 0.1
* @date 2024-02-03
*/
#include <kernel/vga.h>
#include <kernel/io.h>
#include <kernel/log.h>
#include <kernel/mem.h>
enum VGA_COLOR vga_color = VGA_COLOR_WHITE;
uint16_t get_cursor_pos() {
uint16_t pos = 0;
/* Tell CRTC controller we want the low cursor position */
outb(CRTC_ADDR_PORT, CRTC_CURSOR_LO_REGISTER);
/* Read it through the data port */
pos = inb(CRTC_DATA_PORT);
/* Repeat with high position */
outb(CRTC_ADDR_PORT, CRTC_CURSOR_HI_REGISTER);
uint16_t hi_pos = 0;
hi_pos = inb(CRTC_DATA_PORT);
pos |= hi_pos << 8;
return pos;
}
void set_cursor_pos(uint16_t pos) {
/* Tell CRTC controller we want the low cursor position */
outb(CRTC_ADDR_PORT, CRTC_CURSOR_LO_REGISTER);
outb(CRTC_DATA_PORT, (uint8_t)(pos & 0xFF));
/* Repeat with high position */
outb(CRTC_ADDR_PORT, CRTC_CURSOR_HI_REGISTER);
outb(CRTC_DATA_PORT, (uint8_t)((pos >> 8) & 0xFF));
}
void clear_screen(void) {
char *video_memory = (char *)VGA_MEMORY_ADDR;
for (int i = 0; i < VGA_MAX_COLS * VGA_MAX_ROWS; i++) {
video_memory[i * 2] = 0;
}
set_cursor_pos(0);
}
void vga_putc(char character) {
uint16_t pos = get_cursor_pos();
if (pos == VGA_MAX_COLS * VGA_MAX_ROWS) {
if (character != '\n') {
// Move video memory up one row
memcpy((char*)VGA_MEMORY_ADDR, (char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*2), VGA_MAX_COLS * (VGA_MAX_ROWS - 1) * 2);
// Clear last row
for (int i = 0; i < VGA_MAX_COLS*2; i+=2) {
((char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*(VGA_MAX_ROWS - 1)*2))[i] = 0;
((char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*(VGA_MAX_ROWS - 1)*2))[i+1] = 0x0f;
}
pos = VGA_MAX_COLS * (VGA_MAX_ROWS - 1);
} else {
// Move video memory up two rows
memcpy((char*)VGA_MEMORY_ADDR, (char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*2*2), VGA_MAX_COLS * (VGA_MAX_ROWS - 2) * 2);
// Clear last 2 rows
for (int i = 0; i < VGA_MAX_COLS*2*2; i+=2) {
((char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*(VGA_MAX_ROWS - 2)*2))[i] = 0;
((char *)(VGA_MEMORY_ADDR + VGA_MAX_COLS*(VGA_MAX_ROWS - 2)*2))[i+1] = 0x0f;
}
pos = VGA_MAX_COLS * (VGA_MAX_ROWS - 2);
}
}
char *video_memory = (char *)VGA_MEMORY_ADDR + pos * 2;
if (character == '\n') {
uint16_t next_line = VGA_MAX_COLS * (pos / VGA_MAX_COLS + 1);
set_cursor_pos(next_line);
} else {
video_memory[0] = character;
video_memory[1] = vga_color;
set_cursor_pos(pos + 1);
}
}
void popchar() {
uint16_t pos = get_cursor_pos();
if (pos == 0) return;
char *video_memory = (char *)(VGA_MEMORY_ADDR + (pos - 1) * 2);
video_memory[0] = 0;
set_cursor_pos(pos - 1);
}
void set_color(enum VGA_COLOR col) {
vga_color = col;
}

View File

@ -1,14 +1,36 @@
#include "../lib/strcmp.h"
int strlen(const char *str) {
const char *s;
for (s = str; *s; s++)
;
return s - str;
}
void putc(const char c) {
asm volatile (
"movl $1, %%eax\n\t"
"movl $1, %%edi\n\t"
"movl %0, %%esi\n\t"
"movl $1, %%edx\n\t"
"int $0x80"
:
: "r"(&c)
: "%eax", "%edi", "%esi", "%edx"
);
}
void puts(const char *str) {
asm volatile (
"movl $1, %%eax\n\t"
"movl $1, %%edi\n\t"
"movl %0, %%esi\n\t"
"movl %1, %%edx\n\t"
"int $0x80"
:
: "r"(str)
: "%eax", "%edi", "%esi"
: "r"(str), "r"(strlen(str))
: "%eax", "%edi", "%esi", "%edx"
);
}
@ -32,18 +54,50 @@ void reboot() {
);
}
uint64_t uptime() {
uint32_t low = 0;
uint32_t high = 0;
asm volatile (
"movl $3, %%eax\n\t"
"movl %0, %%esi\n\t"
"movl %1, %%edi\n\t"
"int $0x80"
:
: "r" (&low), "r" (&high)
: "eax", "esi"
);
return (uint64_t)low | ((uint64_t)high << 32);
}
extern char *buf;
void print_int(int num){
if (num < 0)
{
putc('-');
num = -num;
}
if (num > 9) print_int(num/10);
putc(('0'+ (num%10)));
}
void _start() {
char buf1[256] = {0};
puts("Welcome to the Hazel user shell!\n");
while (1) {
puts("> ");
puts("$ ");
read(0, buf1, 256);
if (!strcmp(buf1, "SKIBIDI")) {
puts("dop dop yes yes!\n");
} else if (!strcmp(buf1, "REBOOT")) {
reboot();
} else if (!strcmp(buf1, "UPTIME")) {
uint64_t ticks = uptime();
print_int(ticks);
puts("\n");
}
else {
puts("unknown command!\n");