Remove mmio, port io, and debug headers from kernel side, and keep them on the libc. Simplify debugging functions. Add missing comments in several locations. Move ANSI color definitions in a separate file.
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
/// @file debug.c
|
||||
/// @brief Debugging primitives.
|
||||
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
|
||||
/// See LICENSE.md for details.
|
||||
|
||||
#include "io/debug.h"
|
||||
#include "io/port_io.h"
|
||||
#include "io/ansi_colors.h"
|
||||
#include "sys/bitops.h"
|
||||
#include "string.h"
|
||||
#include "stdio.h"
|
||||
#include "math.h"
|
||||
|
||||
/// Serial port for QEMU.
|
||||
#define SERIAL_COM1 (0x03F8)
|
||||
/// Determines the log level.
|
||||
static int max_log_level = LOGLEVEL_DEBUG;
|
||||
|
||||
void dbg_putchar(char c)
|
||||
{
|
||||
outportb(SERIAL_COM1, (uint8_t)c);
|
||||
}
|
||||
|
||||
void dbg_puts(const char *s)
|
||||
{
|
||||
while ((*s) != 0)
|
||||
dbg_putchar(*s++);
|
||||
}
|
||||
|
||||
static inline void __debug_print_header(const char *file, const char *fun, int line, short log_level, char *header)
|
||||
{
|
||||
// "EMERG ", "ALERT ", "CRIT ", "ERR ", "WARNING", "NOTICE ", "INFO ", "DEBUG ", "DEFAULT",
|
||||
static const char *log_level_label[] = { " EM ", " AL ", " CR ", " ER ", " WR ", " NT ", " IN ", " DB ", " DF " };
|
||||
static const char *log_level_color[] = {
|
||||
FG_RED_BRIGHT, // "EMERG "
|
||||
FG_RED_BRIGHT, // "ALERT "
|
||||
FG_RED, // "CRIT "
|
||||
FG_RED, // "ERR "
|
||||
FG_YELLOW_BRIGHT, // "WARNING"
|
||||
FG_RESET, // "NOTICE "
|
||||
FG_CYAN, // "INFO "
|
||||
FG_YELLOW, // "DEBUG "
|
||||
FG_RESET // "DEFAULT"
|
||||
};
|
||||
static char tmp_prefix[BUFSIZ], final_prefix[BUFSIZ];
|
||||
// Check the log level.
|
||||
if ((log_level < LOGLEVEL_EMERG) || (log_level > LOGLEVEL_DEBUG)) {
|
||||
// Set it to default.
|
||||
log_level = 8;
|
||||
}
|
||||
// Set the color.
|
||||
dbg_puts(log_level_color[log_level]);
|
||||
dbg_putchar('[');
|
||||
// Set the label.
|
||||
dbg_puts(log_level_label[log_level]);
|
||||
dbg_putchar('|');
|
||||
// Print the file and line.
|
||||
sprintf(tmp_prefix, "%s:%d", file, line);
|
||||
// Print the message.
|
||||
sprintf(final_prefix, " %-20s ", tmp_prefix);
|
||||
// Print the actual message.
|
||||
dbg_puts(final_prefix);
|
||||
#if 0
|
||||
dbg_putchar('|');
|
||||
sprintf(final_prefix, " %-25s ]", fun);
|
||||
dbg_puts(final_prefix);
|
||||
#else
|
||||
dbg_putchar(']');
|
||||
#endif
|
||||
dbg_putchar(' ');
|
||||
if (header) {
|
||||
dbg_puts(header);
|
||||
dbg_putchar(' ');
|
||||
}
|
||||
}
|
||||
|
||||
void set_log_level(int level)
|
||||
{
|
||||
if ((level >= LOGLEVEL_EMERG) && (level <= LOGLEVEL_DEBUG))
|
||||
max_log_level = level;
|
||||
}
|
||||
|
||||
int get_log_level()
|
||||
{
|
||||
return max_log_level;
|
||||
}
|
||||
|
||||
void dbg_printf(const char *file, const char *fun, int line, char *header, short log_level, const char *format, ...)
|
||||
{
|
||||
// Define a buffer for the formatted string.
|
||||
static char formatted[BUFSIZ];
|
||||
static short new_line = 1;
|
||||
|
||||
// Stage 1: FORMAT
|
||||
if (strlen(format) >= BUFSIZ)
|
||||
return;
|
||||
|
||||
// Start variabile argument's list.
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
// Format the message.
|
||||
vsprintf(formatted, format, ap);
|
||||
// End the list of arguments.
|
||||
va_end(ap);
|
||||
|
||||
// Stage 2: SEND
|
||||
if (new_line) {
|
||||
__debug_print_header(file, fun, line, log_level, header);
|
||||
new_line = 0;
|
||||
}
|
||||
for (int it = 0; (formatted[it] != 0) && (it < BUFSIZ); ++it) {
|
||||
dbg_putchar(formatted[it]);
|
||||
if (formatted[it] != '\n') {
|
||||
continue;
|
||||
}
|
||||
if ((it + 1) >= BUFSIZ) {
|
||||
continue;
|
||||
}
|
||||
if (formatted[it + 1] == 0) {
|
||||
new_line = 1;
|
||||
} else {
|
||||
__debug_print_header(file, fun, line, log_level, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const char *to_human_size(unsigned long bytes)
|
||||
{
|
||||
static char output[200];
|
||||
const char *suffix[] = { "B", "KB", "MB", "GB", "TB" };
|
||||
char length = sizeof(suffix) / sizeof(suffix[0]);
|
||||
int i = 0;
|
||||
double dblBytes = bytes;
|
||||
if (bytes > 1024) {
|
||||
for (i = 0; (bytes / 1024) > 0 && i < length - 1; i++, bytes /= 1024)
|
||||
dblBytes = bytes / 1024.0;
|
||||
}
|
||||
sprintf(output, "%.02lf %2s", dblBytes, suffix[i]);
|
||||
return output;
|
||||
}
|
||||
|
||||
const char *dec_to_binary(unsigned long value, unsigned length)
|
||||
{
|
||||
static char buffer[33];
|
||||
memset(buffer, 0, 33);
|
||||
for (int i = 0, j = 32 - min(max(0, length), 32); j < 32; ++i, ++j)
|
||||
buffer[i] = bit_check(value, 31 - j) ? '1' : '0';
|
||||
return buffer;
|
||||
}
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include "kernel.h"
|
||||
|
||||
void dbg_print_regs(pt_regs *frame)
|
||||
{
|
||||
pr_debug("Interrupt stack frame:\n");
|
||||
pr_debug("GS = 0x%-04x\n", frame->gs);
|
||||
pr_debug("FS = 0x%-04x\n", frame->fs);
|
||||
pr_debug("ES = 0x%-04x\n", frame->es);
|
||||
pr_debug("DS = 0x%-04x\n", frame->ds);
|
||||
pr_debug("EDI = 0x%-09x\n", frame->edi);
|
||||
pr_debug("ESI = 0x%-09x\n", frame->esi);
|
||||
pr_debug("EBP = 0x%-09x\n", frame->ebp);
|
||||
pr_debug("ESP = 0x%-09x\n", frame->esp);
|
||||
pr_debug("EBX = 0x%-09x\n", frame->ebx);
|
||||
pr_debug("EDX = 0x%-09x\n", frame->edx);
|
||||
pr_debug("ECX = 0x%-09x\n", frame->ecx);
|
||||
pr_debug("EAX = 0x%-09x\n", frame->eax);
|
||||
pr_debug("INT_NO = %-9d\n", frame->int_no);
|
||||
pr_debug("ERR_CD = %-9d\n", frame->err_code);
|
||||
pr_debug("EIP = 0x%-09x\n", frame->eip);
|
||||
pr_debug("CS = 0x%-04x\n", frame->cs);
|
||||
pr_debug("EFLAGS = 0x%-09x\n", frame->eflags);
|
||||
pr_debug("UESP = 0x%-09x\n", frame->useresp);
|
||||
pr_debug("SS = 0x%-04x\n", frame->ss);
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user