diff --git a/BUGS/boot.o b/BUGS/boot.o new file mode 100644 index 0000000..88688c0 Binary files /dev/null and b/BUGS/boot.o differ diff --git a/BUGS/boot.s b/BUGS/boot.s new file mode 100644 index 0000000..fb77316 --- /dev/null +++ b/BUGS/boot.s @@ -0,0 +1,29 @@ +; Multiboot header +ALIGNED_4K equ 1<<0 +MEM_INFO equ 1<<1 +FLAGS equ ALIGNED_4K | MEM_INFO +MAGIC equ 0x1BADB002 +CHECKSUM equ -(MAGIC + FLAGS) + +section .multiboot +align 4 + dd MAGIC + dd FLAGS + dd CHECKSUM + +section .bss +align 16 +stack_bottom: + resb 16384 ; 16 KiB for stack +stack_top: + +section .text +global _start:function (_start.end - _start) +_start: + mov esp, stack_top + extern kernel_main + call kernel_main + cli +.hang: hlt + jmp .hang +_start.end: \ No newline at end of file diff --git a/BUGS/bugs.bin b/BUGS/bugs.bin new file mode 100755 index 0000000..d614687 Binary files /dev/null and b/BUGS/bugs.bin differ diff --git a/BUGS/bugs.iso b/BUGS/bugs.iso new file mode 100644 index 0000000..d441211 Binary files /dev/null and b/BUGS/bugs.iso differ diff --git a/BUGS/grub.cfg b/BUGS/grub.cfg new file mode 100644 index 0000000..9427cc1 --- /dev/null +++ b/BUGS/grub.cfg @@ -0,0 +1,3 @@ +menuentry "BUGS" { + multiboot /boot/bugs.bin +} \ No newline at end of file diff --git a/BUGS/isodir/boot/bugs.bin b/BUGS/isodir/boot/bugs.bin new file mode 100755 index 0000000..d614687 Binary files /dev/null and b/BUGS/isodir/boot/bugs.bin differ diff --git a/BUGS/isodir/boot/grub/grub.cfg b/BUGS/isodir/boot/grub/grub.cfg new file mode 100644 index 0000000..9427cc1 --- /dev/null +++ b/BUGS/isodir/boot/grub/grub.cfg @@ -0,0 +1,3 @@ +menuentry "BUGS" { + multiboot /boot/bugs.bin +} \ No newline at end of file diff --git a/BUGS/kernel.c b/BUGS/kernel.c new file mode 100644 index 0000000..766928b --- /dev/null +++ b/BUGS/kernel.c @@ -0,0 +1,202 @@ +#include +#include +#include + +// --- VGA Hardware Constants --- +static const size_t VGA_WIDTH = 80; +static const size_t VGA_HEIGHT = 25; +uint16_t* vga_buffer = (uint16_t*) 0xB8000; + +// System State +size_t terminal_row = 0; +size_t terminal_col = 0; +uint8_t terminal_color = 7; // Light grey on black + +// --- Low Level I/O --- + +static inline void outb(uint16_t port, uint8_t val) { + asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); +} + +static inline uint8_t inb(uint16_t port) { + uint8_t ret; + asm volatile ( "inb %1, %0" : "=a"(ret) : "Nd"(port) ); + return ret; +} + +// --- Hardware Cursor Logic --- + +void update_cursor(int x, int y) { + uint16_t pos = y * VGA_WIDTH + x; + + outb(0x3D4, 0x0F); + outb(0x3D5, (uint8_t) (pos & 0xFF)); + outb(0x3D4, 0x0E); + outb(0x3D5, (uint8_t) ((pos >> 8) & 0xFF)); +} + +// --- String & Memory Utilities --- + +int strlen(const char* str) { + int len = 0; + while (str[len]) len++; + return len; +} + +int strcmp(const char* s1, const char* s2) { + while (*s1 && (*s1 == *s2)) { + s1++; + s2++; + } + return *(unsigned char*)s1 - *(unsigned char*)s2; +} + +char* itoa(int value, char* str, int base) { + char *rc, *ptr, *low; + if (base < 2 || base > 36) return str; + rc = ptr = str; + if (value < 0 && base == 10) *ptr++ = '-'; + low = ptr; + int v = (value < 0) ? -value : value; + do { + *ptr++ = "0123456789abcdefghijklmnopqrstuvwxyz"[v % base]; + v /= base; + } while (v); + *ptr-- = '\0'; + while (low < ptr) { + char tmp = *low; + *low++ = *ptr; + *ptr-- = tmp; + } + return rc; +} + +// --- Terminal Output --- + +void putchar(char c) { + if (c == '\n') { + terminal_col = 0; + terminal_row++; + } else if (c == '\b') { + // Backspace logic is handled in scanf, + // but putchar supports it for generic use + if (terminal_col > 0) terminal_col--; + } else { + const size_t index = terminal_row * VGA_WIDTH + terminal_col; + vga_buffer[index] = (uint16_t) c | (uint16_t) terminal_color << 8; + if (++terminal_col == VGA_WIDTH) { + terminal_col = 0; + terminal_row++; + } + } + + if (terminal_row >= VGA_HEIGHT) { + // Simple scroll: just reset to top for now + terminal_row = 0; + } + update_cursor(terminal_col, terminal_row); +} + +void printf(const char* format, ...) { + va_list args; + va_start(args, format); + for (int i = 0; format[i] != '\0'; i++) { + if (format[i] == '%') { + i++; + if (format[i] == 's') { + char* s = va_arg(args, char*); + while (*s) putchar(*s++); + } else if (format[i] == 'd') { + char buf[32]; + itoa(va_arg(args, int), buf, 10); + for (int j = 0; buf[j]; j++) putchar(buf[j]); + } else if (format[i] == 'c') { + putchar((char)va_arg(args, int)); + } + } else { + putchar(format[i]); + } + } + va_end(args); +} + +// --- Keyboard Input --- + +char getchar() { + static unsigned char map[128] = { + 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', '\b', + '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', + 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', + 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' ' + }; + + while (1) { + if (inb(0x64) & 0x01) { + uint8_t scancode = inb(0x60); + // Ignore key-release events (scancode + 128) and non-mapped keys (Alt/Shift) + if (scancode < 128 && map[scancode] != 0) { + return map[scancode]; + } + } + } +} + +void scanf(char* buffer) { + int i = 0; + while (1) { + char c = getchar(); + if (c == '\n') { + buffer[i] = '\0'; + putchar('\n'); + break; + } else if (c == '\b') { + if (i > 0) { + i--; + if (terminal_col > 0) { + terminal_col--; + } else if (terminal_row > 0) { + terminal_row--; + terminal_col = VGA_WIDTH - 1; + } + // Clear the character visually + vga_buffer[terminal_row * VGA_WIDTH + terminal_col] = (uint16_t)' ' | (uint16_t)terminal_color << 8; + update_cursor(terminal_col, terminal_row); + } + } else { + buffer[i++] = c; + putchar(c); + } + } +} + +// --- Kernel Entry --- + +void kernel_main(void) { + // Clear Screen + for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) { + vga_buffer[i] = (uint16_t)' ' | (uint16_t)7 << 8; + } + update_cursor(0, 0); + + printf("BUGS (Buggy Unverified Greatish Script) v1.1\n"); + printf("Hardware Cursor: ENABLED\n"); + printf("Filtering Alt/Tab symbols: ENABLED\n\n"); + + while (1) { + printf("BUGS> "); + char input[64]; + scanf(input); + + if (strcmp(input, "help") == 0) { + printf("Available commands: help, clear, hello\n"); + } else if (strcmp(input, "clear") == 0) { + for (size_t i = 0; i < VGA_WIDTH * VGA_HEIGHT; i++) vga_buffer[i] = (uint16_t)' ' | (uint16_t)7 << 8; + terminal_row = 0; terminal_col = 0; + update_cursor(0,0); + } else if (strcmp(input, "hello") == 0) { + printf("Greetings from the kernel!\n"); + } else if (strlen(input) > 0) { + printf("Unknown command: %s\n", input); + } + } +} \ No newline at end of file diff --git a/BUGS/kernel.o b/BUGS/kernel.o new file mode 100644 index 0000000..6f00ca2 Binary files /dev/null and b/BUGS/kernel.o differ diff --git a/BUGS/linker.ld b/BUGS/linker.ld new file mode 100644 index 0000000..6152e34 --- /dev/null +++ b/BUGS/linker.ld @@ -0,0 +1,9 @@ +ENTRY(_start) +SECTIONS +{ + . = 1M; /* Standard load address for kernels */ + .text BLOCK(4K) : ALIGN(4K) { *(.multiboot) *(.text) } + .rodata BLOCK(4K) : ALIGN(4K) { *(.rodata) } + .data BLOCK(4K) : ALIGN(4K) { *(.data) } + .bss BLOCK(4K) : ALIGN(4K) { *(COMMON) *(.bss) } +} \ No newline at end of file diff --git a/command-to-compile.txt b/command-to-compile.txt new file mode 100644 index 0000000..115cc98 --- /dev/null +++ b/command-to-compile.txt @@ -0,0 +1 @@ +nasm -felf32 boot.s -o boot.o && gcc -m32 -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra && gcc -m32 -T linker.ld -o bugs.bin -ffreestanding -O2 -nostdlib boot.o kernel.o -lgcc && cp bugs.bin isodir/boot/ && cp grub.cfg isodir/boot/grub/ && grub-mkrescue -o bugs.iso isodir && qemu-system-i386 -cdrom bugs.iso \ No newline at end of file