From 6243b46072026ef735d0641109c1e34f534e9112 Mon Sep 17 00:00:00 2001 From: rami Date: Tue, 6 Aug 2024 21:12:43 -0400 Subject: [PATCH] uptime command and vga textmode scrolling --- Makefile | 2 +- boot/initrd | Bin 1040 -> 1512 bytes include/kernel/acpi.h | 3 ++ include/kernel/kernel.h | 7 +++ include/kernel/tty.h | 21 +++++++++ include/kernel/vga.h | 67 +++++++++++++++++++++++++++ kernel/acpi.c | 37 +++++++++++++++ kernel/init.asm | 2 + kernel/kernel.c | 78 ++++++++++---------------------- kernel/log.c | 1 + kernel/ps2.c | 16 ++++--- kernel/task.c | 24 ---------- kernel/tty.c | 14 ++++++ kernel/vga.c | 98 ++++++++++++++++++++++++++++++++++++++++ user/shell.c | 60 ++++++++++++++++++++++-- 15 files changed, 343 insertions(+), 87 deletions(-) create mode 100644 include/kernel/tty.h create mode 100644 include/kernel/vga.h create mode 100644 kernel/tty.c create mode 100644 kernel/vga.c diff --git a/Makefile b/Makefile index b3fc9e0..e17f7a8 100644 --- a/Makefile +++ b/Makefile @@ -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) diff --git a/boot/initrd b/boot/initrd index d3b310eb58807d2ea750bd6ab485126a2cee35f2..0430873b8473f2cedbe31a8ff409f0eeb878982f 100755 GIT binary patch literal 1512 zcma)6U1$_n6h6C-I+3+Il`51XnLr*~Y*%9g6wAn5+TAFa2CVzkLLY)q3Tu;xwOxpn)b%^_W4CX;aOS(;Io~<= z&Y64Xg7)#@Kp;T=2+}%YCS8)`ZeUe%Bi*FJzk@c?1}E-#rzM$Sv2{dj>)EMbE`DE@ zZA}i?S}0J|k7}5BlDs-wk+A&8fvUL zH41-Xwo{XTWX30;8?(IWANV1Dnqzo4eZ#&lorpX2Mn{I41-bTZv)P1G zRElGAOTv;^gu0|Rj{hq!_RGbXQXC73M`CFf^|+uPpAEX)sXa1;-9FG7ta+f-8A>s1 zsXmLAkoZ|VdN^Iw8lrNSLq)AV$0+8z%54j6zuNbe<0rg#mhE#gO>I8?PHnrp(bX|_ zwVm(8Zstx-PELx2)jveF@+?^SyIm|ss`g4~uvT`&N~@;wJSY|_&)T`6mB+zAHBgRJ z#GJN#YHrqgc!(G}1+=9No z2HbN|k~e#NEAT4#IgfKmzN38JSl`Zwxa#pv;C}F4kM9J=ZsNXTC={gkfVZ*U+d$6$ z05}Z3-{U>NR{c@%Ph0W_z;8m&>u^3ft&2`ju3(vz*T=J2i*or>87mHhBax&+&N`LW zDIOm;&A4eL@=z442{NtxL^?-tJ(;i)fJ~BIDLq3JHK)>6VjO7YT{QferGIWwG@o^n zqTGBP3;o~m7KHo_Ho*A3hk@Vlwf2VpeLBE-&LO@C4NMZAhQa$iQUr6>`JbBqhg(?S x4UYNNvJ4r}Jw}ZGo$Tj&3XIPK|3CcEi@=CafLx2m>#$bc*U;^8BJRW2y#z2b!VCZa delta 536 zcmaFCJ%M9_1lR2b77h~z28JI@6P1+MZZI-1++dvOYsoA|L*`wG3;~zDY*W5bw)!Y3&)EI|NsAQKEjf*2*hcIa==x4hDwFUzn5_?Iw#eD=U}gW#{FW=P4xT=jJBnr6_VSxH~&rDQLL+ zg=#7o8tWP98BD&&B0RZ*S)_h4Fes#fUJ(L1mJdju1M+#He0d-Z3aZ6Wz9^7h2jnY2 z`BFgo#zYnlAjKfSz{H>iq(gx6_COkBo-U9^mInnnGM}M1!!$J~M=zP7ptPizp(r&e zKfeS>C8jXM$0rpR#}}6*7L_m*mlP%E7BIx8rX-dm0;#-|$#YqvCx2%VWzu4t%*QIn z35tRSVEjZ(Hf2?2y1_U(idBvE4Nzdg #include #include +#include #define cpu_relax asm volatile ("pause" ::) #define CHECK_FLAG(x, n) (x & (1< + +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 diff --git a/include/kernel/vga.h b/include/kernel/vga.h new file mode 100644 index 0000000..3de6cc6 --- /dev/null +++ b/include/kernel/vga.h @@ -0,0 +1,67 @@ +#ifndef HAZEL_VGA_H_ +#define HAZEL_VGA_H_ + + +#include + +/* + * 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 diff --git a/kernel/acpi.c b/kernel/acpi.c index 284a8da..31fe453 100644 --- a/kernel/acpi.c +++ b/kernel/acpi.c @@ -1,6 +1,8 @@ #include #include +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; +} diff --git a/kernel/init.asm b/kernel/init.asm index 34a17cf..6f9936c 100644 --- a/kernel/init.asm +++ b/kernel/init.asm @@ -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 diff --git a/kernel/kernel.c b/kernel/kernel.c index 91ce9c5..611c842 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -10,6 +10,7 @@ #include #include #include +#include #include kernel_ctx_t ctx = {0}; @@ -34,9 +35,12 @@ 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]); + } + } } void syscall_read(stack_frame_t r) { @@ -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,10 +121,11 @@ 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 - if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data + if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data if (serial_port_init(COM1)) ctx.log_method = LOG_COM1; LOG("Kernel log being sent to COM1\n"); @@ -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); } } } @@ -160,7 +157,7 @@ void kernel(multiboot_info_t *info) { asm volatile ("sti" ::); ctx.ticks = 0; pit_init(); - + // Setup TSS uint32_t base = (uint32_t)&tss; uint32_t limit = base + sizeof(tss_t); @@ -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}; diff --git a/kernel/log.c b/kernel/log.c index a3ee681..0891458 100644 --- a/kernel/log.c +++ b/kernel/log.c @@ -1,6 +1,7 @@ #include #include #include +#include extern kernel_ctx_t ctx; diff --git a/kernel/ps2.c b/kernel/ps2.c index 8bcb2ac..535ed3d 100644 --- a/kernel/ps2.c +++ b/kernel/ps2.c @@ -2,6 +2,7 @@ #include #include #include +#include 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; diff --git a/kernel/task.c b/kernel/task.c index 7a5f83b..b364bd3 100644 --- a/kernel/task.c +++ b/kernel/task.c @@ -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; diff --git a/kernel/tty.c b/kernel/tty.c new file mode 100644 index 0000000..a0f841b --- /dev/null +++ b/kernel/tty.c @@ -0,0 +1,14 @@ +#include +#include + +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; + } +} diff --git a/kernel/vga.c b/kernel/vga.c new file mode 100644 index 0000000..23a34d9 --- /dev/null +++ b/kernel/vga.c @@ -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 +#include +#include +#include + +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; +} diff --git a/user/shell.c b/user/shell.c index 08d6b16..9ca0db6 100644 --- a/user/shell.c +++ b/user/shell.c @@ -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");