PatchworkOS
Loading...
Searching...
No Matches
log_file.c
Go to the documentation of this file.
2
3#include <kernel/fs/file.h>
4#include <kernel/fs/sysfs.h>
5#include <kernel/log/log.h>
7#include <kernel/log/panic.h>
8#include <kernel/utils/ring.h>
9
10#include <stdlib.h>
11
13
15static char buffer[LOG_FILE_MAX_BUFFER] = {0};
16static ring_t ring = RING_CREATE(buffer, sizeof(buffer));
17static dentry_t* file = NULL;
18
20{
21 (void)file; // Unused
22
24 uint64_t result = ring_read_at(&ring, *offset, buffer, count);
25 *offset += result;
26 return result;
27}
28
30{
31 (void)file; // Unused
32
33 if (count == 0 || buffer == NULL || offset == NULL)
34 {
35 return 0;
36 }
37
38 if (count > MAX_PATH)
39 {
40 errno = EINVAL;
41 return ERR;
42 }
43
44 char string[MAX_PATH];
45 memcpy(string, buffer, count);
46 string[count] = '\0';
47
48 LOG_USER("%s", string);
49 *offset += count;
50 return count;
51}
52
55 .write = log_file_op_write,
56};
57
59{
61 if (file == NULL)
62 {
63 panic(NULL, "failed to create klog sysfs file");
64 }
65}
66
67static void log_file_advance_fake_cursor(char chr, uint64_t* lineLength, uint64_t* lineCount)
68{
69 if (chr == '\n')
70 {
71 (*lineCount)++;
72 *lineLength = 0;
73 }
74 else if (*lineLength >= log_screen_get_width())
75 {
76 (*lineCount)++;
77 *lineLength = SCREEN_WRAP_INDENT;
78 }
79 else
80 {
81 (*lineLength)++;
82 }
83}
84
86{
89
90 uint64_t lineLength = 0;
91 uint64_t lineCount = 0;
92 for (uint64_t i = 0; i < ring_data_length(&ring); i++)
93 {
94 uint8_t chr;
95 ring_get_byte(&ring, i, &chr);
96
97 log_file_advance_fake_cursor(chr, &lineLength, &lineCount);
98 }
99
100 uint64_t totalLines = lineCount;
101 uint64_t linesThatFit = log_screen_get_height();
102
103 lineLength = 0;
104 lineCount = 0;
105
106 uint64_t i = 0;
107 for (; i < ring_data_length(&ring) && lineCount < totalLines - linesThatFit; i++)
108 {
109 uint8_t chr;
110 ring_get_byte(&ring, i, &chr);
111
112 log_file_advance_fake_cursor(chr, &lineLength, &lineCount);
113 }
114
115 for (; i < ring_data_length(&ring);)
116 {
117 uint64_t toRead = MIN(ring_data_length(&ring) - i, sizeof(workingBuffer));
118 ring_read_at(&ring, i, workingBuffer, toRead);
119 i += toRead;
120
122 }
123}
124
125void log_file_write(const char* string, uint64_t length)
126{
127 if (string == NULL || length == 0)
128 {
129 return;
130 }
131
133 ring_write(&ring, string, length);
134}
#define MAX_PATH
Maximum length of filepaths.
Definition MAX_PATH.h:11
#define LOG_FILE_MAX_BUFFER
Maximum buffer size for the log file.
Definition log_file.h:16
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_expose(void)
Expose the kernel log file to userspace in sysfs.
Definition log_file.c:58
void log_file_write(const char *string, uint64_t length)
Write a string to the kernel log file.
Definition log_file.c:125
NORETURN void panic(const interrupt_frame_t *frame, const char *format,...)
Panic the kernel, printing a message and halting.
Definition panic.c:362
#define SCREEN_WRAP_INDENT
Number of spaces to indent when a line wraps.
Definition log_screen.h:22
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
#define LOG_USER(format,...)
Definition log.h:86
#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
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 EINVAL
Invalid argument.
Definition errno.h:142
#define errno
Error number variable.
Definition errno.h:27
#define MIN(x, y)
Definition math.h:16
#define NULL
Pointer error value.
Definition NULL.h:23
#define ERR
Integer error value.
Definition ERR.h:17
static uint64_t log_file_op_read(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition log_file.c:19
static void log_file_advance_fake_cursor(char chr, uint64_t *lineLength, uint64_t *lineCount)
Definition log_file.c:67
static lock_t lock
Definition log_file.c:12
static ring_t ring
Definition log_file.c:16
static dentry_t * file
Definition log_file.c:17
static char buffer[LOG_FILE_MAX_BUFFER]
Definition log_file.c:15
static char workingBuffer[LOG_FILE_MAX_BUFFER]
Definition log_file.c:14
static file_ops_t logFileOps
Definition log_file.c:53
static uint64_t log_file_op_write(file_t *file, const void *buffer, uint64_t count, uint64_t *offset)
Definition log_file.c:29
static atomic_long count
Definition main.c:9
__UINT64_TYPE__ uint64_t
Definition stdint.h:17
__UINT8_TYPE__ uint8_t
Definition stdint.h:11
_PUBLIC void * memcpy(void *_RESTRICT s1, const void *_RESTRICT s2, size_t n)
Definition memcpy.c:4
Directory entry structure.
Definition dentry.h:83
File operations structure.
Definition file.h:57
uint64_t(* read)(file_t *file, void *buffer, uint64_t count, uint64_t *offset)
Definition file.h:61
File structure.
Definition file.h:37
A simple ticket lock implementation.
Definition lock.h:43
Ring buffer structure.
Definition ring.h:19
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