初始化

This commit is contained in:
2026-04-09 21:47:13 +08:00
commit cb952965e6
37 changed files with 1304 additions and 0 deletions

7
clks/arch/aarch64/boot.c Normal file
View File

@@ -0,0 +1,7 @@
#include <clks/cpu.h>
#include <clks/kernel.h>
void _start(void) {
clks_kernel_main();
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,38 @@
OUTPUT_FORMAT(elf64-littleaarch64)
ENTRY(_start)
PHDRS {
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
}
SECTIONS {
. = 0x100000;
.text : {
*(.text .text.*)
} :text
.rodata : {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
*(.rodata .rodata.*)
} :rodata
.data : {
*(.data .data.*)
} :data
.bss : {
*(COMMON)
*(.bss .bss.*)
} :data
/DISCARD/ : {
*(.comment)
*(.eh_frame)
*(.note .note.*)
}
}

7
clks/arch/x86_64/boot.c Normal file
View File

@@ -0,0 +1,7 @@
#include <clks/cpu.h>
#include <clks/kernel.h>
void _start(void) {
clks_kernel_main();
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,42 @@
OUTPUT_FORMAT(elf64-x86-64)
ENTRY(_start)
PHDRS {
text PT_LOAD FLAGS(5);
rodata PT_LOAD FLAGS(4);
data PT_LOAD FLAGS(6);
}
SECTIONS {
. = 0xffffffff80000000;
. = ALIGN(0x1000);
.text : ALIGN(0x1000) {
*(.text .text.*)
} :text
. = ALIGN(0x1000);
.rodata : ALIGN(0x1000) {
KEEP(*(.limine_requests_start))
KEEP(*(.limine_requests))
KEEP(*(.limine_requests_end))
*(.rodata .rodata.*)
} :rodata
. = ALIGN(0x1000);
.data : ALIGN(0x1000) {
*(.data .data.*)
} :data
. = ALIGN(0x1000);
.bss : ALIGN(0x1000) {
*(COMMON)
*(.bss .bss.*)
} :data
/DISCARD/ : {
*(.comment)
*(.eh_frame)
*(.note .note.*)
}
}

View File

@@ -0,0 +1,68 @@
#include <clks/compiler.h>
#include <clks/serial.h>
#include <clks/types.h>
#if defined(CLKS_ARCH_X86_64)
#define CLKS_COM1_PORT 0x3F8
static inline void clks_x86_outb(u16 port, u8 value) {
__asm__ volatile("outb %0, %1" : : "a"(value), "Nd"(port));
}
static inline u8 clks_x86_inb(u16 port) {
u8 value;
__asm__ volatile("inb %1, %0" : "=a"(value) : "Nd"(port));
return value;
}
void clks_serial_init(void) {
clks_x86_outb(CLKS_COM1_PORT + 1, 0x00);
clks_x86_outb(CLKS_COM1_PORT + 3, 0x80);
clks_x86_outb(CLKS_COM1_PORT + 0, 0x03);
clks_x86_outb(CLKS_COM1_PORT + 1, 0x00);
clks_x86_outb(CLKS_COM1_PORT + 3, 0x03);
clks_x86_outb(CLKS_COM1_PORT + 2, 0xC7);
clks_x86_outb(CLKS_COM1_PORT + 4, 0x0B);
}
void clks_serial_write_char(char ch) {
while ((clks_x86_inb(CLKS_COM1_PORT + 5) & 0x20) == 0) {
}
clks_x86_outb(CLKS_COM1_PORT, (u8)ch);
}
#elif defined(CLKS_ARCH_AARCH64)
#define CLKS_PL011_BASE 0x09000000ULL
#define CLKS_PL011_DR (*(volatile u32 *)(CLKS_PL011_BASE + 0x00))
#define CLKS_PL011_FR (*(volatile u32 *)(CLKS_PL011_BASE + 0x18))
#define CLKS_PL011_TXFF (1U << 5)
void clks_serial_init(void) {
}
void clks_serial_write_char(char ch) {
while ((CLKS_PL011_FR & CLKS_PL011_TXFF) != 0) {
}
CLKS_PL011_DR = (u32)(u8)ch;
}
#else
#error "Unsupported architecture"
#endif
void clks_serial_write(const char *text) {
usize i = 0;
while (text[i] != '\0') {
if (text[i] == '\n') {
clks_serial_write_char('\r');
}
clks_serial_write_char(text[i]);
i++;
}
}

View File

@@ -0,0 +1,75 @@
#include "font8x8.h"
#include <clks/types.h>
struct clks_glyph8x8 {
char ch;
u8 rows[8];
};
static const struct clks_glyph8x8 clks_font_table[] = {
{' ', {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
{'[', {0x1E, 0x10, 0x10, 0x10, 0x10, 0x10, 0x1E, 0x00}},
{']', {0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}},
{':', {0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00}},
{'.', {0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00}},
{'-', {0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00}},
{'/', {0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00}},
{'_', {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00}},
{'?', {0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00}},
{'0', {0x3C, 0x42, 0x46, 0x4A, 0x52, 0x62, 0x3C, 0x00}},
{'1', {0x18, 0x28, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00}},
{'2', {0x3C, 0x42, 0x02, 0x0C, 0x30, 0x40, 0x7E, 0x00}},
{'3', {0x3C, 0x42, 0x02, 0x1C, 0x02, 0x42, 0x3C, 0x00}},
{'4', {0x0C, 0x14, 0x24, 0x44, 0x7E, 0x04, 0x04, 0x00}},
{'5', {0x7E, 0x40, 0x7C, 0x02, 0x02, 0x42, 0x3C, 0x00}},
{'6', {0x1C, 0x20, 0x40, 0x7C, 0x42, 0x42, 0x3C, 0x00}},
{'7', {0x7E, 0x02, 0x04, 0x08, 0x10, 0x20, 0x20, 0x00}},
{'8', {0x3C, 0x42, 0x42, 0x3C, 0x42, 0x42, 0x3C, 0x00}},
{'9', {0x3C, 0x42, 0x42, 0x3E, 0x02, 0x04, 0x38, 0x00}},
{'A', {0x18, 0x24, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00}},
{'B', {0x7C, 0x42, 0x42, 0x7C, 0x42, 0x42, 0x7C, 0x00}},
{'C', {0x3C, 0x42, 0x40, 0x40, 0x40, 0x42, 0x3C, 0x00}},
{'D', {0x78, 0x44, 0x42, 0x42, 0x42, 0x44, 0x78, 0x00}},
{'E', {0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x7E, 0x00}},
{'F', {0x7E, 0x40, 0x40, 0x7C, 0x40, 0x40, 0x40, 0x00}},
{'G', {0x3C, 0x42, 0x40, 0x4E, 0x42, 0x42, 0x3C, 0x00}},
{'H', {0x42, 0x42, 0x42, 0x7E, 0x42, 0x42, 0x42, 0x00}},
{'I', {0x3E, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3E, 0x00}},
{'J', {0x1E, 0x04, 0x04, 0x04, 0x44, 0x44, 0x38, 0x00}},
{'K', {0x42, 0x44, 0x48, 0x70, 0x48, 0x44, 0x42, 0x00}},
{'L', {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x7E, 0x00}},
{'M', {0x42, 0x66, 0x5A, 0x5A, 0x42, 0x42, 0x42, 0x00}},
{'N', {0x42, 0x62, 0x52, 0x4A, 0x46, 0x42, 0x42, 0x00}},
{'O', {0x3C, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}},
{'P', {0x7C, 0x42, 0x42, 0x7C, 0x40, 0x40, 0x40, 0x00}},
{'Q', {0x3C, 0x42, 0x42, 0x42, 0x4A, 0x44, 0x3A, 0x00}},
{'R', {0x7C, 0x42, 0x42, 0x7C, 0x48, 0x44, 0x42, 0x00}},
{'S', {0x3C, 0x42, 0x40, 0x3C, 0x02, 0x42, 0x3C, 0x00}},
{'T', {0x7F, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00}},
{'U', {0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3C, 0x00}},
{'V', {0x42, 0x42, 0x42, 0x42, 0x42, 0x24, 0x18, 0x00}},
{'W', {0x42, 0x42, 0x42, 0x5A, 0x5A, 0x66, 0x42, 0x00}},
{'X', {0x42, 0x42, 0x24, 0x18, 0x24, 0x42, 0x42, 0x00}},
{'Y', {0x42, 0x42, 0x24, 0x18, 0x08, 0x08, 0x08, 0x00}},
{'Z', {0x7E, 0x02, 0x04, 0x18, 0x20, 0x40, 0x7E, 0x00}},
};
static const u8 clks_unknown[8] = {0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00};
const u8 *clks_font8x8_get(char ch) {
usize i;
char upper = ch;
if (upper >= 'a' && upper <= 'z') {
upper = (char)(upper - ('a' - 'A'));
}
for (i = 0; i < (sizeof(clks_font_table) / sizeof(clks_font_table[0])); i++) {
if (clks_font_table[i].ch == upper) {
return clks_font_table[i].rows;
}
}
return clks_unknown;
}

View File

@@ -0,0 +1,8 @@
#ifndef CLKS_FONT8X8_H
#define CLKS_FONT8X8_H
#include <clks/types.h>
const u8 *clks_font8x8_get(char ch);
#endif

View File

@@ -0,0 +1,95 @@
#include <clks/framebuffer.h>
#include <clks/string.h>
#include <clks/types.h>
#include "font8x8.h"
struct clks_fb_state {
volatile u8 *address;
struct clks_framebuffer_info info;
clks_bool ready;
};
static struct clks_fb_state clks_fb = {
.address = CLKS_NULL,
.info = {0, 0, 0, 0},
.ready = CLKS_FALSE,
};
static void clks_fb_put_pixel(u32 x, u32 y, u32 rgb) {
volatile u8 *row;
volatile u32 *pixel;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
if (x >= clks_fb.info.width || y >= clks_fb.info.height) {
return;
}
if (clks_fb.info.bpp != 32) {
return;
}
row = clks_fb.address + ((usize)y * (usize)clks_fb.info.pitch);
pixel = (volatile u32 *)(row + ((usize)x * 4));
*pixel = rgb;
}
void clks_fb_init(const struct limine_framebuffer *fb) {
if (fb == CLKS_NULL) {
clks_fb.ready = CLKS_FALSE;
return;
}
clks_fb.address = (volatile u8 *)fb->address;
clks_fb.info.width = (u32)fb->width;
clks_fb.info.height = (u32)fb->height;
clks_fb.info.pitch = (u32)fb->pitch;
clks_fb.info.bpp = fb->bpp;
clks_fb.ready = CLKS_TRUE;
}
clks_bool clks_fb_ready(void) {
return clks_fb.ready;
}
struct clks_framebuffer_info clks_fb_info(void) {
return clks_fb.info;
}
void clks_fb_clear(u32 rgb) {
u32 x;
u32 y;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
for (y = 0; y < clks_fb.info.height; y++) {
for (x = 0; x < clks_fb.info.width; x++) {
clks_fb_put_pixel(x, y, rgb);
}
}
}
void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
const u8 *glyph;
u32 row;
u32 col;
if (clks_fb.ready == CLKS_FALSE) {
return;
}
glyph = clks_font8x8_get(ch);
for (row = 0; row < 8; row++) {
for (col = 0; col < 8; col++) {
u8 mask = (u8)(1U << (7U - col));
u32 color = (glyph[row] & mask) != 0 ? fg_rgb : bg_rgb;
clks_fb_put_pixel(x + col, y + row, color);
}
}
}

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

@@ -0,0 +1,10 @@
#ifndef CLKS_BOOT_H
#define CLKS_BOOT_H
#include <clks/limine.h>
#include <clks/types.h>
clks_bool clks_boot_base_revision_supported(void);
const struct limine_framebuffer *clks_boot_get_framebuffer(void);
#endif

View File

@@ -0,0 +1,17 @@
#ifndef CLKS_COMPILER_H
#define CLKS_COMPILER_H
#define CLKS_USED __attribute__((used))
#define CLKS_NORETURN __attribute__((noreturn))
#define CLKS_PACKED __attribute__((packed))
#define CLKS_ALIGN(N) __attribute__((aligned(N)))
#if defined(CLKS_ARCH_X86_64) && defined(CLKS_ARCH_AARCH64)
#error "Only one architecture can be selected"
#endif
#if !defined(CLKS_ARCH_X86_64) && !defined(CLKS_ARCH_AARCH64)
#error "Missing architecture define: CLKS_ARCH_X86_64 or CLKS_ARCH_AARCH64"
#endif
#endif

24
clks/include/clks/cpu.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef CLKS_CPU_H
#define CLKS_CPU_H
#include <clks/compiler.h>
static inline void clks_cpu_pause(void) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("pause");
#elif defined(CLKS_ARCH_AARCH64)
__asm__ volatile("yield");
#endif
}
static inline CLKS_NORETURN void clks_cpu_halt_forever(void) {
for (;;) {
#if defined(CLKS_ARCH_X86_64)
__asm__ volatile("hlt");
#elif defined(CLKS_ARCH_AARCH64)
__asm__ volatile("wfe");
#endif
}
}
#endif

View File

@@ -0,0 +1,20 @@
#ifndef CLKS_FRAMEBUFFER_H
#define CLKS_FRAMEBUFFER_H
#include <clks/limine.h>
#include <clks/types.h>
struct clks_framebuffer_info {
u32 width;
u32 height;
u32 pitch;
u16 bpp;
};
void clks_fb_init(const struct limine_framebuffer *fb);
clks_bool clks_fb_ready(void);
struct clks_framebuffer_info clks_fb_info(void);
void clks_fb_clear(u32 rgb);
void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb);
#endif

View File

@@ -0,0 +1,6 @@
#ifndef CLKS_KERNEL_H
#define CLKS_KERNEL_H
void clks_kernel_main(void);
#endif

View File

@@ -0,0 +1,56 @@
#ifndef CLKS_LIMINE_H
#define CLKS_LIMINE_H
#include <clks/types.h>
#define LIMINE_COMMON_MAGIC 0xc7b1dd30df4c8b88ULL
#define LIMINE_REQUEST_MAGIC 0x0a82e883a194f07bULL
#define LIMINE_REQUESTS_START_MARKER \
{ 0xf6b8f4b39de7d1aeULL, 0xfab91a6940fcb9cfULL }
#define LIMINE_REQUESTS_END_MARKER \
{ 0xadc0e0531bb10d03ULL, 0x9572709f31764c62ULL }
#define LIMINE_BASE_REVISION(N) \
{ 0xf9562b2d5c95a6c8ULL, 0x6a7b384944536bdcULL, (N) }
#define LIMINE_FRAMEBUFFER_REQUEST \
{ \
LIMINE_COMMON_MAGIC, \
LIMINE_REQUEST_MAGIC, \
0x9d5827dcd881dd75ULL, \
0xa3148604f6fab11bULL \
}
struct limine_framebuffer {
void *address;
u64 width;
u64 height;
u64 pitch;
u16 bpp;
u8 memory_model;
u8 red_mask_size;
u8 red_mask_shift;
u8 green_mask_size;
u8 green_mask_shift;
u8 blue_mask_size;
u8 blue_mask_shift;
u8 unused[7];
u64 edid_size;
void *edid;
};
struct limine_framebuffer_response {
u64 revision;
u64 framebuffer_count;
struct limine_framebuffer **framebuffers;
};
struct limine_framebuffer_request {
u64 id[4];
u64 revision;
struct limine_framebuffer_response *response;
};
#endif

16
clks/include/clks/log.h Normal file
View File

@@ -0,0 +1,16 @@
#ifndef CLKS_LOG_H
#define CLKS_LOG_H
#include <clks/types.h>
enum clks_log_level {
CLKS_LOG_DEBUG = 0,
CLKS_LOG_INFO = 1,
CLKS_LOG_WARN = 2,
CLKS_LOG_ERROR = 3,
};
void clks_log(enum clks_log_level level, const char *tag, const char *message);
void clks_log_hex(enum clks_log_level level, const char *tag, const char *label, u64 value);
#endif

View File

@@ -0,0 +1,8 @@
#ifndef CLKS_SERIAL_H
#define CLKS_SERIAL_H
void clks_serial_init(void);
void clks_serial_write_char(char ch);
void clks_serial_write(const char *text);
#endif

View File

@@ -0,0 +1,12 @@
#ifndef CLKS_STRING_H
#define CLKS_STRING_H
#include <clks/types.h>
usize clks_strlen(const char *str);
void *clks_memset(void *dst, int value, usize count);
void *clks_memcpy(void *dst, const void *src, usize count);
void *clks_memmove(void *dst, const void *src, usize count);
int clks_strcmp(const char *left, const char *right);
#endif

12
clks/include/clks/tty.h Normal file
View File

@@ -0,0 +1,12 @@
#ifndef CLKS_TTY_H
#define CLKS_TTY_H
#include <clks/types.h>
void clks_tty_init(void);
void clks_tty_write(const char *text);
void clks_tty_write_char(char ch);
void clks_tty_switch(u32 tty_index);
u32 clks_tty_active(void);
#endif

23
clks/include/clks/types.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef CLKS_TYPES_H
#define CLKS_TYPES_H
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef signed char i8;
typedef signed short i16;
typedef signed int i32;
typedef signed long long i64;
typedef u64 usize;
typedef enum clks_bool {
CLKS_FALSE = 0,
CLKS_TRUE = 1
} clks_bool;
#define CLKS_NULL ((void *)0)
#endif

48
clks/kernel/kmain.c Normal file
View File

@@ -0,0 +1,48 @@
#include <clks/boot.h>
#include <clks/cpu.h>
#include <clks/framebuffer.h>
#include <clks/kernel.h>
#include <clks/log.h>
#include <clks/serial.h>
#include <clks/tty.h>
#include <clks/types.h>
void clks_kernel_main(void) {
const struct limine_framebuffer *boot_fb;
clks_serial_init();
if (clks_boot_base_revision_supported() == CLKS_FALSE) {
clks_serial_write("[ERROR][BOOT] LIMINE BASE REVISION NOT SUPPORTED\n");
clks_cpu_halt_forever();
}
boot_fb = clks_boot_get_framebuffer();
if (boot_fb != CLKS_NULL) {
clks_fb_init(boot_fb);
clks_tty_init();
}
clks_log(CLKS_LOG_INFO, "BOOT", "CLEONOS STAGE1 START");
if (boot_fb == CLKS_NULL) {
clks_log(CLKS_LOG_WARN, "VIDEO", "NO FRAMEBUFFER FROM LIMINE");
} else {
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "WIDTH", boot_fb->width);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "HEIGHT", boot_fb->height);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "PITCH", boot_fb->pitch);
clks_log_hex(CLKS_LOG_INFO, "VIDEO", "BPP", boot_fb->bpp);
}
#if defined(CLKS_ARCH_X86_64)
clks_log(CLKS_LOG_INFO, "ARCH", "X86_64 ONLINE");
#elif defined(CLKS_ARCH_AARCH64)
clks_log(CLKS_LOG_INFO, "ARCH", "AARCH64 ONLINE");
#endif
clks_log(CLKS_LOG_INFO, "TTY", "VIRTUAL TTY0 READY");
clks_log(CLKS_LOG_DEBUG, "KERNEL", "IDLE LOOP ENTER");
clks_cpu_halt_forever();
}

