diff --git a/docs/escape.txt b/docs/escape.txt new file mode 100644 index 0000000..47b349b --- /dev/null +++ b/docs/escape.txt @@ -0,0 +1,35 @@ +--- Terminal Escape Sequences --- + +Escape character: + char: '\e' + hex: 0x1b + oct: 0o33 + dec: 27 + +Note: the escape character will be denoted by ESC here + +Syntax: + All escape sequenced start with the escape character followed by an opening square bracket '[' + The sequence can take any number of arguments in a semicolon separated list + If a argument is skipped, it will be implicitly set to 0 + The escape sequence must end with a uppercase or lowercase letter + +Available escape sequences: + - Cursor Controls - + `ESC[#A` - Moves cursor # rows up + `ESC[#B` - Moves cursor # rows down + `ESC[#C` - Moves cursor # columns left + `ESC[#D` - Moves cursor # columns right + `ESC[#E` - Moves cursor to #th row + `ESC[#F` - Moves cursor to #th column + `ESC[#G` - Show (# = 1) or hide (# = 0) cursor + `ESC[{row};{col}H` - Moves cursor to specified position (if not arguments given, moves to [0,0])a + - Erase functions - + `ESC[I` - Reserved + `ESC[J` - Erase screen + `ESC[K` - Erase line (not implemented) + `ESC[L` - Erase column (not implemented) + - Text Style - + `ESC[#M` - Sets foreground color to # + `ESC[#N` - Sets backgorund color to # + diff --git a/docs/memory.txt b/docs/memory.txt deleted file mode 100644 index e8a0bb5..0000000 --- a/docs/memory.txt +++ /dev/null @@ -1,8 +0,0 @@ ---- Memory Map --- -0x1000 - Kernel -0x6000 - Font -0x7000 - Filetable (0x7c00 - Bootloader) -0x8500 - ACPI Memory map -0x9000 - VBE Mode Info Block -0x30000 - Memory manager memmap - diff --git a/docs/syscalls.txt b/docs/syscalls.txt index 3b77ed5..fd3ab08 100644 --- a/docs/syscalls.txt +++ b/docs/syscalls.txt @@ -2,10 +2,25 @@ Syscall handlers are prefixed by 'sys_' Syscalls can be called using interrupt 0x80 -The EAX register should countain a syscall number +The EAX register should countain a syscall number on calling and it will contain a return value (if applicable) after calling Here's a list of syscalls: (and their numbers) -syscall(0) : Sleep() +Syscall(0) : Sleep() Args: EBX - Number of miliseconds to sleep for +Syscall(1) : Write() + Args: EBX - File descriptor + ECX - Buffer to write + EDX - Length + Returns: Status + +Syscall(2) : Read() #TBD + +Syscall(3) : Malloc() + Args: EBX - Amount of bytes to malloc + Returns: Address of allocated memory + +Syscall(4) : Free() + Args: EBX - Pointer to free + diff --git a/include/c/stdio.h b/include/c/stdio.h index 018458c..5212ec9 100644 --- a/include/c/stdio.h +++ b/include/c/stdio.h @@ -1,12 +1,18 @@ #ifndef STDIO_H #define STDIO_H -void print(const char* s) { // Use Syscall(1) - Puts() - __asm__ volatile ("int $0x80" : : "a"(1), "b"(s)); +#include +#include + +// TODO: Make a proper file descriptor table +#define STDOUT 1 + +void print(const char* s) { + write(STDOUT, s, strlen(s)); } -void read(char* s) { // Use Syscall(2) - Gets() - __asm__ volatile ("int $0x80" : : "a"(2), "b"(s)); +void read(char* s) { + print("\x1b[1M[ ERROR: Read() Syscall not found! ]\n"); } #endif diff --git a/include/c/syscall.h b/include/c/syscall.h new file mode 100644 index 0000000..7a5067f --- /dev/null +++ b/include/c/syscall.h @@ -0,0 +1,23 @@ +#ifndef SYSCALLNUMS_H +#define SYSCALLNUMS_H + +#include + +#define MAX_SYSCALLS 5 + +typedef enum { + SYS_SLEEP, + SYS_WRITE, + SYS_GETS, + SYS_MALLOC, + SYS_FREE, +} SYSCALL_NUMBERS; + +// TODO: Add malloc() and free() syscall wrappers?? +int32_t write(int32_t fd, const void* buf, uint32_t len) { + int32_t result = -1; + __asm__ volatile ("int $0x80" : "=a"(result) : "a"(SYS_WRITE), "b"(fd), "c"(buf), "d"(len)); + return result; +} + +#endif diff --git a/include/interrupt/syscall.h b/include/interrupt/syscalls.h similarity index 76% rename from include/interrupt/syscall.h rename to include/interrupt/syscalls.h index 8f98ac8..7118bcd 100644 --- a/include/interrupt/syscall.h +++ b/include/interrupt/syscalls.h @@ -3,13 +3,13 @@ #include #include -#include +#include #include #include +#include +#include -// System call count -#define MAX_SYSCALLS 5 - +// Syscall(0) - Sleep() // Args: ebx - number of miliseconds void sys_sleep() { uint32_t ms; @@ -21,12 +21,24 @@ void sys_sleep() { } } -// TODO: Use a Write() syscall and write to stdout -// Args: ebx - char* string -void sys_puts() { - char* s; - __asm__ volatile ("movl %%ebx, %0" : "=r"(s)); - print(s); +// Syscall(1) - Write() +// Args: ebx - int fd +// ecx - void* buf +// edx - uint32_t len +void sys_write() { + int32_t fd = 0; + void* buf = NULL; + uint32_t len = 0; + + __asm__ volatile ("nop" : "=b"(fd), "=c"(buf), "=d"(len)); + + // TODO: Open fd table? + if (fd == 1) { // "stdout" + int32_t result = terminalWrite(buf, len); // Call a terminal print function + __asm__ volatile ("movl %0, %%eax" : : "r"(result)); + } else { // Not implemented + __asm__ volatile ("movl $1, %eax"); + } } // TODO: Use a Read() sycall and read from stdin @@ -37,7 +49,9 @@ void sys_gets() { read(s); } +// Syscall(3) - Malloc() // Args: ebx - amount of bytes to malloc +// Returns: eax - Pointer to allocated memory void sys_malloc() { uint32_t size = 0; __asm__ volatile ("movl %%ebx, %0" : "=b"(size)); @@ -54,6 +68,7 @@ void sys_malloc() { __asm__ volatile ("movl %0, %%eax" : : "r"(ptr)); } +// Syscall(4) - Free() // Args: ebx - allocated pointer void sys_free() { void* ptr = NULL; @@ -62,12 +77,12 @@ void sys_free() { } // System call table -void* syscalls[MAX_SYSCALLS] = { - sys_sleep, // Syscall(0) - sys_puts, // Syscall(1) - sys_gets, // Syscall(2) - sys_malloc, // Syscall(3) - sys_free, // Syscall(4) +void (*syscalls[MAX_SYSCALLS])(void) = { + [SYS_SLEEP] = sys_sleep, + [SYS_WRITE] = sys_write, + [SYS_GETS] = sys_gets, + [SYS_MALLOC] = sys_malloc, + [SYS_FREE] = sys_free, }; // int 0x80 - Syscall interrupt, handled by this function diff --git a/include/memory/addresses.h b/include/memory/addresses.h index 68c5e57..164bd0d 100644 --- a/include/memory/addresses.h +++ b/include/memory/addresses.h @@ -1,9 +1,18 @@ #ifndef ADDRESSES_H #define ADDRESSES_H +// TODO: Don't let these be just random numbers? + // Locations #define KERNEL_LOC 0x100000 #define FILETABLE_LOC 0x7000 +#define TERMINAL_INFO_LOC 0x2000 +#define MODE_INFO_BLOCK_LOC 0x9000 + +// Font +#define FONT_LOC 0x6000 +#define FONT_WIDTH (FONT_LOC) +#define FONT_HEIGHT (FONT_LOC + 1) // Physical memory manager #define MEMMAP_AREA 0x30000 diff --git a/include/screen/gfxmode.h b/include/screen/gfxmode.h new file mode 100644 index 0000000..577a34c --- /dev/null +++ b/include/screen/gfxmode.h @@ -0,0 +1,79 @@ +#ifndef GFXMODE_H +#define GFXMODE_H + +#include +#include + +#define BLACK 0x00000000 // 0 +#define RED 0x00ff0000 // 1 +#define GREEN 0x0000ff00 // 2 +#define YELLOW 0x00ffff00 // 3 +#define BLUE 0x000000ff // 4 +#define MAGENTA 0x00ff00ff // 5 +#define CYAN 0x0000ffff // 6 +#define WHITE 0x00ffffff // 7 + +#define BG_COLOR 0x00010b17 +#define FG_COLOR 0x00ebddf4 + +typedef struct modeInfoBlock_s { + // Required by all VBE revisions + uint16_t modeAttr; + uint8_t windowAAtrr; + uint8_t windowBAttr; + uint16_t windowGranularity; + uint16_t windowSize; + uint16_t windowASegment; + uint16_t windowBSegment; + uint32_t windowFunctionPtr; + uint16_t bytesPerScanline; + + // Required by VBE 1.2+ + uint16_t xRes; + uint16_t yRes; + uint8_t xCharSize; + uint8_t yCharSize; + uint8_t planeCount; + uint8_t bpp; + uint8_t bankCount; + uint8_t memoryModel; + uint8_t bankSize; + uint8_t imagePageCount; + uint8_t reserved1; + + // Direct color fields + uint8_t redMaskSize; + uint8_t redFieldPos; + uint8_t greenMaskSize; + uint8_t greenFieldPos; + uint8_t blueMaskSize; + uint8_t blueFieldPos; + uint8_t reservedMaskSize; + uint8_t reservedFieldPos; + uint8_t directColorModeInfo; + + // Required by VBE 2.0+ + uint32_t physicalBasePtr; + uint32_t reserved2; + uint16_t reserved3; + + // Required by VBE 3.0+ + uint16_t linearBytesPerScanline; + uint8_t bankImagePageCount; + uint8_t linearImagePageCount; + uint8_t linearRedMaskSize; + uint8_t linearRedFieldPos; + uint8_t linearGreenMaskSize; + uint8_t linearGreenFieldPos; + uint8_t linearBlueMaskSize; + uint8_t linearBlueFieldPos; + uint8_t linearReservedMaskSize; + uint8_t linearReservedFieldPos; + uint32_t maxPixelClock; + + uint8_t reserved4[190]; +} __attribute__ ((packed)) modeInfoBlock_t; + +static modeInfoBlock_t* gfxMode = (modeInfoBlock_t*)MODE_INFO_BLOCK_LOC; + +#endif diff --git a/include/screen/text.h b/include/screen/text.h index 51815b5..f9115ce 100644 --- a/include/screen/text.h +++ b/include/screen/text.h @@ -1,89 +1,18 @@ #ifndef SCREEN_H #define SCREEN_H +#include +#include #include #include -// Basic full saturation colors -#define BLACK 0x00000000 // 0 -#define RED 0x00ff0000 // 1 -#define GREEN 0x0000ff00 // 2 -#define YELLOW 0x00ffff00 // 3 -#define BLUE 0x000000ff // 4 -#define MAGENTA 0x00ff00ff // 5 -#define CYAN 0x0000ffff // 6 -#define WHITE 0x00ffffff // 7 - -#define MODE_INFO_BLOCK 0x9000 -#define BG_COLOR 0x00010b17 -#define FG_COLOR 0x00ebddf4 - -typedef struct modeInfoBlock_s { - // Required by all VBE revisions - uint16_t modeAttr; - uint8_t windowAAtrr; - uint8_t windowBAttr; - uint16_t windowGranularity; - uint16_t windowSize; - uint16_t windowASegment; - uint16_t windowBSegment; - uint32_t windowFunctionPtr; - uint16_t bytesPerScanline; - - // Required by VBE 1.2+ - uint16_t xRes; - uint16_t yRes; - uint8_t xCharSize; - uint8_t yCharSize; - uint8_t planeCount; - uint8_t bpp; - uint8_t bankCount; - uint8_t memoryModel; - uint8_t bankSize; - uint8_t imagePageCount; - uint8_t reserved1; - - // Direct color fields - uint8_t redMaskSize; - uint8_t redFieldPos; - uint8_t greenMaskSize; - uint8_t greenFieldPos; - uint8_t blueMaskSize; - uint8_t blueFieldPos; - uint8_t reservedMaskSize; - uint8_t reservedFieldPos; - uint8_t directColorModeInfo; - - // Required by VBE 2.0+ - uint32_t physicalBasePtr; - uint32_t reserved2; - uint16_t reserved3; - - // Required by VBE 3.0+ - uint16_t linearBytesPerScanline; - uint8_t bankImagePageCount; - uint8_t linearImagePageCount; - uint8_t linearRedMaskSize; - uint8_t linearRedFieldPos; - uint8_t linearGreenMaskSize; - uint8_t linearGreenFieldPos; - uint8_t linearBlueMaskSize; - uint8_t linearBlueFieldPos; - uint8_t linearReservedMaskSize; - uint8_t linearReservedFieldPos; - uint32_t maxPixelClock; - - uint8_t reserved4[190]; -} __attribute__ ((packed)) modeInfoBlock_t; - struct cursor_s { uint32_t x; uint32_t y; }; -static char* font = (char*)0x6000; +static char* font = (char*)FONT_LOC; static struct cursor_s cursor = { 0, 0 }; -static modeInfoBlock_t* gfxMode = (modeInfoBlock_t*)MODE_INFO_BLOCK; uint32_t bgColor = BG_COLOR; uint32_t fgColor = FG_COLOR; @@ -105,8 +34,8 @@ uint32_t convertColor(uint32_t color) { // TODO: Reimplement larger text void putcAt(unsigned char c, uint32_t x, uint32_t y) { // Font info - uint8_t charWidth = *(font); - uint8_t charHeight = *(font + 1); + uint8_t charWidth = *(uint8_t*)FONT_WIDTH; + uint8_t charHeight = *(uint8_t*)FONT_HEIGHT; // uint8_t bitmapRowLen = (charWidth - 1) / 8 + 1; // TODO: Larger font support // Video stuff @@ -133,6 +62,7 @@ void putcAt(unsigned char c, uint32_t x, uint32_t y) { } } +// TODO: Probably get rid of this, idk (use terminal control codes) void printAt(const char* str, uint32_t x, uint32_t y) { while (*str != '\0') { putcAt(*str++, x, y); @@ -140,8 +70,9 @@ void printAt(const char* str, uint32_t x, uint32_t y) { } } +// TODO: Use terminal.x/y instead of cursor.x/y void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() helped alot) - uint8_t charHeight = *(font + 1); + uint8_t charHeight = *(uint8_t*)FONT_HEIGHT; if ((cursor.y+1) * charHeight < gfxMode->yRes) { return; } // Check if we should scroll uint32_t bytesPerLine = charHeight * gfxMode->bytesPerScanline; @@ -167,8 +98,9 @@ void scroll() { // TODO: Make this faster (still kinda slow, but memcpy32() help cursor.y--; } +// DEPRICATED - TODO: Remove this from everywhere so i can delete it void putc(char c) { - uint8_t charWidth = *(font); + uint8_t charWidth = *(uint8_t*)FONT_WIDTH; if (c == '\n') { putcAt(' ', cursor.x, cursor.y); // Make sure we don't leave an extra cursor @@ -198,12 +130,14 @@ void putc(char c) { scroll(); } +// DEPRICATED - TODO: Remove this everywhere it's used and delete it's definition here void print(const char* str) { while (*str != '\0') { putc(*str++); } } +// TODO: Make this comply with the new terminal.h thing! void clear() { uint8_t* vidmem = (uint8_t*)gfxMode->physicalBasePtr; uint8_t bytesPerPx = (gfxMode->bpp+1) / 8; diff --git a/include/terminal/terminal.h b/include/terminal/terminal.h new file mode 100644 index 0000000..02fcce0 --- /dev/null +++ b/include/terminal/terminal.h @@ -0,0 +1,65 @@ +#ifndef TERMINAL_H +#define TERMINAL_H + +#include +#include +#include +#include +#include + +typedef struct { + uint32_t x; // X Position of cursor in characters + uint32_t y; // Y Position of cursor in characters + uint32_t bg; // Printed character background + uint32_t fg; // Printed character foreground + uint32_t width; // Width in characters + uint32_t height; // Height in characters + bool showCursor; // Should we display the cursor +} terminal_t; + +terminal_t* terminal = (terminal_t*)TERMINAL_INFO_LOC; + +int32_t terminalWrite(const void* buf, uint32_t len) { + terminal->width = gfxMode->xRes / *(uint8_t*)FONT_WIDTH; + terminal->height = gfxMode->yRes / *(uint8_t*)FONT_HEIGHT; + + char* str = (char*)buf; + uint32_t i; + + // Do we need to check for NULL? Can we just skip it/ignore it? + for (i = 0; i < len && str[i] != '\0'; i++) { + if (str[i] == '\n') { + putcAt(' ', terminal->x, terminal->y); // Remove extra cursor + terminal->y++; + terminal->x = 0; + } else if (str[i] == '\b') { + putcAt(' ', terminal->x, terminal->y); // Remove extra cursor + if (terminal->x == 0) { + terminal->x = terminal->width - 1; + terminal->y--; // Y could be 0? + } else { + terminal->x--; + } + putcAt(' ', terminal->x, terminal->y); + } else if (str[i] == '\x1b') { // Escape sequence + if (str[++i] != '[') { // TODO: Suppord more types of escape sequences + continue; + } + + putcAt(str[++i], terminal->x++, terminal->y); + } else { + putcAt(str[i], terminal->x, terminal->y); + terminal->x++; + + if (terminal->x >= terminal->width) { // Go to next line + terminal->y++; + terminal->x = 0; + } + } + } + scroll(); + + return i; // Number of characters that were printed +} + +#endif diff --git a/todo.txt b/todo.txt index 16dd0ed..380c47a 100644 --- a/todo.txt +++ b/todo.txt @@ -75,7 +75,8 @@ Legend: - [x] PI - [ ] Floating point macros/functions - [ ] Filesystem - - [ ] Utility for filesystem building (not just an assembly file) + - [!] Utility for filesystem building (not just an assembly file) + - [x] Better header for file i/o (disk/filesys.h) - [x] Filetable - [ ] Files - [x] Larger than one sector (512B) @@ -89,7 +90,7 @@ Legend: - [ ] Hard - [ ] System Calls - [x] Sleep() - - [ ] Write() (temporarly puts()) + - [x] Write() - [ ] Read() (temporarly gets()) - [ ] Open() - [ ] Close() @@ -131,7 +132,7 @@ Legend: - [ ] Standalone shell program - [ ] Userspace programs - [ ] Calculator - - [ ] Caledar + - [ ] Calendar - [ ] Code Editor - [ ] Text editor - [ ] Syntax highlighting