uptime command and vga textmode scrolling
This commit is contained in:
parent
c60b008e94
commit
6243b46072
2
Makefile
2
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)
|
||||
|
|
BIN
boot/initrd
BIN
boot/initrd
Binary file not shown.
|
@ -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
|
||||
|
|
|
@ -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
21
include/kernel/tty.h
Normal 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
67
include/kernel/vga.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,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};
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
16
kernel/ps2.c
16
kernel/ps2.c
|
@ -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;
|
||||
|
|
|
@ -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
14
kernel/tty.c
Normal 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
98
kernel/vga.c
Normal 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;
|
||||
}
|
60
user/shell.c
60
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");
|
||||
|
|
Loading…
Reference in New Issue
Block a user