Implement serial logging. Finish modularizing power management.
[monolithium.git] / kernel / include / log.h
1 /*
2  * log.h
3  *
4  * Copyright (C) 2018 Aleksandar Andrejevic <theflash@sdf.lonestar.org>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as
8  * published by the Free Software Foundation, either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #ifndef _LOG_H_
21 #define _LOG_H_
22
23 #include <common.h>
24 #include <stdarg.h>
25 #include <stdio.h>
26
27 #define MAX_LOG_MESSAGE_SIZE 256
28
29 #ifdef DEBUG
30 #define TRACE(x) log_write(LOG_DEBUG, x)
31 #define FTRACE(x, args...) log_write(LOG_DEBUG, x, args)
32 #else
33 #define TRACE(x)
34 #define FTRACE(x, ...)
35 #endif
36
37 typedef enum
38 {
39     LOG_DEBUG,
40     LOG_NORMAL,
41     LOG_WARNING,
42     LOG_ERROR,
43     LOG_CRITICAL,
44 } log_level_t;
45
46 extern char *debug_channel;
47 extern log_level_t debug_min_level;
48
49 void append_log_entry(const char *source, log_level_t level, const char *message);
50
51 static inline void log_write(log_level_t level, const char *format, ...)
52 {
53     extern const char driver_name[];
54     static char log_buffer[MAX_LOG_MESSAGE_SIZE] = "";
55
56     va_list ap;
57     va_start(ap, format);
58     char message[MAX_LOG_MESSAGE_SIZE];
59     vsnprintf(message, MAX_LOG_MESSAGE_SIZE, format, ap);
60     va_end(ap);
61
62     char *ptr = message;
63     while (*ptr)
64     {
65         char *end = strchr(ptr, '\n');
66         if (end) *end = '\0';
67         else break;
68
69         char full_message[2 * MAX_LOG_MESSAGE_SIZE];
70         strcpy(full_message, log_buffer);
71         strcat(full_message, ptr);
72         append_log_entry(driver_name, level, full_message);
73         *log_buffer = '\0';
74
75         ptr = end + 1;
76     }
77
78     strcat(log_buffer, ptr);
79 }
80
81 #endif