diff --git a/kernel/kernel/kernel.c b/kernel/kernel/kernel.c index 99f1bf3..f454fbd 100644 --- a/kernel/kernel/kernel.c +++ b/kernel/kernel/kernel.c @@ -7,12 +7,12 @@ void kernel_main(void) { terminal_initialize(); + init_serial(); printf("Hello from OrionOS!\n"); printf("Testing serial\n"); - init_serial(); - serial_print("Test is success!\n"); - serial_print("Newline test\n"); - serial_print("No newline test "); - serial_print("No newline test"); + serial_printf("Test is success!\n"); + serial_printf("Newline test\n"); + char * test_string = "test"; + serial_printf("This is string from variable: %s", test_string); printf("Test finished success!\n"); } diff --git a/kernel/kernel/serial.h b/kernel/kernel/serial.h index 0451afc..94eb14d 100644 --- a/kernel/kernel/serial.h +++ b/kernel/kernel/serial.h @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #define PORT 0x3f8 // COM1 @@ -38,23 +41,91 @@ char read_serial() { int is_transmit_empty() { return inb(PORT + 5) & 0x20; } - + void write_serial(char a) { while (is_transmit_empty() == 0); outb(PORT, a); } -void serial_print(const char* str, ...) { - size_t len = strlen(str); - for (size_t i=0; i < len; i++) { - if (str[i] == '\n') { - write_serial('\r'); - write_serial('\n'); - } else { - write_serial(str[i]); - } - } +static bool print(const char* data, size_t length) { + const unsigned char* bytes = (const unsigned char*) data; + for (size_t i = 0; i < length; i++) { + if (bytes[i] == '\n') { + write_serial('\r'); + write_serial('\n'); + } else { + write_serial(bytes[i]); + } + } + return true; +} + +int serial_printf(const char* restrict format, ...) { + va_list parameters; + va_start(parameters, format); + + int written = 0; + + while (*format != '\0') { + size_t maxrem = INT_MAX - written; + + if (format[0] != '%' || format[1] == '%') { + if (format[0] == '%') + format++; + size_t amount = 1; + while (format[amount] && format[amount] != '%') + amount++; + if (maxrem < amount) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(format, amount)) + return -1; + format += amount; + written += amount; + continue; + } + + const char* format_begun_at = format++; + + if (*format == 'c') { + format++; + char c = (char) va_arg(parameters, int /* char promotes to int */); + if (!maxrem) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(&c, sizeof(c))) + return -1; + written++; + } else if (*format == 's') { + format++; + const char* str = va_arg(parameters, const char*); + size_t len = strlen(str); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(str, len)) + return -1; + written += len; + } else { + format = format_begun_at; + size_t len = strlen(format); + if (maxrem < len) { + // TODO: Set errno to EOVERFLOW. + return -1; + } + if (!print(format, len)) + return -1; + written += len; + format += len; + } + } + + va_end(parameters); + return written; } inline void outb(uint16_t port, uint8_t val)