logger fixes
This commit is contained in:
+3
-4
@@ -76,12 +76,11 @@ void kernel_early_init() {
|
|||||||
|
|
||||||
[[noreturn]]
|
[[noreturn]]
|
||||||
void kernel_main(struct boot_info* info) {
|
void kernel_main(struct boot_info* info) {
|
||||||
// TODO: Initialize in-memory log ring.
|
|
||||||
kprintf("%s\n", zinnia_banner); // Say hello!
|
|
||||||
kprintf("Command line: %s\n", info->cmdline);
|
|
||||||
|
|
||||||
cmdline_parse(info->cmdline);
|
cmdline_parse(info->cmdline);
|
||||||
|
|
||||||
|
log("%s\n", zinnia_banner); // Say hello!
|
||||||
|
log("Command line: %s\n", info->cmdline);
|
||||||
|
|
||||||
initgraph_run(sched_stage, info);
|
initgraph_run(sched_stage, info);
|
||||||
|
|
||||||
struct task* main_task;
|
struct task* main_task;
|
||||||
|
|||||||
+8
-5
@@ -13,10 +13,17 @@ void console_write(const char* buf, size_t len) {
|
|||||||
spin_unlock(&console_lock);
|
spin_unlock(&console_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void console_replay_write(void* ctx, const char* buf, size_t len) {
|
||||||
|
struct console* con = ctx;
|
||||||
|
con->write(con, buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
bool console_register(struct console* con) {
|
bool console_register(struct console* con) {
|
||||||
if (!con->init(con))
|
if (!con->init(con))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
con->write(con, "\ec", 2);
|
||||||
|
log_replay(console_replay_write, con);
|
||||||
spin_lock(&console_lock);
|
spin_lock(&console_lock);
|
||||||
con->next = registered;
|
con->next = registered;
|
||||||
registered = con;
|
registered = con;
|
||||||
@@ -37,8 +44,4 @@ void console_unregister(struct console* con) {
|
|||||||
spin_unlock(&console_lock);
|
spin_unlock(&console_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
[[__init]]
|
INIT_TASK(console_stage, "core.console");
|
||||||
static void console_stage_init(struct boot_info*) {
|
|
||||||
kprintf("\ec");
|
|
||||||
}
|
|
||||||
INIT_TASK(console_stage, "core.console", console_stage_init);
|
|
||||||
|
|||||||
+26
-5
@@ -26,6 +26,7 @@ enum esc_state {
|
|||||||
|
|
||||||
static struct {
|
static struct {
|
||||||
struct boot_framebuffer fb;
|
struct boot_framebuffer fb;
|
||||||
|
uint32_t* back;
|
||||||
uint32_t fg, bg;
|
uint32_t fg, bg;
|
||||||
size_t cols, rows;
|
size_t cols, rows;
|
||||||
size_t offset_x, offset_y;
|
size_t offset_x, offset_y;
|
||||||
@@ -37,6 +38,15 @@ static inline uint8_t* fb_ptr() {
|
|||||||
return HHDM_PTR(fbcon.fb.base);
|
return HHDM_PTR(fbcon.fb.base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t* back_row(size_t y) {
|
||||||
|
return fbcon.back + y * fbcon.fb.width;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flush_rect(size_t x, size_t y, size_t w, size_t h) {
|
||||||
|
for (size_t j = 0; j < h; j++)
|
||||||
|
memcpy((uint32_t*)(fb_ptr() + (y + j) * fbcon.fb.pitch) + x, back_row(y + j) + x, w * sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t pack_color(uint32_t rgb) {
|
static uint32_t pack_color(uint32_t rgb) {
|
||||||
const struct boot_framebuffer* fb = &fbcon.fb;
|
const struct boot_framebuffer* fb = &fbcon.fb;
|
||||||
uint32_t r = (rgb >> 16) & 0xff;
|
uint32_t r = (rgb >> 16) & 0xff;
|
||||||
@@ -48,10 +58,11 @@ static uint32_t pack_color(uint32_t rgb) {
|
|||||||
|
|
||||||
static void fill_rect(size_t x, size_t y, size_t w, size_t h, uint32_t color) {
|
static void fill_rect(size_t x, size_t y, size_t w, size_t h, uint32_t color) {
|
||||||
for (size_t j = 0; j < h; j++) {
|
for (size_t j = 0; j < h; j++) {
|
||||||
uint32_t* row = (uint32_t*)(fb_ptr() + (y + j) * fbcon.fb.pitch) + x;
|
uint32_t* row = back_row(y + j) + x;
|
||||||
for (size_t i = 0; i < w; i++)
|
for (size_t i = 0; i < w; i++)
|
||||||
row[i] = color;
|
row[i] = color;
|
||||||
}
|
}
|
||||||
|
flush_rect(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_screen() {
|
static void clear_screen() {
|
||||||
@@ -65,19 +76,25 @@ static void draw_glyph(size_t col, size_t row, uint8_t ch) {
|
|||||||
size_t y = fbcon.offset_y + row * FONT_HEIGHT;
|
size_t y = fbcon.offset_y + row * FONT_HEIGHT;
|
||||||
|
|
||||||
for (size_t j = 0; j < FONT_HEIGHT; j++) {
|
for (size_t j = 0; j < FONT_HEIGHT; j++) {
|
||||||
uint32_t* line = (uint32_t*)(fb_ptr() + (y + j) * fbcon.fb.pitch) + x;
|
uint32_t* line = back_row(y + j) + x;
|
||||||
for (size_t i = 0; i < FONT_WIDTH; i++)
|
for (size_t i = 0; i < FONT_WIDTH; i++)
|
||||||
line[i] = (glyph[j] & (0x80 >> i)) ? fbcon.fg : fbcon.bg;
|
line[i] = (glyph[j] & (0x80 >> i)) ? fbcon.fg : fbcon.bg;
|
||||||
}
|
}
|
||||||
|
flush_rect(x, y, FONT_WIDTH, FONT_HEIGHT);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scroll_up() {
|
static void scroll_up() {
|
||||||
const size_t pitch = fbcon.fb.pitch;
|
const size_t width = fbcon.fb.width;
|
||||||
const size_t text_y = fbcon.offset_y;
|
const size_t text_y = fbcon.offset_y;
|
||||||
const size_t text_h = fbcon.rows * FONT_HEIGHT;
|
const size_t text_h = fbcon.rows * FONT_HEIGHT;
|
||||||
|
|
||||||
memmove(fb_ptr() + text_y * pitch, fb_ptr() + (text_y + FONT_HEIGHT) * pitch, (text_h - FONT_HEIGHT) * pitch);
|
memmove(back_row(text_y), back_row(text_y + FONT_HEIGHT), (text_h - FONT_HEIGHT) * width * sizeof(uint32_t));
|
||||||
fill_rect(0, text_y + text_h - FONT_HEIGHT, fbcon.fb.width, FONT_HEIGHT, fbcon.bg);
|
for (size_t j = text_y + text_h - FONT_HEIGHT; j < text_y + text_h; j++) {
|
||||||
|
uint32_t* row = back_row(j);
|
||||||
|
for (size_t i = 0; i < width; i++)
|
||||||
|
row[i] = fbcon.bg;
|
||||||
|
}
|
||||||
|
flush_rect(0, text_y, width, text_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void newline() {
|
static void newline() {
|
||||||
@@ -178,6 +195,10 @@ void fbcon_init(struct boot_info* info) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fbcon.back = mem_alloc(fb->width * fb->height * sizeof(uint32_t), ALLOC_NOZERO);
|
||||||
|
if (!fbcon.back)
|
||||||
|
return;
|
||||||
|
|
||||||
console_register(&fbcon_con);
|
console_register(&fbcon_con);
|
||||||
}
|
}
|
||||||
INIT_TASK(fbcon_stage, "core.fbcon", fbcon_init);
|
INIT_TASK(fbcon_stage, "core.fbcon", fbcon_init);
|
||||||
|
|||||||
+29
-11
@@ -430,13 +430,39 @@ static const char* const log_level_colors[] = {
|
|||||||
[LOG_PANIC] = "\e[1;31m",
|
[LOG_PANIC] = "\e[1;31m",
|
||||||
};
|
};
|
||||||
|
|
||||||
static void log_console_printf(const char* fmt, ...) {
|
static void log_cb_printf(log_fn_t callback, void* ctx, const char* fmt, ...) {
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
print_fmt(printf_console, nullptr, fmt, args);
|
print_fmt(callback, ctx, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Formats a single record and passes it to `callback`.
|
||||||
|
static void log_emit(log_fn_t callback, void* ctx, const struct log_record* rec, const char* msg) {
|
||||||
|
log_cb_printf(
|
||||||
|
callback,
|
||||||
|
ctx,
|
||||||
|
"[%5lu.%06lu] [%5lu] %s",
|
||||||
|
rec->time_ns / 1'000'000'000,
|
||||||
|
rec->time_ns / 1'000 % 1'000'000,
|
||||||
|
(uint64_t)rec->tid,
|
||||||
|
log_level_colors[rec->level]
|
||||||
|
);
|
||||||
|
callback(ctx, msg, rec->len);
|
||||||
|
callback(ctx, "\e[0m\n", 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void log_replay(log_fn_t callback, void* ctx) {
|
||||||
|
char msg[LOG_MESSAGE_MAX];
|
||||||
|
for (size_t offset = log_tail; offset != log_head;) {
|
||||||
|
struct log_record rec;
|
||||||
|
log_ring_peek(offset, &rec, sizeof(rec));
|
||||||
|
log_ring_peek(offset + sizeof(rec), msg, rec.len);
|
||||||
|
log_emit(callback, ctx, &rec, msg);
|
||||||
|
offset += sizeof(rec) + rec.len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void log_vwrite(enum log_level level, const char* message, va_list args) {
|
void log_vwrite(enum log_level level, const char* message, va_list args) {
|
||||||
log_vwrite_prefixed(level, "", message, args);
|
log_vwrite_prefixed(level, "", message, args);
|
||||||
}
|
}
|
||||||
@@ -458,15 +484,7 @@ void log_vwrite_prefixed(enum log_level level, const char* prefix, const char* m
|
|||||||
|
|
||||||
spin_lock(&print_lock);
|
spin_lock(&print_lock);
|
||||||
log_store(&rec, line.buf);
|
log_store(&rec, line.buf);
|
||||||
log_console_printf(
|
log_emit(printf_console, nullptr, &rec, line.buf);
|
||||||
"[%5lu.%06lu] [%5lu] %s",
|
|
||||||
rec.time_ns / 1'000'000'000,
|
|
||||||
rec.time_ns / 1'000 % 1'000'000,
|
|
||||||
(uint64_t)rec.tid,
|
|
||||||
log_level_colors[level]
|
|
||||||
);
|
|
||||||
console_write(line.buf, line.len);
|
|
||||||
console_write("\e[0m\n", 5);
|
|
||||||
spin_unlock(&print_lock);
|
spin_unlock(&print_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,9 @@ void log_vwrite(enum log_level level, const char* message, va_list args);
|
|||||||
// Like log_vwrite(), but prepends a `prefix` to the message.
|
// Like log_vwrite(), but prepends a `prefix` to the message.
|
||||||
void log_vwrite_prefixed(enum log_level level, const char* prefix, const char* message, va_list args);
|
void log_vwrite_prefixed(enum log_level level, const char* prefix, const char* message, va_list args);
|
||||||
|
|
||||||
|
// Passes every record currently in the log buffer to `callback`.
|
||||||
|
void log_replay(log_fn_t callback, void* ctx);
|
||||||
|
|
||||||
#ifndef pr_fmt
|
#ifndef pr_fmt
|
||||||
#define pr_fmt(fmt) fmt
|
#define pr_fmt(fmt) fmt
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user