435 lines
No EOL
11 KiB
C
435 lines
No EOL
11 KiB
C
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <lock.h>
|
|
#include "../include/kprint.h"
|
|
#include "../drivers/serial.h"
|
|
#include "../hal/tsc.h"
|
|
|
|
|
|
#define FORMAT_LENGTH 1
|
|
#define NORMAL 0
|
|
#define STATE_SHORT 2
|
|
#define STATE_LONG 3
|
|
#define FORMAT_SPECIFIER 1
|
|
|
|
#define LENGTH_DEFAULT 0
|
|
#define LENGTH_SHORT_SHORT 1
|
|
#define LENGTH_SHORT 2
|
|
#define LENGTH_LONG 3
|
|
#define LENGTH_LONG_LONG 4
|
|
|
|
extern bool serial_enabled;
|
|
|
|
void klog(const char *func, const char *msg, ...){
|
|
kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg);
|
|
serial_kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
atomic_flag printf_lock = ATOMIC_FLAG_INIT;
|
|
|
|
/*
|
|
printf()
|
|
params:
|
|
string
|
|
arguments
|
|
|
|
available format specifiers:
|
|
{i}, {d} - integer
|
|
{s} - string
|
|
{c} - char
|
|
{k} - color
|
|
{n} - newline (doesnt take in a argument)
|
|
{x} - base16
|
|
{b} - binary
|
|
*/
|
|
|
|
int kprintf(const char *format_string, ...){
|
|
extern struct flanterm_context *ft_ctx;
|
|
acquire_spinlock(&printf_lock);
|
|
int state = NORMAL;
|
|
va_list a_list;
|
|
va_start(a_list, format_string);
|
|
for(uint64_t i = 0; i < strlen(format_string); i++){
|
|
char current = format_string[i]; // current char in string
|
|
switch (state){
|
|
case NORMAL:
|
|
switch (current) {
|
|
case '{':
|
|
state = FORMAT_SPECIFIER;
|
|
break;
|
|
default:
|
|
print_char(ft_ctx, current);
|
|
break;
|
|
}
|
|
break;
|
|
case FORMAT_SPECIFIER:
|
|
switch (current) {
|
|
case 'n':
|
|
print_str(ft_ctx, "\n");
|
|
break;
|
|
case 'k':
|
|
print_str(ft_ctx, va_arg(a_list, char*));
|
|
break;
|
|
case 'd':
|
|
case 'i':
|
|
print_int(ft_ctx, va_arg(a_list, long long));
|
|
break;
|
|
case 's':
|
|
print_str(ft_ctx, va_arg(a_list, char*));
|
|
break;
|
|
case 'c':
|
|
;
|
|
int ch = va_arg(a_list, int);
|
|
print_char(ft_ctx, ch);
|
|
break;
|
|
case 'x':
|
|
print_hex(ft_ctx, va_arg(a_list, uint64_t));
|
|
break;
|
|
case 'b':
|
|
print_bin(ft_ctx, va_arg(a_list, uint64_t));
|
|
break;
|
|
case 'l':
|
|
current++;
|
|
switch (current) {
|
|
case 'd':
|
|
print_int(ft_ctx, va_arg(a_list, long long int));
|
|
break;
|
|
|
|
}
|
|
break;
|
|
case '}':
|
|
state = NORMAL;
|
|
break;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
va_end(a_list);
|
|
free_spinlock(&printf_lock);
|
|
return 0;
|
|
}
|
|
|
|
int serial_kprintf(const char *format_string, ...){
|
|
int state = NORMAL;
|
|
va_list a_list;
|
|
va_start(a_list, format_string);
|
|
for(uint64_t i = 0; i < strlen(format_string); i++){
|
|
char current = format_string[i]; // current char in string
|
|
switch (state){
|
|
case NORMAL:
|
|
switch (current) {
|
|
case '{':
|
|
state = FORMAT_SPECIFIER;
|
|
break;
|
|
default:
|
|
serial_print_char(current);
|
|
break;
|
|
}
|
|
break;
|
|
case FORMAT_SPECIFIER:
|
|
switch (current) {
|
|
case 'n':
|
|
serial_print("\n");
|
|
break;
|
|
case 'k':
|
|
serial_print(va_arg(a_list, char*));
|
|
break;
|
|
case 'd':
|
|
case 'i':
|
|
serial_print_int(va_arg(a_list, long long));
|
|
break;
|
|
case 's':
|
|
serial_print(va_arg(a_list, char*));
|
|
break;
|
|
case 'c':
|
|
;
|
|
int ch = va_arg(a_list, int);
|
|
serial_print_char(ch);
|
|
|
|
break;
|
|
case 'x':
|
|
serial_print_hex(va_arg(a_list, uint64_t));
|
|
break;
|
|
case 'b':
|
|
serial_print_bin(va_arg(a_list, uint64_t));
|
|
break;
|
|
case 'l':
|
|
current++;
|
|
switch (current) {
|
|
case 'd':
|
|
case 'i':
|
|
serial_print_int(va_arg(a_list, long long int));
|
|
break;
|
|
|
|
}
|
|
break;
|
|
case '}':
|
|
state = NORMAL;
|
|
break;
|
|
|
|
}
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
va_end(a_list);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define MAX_INTERGER_SIZE 128
|
|
|
|
void print_char(struct flanterm_context *ft_ctx, char c){
|
|
kernel_framebuffer_print(&c, 1);
|
|
}
|
|
|
|
void serial_print_char(char c){
|
|
serial_write(c);
|
|
}
|
|
|
|
void print_str(struct flanterm_context *ft_ctx, char *str){
|
|
kernel_framebuffer_print(str, strlen(str));
|
|
}
|
|
|
|
void print_int(struct flanterm_context *ft_ctx, uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
if(num == 0){
|
|
buffer[0] = '0';
|
|
}
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 10;
|
|
arr[j] = dtoc(mod);
|
|
num /= 10;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_framebuffer_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
void print_hex(struct flanterm_context *ft_ctx, uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
if(num == 0){
|
|
buffer[0] = '0';
|
|
}
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 16;
|
|
arr[j] = dtoc(mod);
|
|
num /= 16;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_framebuffer_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
void print_bin(struct flanterm_context *ft_ctx, uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 2;
|
|
arr[j] = dtoc(mod);
|
|
num /= 2;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_framebuffer_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
void serial_print_int(uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 10;
|
|
arr[j] = dtoc(mod);
|
|
num /= 10;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_serial_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
void serial_print_hex(uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 16;
|
|
arr[j] = dtoc(mod);
|
|
num /= 16;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_serial_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
void serial_print_bin(uint64_t num){
|
|
char buffer[MAX_INTERGER_SIZE] = {0};
|
|
|
|
int arr[MAX_INTERGER_SIZE] = {0};
|
|
int j = 0;
|
|
|
|
while(num != 0){
|
|
int mod = num % 2;
|
|
arr[j] = dtoc(mod);
|
|
num /= 2;
|
|
j++;
|
|
|
|
if(j == MAX_INTERGER_SIZE){
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Reverse buffer */
|
|
for(int i = 0; i < j; i++){
|
|
buffer[i] = arr[j - i - 1];
|
|
}
|
|
|
|
kernel_serial_print(buffer, strlen(buffer));
|
|
}
|
|
|
|
|
|
char toupper(char c){
|
|
switch(c){
|
|
case 'a':
|
|
return 'A';
|
|
case 'b':
|
|
return 'B';
|
|
case 'c':
|
|
return 'C';
|
|
case 'd':
|
|
return 'D';
|
|
case 'e':
|
|
return 'E';
|
|
case 'f':
|
|
return 'F';
|
|
case 'g':
|
|
return 'G';
|
|
case 'h':
|
|
return 'H';
|
|
case 'i':
|
|
return 'I';
|
|
case 'j':
|
|
return 'J';
|
|
case 'k':
|
|
return 'K';
|
|
case 'l':
|
|
return 'L';
|
|
case 'm':
|
|
return 'M';
|
|
case 'n':
|
|
return 'N';
|
|
case 'o':
|
|
return 'O';
|
|
case 'p':
|
|
return 'P';
|
|
case 't':
|
|
return 'T';
|
|
case 'r':
|
|
return 'R';
|
|
case 's':
|
|
return 'S';
|
|
case 'u':
|
|
return 'U';
|
|
case 'v':
|
|
return 'V';
|
|
case 'w':
|
|
return 'W';
|
|
case 'x':
|
|
return 'X';
|
|
case 'y':
|
|
return 'Y';
|
|
case 'z':
|
|
return 'Z';
|
|
default:
|
|
return c;
|
|
|
|
}
|
|
}
|
|
|
|
/* Eventually fix printf so that these print_* functions dont
|
|
write to the framebuffer but instead return to printf */
|
|
|
|
/* Prints a char array to the framebuffer, thread safe*/
|
|
void kernel_framebuffer_print(char *buffer, size_t n){
|
|
extern struct flanterm_context *ft_ctx;
|
|
flanterm_write(ft_ctx, buffer, n);
|
|
}
|
|
|
|
/* Prints a char array to serial, thread safe*/
|
|
void kernel_serial_print(char *buffer, size_t n){
|
|
for(size_t i = 0; i < n; i++){
|
|
serial_print_char(buffer[i]);
|
|
}
|
|
} |