this is working pretty well right now
This commit is contained in:
BIN
BUGS/boot.o
Normal file
BIN
BUGS/boot.o
Normal file
Binary file not shown.
29
BUGS/boot.s
Normal file
29
BUGS/boot.s
Normal file
@@ -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:
|
||||||
BIN
BUGS/bugs.bin
Executable file
BIN
BUGS/bugs.bin
Executable file
Binary file not shown.
BIN
BUGS/bugs.iso
Normal file
BIN
BUGS/bugs.iso
Normal file
Binary file not shown.
3
BUGS/grub.cfg
Normal file
3
BUGS/grub.cfg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
menuentry "BUGS" {
|
||||||
|
multiboot /boot/bugs.bin
|
||||||
|
}
|
||||||
BIN
BUGS/isodir/boot/bugs.bin
Executable file
BIN
BUGS/isodir/boot/bugs.bin
Executable file
Binary file not shown.
3
BUGS/isodir/boot/grub/grub.cfg
Normal file
3
BUGS/isodir/boot/grub/grub.cfg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
menuentry "BUGS" {
|
||||||
|
multiboot /boot/bugs.bin
|
||||||
|
}
|
||||||
202
BUGS/kernel.c
Normal file
202
BUGS/kernel.c
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
// --- 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
BUGS/kernel.o
Normal file
BIN
BUGS/kernel.o
Normal file
Binary file not shown.
9
BUGS/linker.ld
Normal file
9
BUGS/linker.ld
Normal file
@@ -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) }
|
||||||
|
}
|
||||||
1
command-to-compile.txt
Normal file
1
command-to-compile.txt
Normal file
@@ -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
|
||||||
Reference in New Issue
Block a user