diff --git a/com1.out b/com1.out index 66b5100..10c4e1d 100644 Binary files a/com1.out and b/com1.out differ diff --git a/iso/boot/kernel.elf b/iso/boot/kernel.elf index 4430a0e..8e5c86c 100755 Binary files a/iso/boot/kernel.elf and b/iso/boot/kernel.elf differ diff --git a/src/drivers/serial.c b/src/drivers/serial.c index 8e5861b..b4c28bb 100644 --- a/src/drivers/serial.c +++ b/src/drivers/serial.c @@ -1,5 +1,6 @@ #include "../kernel/io.h" #include "serial.h" +#include "../libc/stdio.h" int init_serial() { @@ -61,5 +62,220 @@ void log(const char* str, const int errlevel) break; } serial_puts(str); +} + +const char serial_charset[] = "0123456789abcdef"; + +int* serial_printf_number(int* argp, int length, bool sign, int radix) +{ + char buffer[32]; + unsigned long long number; + int number_sign = 1; + int pos = 0; + + switch(length) + { + case PRINTF_LENGTH_SHORT_SHORT: + case PRINTF_LENGTH_SHORT: + case PRINTF_LENGTH_START: + if (sign) + { + int n = *argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned int*) argp; + } + argp++; + break; + case PRINTF_LENGTH_LONG: + if (sign) + { + long int n = *(long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned long int*) argp; + } + argp += 2; + break; + case PRINTF_LENGTH_LONG_LONG: + if (sign) + { + long long int n = *(long long int*)argp; + if (n < 0) + { + n = -n; + number_sign = -1; + } + number = (unsigned long long) n; + } + else { + number = *(unsigned long long int*) argp; + } + argp += 4; + break; + } + + do { + uint32_t rem; + x86_div64_32(number, radix, &number, &rem); + buffer[pos++] = serial_charset[rem]; + } while (number > 0); + + if (sign && number_sign < 0) + { + buffer[pos++] = '-'; + } + + while (--pos >= 0) + { + write_serial(buffer[pos]); + } + + return argp; +} +void serial_printf(int errlevel, const char* fmt, ...) +{ + switch (errlevel) + { + case 0: + serial_puts("[ERROR] "); + break; + case 1: + serial_puts("[WARNING] "); + break; + case 2: + serial_puts("[INFO] "); + break; + case 3: + serial_puts("[DEBUG] "); + break; + } + + int* argp = (int*) &fmt; + int state = PRINTF_STATE_START; + int length = PRINTF_LENGTH_START; + int radix = 10; + bool sign = false; + + argp++; + while (*fmt) + { + switch(state) { + case PRINTF_STATE_START: + if (*fmt == '%') + { + state = PRINTF_STATE_LENGTH; + } + else { + write_serial(*fmt); + } + break; + case PRINTF_STATE_LENGTH: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT; + state = PRINTF_STATE_SHORT; + } + else if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG; + state = PRINTF_STATE_LONG; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SHORT: + if (*fmt == 'h') + { + length = PRINTF_LENGTH_SHORT_SHORT; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_LONG: + if (*fmt == 'l') + { + length = PRINTF_LENGTH_LONG_LONG; + state = PRINTF_STATE_SPEC; + } + else { + goto PRINTF_STATE_SPEC_; + } + break; + case PRINTF_STATE_SPEC: + PRINTF_STATE_SPEC_: + switch(*fmt) + { + case 'c': + serial_puts(*(const char **)argp); + argp++; + break; + case 's': + serial_puts(*(const char **)argp); + argp++; + break; + case '%': + putc('%'); + break; + case 'd': + case 'i': + radix = 10; + sign = true; + argp = serial_printf_number(argp, length, sign, radix); + break; + case 'u': + radix = 10; + sign = false; + argp = serial_printf_number(argp, length, sign, radix); + break; + case 'X': + case 'x': + case 'p': + radix = 16; + sign = false; + argp = serial_printf_number(argp, length, sign, radix); + break; + case 'o': + radix = 8; + sign = false; + argp = serial_printf_number(argp, length, sign, radix); + break; + case 'f': { + // Handle floating-point numbers + double* dargp = (double*)argp; + double d = *(double*)dargp; + char buffer[64]; + dtostrf(d, buffer, 6); // Default precision: 6 + serial_puts(buffer); + argp += 2; // Incrementing by 2 to move past the double argument + break; + } + default: + break; + } + state = PRINTF_STATE_START; + length = PRINTF_LENGTH_START; + radix = 10; + sign = false; + break; + } + fmt++; + } serial_puts("\n"); } + diff --git a/src/drivers/serial.h b/src/drivers/serial.h index 447024f..52cc4b4 100644 --- a/src/drivers/serial.h +++ b/src/drivers/serial.h @@ -8,5 +8,5 @@ int is_transmit_empty(); void write_serial(const char a); void serial_puts(const char* str); void log(const char* str, const int errlevel); - +void serial_printf(int errlevel, const char* fmt, ...); #endif diff --git a/src/kernel/kmain.c b/src/kernel/kmain.c index 0a9e5be..c2f8806 100644 --- a/src/kernel/kmain.c +++ b/src/kernel/kmain.c @@ -21,25 +21,25 @@ void kmain(unsigned int multiboot_info_address) g_multiboot_info_address = multiboot_info_address; init_serial(); - log("serial connection established", 3); + log("serial connection established\n", 3); gdt_install(); - log("initialized GDT entries", 2); + log("initialized GDT entries\n", 2); idt_install(); - log("initialized IDT", 2); + log("initialized IDT\n", 2); isr_install(); - log("initialized ISRs", 2); + log("initialized ISRs\n", 2); irq_install(); __asm__ __volatile__("sti"); - log("initialized IRQs", 2), + log("initialized IRQs\n", 2), clear(); colorputs(ascii_title, 10); colorputs(" by @xamidev - star the repo for a cookie!\n\n", 14); timer_install(); - log("initialized timer handler", 2); - keyboard_install(); - log("initialized keyboard driver", 2); + serial_printf(2, "%d\tinitialized timer handler", global_ticks); + keyboard_install(); + serial_printf(2, "%d\tinitialized keyboard handler", global_ticks); shell_install(); - log("started system shell", 2); + serial_printf(2, "%d\tstarted system shell", global_ticks); } diff --git a/src/libc/stdio.h b/src/libc/stdio.h index 7337340..e7882fb 100644 --- a/src/libc/stdio.h +++ b/src/libc/stdio.h @@ -40,4 +40,6 @@ int* printf_number(int* argp, int length, bool sign, int radix); int getch(); void get_input(char *buffer, int size); +void dtostrf(double val, char *buffer, int precision); + #endif diff --git a/src/programs/sysinfo.c b/src/programs/sysinfo.c index 3ef7b45..778b67f 100644 --- a/src/programs/sysinfo.c +++ b/src/programs/sysinfo.c @@ -2,6 +2,7 @@ #include "../kernel/sysinfo.h" #include "../libc/stdio.h" #include "../kernel/system.h" +#include "../libc/string.h" extern unsigned int multiboot_info_address; @@ -35,7 +36,7 @@ void get_cpuid() printf("CPU information\n\tvendor: %s\n\tfamily: %u\n\tmodel: %u\n\tfeatures: 0x%x\n", vendor, family, model, edx); } -void get_meminfo(unsigned int multiboot_info_address) +void get_meminfo(unsigned int multiboot_info_address, int verbose) { // RAM @@ -44,21 +45,34 @@ void get_meminfo(unsigned int multiboot_info_address) printf("RAM information\n\tLower memory: %u KB\n\tUpper memory: %u KB\n", mem_lower, mem_upper); - multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44)); - printf("\tMemory map:\n"); - - while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40))) + if (verbose) { - printf("\t\tBase addr: 0x%x%x\n\t\tLength: 0x%x%x\n\t\tType: %u\n", - mmap->base_addr_high, mmap->base_addr_low, - mmap->length_high, mmap->length_low, - mmap->type); - mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int)); + multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44)); + printf("Memory map:\nBase addr | Length | Type\n----------------------------------------------------\n"); + + while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40))) + { + if (mmap->length_high != 0 && mmap->length_low != 0) + { + printf("0x%x%x | 0x%x%x | %u\n", + mmap->base_addr_high, mmap->base_addr_low, + mmap->length_high, mmap->length_low, + mmap->type); + } + mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int)); + } } } -void program_sysinfo() +void program_sysinfo(int argc, char* argv[]) { - get_cpuid(); - get_meminfo(g_multiboot_info_address); + if (argc == 1) + { + get_cpuid(); + get_meminfo(g_multiboot_info_address, 0); + } else if (argc == 2 && strcmp(argv[1], "-v") == 0) + { + get_cpuid(); + get_meminfo(g_multiboot_info_address, 1); + } }