PatchworkOS  966e257
A non-POSIX operating system.
Loading...
Searching...
No Matches
log_file.c
Go to the documentation of this file.
1#include "gnu-efi/inc/x86_64/efibind.h"
3
4#include <kernel/fs/file.h>
5#include <kernel/fs/sysfs.h>
6#include <kernel/log/log.h>
8#include <kernel/log/panic.h>
9#include <kernel/sched/wait.h>
10#include <kernel/utils/ring.h>
11
12#include <stdlib.h>
13#include <sys/io.h>
14
16
18
20static char buffer[LOG_FILE_MAX_BUFFER] = {0};
21static ring_t ring = RING_CREATE(buffer, sizeof(buffer));
22static dentry_t* file = NULL;
23
25{
26 (void)file; // Unused
27
29 uint64_t result = ring_read_at(&ring, *offset, buffer, count);
30 *offset += result;
31 return result;
32}
33
35{
36 (void)file; // Unused
37 (void)offset; // Unused
38
40 return count;
41}
42
44{
45 (void)file;
46
48 if (ring.writeIndex != file->pos)
49 {
50 *revents |= POLLIN;
51 }
52
53 return &waitQueue;
54}
55
58 .write = log_file_op_write,
59 .poll = log_file_op_poll,
60};
61
63{
65 if (file == NULL)
66 {
67 panic(NULL, "failed to create klog sysfs file");
68 }
69}
70
71static void log_file_advance_fake_cursor(char chr, uint64_t* lineLength, uint64_t* lineCount)
72{
73 if (chr == '\n')
74 {
75 (*lineCount)++;
76 *lineLength = 0;
77 }
78 else if (*lineLength >= log_screen_get_width())
79 {
80 (*lineCount)++;
81 *lineLength = SCREEN_WRAP_INDENT;
82 }
83 else
84 {
85 (*lineLength)++;
86 }
87}
88
90{
93
94 uint64_t lineLength = 0;
95 uint64_t lineCount = 0;
96 for (uint64_t i = 0; i < ring_data_length(&ring); i++)
97 {
98 uint8_t chr;
99 ring_get_byte(&ring, i, &chr);
100
101 log_file_advance_fake_cursor(chr, &lineLength, &lineCount);
102 }
103
104 uint64_t totalLines = lineCount;
105 uint64_t linesThatFit = log_screen_get_height();
106
107 lineLength = 0;
108 lineCount = 0;
109
110 uint64_t i = 0;
111 for (; i < ring_data_length(&ring) && lineCount < totalLines - linesThatFit; i++)
112 {
113 uint8_t chr;
114 ring_get_byte(&ring, i, &chr);
115
116 log_file_advance_fake_cursor(chr, &lineLength, &lineCount);
117 }
118
119 for (; i < ring_data_length(&ring);)
120 {
121 uint64_t toRead = MIN(ring_data_length(&ring) - i, sizeof(workingBuffer));
122 ring_read_at(&ring, i, workingBuffer, toRead);
123 i += toRead;
124
126 }
127}
128
129void log_file_write(const char* string, uint64_t length)
130{
131 if (string == NULL || length == 0)
132 {
133 return;
134 }
135
137 ring_write(&ring, string, length);
138
140}
#define LOG_FILE_MAX_BUFFER
Maximum buffer size for the log file.
Definition log_file.h:18
void log_file_flush_to_screen(void)
Flush the content of the log file to the screen.
Definition log_file.c:89
void log_file_expose(void)
Expose the kernel log file to userspace in sysfs.
Definition log_file.c:62
void log_file_write(const char *string, uint64_t length)
Write a string to the kernel log file.
Definition log_file.c:129
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:266
#define SCREEN_WRAP_INDENT
Number of spaces to indent when a line wraps.
Definition log_screen.h:24
void log_screen_write(const char *string, uint64_t length)
Write a string to the screen.
Definition log_screen.c:204
uint64_t log_screen_get_width(void)
Get screen width in characters.
Definition log_screen.c:194
void log_screen_clear(void)
Clear the screen.
Definition log_screen.c:172
uint64_t log_screen_get_height(void)
Get screen height in characters.
Definition log_screen.c:199
void log_nprint(log_level_t level, const char *string, uint64_t length)
Print a unformatted log message.
Definition log.c:168
@ LOG_LEVEL_USER
Definition log.h:43
uint64_t wait_unblock(wait_queue_t *queue, uint64_t amount, errno_t err)
Unblock threads waiting on a wait queue.
Definition wait.c:296
#define WAIT_ALL
Used to indicate that the wait should unblock all waiting threads.
Definition wait.h:40
#define WAIT_QUEUE_CREATE(name)
Create a wait queue initializer.
Definition wait.h:219
#define LOCK_CREATE()
Create a lock initializer.
Definition lock.h:68
#define LOCK_SCOPE(lock)
Acquires a lock for the reminder of the current scope.
Definition lock.h:57
static uint64_t ring_write(ring_t *ring, const void *buffer, uint64_t count)
Write data to the ring buffer.
Definition ring.h:85
#define RING_CREATE(bufferPtr, bufferSize)
Create a ring buffer initializer.
Definition ring.h:33
static uint64_t ring_get_byte(const ring_t *ring, uint64_t offset, uint8_t *byte)
Get a byte from the ring buffer at a specific offset without modifying the read index.
Definition ring.h:210
static uint64_t ring_data_length(const ring_t *ring)
Get the length of data currently stored in the ring buffer.
Definition ring.h:58
static uint64_t ring_read_at(const ring_t *ring, uint64_t offset, void *buffer, uint64_t count)
Read data from the ring buffer at a specific offset without modifying the read index.
Definition ring.h:156
#define EOK
No error.
Definition errno.h:32
poll_events_t
Poll events type.
Definition io.h:257
@ POLLIN
File descriptor is ready to read.
Definition io.h:259
#define MIN(x, y)
Definition math.h:16
#define NULL
Pointer error value.
Definition NULL.h:23
static wait_queue_t * log_file_op_poll(file_t *file, poll_events_t *revents)
Definition log_file.c:43
static uint64_t log_file_op_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition log_file.c:24
static void log_file_advance_fake_cursor(char chr, uint64_t *lineLength, uint64_t *lineCount)
Definition log_file.c:71
static lock_t lock
Definition log_file.c:15
static ring_t ring
Definition log_file.c:21
static dentry_t * file
Definition log_file.c:22
static char buffer[LOG_FILE_MAX_BUFFER]
Definition log_file.c:20
static char workingBuffer[LOG_FILE_MAX_BUFFER]
Definition log_file.c:19
static file_ops_t logFileOps
Definition log_file.c:56
static wait_queue_t waitQueue
Definition log_file.c:17
static uint64_t log_file_op_write(file_t *file, const void *buffer, uint64_t count, uint64_t *offset)
Definition log_file.c:34
static atomic_long count
Definition main.c:10
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
Directory entry structure.
Definition dentry.h:84
File operations structure.
Definition file.h:54
uint64_t(* read)(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition file.h:58
File structure.
Definition file.h:39
A simple ticket lock implementation.
Definition lock.h:43
Ring buffer structure.
Definition ring.h:19
uint64_t writeIndex
Definition ring.h:23
The primitive that threads block on.
Definition wait.h:182
dentry_t * sysfs_file_new(dentry_t *parent, const char *name, const inode_ops_t *inodeOps, const file_ops_t *fileOps, void *private)
Create a new file inside a mounted SysFS instance.
Definition sysfs.c:216