PatchworkOS
Loading...
Searching...
No Matches
log.c
Go to the documentation of this file.
1#include <kernel/log/log.h>
2
3#include <kernel/cpu/cpu.h>
4#include <kernel/cpu/smp.h>
9#include <kernel/sync/lock.h>
10
11#include <boot/boot_info.h>
12#include <kernel/version.h>
13
14#include <stdarg.h>
15#include <stdint.h>
16#include <stdio.h>
17#include <sys/io.h>
18#include <sys/proc.h>
19
21
22static char lineBuffer[LOG_MAX_BUFFER] = {0};
23static char workingBuffer[LOG_MAX_BUFFER] = {0};
26static bool isLastCharNewline = 0;
27static bool firstHeaderPrinted = false;
28
29static const char* levelNames[] = {
30 [LOG_LEVEL_DEBUG] = "D",
31 [LOG_LEVEL_USER] = "U",
32 [LOG_LEVEL_INFO] = "I",
33 [LOG_LEVEL_WARN] = "W",
34 [LOG_LEVEL_ERR] = "E",
35 [LOG_LEVEL_PANIC] = "P",
36};
37
38static void log_splash(void)
39{
40#ifdef NDEBUG
41 LOG_INFO("Booting %s-kernel %s (Built %s %s)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
42#else
43 LOG_INFO("Booting %s-kernel DEBUG %s (Built %s %s)\n", OS_NAME, OS_VERSION, __DATE__, __TIME__);
44#endif
45 LOG_INFO("Copyright (C) 2025 Kai Norberg. MIT Licensed. See /usr/license/LICENSE for details.\n");
46 LOG_INFO("min_level=%s outputs=%s%s%s\n", levelNames[minLevel], (outputs & LOG_OUTPUT_SERIAL) ? "serial " : "",
47 (outputs & LOG_OUTPUT_SCREEN) ? "screen " : "", (outputs & LOG_OUTPUT_FILE) ? "file " : "");
48}
49
51{
53
54 outputs = 0;
55#ifndef NDEBUG
57#else
59#endif
60 isLastCharNewline = true;
61
64#if CONFIG_LOG_SERIAL
67#endif
68
69 log_splash();
70}
71
73{
75
77 {
78 return;
79 }
80
83}
84
86{
88
89 outputs &= ~LOG_OUTPUT_SCREEN;
90}
91
92void log_write(const char* string, uint64_t length)
93{
95 {
96 log_file_write(string, length);
97 }
98
100 {
101 for (uint64_t i = 0; i < length; i++)
102 {
103 com_write(COM1, string[i]);
104 }
105 }
106
108 {
109 log_screen_write(string, length);
110 }
111}
112
113static void log_print_header(log_level_t level, const char* prefix)
114{
116 {
117 firstHeaderPrinted = true;
118 }
119 else
120 {
121 log_write("\n", 1);
122 }
123
124 if (level == LOG_LEVEL_PANIC)
125 {
126 int length = sprintf(workingBuffer, "[XXXX.XXX-XX-X-XXXXXXXXXX] ");
127 log_write(workingBuffer, length);
128 return;
129 }
130
132 uint64_t seconds = uptime / CLOCKS_PER_SEC;
133 uint64_t milliseconds = (uptime % CLOCKS_PER_SEC) / (CLOCKS_PER_SEC / 1000);
134
135 cpu_t* self = smp_self_unsafe();
136
137 int length = sprintf(workingBuffer, "[%4llu.%03llu-%02x-%s-%-10s] ", seconds, milliseconds, self->id,
138 levelNames[level], prefix != NULL ? prefix : "unknown");
139 log_write(workingBuffer, length);
140}
141
142static void log_handle_char(log_level_t level, const char* prefix, char chr)
143{
144 if (isLastCharNewline && chr != '\n')
145 {
146 isLastCharNewline = false;
147
148 log_print_header(level, prefix);
149 }
150
151 if (chr == '\n')
152 {
154 {
155 log_print_header(level, prefix);
156 }
157 isLastCharNewline = true;
158 return;
159 }
160
161 log_write(&chr, 1);
162}
163
164uint64_t log_print(log_level_t level, const char* prefix, const char* format, ...)
165{
166 va_list args;
167 va_start(args, format);
168 uint64_t result = log_vprint(level, prefix, format, args);
169 va_end(args);
170 return result;
171}
172
173uint64_t log_vprint(log_level_t level, const char* prefix, const char* format, va_list args)
174{
176
177 if (level < minLevel)
178 {
179 return 0;
180 }
181
182 int length = vsnprintf(lineBuffer, LOG_MAX_BUFFER, format, args);
183 if (length < 0)
184 {
185 errno = EINVAL;
186 return ERR;
187 }
188
189 if (length >= LOG_MAX_BUFFER)
190 {
191 length = LOG_MAX_BUFFER - 1;
192 lineBuffer[length] = '\0';
193 }
194
195 for (int i = 0; i < length; i++)
196 {
197 log_handle_char(level, prefix, lineBuffer[i]);
198 }
199
200 return 0;
201}
#define CLOCKS_PER_SEC
Definition clock_t.h:15
@ COM1
Definition com.h:7
void com_write(com_port_t port, uint8_t value)
Definition com.c:23
void com_init(com_port_t port)
Definition com.c:4
static cpu_t * smp_self_unsafe(void)
Returns a pointer to the cpu_t structure of the current CPU.
Definition smp.h:90
void log_file_flush_to_screen(void)
Flush the content of the log file to the screen.
Definition log_file.c:85
void log_file_write(const char *string, uint64_t length)
Write a string to the kernel log file.
Definition log_file.c:125
void log_screen_write(const char *string, uint64_t length)
Write a string to the screen.
Definition log_screen.c:204
void log_screen_init(const boot_gop_t *bootGop)
Initialize the screen logging.
Definition log_screen.c:83
uint64_t log_vprint(log_level_t level, const char *prefix, const char *format, va_list args)
Print a formatted log message with a va_list.
Definition log.c:173
#define LOG_INFO(format,...)
Definition log.h:87
#define LOG_MAX_BUFFER
Maximum buffer size for a single log line.
Definition log.h:23
log_level_t
Log levels.
Definition log.h:39
void log_screen_disable(void)
Disable logging to the screen.
Definition log.c:85
uint64_t log_print(log_level_t level, const char *prefix, const char *format,...)
Print a formatted log message.
Definition log.c:164
void log_write(const char *string, uint64_t length)
Write directly to the log outputs without any formatting or headers.
Definition log.c:92
void log_screen_enable()
Enable logging to the screen.
Definition log.c:72
void log_init(const boot_gop_t *gop)
Initialize the logging system.
Definition log.c:50
log_output_t
Logging output options.
Definition log.h:29
@ LOG_LEVEL_ERR
Definition log.h:44
@ LOG_LEVEL_DEBUG
Definition log.h:40
@ LOG_LEVEL_USER
Definition log.h:41
@ LOG_LEVEL_WARN
Definition log.h:43
@ LOG_LEVEL_PANIC
Definition log.h:45
@ LOG_LEVEL_INFO
Definition log.h:42
@ LOG_OUTPUT_SCREEN
Definition log.h:31
@ LOG_OUTPUT_SERIAL
Definition log.h:30
@ LOG_OUTPUT_FILE
Definition log.h:32
#define LOCK_CREATE
Create a lock initializer. @macro LOCK_CREATE.
Definition lock.h:66
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
clock_t timer_uptime(void)
Time since boot.
Definition timer.c:73
#define EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
clock_t uptime(void)
System call for retreving the time since boot.
Definition uptime.c:6
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
__UINT64_TYPE__ clock_t
A nanosecond time.
Definition clock_t.h:13
static void log_splash(void)
Definition log.c:38
static log_level_t minLevel
Definition log.c:25
static void log_print_header(log_level_t level, const char *prefix)
Definition log.c:113
static log_output_t outputs
Definition log.c:24
static const char * levelNames[]
Definition log.c:29
static lock_t lock
Definition log.c:20
static bool isLastCharNewline
Definition log.c:26
static void log_handle_char(log_level_t level, const char *prefix, char chr)
Definition log.c:142
static char lineBuffer[LOG_MAX_BUFFER]
Definition log.c:22
static char workingBuffer[LOG_MAX_BUFFER]
Definition log.c:23
static bool firstHeaderPrinted
Definition log.c:27
boot_gop_t * gop
Definition mem.c:18
#define va_start(ap, parmN)
Definition stdarg.h:14
#define va_end(ap)
Definition stdarg.h:13
__builtin_va_list va_list
Definition stdarg.h:9
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
_PUBLIC int vsnprintf(char *_RESTRICT s, size_t n, const char *_RESTRICT format, va_list arg)
Definition vsnprintf.c:5
_PUBLIC int sprintf(char *_RESTRICT s, const char *_RESTRICT format,...)
Definition sprintf.c:5
CPU structure.
Definition cpu.h:42
cpuid_t id
Definition cpu.h:43
A simple ticket lock implementation.
Definition lock.h:43