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:
Enrico Fraccaroli
2023-01-18 11:40:53 -05:00
parent 54d755e3d2
commit 2fee354b4b
35 changed files with 625 additions and 616 deletions
+8 -2
View File
@@ -20,6 +20,14 @@ if (DOXYGEN_FOUND)
set(DOXYGEN_SHOW_INCLUDE_FILES NO)
set(DOXYGEN_GENERATE_TREEVIEW NO)
set(DOXYGEN_WARN_NO_PARAMDOC YES)
set(DOXYGEN_ENABLE_PREPROCESSING YES)
set(DOXYGEN_EXTRACT_STATIC YES)
set(DOXYGEN_MACRO_EXPANSION YES)
set(DOXYGEN_EXPAND_ONLY_PREDEF YES)
set(DOXYGEN_PREDEFINED "__attribute__((x))= _syscall0= _syscall0(x)= _syscall1(x)= _syscall2(x)= _syscall3(x)=")
set(DOXYGEN_WARN_FORMAT "$file($line): $text")
set(DOXYGEN_HTML_STYLESHEET ${PROJECT_SOURCE_DIR}/doc/doxygen.css)
doxygen_add_docs(
${PROJECT_NAME}_documentation
@@ -164,8 +172,6 @@ if (DOXYGEN_FOUND)
${PROJECT_SOURCE_DIR}/mentos/inc/hardware/pic8259.h
${PROJECT_SOURCE_DIR}/mentos/inc/hardware/timer.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/debug.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/mm_io.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/port_io.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/proc_modules.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/vga/vga.h
${PROJECT_SOURCE_DIR}/mentos/inc/io/vga/vga_font.h
+1 -1
View File
@@ -99,6 +99,7 @@ add_library(
${PROJECT_SOURCE_DIR}/src/abort.c
${PROJECT_SOURCE_DIR}/src/io/mm_io.c
${PROJECT_SOURCE_DIR}/src/io/port_io.c
${PROJECT_SOURCE_DIR}/src/io/debug.c
${PROJECT_SOURCE_DIR}/src/ipc/ipc.c
${PROJECT_SOURCE_DIR}/src/sys/unistd.c
${PROJECT_SOURCE_DIR}/src/sys/errno.c
@@ -137,7 +138,6 @@ add_library(
${PROJECT_SOURCE_DIR}/src/unistd/signal.c
${PROJECT_SOURCE_DIR}/src/unistd/interval.c
${PROJECT_SOURCE_DIR}/src/libc_start.c
${PROJECT_SOURCE_DIR}/src/debug.c
${PROJECT_SOURCE_DIR}/src/crt0.S
)
-44
View File
@@ -1,44 +0,0 @@
/// @file debug.h
/// @brief Debugging primitives.
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#ifndef __DEBUG_HEADER__
/// Header for identifying outputs coming from a mechanism.
#define __DEBUG_HEADER__
#endif
/// @brief Extract the filename from the full path provided by __FILE__.
#define __FILENAME__ (__builtin_strrchr(__FILE__, '/') ? __builtin_strrchr(__FILE__, '/') + 1 : __FILE__)
/// @brief Prints the given character to debug output.
/// @param c The character to print.
void dbg_putchar(char c);
/// @brief Prints the given string to debug output.
/// @param s The string to print.
void dbg_puts(const char *s);
/// @brief Prints the given string to the debug output.
/// @param file The name of the file.
/// @param fun The name of the function.
/// @param line The line inside the file.
/// @param format The format to used, see printf.
/// @param ... The list of arguments.
void dbg_printf(const char *file, const char *fun, int line, const char *format, ...);
/// @brief Transforms the given amount of bytes to a readable string.
/// @param bytes The bytes to turn to string.
/// @return String representing the bytes in human readable form.
const char *to_human_size(unsigned long bytes);
/// @brief Transforms the given value to a binary string.
/// @param value to print.
/// @param length of the binary output.
/// @return String representing the binary value.
const char *dec_to_binary(unsigned long value, unsigned length);
/// Prints a debugging message.
#define pr_debug(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__ __VA_ARGS__)
+63
View File
@@ -0,0 +1,63 @@
/// @file ansi_colors.h
/// @author Enrico Fraccaroli (enry.frak@gmail.com)
/// @brief List of ANSI colors.
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#define FG_RESET "\033[0m" ///< ANSI code for resetting.
#define FG_BLACK "\033[30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED "\033[31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN "\033[32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW "\033[33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE "\033[34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA "\033[35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN "\033[36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE "\033[37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BOLD "\033[1;30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED_BOLD "\033[1;31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN_BOLD "\033[1;32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW_BOLD "\033[1;33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE_BOLD "\033[1;34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA_BOLD "\033[1;35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN_BOLD "\033[1;36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE_BOLD "\033[1;37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BRIGHT "\033[90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT "\033[91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT "\033[92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT "\033[93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT "\033[94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT "\033[95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT "\033[96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT "\033[97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define FG_BLACK_BRIGHT_BOLD "\033[1;90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT_BOLD "\033[1;91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT_BOLD "\033[1;92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT_BOLD "\033[1;93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT_BOLD "\033[1;94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT_BOLD "\033[1;95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT_BOLD "\033[1;96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT_BOLD "\033[1;97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define BG_BLACK "\033[40m" ///< ANSI code for setting a BLACK background.
#define BG_RED "\033[41m" ///< ANSI code for setting a RED background.
#define BG_GREEN "\033[42m" ///< ANSI code for setting a GREEN background.
#define BG_YELLOW "\033[43m" ///< ANSI code for setting a YELLOW background.
#define BG_BLUE "\033[44m" ///< ANSI code for setting a BLUE background.
#define BG_MAGENTA "\033[45m" ///< ANSI code for setting a MAGENTA background.
#define BG_CYAN "\033[46m" ///< ANSI code for setting a CYAN background.
#define BG_WHITE "\033[47m" ///< ANSI code for setting a WHITE background.
#define BG_BRIGHT_BLACK "\033[100m" ///< ANSI code for setting a BRIGHT_BLACK background.
#define BG_BRIGHT_RED "\033[101m" ///< ANSI code for setting a BRIGHT_RED background.
#define BG_BRIGHT_GREEN "\033[102m" ///< ANSI code for setting a BRIGHT_GREEN background.
#define BG_BRIGHT_YELLOW "\033[103m" ///< ANSI code for setting a BRIGHT_YELLOW background.
#define BG_BRIGHT_BLUE "\033[104m" ///< ANSI code for setting a BRIGHT_BLUE background.
#define BG_BRIGHT_MAGENTA "\033[105m" ///< ANSI code for setting a BRIGHT_MAGENTA background.
#define BG_BRIGHT_CYAN "\033[106m" ///< ANSI code for setting a BRIGHT_CYAN background.
#define BG_BRIGHT_WHITE "\033[107m" ///< ANSI code for setting a BRIGHT_WHITE background.
+45 -32
View File
@@ -7,10 +7,8 @@
#include "sys/kernel_levels.h"
struct pt_regs;
#ifndef __DEBUG_LEVEL__
/// Defines the debug level.
/// Defines the debug level, by default we set it to notice.
#define __DEBUG_LEVEL__ LOGLEVEL_NOTICE
#endif
@@ -39,17 +37,14 @@ void dbg_putchar(char c);
void dbg_puts(const char *s);
/// @brief Prints the given string to the debug output.
/// @param file The name of the file.
/// @param fun The name of the function.
/// @param line The line inside the file.
/// @param header The header to print.
/// @param format The format to used, see printf.
/// @param ... The list of arguments.
void dbg_printf(const char *file, const char *fun, int line, char *header, const char *format, ...);
/// @brief Prints the registers on debug output.
/// @param frame Pointer to the register.
void dbg_print_regs(struct pt_regs *frame);
/// @param file the name of the file.
/// @param fun the name of the function.
/// @param line the line inside the file.
/// @param header the header to print.
/// @param log_level the log level.
/// @param format the format to used, see printf.
/// @param ... the list of arguments.
void dbg_printf(const char *file, const char *fun, int line, char *header, short log_level, const char *format, ...);
/// @brief Transforms the given amount of bytes to a readable string.
/// @param bytes The bytes to turn to string.
@@ -62,53 +57,71 @@ const char *to_human_size(unsigned long bytes);
/// @return String representing the binary value.
const char *dec_to_binary(unsigned long value, unsigned length);
/// Prints a KERN_DEFAULT.
#define pr_default(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_DEFAULT __VA_ARGS__)
/// Prints a KERN_EMERG.
/// Prints a default message, which is always shown.
#define pr_default(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_DEFAULT, __VA_ARGS__)
/// Prints an emergency message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_EMERG
#define pr_emerg(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_EMERG __VA_ARGS__)
#define pr_emerg(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_EMERG, __VA_ARGS__)
#else
#define pr_emerg(...)
#endif
/// Prints a KERN_ALERT.
/// Prints an alert message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_ALERT
#define pr_alert(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_ALERT __VA_ARGS__)
#define pr_alert(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_ALERT, __VA_ARGS__)
#else
#define pr_alert(...)
#endif
/// Prints a KERN_CRIT.
/// Prints a critical message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_CRIT
#define pr_crit(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_CRIT __VA_ARGS__)
#define pr_crit(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_CRIT, __VA_ARGS__)
#else
#define pr_crit(...)
#endif
/// Prints a KERN_ERR.
/// Prints an error message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_ERR
#define pr_err(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_ERR __VA_ARGS__)
#define pr_err(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_ERR, __VA_ARGS__)
#else
#define pr_err(...)
#endif
/// Prints a KERN_WARNING.
/// Prints a warning message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_WARNING
#define pr_warning(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_WARNING __VA_ARGS__)
#define pr_warning(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_WARNING, __VA_ARGS__)
#else
#define pr_warning(...)
#endif
/// Prints a KERN_NOTICE.
/// Prints a notice message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_NOTICE
#define pr_notice(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_NOTICE __VA_ARGS__)
#define pr_notice(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_NOTICE, __VA_ARGS__)
#else
#define pr_notice(...)
#endif
/// Prints a KERN_INFO.
/// Prints a info message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_INFO
#define pr_info(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_INFO __VA_ARGS__)
#define pr_info(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_INFO, __VA_ARGS__)
#else
#define pr_info(...)
#endif
/// Prints a KERN_DEBUG.
/// Prints a debug message.
#if __DEBUG_LEVEL__ >= LOGLEVEL_DEBUG
#define pr_debug(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, KERN_DEBUG __VA_ARGS__)
#define pr_debug(...) dbg_printf(__FILENAME__, __func__, __LINE__, __DEBUG_HEADER__, LOGLEVEL_DEBUG, __VA_ARGS__)
#else
#define pr_debug(...)
#endif
#ifdef __KERNEL__
struct pt_regs;
/// @brief Prints the registers on debug output.
/// @param frame Pointer to the register.
void dbg_print_regs(struct pt_regs *frame);
#endif
+12
View File
@@ -8,19 +8,31 @@
#include "stdint.h"
/// @brief Reads a 8-bit value from the given address.
/// @param addr the address we want to read from.
/// @return the value we read.
uint8_t in_memb(uint32_t addr);
/// @brief Reads a 16-bit value from the given address.
/// @param addr the address we want to read from.
/// @return the value we read.
uint16_t in_mems(uint32_t addr);
/// @brief Reads a 32-bit value from the given address.
/// @param addr the address we want to read from.
/// @return the value we read.
uint32_t in_meml(uint32_t addr);
/// @brief Writes a 8-bit value at the given address.
/// @param addr the address we want to write to.
/// @param value the value we want to write.
void out_memb(uint32_t addr, uint8_t value);
/// @brief Writes a 16-bit value at the given address.
/// @param addr the address we want to write to.
/// @param value the value we want to write.
void out_mems(uint32_t addr, uint16_t value);
/// @brief Writes a 32-bit value at the given address.
/// @param addr the address we want to write to.
/// @param value the value we want to write.
void out_meml(uint32_t addr, uint32_t value);
+32 -24
View File
@@ -7,36 +7,44 @@
#include "stdint.h"
/// @brief Used for reading from the I/O ports.
/// @param port The input port.
/// @return The read value.
/// @brief Reads a 8-bit value from the given port.
/// @param port the port we want to read from.
/// @return the value we read.
uint8_t inportb(uint16_t port);
/// @brief Used for reading 2 bytes from the I/O ports.
/// @param port The input port.
/// @return The read value.
/// @brief Reads a 16-bit value from the given port.
/// @param port the port we want to read from.
/// @return the value we read.
uint16_t inports(uint16_t port);
void inportsm(uint16_t port, uint8_t *data, unsigned long size);
/// @brief Used for reading 4 bytes from the I/O ports.
/// @param port The input port.
/// @return The read value.
/// @brief Reads a 32-bit value from the given port.
/// @param port the port we want to read from.
/// @return the value we read.
uint32_t inportl(uint16_t port);
/// @brief Use this to write to I/O ports to send bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outportb(uint16_t port, uint8_t data);
/// @brief Writes a 8-bit value at the given port.
/// @param port the port we want to write to.
/// @param value the value we want to write.
void outportb(uint16_t port, uint8_t value);
/// @brief Use this to write to I/O ports to send 2 bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outports(uint16_t port, uint16_t data);
/// @brief Writes a 16-bit value at the given port.
/// @param port the port we want to write to.
/// @param value the value we want to write.
void outports(uint16_t port, uint16_t value);
void outportsm(uint16_t port, uint8_t *data, uint16_t size);
/// @brief Writes a 32-bit value at the given port.
/// @param port the port we want to write to.
/// @param value the value we want to write.
void outportl(uint16_t port, uint32_t value);
/// @brief Use this to write to I/O ports to send 4 bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outportl(uint16_t port, uint32_t data);
/// @brief Reads multiple 16-bit values from the given port.
/// @param port the port we want to read from.
/// @param value the location where we store the values we read.
/// @param size the amount of values we want to read.
void inportsm(uint16_t port, uint8_t *value, unsigned long size);
/// @brief Writes multiple 16-bit values to the given port.
/// @param port the port we want to write to.
/// @param value the location where we get the values we need to write.
/// @param size the amount of values we want to write.
void outportsm(uint16_t port, uint8_t *value, uint16_t size);
+17
View File
@@ -0,0 +1,17 @@
/// @file kernel_levels.h
/// @brief
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
// Integer equivalents of KERN_<LEVEL>
#define LOGLEVEL_DEFAULT (-1) ///< default-level messages.
#define LOGLEVEL_EMERG 0 ///< system is unusable.
#define LOGLEVEL_ALERT 1 ///< action must be taken immediately.
#define LOGLEVEL_CRIT 2 ///< critical conditions.
#define LOGLEVEL_ERR 3 ///< error conditions.
#define LOGLEVEL_WARNING 4 ///< warning conditions.
#define LOGLEVEL_NOTICE 5 ///< normal but significant condition.
#define LOGLEVEL_INFO 6 ///< informational.
#define LOGLEVEL_DEBUG 7 ///< debug-level messages.
-108
View File
@@ -1,108 +0,0 @@
/// @file debug.c
/// @brief Debugging primitives.
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <debug.h>
#include <stddef.h>
#include <io/port_io.h>
#include <stdio.h>
#include <string.h>
#include <sys/bitops.h>
#include <math.h>
/// Serial port for QEMU.
#define SERIAL_COM1 (0x03F8)
#define FG_RESET "\033[0m" ///< ANSI code for resetting.
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)
{
static char tmp_prefix[BUFSIZ], final_prefix[BUFSIZ];
dbg_puts(FG_RESET);
dbg_puts("[ LB |");
sprintf(tmp_prefix, "%s:%d", file, line);
sprintf(final_prefix, " %-20s ", tmp_prefix);
dbg_puts(final_prefix);
#if 0
dbg_putchar('|');
sprintf(final_prefix, " %-25s ]", fun);
dbg_puts(final_prefix);
#else
dbg_putchar(']');
#endif
}
void dbg_printf(const char *file, const char *fun, int line, 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);
new_line = 0;
}
for (size_t 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);
}
}
}
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, "%.03lf %2s", dblBytes, suffix[i]);
return output;
}
const char *dec_to_binary(unsigned long value, unsigned length)
{
static char buffer[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;
}
+9 -1
View File
@@ -6,12 +6,13 @@
#include "grp.h"
#include "sys/unistd.h"
#include "sys/errno.h"
#include "io/debug.h"
#include "assert.h"
#include "string.h"
#include "stdio.h"
#include "debug.h"
#include "fcntl.h"
/// Holds the file descriptor while we are working with `/etc/group`.
static int __fd = -1;
/// @brief It parses the line (as string) and saves its content inside the
@@ -42,6 +43,13 @@ static inline void __parse_line(group_t *grp, char *buf)
grp->gr_mem[found_users] = "\0";
}
/// @brief Searches an entry in `/etc/group`.
/// @param fd the file descriptor pointing to `/etc/group`.
/// @param buf the buffer we are going to use to search the entry.
/// @param buflen the length of the buffer.
/// @param name the name we are looking for.
/// @param gid the group id we must match.
/// @return a pointer to the filled input buffer on success, NULL on failure.
static inline char *__search_entry(int fd, char *buf, int buflen, const char *name, gid_t gid)
{
int ret;
+179
View File
@@ -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
+6 -6
View File
@@ -5,32 +5,32 @@
#include "io/mm_io.h"
uint8_t in_memb(uint32_t addr)
inline uint8_t in_memb(uint32_t addr)
{
return *((uint8_t *) (addr));
}
uint16_t in_mems(uint32_t addr)
inline uint16_t in_mems(uint32_t addr)
{
return *((uint16_t *) (addr));
}
uint32_t in_meml(uint32_t addr)
inline uint32_t in_meml(uint32_t addr)
{
return *((uint32_t *) (addr));
}
void out_memb(uint32_t addr, uint8_t value)
inline void out_memb(uint32_t addr, uint8_t value)
{
(*((uint8_t *) (addr))) = (value);
}
void out_mems(uint32_t addr, uint16_t value)
inline void out_mems(uint32_t addr, uint16_t value)
{
(*((uint16_t *) (addr))) = (value);
}
void out_meml(uint32_t addr, uint32_t value)
inline void out_meml(uint32_t addr, uint32_t value)
{
(*((uint32_t *) (addr))) = (value);
}
+33 -23
View File
@@ -7,51 +7,61 @@
inline uint8_t inportb(uint16_t port)
{
unsigned char data = 0;
__asm__ __volatile__("inb %%dx, %%al" : "=a"(data) : "d"(port));
return data;
unsigned char value = 0;
__asm__ __volatile__("inb %%dx, %%al"
: "=a"(value)
: "d"(port));
return value;
}
inline uint16_t inports(uint16_t port)
{
uint16_t rv;
__asm__ __volatile__("inw %1, %0" : "=a"(rv) : "dN"(port));
__asm__ __volatile__("inw %1, %0"
: "=a"(rv)
: "dN"(port));
return rv;
}
void inportsm(uint16_t port, uint8_t *data, unsigned long size)
{
__asm__ __volatile__("rep insw"
: "+D"(data), "+c"(size)
: "d"(port)
: "memory");
}
inline uint32_t inportl(uint16_t port)
{
uint32_t rv;
__asm__ __volatile__("inl %%dx, %%eax" : "=a"(rv) : "dN"(port));
__asm__ __volatile__("inl %%dx, %%eax"
: "=a"(rv)
: "dN"(port));
return rv;
}
inline void outportb(uint16_t port, uint8_t data)
inline void outportb(uint16_t port, uint8_t value)
{
__asm__ __volatile__("outb %%al, %%dx" ::"a"(data), "d"(port));
__asm__ __volatile__("outb %%al, %%dx" ::"a"(value), "d"(port));
}
inline void outports(uint16_t port, uint16_t data)
inline void outports(uint16_t port, uint16_t value)
{
__asm__ __volatile__("outw %1, %0" : : "dN"(port), "a"(data));
__asm__ __volatile__("outw %1, %0"
:
: "dN"(port), "a"(value));
}
void outportsm(uint16_t port, uint8_t *data, uint16_t size)
inline void outportl(uint16_t port, uint32_t value)
{
__asm__ __volatile__("rep outsw" : "+S"(data), "+c"(size) : "d"(port));
__asm__ __volatile__("outl %%eax, %%dx"
:
: "dN"(port), "a"(value));
}
inline void outportl(uint16_t port, uint32_t data)
void inportsm(uint16_t port, uint8_t *value, unsigned long size)
{
__asm__ __volatile__("outl %%eax, %%dx" : : "dN"(port), "a"(data));
__asm__ __volatile__("rep insw"
: "+D"(value), "+c"(size)
: "d"(port)
: "memory");
}
void outportsm(uint16_t port, uint8_t *value, uint16_t size)
{
__asm__ __volatile__("rep outsw"
: "+S"(value), "+c"(size)
: "d"(port));
}
+4 -1
View File
@@ -6,12 +6,15 @@
#include "pwd.h"
#include "sys/unistd.h"
#include "sys/errno.h"
#include "io/debug.h"
#include "assert.h"
#include "string.h"
#include "stdio.h"
#include "fcntl.h"
#include "debug.h"
/// @brief Parses the input buffer and fills pwd with its details.
/// @param pwd the structure we need to fill.
/// @param buf the buffer from which we extract the information.
static inline void __parse_line(passwd_t *pwd, char *buf)
{
assert(pwd && "Received null pwd!");
+3 -1
View File
@@ -10,7 +10,9 @@
char **environ;
static char **__environ = NULL;
/// @brief Global environ list.
static char **__environ = NULL;
/// @brief Size of the global environ list.
static size_t __environ_size = 0;
/// @brief Finds the entry in the environ.
+2
View File
@@ -9,10 +9,12 @@
#include "string.h"
#include "stdio.h"
/// @brief List of week days name.
static const char *weekdays[] = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
};
/// @brief List of months name.
static const char *months[] = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
+7 -12
View File
@@ -3,12 +3,11 @@
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <debug.h>
#include "sys/unistd.h"
#include "system/syscall_types.h"
#include "sys/errno.h"
#include "sys/stat.h"
#include "io/debug.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
@@ -59,16 +58,12 @@ static inline int __find_in_path(const char *file, char *buf, size_t buf_len)
return -1;
}
/// @brief Replaces the current process image with a new process
/// image (argument vector), allows the caller to specify
/// the environment of the executed program via `envp`.
/// @param path The absolute path to the binary file to execute.
/// @param argv A vector of one or more pointers to null-terminated strings that represent
/// the argument list available to the executed program.
/// @param envp A vector of one or more pointers to null-terminated strings that represent
/// the environment list available to the executed program.
/// @return Returns -1 only if an error has occurred, and sets errno.
_syscall3(int, execve, const char *, path, char *const *, argv, char *const *, envp)
int execve(const char *path, char *const argv[], char *const envp[])
{
long __res;
__inline_syscall3(__res, execve, path, argv, envp);
__syscall_return(int, __res);
}
int execv(const char *path, char *const argv[])
{
+3
View File
@@ -10,10 +10,13 @@
#include "signal.h"
#include "sys/bitops.h"
/// @brief Implement the sigreturn function.
_syscall0(int, sigreturn)
/// @brief Implement the sigprocmask function.
_syscall3(int, sigprocmask, int, how, const sigset_t *, set, sigset_t *, oldset)
/// @brief List of signals names.
static const char *sys_siglist[] = {
"HUP",
"INT",
+18 -6
View File
@@ -8,7 +8,13 @@
#include <stdio.h>
#include <sys/unistd.h>
static int vsscanf(const char *buf, const char *s, va_list ap)
/// @brief Read formatted data from string.
/// @param buf String processed as source to retrieve the data.
/// @param s Format string, following the same specifications as printf.
/// @param ap The list of arguments where the values are stored.
/// @return On success, the function returns the number of items of the
/// argument list successfully filled. EOF otherwise.
static int __vsscanf(const char *buf, const char *s, va_list ap)
{
int count = 0, noassign = 0, width = 0, base = 0;
const char *tc;
@@ -92,14 +98,20 @@ static int vsscanf(const char *buf, const char *s, va_list ap)
return (count);
}
static int vfscanf(int fd, const char *fmt, va_list ap)
/// @brief Read formatted data from file.
/// @param fd the file descriptor associated with the file.
/// @param fmt format string, following the same specifications as printf.
/// @param ap the list of arguments where the values are stored.
/// @return On success, the function returns the number of items of the
/// argument list successfully filled. EOF otherwise.
static int __vfscanf(int fd, const char *fmt, va_list ap)
{
int count;
char buf[BUFSIZ + 1];
if (fgets(buf, BUFSIZ, fd) == 0)
return (-1);
count = vsscanf(buf, fmt, ap);
count = __vsscanf(buf, fmt, ap);
return (count);
}
@@ -109,7 +121,7 @@ int scanf(const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
count = vfscanf(STDIN_FILENO, fmt, ap);
count = __vfscanf(STDIN_FILENO, fmt, ap);
va_end(ap);
return (count);
}
@@ -120,7 +132,7 @@ int fscanf(int fd, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
count = vfscanf(fd, fmt, ap);
count = __vfscanf(fd, fmt, ap);
va_end(ap);
return (count);
}
@@ -131,7 +143,7 @@ int sscanf(const char *buf, const char *fmt, ...)
va_list ap;
va_start(ap, fmt);
count = vsscanf(buf, fmt, ap);
count = __vsscanf(buf, fmt, ap);
va_end(ap);
return (count);
}
+11 -1
View File
@@ -3,7 +3,7 @@
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include <sys/bitops.h>
#include "sys/bitops.h"
#include "fcvt.h"
#include "ctype.h"
#include "string.h"
@@ -30,6 +30,8 @@ static char *_digits = "0123456789abcdefghijklmnopqrstuvwxyz";
static char *_upper_digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
/// @brief Returns the index of the first non-integer character.
/// @param s the string we need to analyze.
/// @return the index of the first non-integer character.
static inline int skip_atoi(const char **s)
{
int i = 0;
@@ -38,6 +40,14 @@ static inline int skip_atoi(const char **s)
return i;
}
/// @brief Transforms the number into a string.
/// @param str the output string.
/// @param num the number to transform to string.
/// @param base the base to use for number transformation.
/// @param size the size of the output string.
/// @param precision the precision for floating point numbers.
/// @param flags control flags.
/// @return the number turned into a string.
static char *number(char *str, long num, int base, int size, int32_t precision, unsigned flags)
{
char c, tmp[66] = { 0 };
+80 -80
View File
@@ -97,86 +97,86 @@ endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
# Define the list of files.
set(KERNEL_SOURCES
src/kernel.c
src/multiboot.c
src/devices/pci.c
src/devices/fpu.c
src/drivers/ata.c
src/drivers/rtc.c
src/drivers/fdc.c
src/drivers/mouse.c
src/drivers/ps2.c
src/drivers/keyboard/keyboard.c
src/drivers/keyboard/keymap.c
src/fs/vfs.c
src/fs/read_write.c
src/fs/open.c
src/fs/stat.c
src/fs/readdir.c
src/fs/procfs.c
src/fs/ioctl.c
src/fs/namei.c
src/fs/ext2.c
src/hardware/timer.c
src/hardware/cpuid.c
src/hardware/pic8259.c
src/io/port_io.c
src/io/mm_io.c
src/io/video.c
src/io/stdio.c
src/io/debug.c
src/io/proc_video.c
src/io/proc_running.c
src/io/proc_system.c
src/io/vga/vga.c
src/ipc/msg.c
src/ipc/sem.c
src/ipc/shm.c
src/kernel/sys.c
src/klib/assert.c
src/klib/ctype.c
src/klib/mutex.c
src/klib/string.c
src/klib/vsprintf.c
src/klib/vscanf.c
src/klib/time.c
src/klib/libgen.c
src/klib/strerror.c
src/klib/math.c
src/klib/fcvt.c
src/klib/spinlock.c
src/klib/rbtree.c
src/klib/ndtree.c
src/klib/hashmap.c
src/klib/list.c
src/mem/kheap.c
src/mem/paging.c
src/mem/slab.c
src/mem/vmem_map.c
src/mem/zone_allocator.c
src/elf/elf.c
src/descriptor_tables/gdt.c
src/descriptor_tables/gdt.S
src/descriptor_tables/interrupt.c
src/descriptor_tables/exception.c
src/descriptor_tables/interrupt.S
src/descriptor_tables/exception.S
src/descriptor_tables/idt.c
src/descriptor_tables/idt.S
src/descriptor_tables/tss.c
src/descriptor_tables/tss.S
src/process/scheduler_algorithm.c
src/process/scheduler.c
src/process/process.c
src/process/wait.c
src/process/user.S
src/sys/utsname.c
src/sys/module.c
src/system/errno.c
src/system/panic.c
src/system/printk.c
src/system/signal.c
src/system/syscall.c
${PROJECT_SOURCE_DIR}/src/kernel.c
${PROJECT_SOURCE_DIR}/src/multiboot.c
${PROJECT_SOURCE_DIR}/src/devices/pci.c
${PROJECT_SOURCE_DIR}/src/devices/fpu.c
${PROJECT_SOURCE_DIR}/src/drivers/ata.c
${PROJECT_SOURCE_DIR}/src/drivers/rtc.c
${PROJECT_SOURCE_DIR}/src/drivers/fdc.c
${PROJECT_SOURCE_DIR}/src/drivers/mouse.c
${PROJECT_SOURCE_DIR}/src/drivers/ps2.c
${PROJECT_SOURCE_DIR}/src/drivers/keyboard/keyboard.c
${PROJECT_SOURCE_DIR}/src/drivers/keyboard/keymap.c
${PROJECT_SOURCE_DIR}/src/fs/vfs.c
${PROJECT_SOURCE_DIR}/src/fs/read_write.c
${PROJECT_SOURCE_DIR}/src/fs/open.c
${PROJECT_SOURCE_DIR}/src/fs/stat.c
${PROJECT_SOURCE_DIR}/src/fs/readdir.c
${PROJECT_SOURCE_DIR}/src/fs/procfs.c
${PROJECT_SOURCE_DIR}/src/fs/ioctl.c
${PROJECT_SOURCE_DIR}/src/fs/namei.c
${PROJECT_SOURCE_DIR}/src/fs/ext2.c
${PROJECT_SOURCE_DIR}/src/hardware/timer.c
${PROJECT_SOURCE_DIR}/src/hardware/cpuid.c
${PROJECT_SOURCE_DIR}/src/hardware/pic8259.c
${PROJECT_SOURCE_DIR}/src/io/debug.c
${PROJECT_SOURCE_DIR}/src/io/port_io.c
${PROJECT_SOURCE_DIR}/src/io/mm_io.c
${PROJECT_SOURCE_DIR}/src/io/video.c
${PROJECT_SOURCE_DIR}/src/io/stdio.c
${PROJECT_SOURCE_DIR}/src/io/proc_video.c
${PROJECT_SOURCE_DIR}/src/io/proc_running.c
${PROJECT_SOURCE_DIR}/src/io/proc_system.c
${PROJECT_SOURCE_DIR}/src/io/vga/vga.c
${PROJECT_SOURCE_DIR}/src/ipc/msg.c
${PROJECT_SOURCE_DIR}/src/ipc/sem.c
${PROJECT_SOURCE_DIR}/src/ipc/shm.c
${PROJECT_SOURCE_DIR}/src/kernel/sys.c
${PROJECT_SOURCE_DIR}/src/klib/assert.c
${PROJECT_SOURCE_DIR}/src/klib/ctype.c
${PROJECT_SOURCE_DIR}/src/klib/mutex.c
${PROJECT_SOURCE_DIR}/src/klib/string.c
${PROJECT_SOURCE_DIR}/src/klib/vsprintf.c
${PROJECT_SOURCE_DIR}/src/klib/vscanf.c
${PROJECT_SOURCE_DIR}/src/klib/time.c
${PROJECT_SOURCE_DIR}/src/klib/libgen.c
${PROJECT_SOURCE_DIR}/src/klib/strerror.c
${PROJECT_SOURCE_DIR}/src/klib/math.c
${PROJECT_SOURCE_DIR}/src/klib/fcvt.c
${PROJECT_SOURCE_DIR}/src/klib/spinlock.c
${PROJECT_SOURCE_DIR}/src/klib/rbtree.c
${PROJECT_SOURCE_DIR}/src/klib/ndtree.c
${PROJECT_SOURCE_DIR}/src/klib/hashmap.c
${PROJECT_SOURCE_DIR}/src/klib/list.c
${PROJECT_SOURCE_DIR}/src/mem/kheap.c
${PROJECT_SOURCE_DIR}/src/mem/paging.c
${PROJECT_SOURCE_DIR}/src/mem/slab.c
${PROJECT_SOURCE_DIR}/src/mem/vmem_map.c
${PROJECT_SOURCE_DIR}/src/mem/zone_allocator.c
${PROJECT_SOURCE_DIR}/src/elf/elf.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/gdt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/gdt.S
${PROJECT_SOURCE_DIR}/src/descriptor_tables/interrupt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/exception.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/interrupt.S
${PROJECT_SOURCE_DIR}/src/descriptor_tables/exception.S
${PROJECT_SOURCE_DIR}/src/descriptor_tables/idt.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/idt.S
${PROJECT_SOURCE_DIR}/src/descriptor_tables/tss.c
${PROJECT_SOURCE_DIR}/src/descriptor_tables/tss.S
${PROJECT_SOURCE_DIR}/src/process/scheduler_algorithm.c
${PROJECT_SOURCE_DIR}/src/process/scheduler.c
${PROJECT_SOURCE_DIR}/src/process/process.c
${PROJECT_SOURCE_DIR}/src/process/wait.c
${PROJECT_SOURCE_DIR}/src/process/user.S
${PROJECT_SOURCE_DIR}/src/sys/utsname.c
${PROJECT_SOURCE_DIR}/src/sys/module.c
${PROJECT_SOURCE_DIR}/src/system/errno.c
${PROJECT_SOURCE_DIR}/src/system/panic.c
${PROJECT_SOURCE_DIR}/src/system/printk.c
${PROJECT_SOURCE_DIR}/src/system/signal.c
${PROJECT_SOURCE_DIR}/src/system/syscall.c
)
# =============================================================================
+10 -1
View File
@@ -233,24 +233,33 @@ typedef enum {
typedef void (*pci_scan_func_t)(uint32_t device, uint16_t vendor_id, uint16_t device_id, void *extra);
/// @brief Extract the `bus` from the device.
/// @param device the device details.
/// @return the `bus` value.
static inline int pci_extract_bus(uint32_t device)
{
return (uint8_t)((device >> 16));
}
/// @brief Extract the `slot` from the device.
/// @param device the device details.
/// @return the `slot` value.
static inline int pci_extract_slot(uint32_t device)
{
return (uint8_t)((device >> 8));
}
/// @brief Extract the `func` from the device.
/// @param device the device details.
/// @return the `func` value.
static inline int pci_extract_func(uint32_t device)
{
return (uint8_t)(device);
}
/// @brief TODO: doxygen comment.
/// @brief TODO: Comment.
/// @param device
/// @param field
/// @return
static inline uint32_t pci_get_addr(uint32_t device, int field)
{
return 0x80000000 | (pci_extract_bus(device) << 16) |
-1
View File
@@ -157,7 +157,6 @@ void init_keymaps();
#define KEY_DOWN_ARROW 0xE050U ///< Down Arrow 57424
#define CODE_BREAK 0x0080U ///< Code break code
#define MULTIMEDIA_SCAN_CODE 0xE0
/// @}
/// @}
-38
View File
@@ -1,38 +0,0 @@
/// @file mm_io.h
/// @brief Memory Mapped IO functions.
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#include "stdint.h"
/// @brief Reads a 8-bit value from the given address.
/// @param addr The address from which we read.
/// @return The content read from the address.
uint8_t in_memb(uint32_t addr);
/// @brief Reads a 16-bit value from the given address.
/// @param addr The address from which we read.
/// @return The content read from the address.
uint16_t in_mems(uint32_t addr);
/// @brief Reads a 32-bit value from the given address.
/// @param addr The address from which we read.
/// @return The content read from the address.
uint32_t in_meml(uint32_t addr);
/// @brief Writes a 8-bit value at the given address.
/// @param addr The address where we want to write.
/// @param value The value we want to write.
void out_memb(uint32_t addr, uint8_t value);
/// @brief Writes a 16-bit value at the given address.
/// @param addr The address where we want to write.
/// @param value The value we want to write.
void out_mems(uint32_t addr, uint16_t value);
/// @brief Writes a 32-bit value at the given address.
/// @param addr The address where we want to write.
/// @param value The value we want to write.
void out_meml(uint32_t addr, uint32_t value);
-50
View File
@@ -1,50 +0,0 @@
/// @file port_io.h
/// @brief Byte I/O on ports prototypes.
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#include "stdint.h"
/// @brief Used for reading from the I/O ports.
/// @param port The input port.
/// @return The read value.
uint8_t inportb(uint16_t port);
/// @brief Used for reading 2 bytes from the I/O ports.
/// @param port The input port.
/// @return The read value.
uint16_t inports(uint16_t port);
/// @brief Read from the given port and store what we read in `data`.
/// @param port The input port.
/// @param data The buffer where we store what we read.
/// @param size The dimension of the buffer.
void inportsm(uint16_t port, uint8_t *data, unsigned long size);
/// @brief Used for reading 4 bytes from the I/O ports.
/// @param port The input port.
/// @return The read value.
uint32_t inportl(uint16_t port);
/// @brief Use this to write to I/O ports to send bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outportb(uint16_t port, uint8_t data);
/// @brief Use this to write to I/O ports to send 2 bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outports(uint16_t port, uint16_t data);
/// @brief Write to the given port what it is stored inside `data`.
/// @param port The output port.
/// @param data The buffer where we have the data.
/// @param size The dimension of the buffer.
void outportsm(uint16_t port, uint8_t *data, uint16_t size);
/// @brief Use this to write to I/O ports to send 4 bytes to devices.
/// @param port The output port.
/// @param data The data to write.
void outportl(uint16_t port, uint32_t data);
+3
View File
@@ -38,6 +38,7 @@ void vga_draw_pixel(int x, int y, unsigned char color);
/// @brief Reads a pixel at the given position.
/// @param x x-axis position.
/// @param y y-axis position.
/// @return the pixel we read.
unsigned int vga_read_pixel(int x, int y);
/// @brief Draws a character at the given position.
@@ -114,6 +115,8 @@ void vga_get_screen_size(unsigned int * width, unsigned int * height);
void vga_new_line();
/// @brief Change the color.
/// @param color the color to set.
void vga_set_color(unsigned int color);
/// @brief Run some VGA tests.
void vga_run_test();
+1 -56
View File
@@ -6,62 +6,7 @@
#pragma once
#include "stdint.h"
#define FG_RESET "\033[0m" ///< ANSI code for resetting.
#define FG_BLACK "\033[30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED "\033[31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN "\033[32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW "\033[33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE "\033[34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA "\033[35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN "\033[36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE "\033[37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BOLD "\033[1;30m" ///< ANSI code for setting a BLACK foreground.
#define FG_RED_BOLD "\033[1;31m" ///< ANSI code for setting a RED foreground.
#define FG_GREEN_BOLD "\033[1;32m" ///< ANSI code for setting a GREEN foreground.
#define FG_YELLOW_BOLD "\033[1;33m" ///< ANSI code for setting a YELLOW foreground.
#define FG_BLUE_BOLD "\033[1;34m" ///< ANSI code for setting a BLUE foreground.
#define FG_MAGENTA_BOLD "\033[1;35m" ///< ANSI code for setting a MAGENTA foreground.
#define FG_CYAN_BOLD "\033[1;36m" ///< ANSI code for setting a CYAN foreground.
#define FG_WHITE_BOLD "\033[1;37m" ///< ANSI code for setting a WHITE foreground.
#define FG_BLACK_BRIGHT "\033[90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT "\033[91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT "\033[92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT "\033[93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT "\033[94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT "\033[95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT "\033[96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT "\033[97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define FG_BLACK_BRIGHT_BOLD "\033[1;90m" ///< ANSI code for setting a BRIGHT_BLACK foreground.
#define FG_RED_BRIGHT_BOLD "\033[1;91m" ///< ANSI code for setting a BRIGHT_RED foreground.
#define FG_GREEN_BRIGHT_BOLD "\033[1;92m" ///< ANSI code for setting a BRIGHT_GREEN foreground.
#define FG_YELLOW_BRIGHT_BOLD "\033[1;93m" ///< ANSI code for setting a BRIGHT_YELLOW foreground.
#define FG_BLUE_BRIGHT_BOLD "\033[1;94m" ///< ANSI code for setting a BRIGHT_BLUE foreground.
#define FG_MAGENTA_BRIGHT_BOLD "\033[1;95m" ///< ANSI code for setting a BRIGHT_MAGENTA foreground.
#define FG_CYAN_BRIGHT_BOLD "\033[1;96m" ///< ANSI code for setting a BRIGHT_CYAN foreground.
#define FG_WHITE_BRIGHT_BOLD "\033[1;97m" ///< ANSI code for setting a BRIGHT_WHITE foreground.
#define BG_BLACK "\033[40m" ///< ANSI code for setting a BLACK background.
#define BG_RED "\033[41m" ///< ANSI code for setting a RED background.
#define BG_GREEN "\033[42m" ///< ANSI code for setting a GREEN background.
#define BG_YELLOW "\033[43m" ///< ANSI code for setting a YELLOW background.
#define BG_BLUE "\033[44m" ///< ANSI code for setting a BLUE background.
#define BG_MAGENTA "\033[45m" ///< ANSI code for setting a MAGENTA background.
#define BG_CYAN "\033[46m" ///< ANSI code for setting a CYAN background.
#define BG_WHITE "\033[47m" ///< ANSI code for setting a WHITE background.
#define BG_BRIGHT_BLACK "\033[100m" ///< ANSI code for setting a BRIGHT_BLACK background.
#define BG_BRIGHT_RED "\033[101m" ///< ANSI code for setting a BRIGHT_RED background.
#define BG_BRIGHT_GREEN "\033[102m" ///< ANSI code for setting a BRIGHT_GREEN background.
#define BG_BRIGHT_YELLOW "\033[103m" ///< ANSI code for setting a BRIGHT_YELLOW background.
#define BG_BRIGHT_BLUE "\033[104m" ///< ANSI code for setting a BRIGHT_BLUE background.
#define BG_BRIGHT_MAGENTA "\033[105m" ///< ANSI code for setting a BRIGHT_MAGENTA background.
#define BG_BRIGHT_CYAN "\033[106m" ///< ANSI code for setting a BRIGHT_CYAN background.
#define BG_BRIGHT_WHITE "\033[107m" ///< ANSI code for setting a BRIGHT_WHITE background.
#include "io/ansi_colors.h"
/// @brief Initialize the video.
void video_init();
+18 -17
View File
@@ -10,9 +10,10 @@
#include "stdint.h"
/// @brief Enable IRQs (nested).
/// @details If called after calling irq_nested_disable, this function will
/// not activate IRQs if they were not active before.
inline static void irq_nested_enable(uint8_t flags)
/// @details If called after calling irq_disable, this function will not
/// activate IRQs if they were not active before.
/// @param flags the flags to control this behaviour.
inline static void irq_enable(uint8_t flags)
{
if (flags) {
sti();
@@ -20,32 +21,32 @@ inline static void irq_nested_enable(uint8_t flags)
}
/// @brief Disable IRQs (nested).
/// @details Disable IRQs when unsure if IRQs were enabled at all.
/// This function together with irq_nested_enable can be used in
/// situations when interrupts shouldn't be activated if they were not
/// activated before calling this function.
inline static uint8_t irq_nested_disable()
/// @details Disable IRQs when unsure if IRQs were enabled at all. This function
/// together with irq_enable can be used in situations when interrupts
/// shouldn't be activated if they were not activated before calling this
/// function.
/// @return 1 if the IRQ is enable for the CPU.
inline static uint8_t irq_disable()
{
size_t flags;
__asm__ __volatile__("pushf; cli; pop %0"
// We are pushing the entire contents of the EFLAGS register onto the stack,
// clearing the interrupt line, and with the pop, getting the current status
// of the flags.
__asm__ __volatile__("pushf; cli; pop %0;"
: "=r"(flags)
:
: "memory");
if (flags & (1 << 9))
return 1;
return 0;
return flags & (1 << 9);
}
/// @brief Determines, if the interrupt flags (IF) is set.
/// @return 1 if the IRQ is enable for the CPU.
inline static uint8_t is_irq_enabled()
{
size_t flags;
__asm__ __volatile__("pushf; pop %0"
__asm__ __volatile__("pushf; pop %0;"
: "=r"(flags)
:
: "memory");
if (flags & (1 << 9)) {
return 1;
}
return 0;
return flags & (1 << 9);
}
-30
View File
@@ -1,30 +0,0 @@
/// @file kernel_levels.h
/// @brief
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#pragma once
#define KERN_SOH "\001" ///< ASCII Start Of Header.
#define KERN_SOH_ASCII '\001' ///< Character version of the SOH.
#define KERN_EMERG KERN_SOH "0" ///< Emergency messages (precede a crash)
#define KERN_ALERT KERN_SOH "1" ///< Error requiring immediate attention
#define KERN_CRIT KERN_SOH "2" ///< Critical error (hardware or software)
#define KERN_ERR KERN_SOH "3" ///< Error conditions (common in drivers)
#define KERN_WARNING KERN_SOH "4" ///< Warning conditions (could lead to errors)
#define KERN_NOTICE KERN_SOH "5" ///< Not an error but a significant condition
#define KERN_INFO KERN_SOH "6" ///< Informational message
#define KERN_DEBUG KERN_SOH "7" ///< Used only for debug messages
#define KERN_DEFAULT "" ///< Default kernel logging level
// Integer equivalents of KERN_<LEVEL>
#define LOGLEVEL_DEFAULT (-1) ///< default-level messages.
#define LOGLEVEL_EMERG 0 ///< system is unusable.
#define LOGLEVEL_ALERT 1 ///< action must be taken immediately.
#define LOGLEVEL_CRIT 2 ///< critical conditions.
#define LOGLEVEL_ERR 3 ///< error conditions.
#define LOGLEVEL_WARNING 4 ///< warning conditions.
#define LOGLEVEL_NOTICE 5 ///< normal but significant condition.
#define LOGLEVEL_INFO 6 ///< informational.
#define LOGLEVEL_DEBUG 7 ///< debug-level messages.
+55 -76
View File
@@ -3,14 +3,13 @@
/// @copyright (c) 2014-2022 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "sys/bitops.h"
#include "io/debug.h"
#include "klib/spinlock.h"
#include "io/port_io.h"
#include "io/ansi_colors.h"
#include "sys/bitops.h"
#include "kernel.h"
#include "string.h"
#include "stdio.h"
#include "io/video.h"
#include "math.h"
/// Serial port for QEMU.
@@ -29,41 +28,38 @@ void dbg_puts(const char *s)
dbg_putchar(*s++);
}
static inline void __debug_print_header(const char *file, const char *fun, int line, int log_level, char *header)
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];
if (log_level == LOGLEVEL_EMERG)
dbg_puts(FG_RED_BRIGHT);
else if (log_level == LOGLEVEL_ALERT)
dbg_puts(FG_RED_BRIGHT);
else if (log_level == LOGLEVEL_CRIT)
dbg_puts(FG_RED);
else if (log_level == LOGLEVEL_ERR)
dbg_puts(FG_RED);
else if (log_level == LOGLEVEL_WARNING)
dbg_puts(FG_YELLOW_BRIGHT);
else if (log_level == LOGLEVEL_DEBUG)
dbg_puts(FG_CYAN);
else if (log_level == LOGLEVEL_NOTICE)
dbg_puts(FG_RESET);
else if (log_level == LOGLEVEL_INFO)
dbg_puts(FG_RESET);
else
dbg_puts(FG_RESET);
// 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('[');
dbg_puts(
(log_level == LOGLEVEL_EMERG) ? " EM " /*"EMERG "*/ :
(log_level == LOGLEVEL_ALERT) ? " AL " /*"ALERT "*/ :
(log_level == LOGLEVEL_CRIT) ? " CR " /*"CRIT "*/ :
(log_level == LOGLEVEL_ERR) ? " ER " /*"ERR "*/ :
(log_level == LOGLEVEL_WARNING) ? " WR " /*"WARNING"*/ :
(log_level == LOGLEVEL_NOTICE) ? " NT " /*"NOTICE "*/ :
(log_level == LOGLEVEL_INFO) ? " IN " /*"INFO "*/ :
(log_level == LOGLEVEL_DEBUG) ? " DB " /*"DEBUG "*/ :
" DF " /*"DEFAULT*/);
// 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('|');
@@ -90,7 +86,7 @@ int get_log_level()
return max_log_level;
}
void dbg_printf(const char *file, const char *fun, int line, char *header, const char *format, ...)
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];
@@ -100,23 +96,6 @@ void dbg_printf(const char *file, const char *fun, int line, char *header, const
if (strlen(format) >= BUFSIZ)
return;
// Check the log level.
int log_level = LOGLEVEL_DEFAULT;
if ((format[0] != '\0') && (format[0] == KERN_SOH_ASCII)) {
// Remove the Start Of Header.
++format;
// Compute the log level.
log_level = (format[0] - '0');
// Check the log_level.
if ((log_level < LOGLEVEL_EMERG) || (log_level > LOGLEVEL_DEBUG))
log_level = 8;
// Remove the log_level;
++format;
}
if (log_level > max_log_level) {
return;
}
// Start variabile argument's list.
va_list ap;
va_start(ap, format);
@@ -128,7 +107,7 @@ void dbg_printf(const char *file, const char *fun, int line, char *header, const
// Stage 2: SEND
if (new_line) {
__debug_print_header(file, fun, line, log_level, header);
new_line = false;
new_line = 0;
}
for (int it = 0; (formatted[it] != 0) && (it < BUFSIZ); ++it) {
dbg_putchar(formatted[it]);
@@ -139,37 +118,13 @@ void dbg_printf(const char *file, const char *fun, int line, char *header, const
continue;
}
if (formatted[it + 1] == 0) {
new_line = true;
new_line = 1;
} else {
__debug_print_header(file, fun, line, log_level, header);
}
}
}
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);
}
const char *to_human_size(unsigned long bytes)
{
static char output[200];
@@ -193,3 +148,27 @@ const char *dec_to_binary(unsigned long value, unsigned length)
buffer[i] = bit_check(value, 31 - j) ? '1' : '0';
return buffer;
}
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);
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include <termios.h>
#include <stdbool.h>
#include <string.h>
#include <debug.h>
#include <io/debug.h>
#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
+1 -1
View File
@@ -9,7 +9,7 @@
#include <limits.h>
#include <strerror.h>
#include <ctype.h>
#include <debug.h>
#include <io/debug.h>
static inline int is_number(char *s)
{
+1 -1
View File
@@ -14,7 +14,7 @@
#include <pwd.h>
#include <strerror.h>
#include <stdlib.h>
#include <debug.h>
#include <io/debug.h>
#include "ansi_colors.h"
+1 -1
View File
@@ -14,7 +14,7 @@
#include <sys/stat.h>
#include <libgen.h>
#include <sys/bitops.h>
#include <debug.h>
#include <io/debug.h>
#define FLAG_L (1U << 0U)
#define FLAG_A (1U << 1U)
+1 -1
View File
@@ -9,7 +9,7 @@
#include <libgen.h>
#include <sys/stat.h>
#include <signal.h>
#include <debug.h>
#include <io/debug.h>
#include <sys/bitops.h>
#include "stdbool.h"
#include "stddef.h"