View File

@@ -0,0 +1,36 @@
#include <clks/boot.h>
#include <clks/compiler.h>
CLKS_USED static volatile u64 limine_requests_start[]
__attribute__((section(".limine_requests_start"))) = LIMINE_REQUESTS_START_MARKER;
CLKS_USED static volatile u64 limine_base_revision[]
__attribute__((section(".limine_requests"))) = LIMINE_BASE_REVISION(3);
CLKS_USED static volatile struct limine_framebuffer_request limine_framebuffer_request
__attribute__((section(".limine_requests"))) = {
.id = LIMINE_FRAMEBUFFER_REQUEST,
.revision = 0,
.response = CLKS_NULL,
};
CLKS_USED static volatile u64 limine_requests_end[]
__attribute__((section(".limine_requests_end"))) = LIMINE_REQUESTS_END_MARKER;
clks_bool clks_boot_base_revision_supported(void) {
return (limine_base_revision[2] == 0) ? CLKS_TRUE : CLKS_FALSE;
}
const struct limine_framebuffer *clks_boot_get_framebuffer(void) {
volatile struct limine_framebuffer_request *request = &limine_framebuffer_request;
if (request->response == CLKS_NULL) {
return CLKS_NULL;
}
if (request->response->framebuffer_count < 1) {
return CLKS_NULL;
}
return request->response->framebuffers[0];
}

