From ed18f4ac4ba9e934260820568c32b0524ee131d7 Mon Sep 17 00:00:00 2001 From: Tom-on64 Date: Wed, 29 May 2024 11:35:10 +0200 Subject: [PATCH] IMPLEMENTED printf()!!!!!!! It's kinda bad :/ --- include/c/stdio.h | 57 ++++++++++++++++++-- include/c/string.h | 11 ++-- include/interrupt/exceptions.h | 10 ++-- include/interrupt/syscalls.h | 2 +- src/kernel.c | 96 +++++++++------------------------- todo.txt | 3 +- 6 files changed, 89 insertions(+), 90 deletions(-) diff --git a/include/c/stdio.h b/include/c/stdio.h index 2d281bb..6294e44 100644 --- a/include/c/stdio.h +++ b/include/c/stdio.h @@ -7,6 +7,14 @@ // TODO: Make a proper file descriptor table #define STDOUT 1 +/* --- Output --- */ +void putc(char c) { + // write(STDOUT, &c, 1); TODO: This doesn't work and we need to use a static variable + static char _c; + _c = c; + write(STDOUT, &_c, 1); +} + void print(const char* s) { write(STDOUT, s, strlen(s)); } @@ -15,12 +23,53 @@ void clear() { print("\x1b[J"); } -void putc(char c) { - static char _c; // We need to pass in a static address. Idk why - _c = c; - write(STDOUT, &_c, 1); +// TODO: Dynamically allocate memory and print once instead of calling putc for every character :/ +// TODO: Support negative numbers +// TODO: Printing individual characters doesn't let escape sequences work :( +int printf(const char* fmt, ...) { + char* argPtr = (char*)&fmt + sizeof(char*); // First arg after fmt + uint8_t state = 0; + + for (uint32_t i = 0; fmt[i] != '\0'; i++) { + char c = fmt[i]; + + if (state == 0) { + if (c == '%') state = '%'; + else putc(c); + } else if (state == '%') { + switch (c) { + case 'd': // Decimal number + print(itoa(*(uint32_t*)argPtr, 10)); + argPtr += sizeof(unsigned int); + break; + case 'x': // Hex number + print(itoa(*(uint32_t*)argPtr, 16)); + argPtr += sizeof(unsigned int); + break; + case 's': // String + print(*(char**)argPtr); + argPtr += sizeof(char*); + break; + case 'c': // Char + putc(*(char*)argPtr); + argPtr += sizeof(char); + break; + case '%': // Just print '%' + putc('%'); + break; + default: + putc('%'); + putc(c); + break; + } + state = 0; + } + } + + return 0; } +/* --- Input --- */ char getc() { char* character = (char*)0x2100; *character = '\0'; diff --git a/include/c/string.h b/include/c/string.h index cc0dce8..24878df 100644 --- a/include/c/string.h +++ b/include/c/string.h @@ -6,19 +6,16 @@ // Source: http://www.strudel.org.uk/itoa/ char* itoa(uint32_t val, uint8_t base) { static char buf[32] = { 0 }; - - if (base == 0 || base > 16) { - // TODO: Add errors!! - return NULL; - } + + if (base == 0 || base > 16) { return NULL; } if (val == 0) { buf[0] = '0'; return buf; } - int i = 30; - for (; val && i; i--, val /= base) { + int i; + for (i = 30; val && i; i--, val /= base) { buf[i] = "0123456789abcdef"[val % base]; } diff --git a/include/interrupt/exceptions.h b/include/interrupt/exceptions.h index e05546a..c26c086 100644 --- a/include/interrupt/exceptions.h +++ b/include/interrupt/exceptions.h @@ -7,13 +7,13 @@ // Exception handlers __attribute__ ((interrupt)) void excp_divideErr(intFrame_t* iframe) { // ISR 0 - print("\x1b[1M[ Division Error ]\n\x1b[8M"); + printf("\x1b[1M[ Division Error ]\n\x1b[8M"); iframe->eip++; } __attribute__ ((interrupt)) void excp_doubleFault(intFrame_t* iframe, uint32_t errCode) { // ISR 8 - print("\x1b[1M[ Double Fault ]\n\x1b[8M"); // Error code should be 0 (TODO: Maybe check if it's != 0?) + printf("\x1b[1M[ Double Fault ]\n\x1b[8M"); // Error code should be 0 (TODO: Maybe check if it's != 0?) __asm__ volatile ("cli; hlt"); } @@ -24,11 +24,7 @@ void excp_pageFault(intFrame_t* iframe, uint32_t errCode) { // ISR 14 // cr2 should contain invalid address __asm__ volatile("movl %%cr2, %0" : "=r"(badAddress)); - print("\x1b[1M[ Page Fault : 0x"); - print(itoa(errCode, 16)); - print(" ] - Tried to access 0x"); - print(itoa(badAddress, 16)); - print(".\n\x1b[8M"); + printf("\x1b[1M[ Page Fault : 0x%x ] - Tried to access 0x%x.\n\x1b[8M", errCode, badAddress); __asm__ volatile ("cli; hlt"); } diff --git a/include/interrupt/syscalls.h b/include/interrupt/syscalls.h index 67923a9..6634424 100644 --- a/include/interrupt/syscalls.h +++ b/include/interrupt/syscalls.h @@ -36,7 +36,7 @@ void sys_write() { 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"); + __asm__ volatile ("movl $-1, %eax"); } } diff --git a/src/kernel.c b/src/kernel.c index 4a24e2d..0281927 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -56,7 +56,7 @@ void main() { terminal->fg = FG_COLOR; terminal->bg = BG_COLOR; clear(); - print("kern.\n\n"); + printf("\x1b[2Mkern.\n\n\x1b[8M"); // Run Interactive Shell Program // TODO: Make it in another file @@ -97,7 +97,7 @@ void main() { } } *str = '\0'; - print(printStr); + printf("%s", printStr); } else if (strcmp(input, "exit") == 0) { break; } else if (strcmp(input, "gfx") == 0) { @@ -160,7 +160,7 @@ void main() { sleep(ms); } else if (strcmp(input, "soundtest") == 0) { - print("Playing...\n"); + printf("Playing...\n"); enableSpeaker(); /* @@ -185,38 +185,12 @@ void main() { disableSpeaker(); } else if (strcmp(input, "test") == 0) { - print("Running Tests...\n"); - uint8_t buf[512]; - - print("Read Test .......... "); - diskRead(0, 1, (char*)buf); - if (buf[510] == 0x55 && buf[511] == 0xaa) { - print("[ DONE ]\n"); - } else { - print("[ FAIL ]\n"); - } - print("Write Test ......... "); - buf[510] = 0x55; buf[511] = 0xaa; - diskWrite(0, 1, (char*)buf); - diskRead(0, 1, (char*)buf); // Idk how else to test if the right data was written (also could break the bootloader if it fails) - if (buf[510] == 0x55 && buf[511] == 0xaa) { - print("[ DONE ]\n"); - } else { - print("[ FAIL ]\n"); - } - print("Malloc Test ........ "); - void* buffer = malloc(100); - free(buffer); - print("[ DONE ]\n"); - - print("\nTests Finished!\n"); + printf("\x1b[1MError: 'test' is not available.\x1b[8M"); } else { fileEntry_t* file = findFile(input); if (file == NULL) { - print("Command not found: "); - print(input); - putc('\n'); + printf("Command not found: %s\n", input); continue; } @@ -229,7 +203,7 @@ void main() { uint32_t physicalAddress = (uint32_t)allocPage(&page); if (mapPage((void*)physicalAddress, (void*)(entryPoint + i * PAGE_SIZE)) != 0) { - print("\n\x1b[1MNot enough memory to allocate!\n"); + printf("\n\x1b[1MNot enough memory to allocate!\n"); break; } } @@ -262,11 +236,9 @@ void main() { } else if (strcmp(file->filetype, "tab") == 0) { printFiletable(entryPoint); } else if (strcmp(file->filetype, "fnt") == 0) { - print("Loading "); - print(file->filename); - print("...\n"); + printf("Loading %s...\n", file->filename); memcpy(entryPoint, (char*)FONT_LOC, file->length * 512); - print("Font loaded\n"); + printf("Font loaded\n"); } else { for (size_t i = 0; i < file->length * 512; i++) { if (entryPoint[i] != '\0') { @@ -308,24 +280,21 @@ void printFiletable(char* ft) { uint8_t sector = *ft++; uint8_t size = *ft++; + // TODO: Use printf() here for padding if (sector < 10) putc('0'); if (sector == 0) putc('0'); - else print(itoa(sector, 10)); - print(": "); - print(filename); + else printf("%d", sector); + printf(": %s", filename); for (uint8_t i = 14 - strlen(filename); i > 0; i--) { - putc(' '); + printf(" "); } - print(" | "); + printf(" | "); if (size >> 1) { - print(itoa(size >> 1, 10)); - if (size & 0x01) { print(".5"); } - print("kB\n"); + printf("%d%skB\n", size >> 1, (size & 0x01) ? ".5" : ""); } else { - print(itoa(size*512, 10)); - print("B\n"); + printf("%dB\n", size * 512); } } } @@ -335,39 +304,26 @@ void printPhysicalMemmap() { smapEntry_t* smapEntry = (smapEntry_t*)SMAP_ENTRIES; for (uint32_t i = 0; i < entryCount; i++) { - print("Region "); - print(itoa(i, 10)); - print(" - base: 0x"); - print(itoa(smapEntry->baseAddress, 16)); - print(" length: 0x"); - print(itoa(smapEntry->length, 16)); - print(" type: "); - print(itoa(smapEntry->type, 10)); + // Need to cast to uint32_t because they are uint64_t + printf("Region %d - base: 0x%x length: 0x%x type: %d ", i, (uint32_t)smapEntry->baseAddress, (uint32_t)smapEntry->length, smapEntry->type); switch (smapEntry->type) { - case 1: print(" (Available)"); break; - case 2: print(" (Reserved)"); break; - case 3: print(" (ACPI Reclaim)"); break; - case 4: print(" (ACPI NVS)"); break; - default: print(" (Reserved)"); break; + case 1: printf("(Available)\n"); break; + case 2: printf("(Reserved)\n"); break; + case 3: printf("(ACPI Reclaim)\n"); break; + case 4: printf("(ACPI NVS)\n"); break; + default: printf("(Reserved)\n"); break; } - putc('\n'); smapEntry++; } smapEntry--; // We incremented it after the last entry - print("\nTotal memory: 0x"); - print(itoa(smapEntry->baseAddress + smapEntry->length - 1, 16)); - print(" Bytes\n"); + printf("\nTotal memory: 0x%x Bytes\n", smapEntry->baseAddress + smapEntry->length - 1); - print("Total 4kB Blocks: "); - print(itoa(maxBlocks, 10)); - print("\nUsed or reserved blocks: "); - print(itoa(usedBlocks, 10)); - print("\nFree blocks: "); - print(itoa(maxBlocks - usedBlocks, 10)); - print("\n\n"); + printf("Total 4kB Blocks: %d\n", maxBlocks); + printf("Used or reserved blocks: %d\n", usedBlocks); + printf("Free blocks: %d\n\n", maxBlocks - usedBlocks); } diff --git a/todo.txt b/todo.txt index a7a0c71..9746489 100644 --- a/todo.txt +++ b/todo.txt @@ -9,7 +9,7 @@ Legend: - [x] Multistage Bootloader - [ ] Bootloader reads filetable to find files -- [ ] The almighty 'printf()' +- [x] The almighty 'printf()' - [!] Makefile refactorin' - [x] Write down where stuff is in memory (in notes.txt) - [ ] "Text" mode (not actually) @@ -79,6 +79,7 @@ Legend: - [!] Utility for filesystem building (not just an assembly file) - [x] Better header for file i/o (disk/filesys.h) - [x] Filetable + - [ ] A better filesystem using INodes etc. - [ ] Files - [x] Larger than one sector (512B) - [ ] Any file size (Not multiples of 512B)