Add: serial printf
This commit is contained in:
Binary file not shown.
@@ -1,5 +1,6 @@
|
|||||||
#include "../kernel/io.h"
|
#include "../kernel/io.h"
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
#include "../libc/stdio.h"
|
||||||
|
|
||||||
int init_serial()
|
int init_serial()
|
||||||
{
|
{
|
||||||
@@ -61,5 +62,220 @@ void log(const char* str, const int errlevel)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
serial_puts(str);
|
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");
|
serial_puts("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,5 +8,5 @@ int is_transmit_empty();
|
|||||||
void write_serial(const char a);
|
void write_serial(const char a);
|
||||||
void serial_puts(const char* str);
|
void serial_puts(const char* str);
|
||||||
void log(const char* str, const int errlevel);
|
void log(const char* str, const int errlevel);
|
||||||
|
void serial_printf(int errlevel, const char* fmt, ...);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,25 +21,25 @@ void kmain(unsigned int multiboot_info_address)
|
|||||||
g_multiboot_info_address = multiboot_info_address;
|
g_multiboot_info_address = multiboot_info_address;
|
||||||
|
|
||||||
init_serial();
|
init_serial();
|
||||||
log("serial connection established", 3);
|
log("serial connection established\n", 3);
|
||||||
gdt_install();
|
gdt_install();
|
||||||
log("initialized GDT entries", 2);
|
log("initialized GDT entries\n", 2);
|
||||||
idt_install();
|
idt_install();
|
||||||
log("initialized IDT", 2);
|
log("initialized IDT\n", 2);
|
||||||
isr_install();
|
isr_install();
|
||||||
log("initialized ISRs", 2);
|
log("initialized ISRs\n", 2);
|
||||||
irq_install();
|
irq_install();
|
||||||
__asm__ __volatile__("sti");
|
__asm__ __volatile__("sti");
|
||||||
log("initialized IRQs", 2),
|
log("initialized IRQs\n", 2),
|
||||||
|
|
||||||
clear();
|
clear();
|
||||||
colorputs(ascii_title, 10);
|
colorputs(ascii_title, 10);
|
||||||
colorputs(" by @xamidev - star the repo for a cookie!\n\n", 14);
|
colorputs(" by @xamidev - star the repo for a cookie!\n\n", 14);
|
||||||
|
|
||||||
timer_install();
|
timer_install();
|
||||||
log("initialized timer handler", 2);
|
serial_printf(2, "%d\tinitialized timer handler", global_ticks);
|
||||||
keyboard_install();
|
keyboard_install();
|
||||||
log("initialized keyboard driver", 2);
|
serial_printf(2, "%d\tinitialized keyboard handler", global_ticks);
|
||||||
shell_install();
|
shell_install();
|
||||||
log("started system shell", 2);
|
serial_printf(2, "%d\tstarted system shell", global_ticks);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,4 +40,6 @@ int* printf_number(int* argp, int length, bool sign, int radix);
|
|||||||
int getch();
|
int getch();
|
||||||
void get_input(char *buffer, int size);
|
void get_input(char *buffer, int size);
|
||||||
|
|
||||||
|
void dtostrf(double val, char *buffer, int precision);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "../kernel/sysinfo.h"
|
#include "../kernel/sysinfo.h"
|
||||||
#include "../libc/stdio.h"
|
#include "../libc/stdio.h"
|
||||||
#include "../kernel/system.h"
|
#include "../kernel/system.h"
|
||||||
|
#include "../libc/string.h"
|
||||||
|
|
||||||
extern unsigned int multiboot_info_address;
|
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);
|
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
|
// 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);
|
printf("RAM information\n\tLower memory: %u KB\n\tUpper memory: %u KB\n", mem_lower, mem_upper);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
{
|
||||||
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44));
|
multiboot_memory_map_t* mmap = (multiboot_memory_map_t*)*((unsigned int*)(multiboot_info_address + 44));
|
||||||
printf("\tMemory map:\n");
|
printf("Memory map:\nBase addr | Length | Type\n----------------------------------------------------\n");
|
||||||
|
|
||||||
while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40)))
|
while ((unsigned int)mmap < multiboot_info_address + *((unsigned int*)(multiboot_info_address + 40)))
|
||||||
{
|
{
|
||||||
printf("\t\tBase addr: 0x%x%x\n\t\tLength: 0x%x%x\n\t\tType: %u\n",
|
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->base_addr_high, mmap->base_addr_low,
|
||||||
mmap->length_high, mmap->length_low,
|
mmap->length_high, mmap->length_low,
|
||||||
mmap->type);
|
mmap->type);
|
||||||
|
}
|
||||||
mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int));
|
mmap = (multiboot_memory_map_t*)((unsigned int)mmap + mmap->size + sizeof(unsigned int));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void program_sysinfo()
|
void program_sysinfo(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
if (argc == 1)
|
||||||
|
{
|
||||||
get_cpuid();
|
get_cpuid();
|
||||||
get_meminfo(g_multiboot_info_address);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user