96
clks/kernel/log.c Normal file
View File

@@ -0,0 +1,96 @@
#include <clks/log.h>
#include <clks/serial.h>
#include <clks/tty.h>
#include <clks/types.h>
#define CLKS_LOG_LINE_MAX 256
static const char *clks_log_level_name(enum clks_log_level level) {
switch (level) {
case CLKS_LOG_DEBUG:
return "DEBUG";
case CLKS_LOG_INFO:
return "INFO";
case CLKS_LOG_WARN:
return "WARN";
case CLKS_LOG_ERROR:
return "ERROR";
default:
return "UNK";
}
}
static void clks_log_append_char(char *buffer, usize *cursor, char ch) {
if (*cursor >= (CLKS_LOG_LINE_MAX - 1)) {
return;
}
buffer[*cursor] = ch;
(*cursor)++;
}
static void clks_log_append_text(char *buffer, usize *cursor, const char *text) {
usize i = 0;
while (text[i] != '\0') {
clks_log_append_char(buffer, cursor, text[i]);
i++;
}
}
static void clks_log_append_hex_u64(char *buffer, usize *cursor, u64 value) {
int nibble;
clks_log_append_text(buffer, cursor, "0X");
for (nibble = 15; nibble >= 0; nibble--) {
u8 current = (u8)((value >> (nibble * 4)) & 0x0FULL);
char out = (current < 10) ? (char)('0' + current) : (char)('A' + (current - 10));
clks_log_append_char(buffer, cursor, out);
}
}
static void clks_log_emit_line(const char *line) {
clks_serial_write(line);
clks_serial_write("\n");
clks_tty_write(line);
clks_tty_write("\n");
}
void clks_log(enum clks_log_level level, const char *tag, const char *message) {
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, message);
line[cursor] = '\0';
clks_log_emit_line(line);
}
void clks_log_hex(enum clks_log_level level, const char *tag, const char *label, u64 value) {
char line[CLKS_LOG_LINE_MAX];
usize cursor = 0;
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, clks_log_level_name(level));
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, '[');
clks_log_append_text(line, &cursor, tag);
clks_log_append_char(line, &cursor, ']');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_text(line, &cursor, label);
clks_log_append_char(line, &cursor, ':');
clks_log_append_char(line, &cursor, ' ');
clks_log_append_hex_u64(line, &cursor, value);
line[cursor] = '\0';
clks_log_emit_line(line);
}

