This commit is contained in:
2026-04-11 22:27:54 +08:00
parent b65829c94f
commit 5e75e09e5d
12 changed files with 591 additions and 58 deletions

View File

@@ -19,7 +19,7 @@ static struct clks_fb_state clks_fb = {
.address = CLKS_NULL,
.info = {0, 0, 0, 0},
.font = CLKS_NULL,
.external_font = {0, 0, 0, 0, CLKS_NULL},
.external_font = {0, 0, 0, 0, 0, CLKS_NULL},
.external_font_active = CLKS_FALSE,
.glyph_width = 8U,
.glyph_height = 8U,
@@ -149,6 +149,7 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
u32 col;
u32 cols;
u32 rows;
u32 row_stride;
if (clks_fb.ready == CLKS_FALSE || clks_fb.font == CLKS_NULL) {
return;
@@ -167,15 +168,26 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
rows = 8U;
}
if (cols > 8U) {
cols = 8U;
row_stride = clks_fb.font->bytes_per_row;
if (row_stride == 0U) {
row_stride = (cols + 7U) / 8U;
}
if (row_stride == 0U) {
return;
}
if (((usize)row_stride * (usize)rows) > (usize)clks_fb.font->bytes_per_glyph) {
return;
}
for (row = 0U; row < rows; row++) {
u8 bits = glyph[row];
const u8 *row_bits = glyph + ((usize)row * (usize)row_stride);
for (col = 0U; col < cols; col++) {
u8 mask = (u8)(1U << (7U - col));
u8 bits = row_bits[col >> 3U];
u8 mask = (u8)(0x80U >> (col & 7U));
u32 color = (bits & mask) != 0U ? fg_rgb : bg_rgb;
clks_fb_put_pixel(x + col, y + row, color);
}
@@ -183,7 +195,7 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
}
clks_bool clks_fb_load_psf_font(const void *blob, u64 blob_size) {
struct clks_psf_font parsed = {0, 0, 0, 0, CLKS_NULL};
struct clks_psf_font parsed = {0, 0, 0, 0, 0, CLKS_NULL};
if (clks_psf_parse_font(blob, blob_size, &parsed) == CLKS_FALSE) {
return CLKS_FALSE;
@@ -201,4 +213,4 @@ u32 clks_fb_cell_width(void) {
u32 clks_fb_cell_height(void) {
return clks_fb.glyph_height == 0U ? 8U : clks_fb.glyph_height;
}
}

View File

@@ -10,12 +10,26 @@
#define CLKS_PSF1_GLYPH_BYTES 8U
#define CLKS_PSF1_BLOB_SIZE (CLKS_PSF1_HEADER_SIZE + (CLKS_PSF1_GLYPH_COUNT * CLKS_PSF1_GLYPH_BYTES))
#define CLKS_PSF2_MAGIC 0x864AB572U
#define CLKS_PSF2_HEADER_MIN_SIZE 32U
struct clks_psf1_header {
u8 magic[2];
u8 mode;
u8 charsize;
};
struct clks_psf2_header {
u32 magic;
u32 version;
u32 headersize;
u32 flags;
u32 length;
u32 charsize;
u32 height;
u32 width;
};
struct clks_psf_seed_glyph {
u8 code;
u8 rows[CLKS_PSF1_GLYPH_BYTES];
@@ -74,7 +88,7 @@ static const struct clks_psf_seed_glyph clks_psf_seed_table[] = {
};
static u8 clks_psf_default_blob[CLKS_PSF1_BLOB_SIZE];
static struct clks_psf_font clks_psf_default = {8U, 8U, 0U, 0U, CLKS_NULL};
static struct clks_psf_font clks_psf_default = {8U, 8U, 0U, 0U, 1U, CLKS_NULL};
static clks_bool clks_psf_default_ready = CLKS_FALSE;
static clks_bool clks_psf_parse_psf1(const u8 *blob, usize blob_size, struct clks_psf_font *out_font) {
@@ -114,10 +128,70 @@ static clks_bool clks_psf_parse_psf1(const u8 *blob, usize blob_size, struct clk
out_font->height = glyph_bytes;
out_font->glyph_count = glyph_count;
out_font->bytes_per_glyph = glyph_bytes;
out_font->bytes_per_row = 1U;
out_font->glyphs = blob + CLKS_PSF1_HEADER_SIZE;
return CLKS_TRUE;
}
static clks_bool clks_psf_parse_psf2(const u8 *blob, usize blob_size, struct clks_psf_font *out_font) {
const struct clks_psf2_header *hdr;
u32 bytes_per_row;
usize min_bytes_per_glyph;
usize payload_size;
if (blob == CLKS_NULL || out_font == CLKS_NULL) {
return CLKS_FALSE;
}
if (blob_size < CLKS_PSF2_HEADER_MIN_SIZE) {
return CLKS_FALSE;
}
hdr = (const struct clks_psf2_header *)blob;
if (hdr->magic != CLKS_PSF2_MAGIC) {
return CLKS_FALSE;
}
if (hdr->headersize < CLKS_PSF2_HEADER_MIN_SIZE || hdr->headersize > blob_size) {
return CLKS_FALSE;
}
if (hdr->width == 0U || hdr->height == 0U || hdr->length == 0U || hdr->charsize == 0U) {
return CLKS_FALSE;
}
bytes_per_row = (hdr->width + 7U) / 8U;
if (bytes_per_row == 0U) {
return CLKS_FALSE;
}
min_bytes_per_glyph = (usize)bytes_per_row * (usize)hdr->height;
if (min_bytes_per_glyph > hdr->charsize) {
return CLKS_FALSE;
}
if ((usize)hdr->length > (((usize)-1) / (usize)hdr->charsize)) {
return CLKS_FALSE;
}
payload_size = (usize)hdr->length * (usize)hdr->charsize;
if (payload_size > (blob_size - (usize)hdr->headersize)) {
return CLKS_FALSE;
}
out_font->width = hdr->width;
out_font->height = hdr->height;
out_font->glyph_count = hdr->length;
out_font->bytes_per_glyph = hdr->charsize;
out_font->bytes_per_row = bytes_per_row;
out_font->glyphs = blob + hdr->headersize;
return CLKS_TRUE;
}
static void clks_psf_seed_default_blob(void) {
struct clks_psf1_header *hdr;
u32 i;
@@ -157,6 +231,7 @@ const struct clks_psf_font *clks_psf_default_font(void) {
clks_psf_default.height = 8U;
clks_psf_default.glyph_count = 1U;
clks_psf_default.bytes_per_glyph = CLKS_PSF1_GLYPH_BYTES;
clks_psf_default.bytes_per_row = 1U;
clks_psf_default.glyphs = clks_psf_unknown;
}
@@ -185,9 +260,26 @@ const u8 *clks_psf_glyph(const struct clks_psf_font *font, u32 codepoint) {
}
clks_bool clks_psf_parse_font(const void *blob, u64 blob_size, struct clks_psf_font *out_font) {
if (blob_size == 0ULL) {
const u8 *bytes;
u32 magic32;
if (blob == CLKS_NULL || out_font == CLKS_NULL || blob_size == 0ULL) {
return CLKS_FALSE;
}
return clks_psf_parse_psf1((const u8 *)blob, (usize)blob_size, out_font);
bytes = (const u8 *)blob;
if (blob_size >= 4ULL) {
magic32 =
((u32)bytes[0]) |
(((u32)bytes[1]) << 8U) |
(((u32)bytes[2]) << 16U) |
(((u32)bytes[3]) << 24U);
if (magic32 == CLKS_PSF2_MAGIC) {
return clks_psf_parse_psf2(bytes, (usize)blob_size, out_font);
}
}
return clks_psf_parse_psf1(bytes, (usize)blob_size, out_font);
}

View File

@@ -8,6 +8,7 @@ struct clks_psf_font {
u32 height;
u32 glyph_count;
u32 bytes_per_glyph;
u32 bytes_per_row;
const u8 *glyphs;
};
@@ -15,4 +16,4 @@ const struct clks_psf_font *clks_psf_default_font(void);
const u8 *clks_psf_glyph(const struct clks_psf_font *font, u32 codepoint);
clks_bool clks_psf_parse_font(const void *blob, u64 blob_size, struct clks_psf_font *out_font);
#endif
#endif

10
clks/include/clks/panic.h Normal file
View File

@@ -0,0 +1,10 @@
#ifndef CLKS_PANIC_H
#define CLKS_PANIC_H
#include <clks/compiler.h>
#include <clks/types.h>
CLKS_NORETURN void clks_panic(const char *reason);
CLKS_NORETURN void clks_panic_exception(const char *name, u64 vector, u64 error_code, u64 rip);
#endif

View File

@@ -3,6 +3,7 @@
#include <clks/interrupts.h>
#include <clks/log.h>
#include <clks/keyboard.h>
#include <clks/panic.h>
#include <clks/scheduler.h>
#include <clks/syscall.h>
#include <clks/types.h>
@@ -247,11 +248,7 @@ void clks_interrupt_dispatch(struct clks_interrupt_frame *frame) {
}
if (vector < 32U) {
clks_log(CLKS_LOG_ERROR, "EXC", clks_exception_names[vector]);
clks_log_hex(CLKS_LOG_ERROR, "EXC", "VECTOR", vector);
clks_log_hex(CLKS_LOG_ERROR, "EXC", "ERROR", frame->error_code);
clks_log_hex(CLKS_LOG_ERROR, "EXC", "RIP", frame->rip);
clks_cpu_halt_forever();
clks_panic_exception(clks_exception_names[vector], vector, frame->error_code, frame->rip);
}
if (vector == CLKS_IRQ_TIMER) {

View File

@@ -96,7 +96,7 @@ void clks_kernel_main(void) {
clks_tty_init();
}
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS Stage23 START");
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS Stage24 START");
if (boot_fb == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");

239
clks/kernel/panic.c Normal file
View File

@@ -0,0 +1,239 @@
#include <clks/cpu.h>
#include <clks/framebuffer.h>
#include <clks/panic.h>
#include <clks/serial.h>
#include <clks/string.h>
#include <clks/types.h>
#define CLKS_PANIC_BG 0x00200000U
#define CLKS_PANIC_FG 0x00FFE0E0U
struct clks_panic_console {
u32 cols;
u32 rows;
u32 row;
u32 col;
u32 cell_w;
u32 cell_h;
};
static clks_bool clks_panic_active = CLKS_FALSE;
static inline void clks_panic_disable_interrupts(void) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("cli");
#elif defined(CLKS_ARCH_AARCH64)
__asm__ volatile("msr daifset, #0xf");
#endif
}
static void clks_panic_u64_to_hex(u64 value, char out[19]) {
int nibble;
out[0] = '0';
out[1] = 'X';
for (nibble = 0; nibble < 16; nibble++) {
u8 current = (u8)((value >> ((15 - nibble) * 4)) & 0x0FULL);
out[2 + nibble] = (current < 10U) ? (char)('0' + current) : (char)('A' + (current - 10U));
}
out[18] = '\0';
}
static clks_bool clks_panic_console_init(struct clks_panic_console *console) {
struct clks_framebuffer_info info;
if (console == CLKS_NULL || clks_fb_ready() == CLKS_FALSE) {
return CLKS_FALSE;
}
info = clks_fb_info();
console->cell_w = clks_fb_cell_width();
console->cell_h = clks_fb_cell_height();
if (console->cell_w == 0U) {
console->cell_w = 8U;
}
if (console->cell_h == 0U) {
console->cell_h = 8U;
}
console->cols = info.width / console->cell_w;
console->rows = info.height / console->cell_h;
console->row = 0U;
console->col = 0U;
if (console->cols == 0U || console->rows == 0U) {
return CLKS_FALSE;
}
return CLKS_TRUE;
}
static void clks_panic_console_newline(struct clks_panic_console *console) {
if (console == CLKS_NULL) {
return;
}
console->col = 0U;
if (console->row + 1U < console->rows) {
console->row++;
}
}
static void clks_panic_console_put_char(struct clks_panic_console *console, char ch) {
u32 x;
u32 y;
if (console == CLKS_NULL) {
return;
}
if (ch == '\n') {
clks_panic_console_newline(console);
return;
}
if (ch == '\r') {
console->col = 0U;
return;
}
if (console->row >= console->rows || console->col >= console->cols) {
return;
}
x = console->col * console->cell_w;
y = console->row * console->cell_h;
clks_fb_draw_char(x, y, ch, CLKS_PANIC_FG, CLKS_PANIC_BG);
console->col++;
if (console->col >= console->cols) {
clks_panic_console_newline(console);
}
}
static void clks_panic_console_write(struct clks_panic_console *console, const char *text) {
usize i = 0U;
if (console == CLKS_NULL || text == CLKS_NULL) {
return;
}
while (text[i] != '\0') {
clks_panic_console_put_char(console, text[i]);
i++;
}
}
static void clks_panic_serial_write_line(const char *line) {
if (line == CLKS_NULL) {
return;
}
clks_serial_write(line);
clks_serial_write("\n");
}
static CLKS_NORETURN void clks_panic_halt_loop(void) {
clks_cpu_halt_forever();
}
CLKS_NORETURN void clks_panic(const char *reason) {
struct clks_panic_console console;
clks_panic_disable_interrupts();
if (clks_panic_active == CLKS_TRUE) {
clks_panic_halt_loop();
}
clks_panic_active = CLKS_TRUE;
clks_panic_serial_write_line("[PANIC] CLeonOS KERNEL PANIC");
if (reason != CLKS_NULL) {
clks_panic_serial_write_line(reason);
}
if (clks_panic_console_init(&console) == CLKS_TRUE) {
clks_fb_clear(CLKS_PANIC_BG);
clks_panic_console_write(&console, "CLeonOS KERNEL PANIC\n");
clks_panic_console_write(&console, "====================\n\n");
if (reason != CLKS_NULL) {
clks_panic_console_write(&console, "REASON: ");
clks_panic_console_write(&console, reason);
clks_panic_console_write(&console, "\n");
}
clks_panic_console_write(&console, "\nSystem halted. Please reboot the VM.\n");
}
clks_panic_halt_loop();
}
CLKS_NORETURN void clks_panic_exception(const char *name, u64 vector, u64 error_code, u64 rip) {
struct clks_panic_console console;
char hex_buf[19];
clks_panic_disable_interrupts();
if (clks_panic_active == CLKS_TRUE) {
clks_panic_halt_loop();
}
clks_panic_active = CLKS_TRUE;
clks_panic_serial_write_line("[PANIC] CPU EXCEPTION");
if (name != CLKS_NULL) {
clks_panic_serial_write_line(name);
}
clks_panic_u64_to_hex(vector, hex_buf);
clks_panic_serial_write_line(hex_buf);
clks_panic_u64_to_hex(error_code, hex_buf);
clks_panic_serial_write_line(hex_buf);
clks_panic_u64_to_hex(rip, hex_buf);
clks_panic_serial_write_line(hex_buf);
if (clks_panic_console_init(&console) == CLKS_TRUE) {
clks_fb_clear(CLKS_PANIC_BG);
clks_panic_console_write(&console, "CLeonOS KERNEL PANIC\n");
clks_panic_console_write(&console, "====================\n\n");
clks_panic_console_write(&console, "TYPE: CPU EXCEPTION\n");
if (name != CLKS_NULL) {
clks_panic_console_write(&console, "NAME: ");
clks_panic_console_write(&console, name);
clks_panic_console_write(&console, "\n");
}
clks_panic_u64_to_hex(vector, hex_buf);
clks_panic_console_write(&console, "VECTOR: ");
clks_panic_console_write(&console, hex_buf);
clks_panic_console_write(&console, "\n");
clks_panic_u64_to_hex(error_code, hex_buf);
clks_panic_console_write(&console, "ERROR: ");
clks_panic_console_write(&console, hex_buf);
clks_panic_console_write(&console, "\n");
clks_panic_u64_to_hex(rip, hex_buf);
clks_panic_console_write(&console, "RIP: ");
clks_panic_console_write(&console, hex_buf);
clks_panic_console_write(&console, "\n\n");
clks_panic_console_write(&console, "System halted. Please reboot the VM.\n");
}
clks_panic_halt_loop();
}

View File

@@ -3,6 +3,7 @@
#include <clks/heap.h>
#include <clks/keyboard.h>
#include <clks/log.h>
#include <clks/panic.h>
#include <clks/pmm.h>
#include <clks/scheduler.h>
#include <clks/shell.h>
@@ -696,6 +697,7 @@ static clks_bool clks_shell_cmd_help(void) {
clks_shell_writeln(" dmesg [n]");
clks_shell_writeln(" shstat");
clks_shell_writeln(" rusttest");
clks_shell_writeln(" panic");
clks_shell_writeln(" exec <path|name>");
clks_shell_writeln(" clear");
clks_shell_writeln(" kbdstat");
@@ -1209,6 +1211,11 @@ static clks_bool clks_shell_cmd_rusttest(void) {
return CLKS_TRUE;
}
static clks_bool clks_shell_cmd_panic(void) {
clks_panic("MANUAL PANIC FROM KERNEL SHELL");
return CLKS_FALSE;
}
static void clks_shell_execute_line(const char *line) {
char line_buf[CLKS_SHELL_LINE_MAX];
char cmd[CLKS_SHELL_CMD_MAX];
@@ -1271,6 +1278,8 @@ static void clks_shell_execute_line(const char *line) {
success = clks_shell_cmd_shstat();
} else if (clks_shell_streq(cmd, "rusttest") == CLKS_TRUE) {
success = clks_shell_cmd_rusttest();
} else if (clks_shell_streq(cmd, "panic") == CLKS_TRUE) {
success = clks_shell_cmd_panic();
} else if (clks_shell_streq(cmd, "exec") == CLKS_TRUE || clks_shell_streq(cmd, "run") == CLKS_TRUE) {
success = clks_shell_cmd_exec(arg);
} else if (clks_shell_streq(cmd, "clear") == CLKS_TRUE) {