Kernel: Serial: Add serial_printf function

This function can output with decorators (like printf from stdio)
This commit is contained in:
g1n 2021-08-07 12:58:04 +03:00
parent 99888ea24d
commit beaa4078f7
2 changed files with 87 additions and 16 deletions

View File

@ -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");
}

View File

@ -1,5 +1,8 @@
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include <limits.h>
#include <stdbool.h>
#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)