194
clks/kernel/tty.c Normal file
View File

@@ -0,0 +1,194 @@
#include <clks/framebuffer.h>
#include <clks/string.h>
#include <clks/tty.h>
#include <clks/types.h>
#define CLKS_TTY_COUNT 4
#define CLKS_TTY_MAX_ROWS 128
#define CLKS_TTY_MAX_COLS 256
#define CLKS_TTY_FG 0x00E6E6E6U
#define CLKS_TTY_BG 0x00101010U
static char clks_tty_cells[CLKS_TTY_COUNT][CLKS_TTY_MAX_ROWS][CLKS_TTY_MAX_COLS];
static u32 clks_tty_cursor_row[CLKS_TTY_COUNT];
static u32 clks_tty_cursor_col[CLKS_TTY_COUNT];
static u32 clks_tty_rows = 0;
static u32 clks_tty_cols = 0;
static u32 clks_tty_active_index = 0;
static clks_bool clks_tty_is_ready = CLKS_FALSE;
static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
u32 col;
for (col = 0; col < clks_tty_cols; col++) {
clks_tty_cells[tty_index][row][col] = ch;
}
}
static void clks_tty_draw_cell(u32 row, u32 col, char ch) {
clks_fb_draw_char(col * 8U, row * 8U, ch, CLKS_TTY_FG, CLKS_TTY_BG);
}
static void clks_tty_redraw_active(void) {
u32 row;
u32 col;
clks_fb_clear(CLKS_TTY_BG);
for (row = 0; row < clks_tty_rows; row++) {
for (col = 0; col < clks_tty_cols; col++) {
clks_tty_draw_cell(row, col, clks_tty_cells[clks_tty_active_index][row][col]);
}
}
}
static void clks_tty_scroll_up(u32 tty_index) {
u32 row;
for (row = 1; row < clks_tty_rows; row++) {
clks_memcpy(
clks_tty_cells[tty_index][row - 1],
clks_tty_cells[tty_index][row],
clks_tty_cols
);
}
clks_tty_fill_row(tty_index, clks_tty_rows - 1, ' ');
if (tty_index == clks_tty_active_index) {
clks_tty_redraw_active();
}
}
static void clks_tty_put_visible(u32 tty_index, u32 row, u32 col, char ch) {
clks_tty_cells[tty_index][row][col] = ch;
if (tty_index == clks_tty_active_index) {
clks_tty_draw_cell(row, col, ch);
}
}
void clks_tty_init(void) {
struct clks_framebuffer_info info;
u32 tty;
u32 row;
if (clks_fb_ready() == CLKS_FALSE) {
clks_tty_is_ready = CLKS_FALSE;
return;
}
info = clks_fb_info();
clks_tty_rows = info.height / 8U;
clks_tty_cols = info.width / 8U;
if (clks_tty_rows > CLKS_TTY_MAX_ROWS) {
clks_tty_rows = CLKS_TTY_MAX_ROWS;
}
if (clks_tty_cols > CLKS_TTY_MAX_COLS) {
clks_tty_cols = CLKS_TTY_MAX_COLS;
}
if (clks_tty_rows == 0 || clks_tty_cols == 0) {
clks_tty_is_ready = CLKS_FALSE;
return;
}
for (tty = 0; tty < CLKS_TTY_COUNT; tty++) {
clks_tty_cursor_row[tty] = 0;
clks_tty_cursor_col[tty] = 0;
for (row = 0; row < clks_tty_rows; row++) {
clks_tty_fill_row(tty, row, ' ');
}
}
clks_tty_active_index = 0;
clks_tty_is_ready = CLKS_TRUE;
clks_tty_redraw_active();
}
void clks_tty_write_char(char ch) {
u32 tty_index;
u32 row;
u32 col;
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
tty_index = clks_tty_active_index;
row = clks_tty_cursor_row[tty_index];
col = clks_tty_cursor_col[tty_index];
if (ch == '\r') {
clks_tty_cursor_col[tty_index] = 0;
return;
}
if (ch == '\n') {
clks_tty_cursor_col[tty_index] = 0;
clks_tty_cursor_row[tty_index]++;
if (clks_tty_cursor_row[tty_index] >= clks_tty_rows) {
clks_tty_scroll_up(tty_index);
clks_tty_cursor_row[tty_index] = clks_tty_rows - 1;
}
return;
}
if (ch == '\t') {
clks_tty_write_char(' ');
clks_tty_write_char(' ');
clks_tty_write_char(' ');
clks_tty_write_char(' ');
return;
}
clks_tty_put_visible(tty_index, row, col, ch);
clks_tty_cursor_col[tty_index]++;
if (clks_tty_cursor_col[tty_index] >= clks_tty_cols) {
clks_tty_cursor_col[tty_index] = 0;
clks_tty_cursor_row[tty_index]++;
if (clks_tty_cursor_row[tty_index] >= clks_tty_rows) {
clks_tty_scroll_up(tty_index);
clks_tty_cursor_row[tty_index] = clks_tty_rows - 1;
}
}
}
void clks_tty_write(const char *text) {
usize i = 0;
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
while (text[i] != '\0') {
clks_tty_write_char(text[i]);
i++;
}
}
void clks_tty_switch(u32 tty_index) {
if (clks_tty_is_ready == CLKS_FALSE) {
return;
}
if (tty_index >= CLKS_TTY_COUNT) {
return;
}
clks_tty_active_index = tty_index;
clks_tty_redraw_active();
}
u32 clks_tty_active(void) {
return clks_tty_active_index;
}

70
clks/lib/string.c Normal file
View File

@@ -0,0 +1,70 @@
#include <clks/string.h>
usize clks_strlen(const char *str) {
usize len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
void *clks_memset(void *dst, int value, usize count) {
u8 *d = (u8 *)dst;
u8 v = (u8)value;
usize i;
for (i = 0; i < count; i++) {
d[i] = v;
}
return dst;
}
void *clks_memcpy(void *dst, const void *src, usize count) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
usize i;
for (i = 0; i < count; i++) {
d[i] = s[i];
}
return dst;
}
void *clks_memmove(void *dst, const void *src, usize count) {
u8 *d = (u8 *)dst;
const u8 *s = (const u8 *)src;
usize i;
if (d == s || count == 0) {
return dst;
}
if (d < s) {
for (i = 0; i < count; i++) {
d[i] = s[i];
}
} else {
for (i = count; i != 0; i--) {
d[i - 1] = s[i - 1];
}
}
return dst;
}
int clks_strcmp(const char *left, const char *right) {
usize i = 0;
while (left[i] != '\0' && right[i] != '\0') {
if (left[i] != right[i]) {
return (int)((u8)left[i] - (u8)right[i]);
}
i++;
}
return (int)((u8)left[i] - (u8)right[i]);
}