This commit is contained in:
2026-04-11 16:11:16 +08:00
parent c7fee12291
commit 462f19f754
9 changed files with 428 additions and 44 deletions

View File

@@ -4,11 +4,7 @@ project(CLeonOS NONE)
# User-configurable toolchain and tool variables (Makefile-compatible defaults). # User-configurable toolchain and tool variables (Makefile-compatible defaults).
set(NO_COLOR 0 CACHE STRING "Disable colored log output when set to 1") set(NO_COLOR 0 CACHE STRING "Disable colored log output when set to 1")
include("${CMAKE_SOURCE_DIR}/cmake/log.cmake") include("${CMAKE_SOURCE_DIR}/cmake/log.cmake")
if(NO_COLOR) set(CL_LOG_EMIT_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/log_emit.cmake")
set(BUILD_LOG_COLOR_OPT --no-color)
else()
set(BUILD_LOG_COLOR_OPT)
endif()
set(CC "x86_64-elf-gcc" CACHE STRING "Kernel C compiler") set(CC "x86_64-elf-gcc" CACHE STRING "Kernel C compiler")
set(LD "x86_64-elf-ld" CACHE STRING "Kernel linker") set(LD "x86_64-elf-ld" CACHE STRING "Kernel linker")
@@ -48,12 +44,12 @@ function(resolve_tool_with_fallback VAR_NAME)
set(_requested "${${VAR_NAME}}") set(_requested "${${VAR_NAME}}")
if("${_requested}" STREQUAL "") if("${_requested}" STREQUAL "")
message(FATAL_ERROR "[ERROR] empty tool variable: ${VAR_NAME}") cl_log_error("empty tool variable: ${VAR_NAME}")
endif() endif()
if(IS_ABSOLUTE "${_requested}") if(IS_ABSOLUTE "${_requested}")
if(NOT EXISTS "${_requested}") if(NOT EXISTS "${_requested}")
message(FATAL_ERROR "[ERROR] ${VAR_NAME} not found: ${_requested}") cl_log_error("${VAR_NAME} not found: ${_requested}")
endif() endif()
set(_resolved "${_requested}") set(_resolved "${_requested}")
else() else()
@@ -71,7 +67,7 @@ function(resolve_tool_with_fallback VAR_NAME)
endif() endif()
endforeach() endforeach()
if("${_resolved}" STREQUAL "") if("${_resolved}" STREQUAL "")
message(FATAL_ERROR "[ERROR] ${VAR_NAME} tool not found: '${_requested}', fallbacks='${_fallbacks}'") cl_log_error("${VAR_NAME} tool not found: '${_requested}', fallbacks='${_fallbacks}'")
endif() endif()
endif() endif()
endif() endif()
@@ -175,7 +171,7 @@ set(KELF_LDFLAGS
) )
if(NOT CLKS_ARCH STREQUAL "x86_64") if(NOT CLKS_ARCH STREQUAL "x86_64")
message(FATAL_ERROR "[ERROR] CLKS_ARCH=${CLKS_ARCH} is not supported by this CMake build yet; use x86_64") cl_log_error("CLKS_ARCH=${CLKS_ARCH} is not supported by this CMake build yet; use x86_64")
endif() endif()
set(KERNEL_SOURCE_DIRS set(KERNEL_SOURCE_DIRS
@@ -207,10 +203,10 @@ list(SORT C_SOURCES)
list(SORT ASM_SOURCES) list(SORT ASM_SOURCES)
if(NOT C_SOURCES) if(NOT C_SOURCES)
message(FATAL_ERROR "[ERROR] no kernel C sources found in clks/") cl_log_error("no kernel C sources found in clks/")
endif() endif()
if(NOT EXISTS "${LINKER_SCRIPT}") if(NOT EXISTS "${LINKER_SCRIPT}")
message(FATAL_ERROR "[ERROR] missing linker script: ${LINKER_SCRIPT}") cl_log_error("missing linker script: ${LINKER_SCRIPT}")
endif() endif()
file(GLOB_RECURSE USER_COMMON_SOURCES_ABS CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/cleonos/c/src/*.c") file(GLOB_RECURSE USER_COMMON_SOURCES_ABS CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/cleonos/c/src/*.c")
@@ -238,13 +234,13 @@ list(SORT USER_APP_MAIN_SOURCES)
list(SORT USER_APP_KMAIN_SOURCES) list(SORT USER_APP_KMAIN_SOURCES)
if(NOT USER_COMMON_SOURCES) if(NOT USER_COMMON_SOURCES)
message(FATAL_ERROR "[ERROR] no user common sources found in cleonos/c/src/") cl_log_error("no user common sources found in cleonos/c/src/")
endif() endif()
if(NOT USER_APP_MAIN_SOURCES) if(NOT USER_APP_MAIN_SOURCES)
message(FATAL_ERROR "[ERROR] no user app *_main.c found in cleonos/c/apps/") cl_log_error("no user app *_main.c found in cleonos/c/apps/")
endif() endif()
if(NOT USER_APP_KMAIN_SOURCES) if(NOT USER_APP_KMAIN_SOURCES)
message(FATAL_ERROR "[ERROR] no kernel app *_kmain.c found in cleonos/c/apps/") cl_log_error("no kernel app *_kmain.c found in cleonos/c/apps/")
endif() endif()
function(add_kernel_c_object SRC OUTPUT_LIST_VAR) function(add_kernel_c_object SRC OUTPUT_LIST_VAR)
@@ -353,7 +349,7 @@ foreach(SRC IN LISTS USER_APP_MAIN_SOURCES)
list(FIND USER_APP_NAMES "${_app_name}" _dup_name_idx) list(FIND USER_APP_NAMES "${_app_name}" _dup_name_idx)
if(NOT _dup_name_idx EQUAL -1) if(NOT _dup_name_idx EQUAL -1)
message(FATAL_ERROR "[ERROR] duplicate user app name: ${_app_name}") cl_log_error("duplicate user app name: ${_app_name}")
endif() endif()
list(APPEND USER_APP_NAMES "${_app_name}") list(APPEND USER_APP_NAMES "${_app_name}")
@@ -381,7 +377,7 @@ foreach(SRC IN LISTS USER_APP_KMAIN_SOURCES)
list(FIND USER_APP_NAMES "${_app_name}" _dup_name_idx) list(FIND USER_APP_NAMES "${_app_name}" _dup_name_idx)
if(NOT _dup_name_idx EQUAL -1) if(NOT _dup_name_idx EQUAL -1)
message(FATAL_ERROR "[ERROR] duplicate user app name: ${_app_name}") cl_log_error("duplicate user app name: ${_app_name}")
endif() endif()
list(APPEND USER_APP_NAMES "${_app_name}") list(APPEND USER_APP_NAMES "${_app_name}")
@@ -400,7 +396,7 @@ foreach(SRC IN LISTS USER_APP_KMAIN_SOURCES)
endforeach() endforeach()
if(NOT USER_APP_OUTPUTS) if(NOT USER_APP_OUTPUTS)
message(FATAL_ERROR "[ERROR] no user ELF apps were discovered") cl_log_error("no user ELF apps were discovered")
endif() endif()
add_custom_target(userapps DEPENDS ${USER_APP_OUTPUTS}) add_custom_target(userapps DEPENDS ${USER_APP_OUTPUTS})
@@ -408,7 +404,11 @@ add_custom_target(userapps DEPENDS ${USER_APP_OUTPUTS})
add_custom_command( add_custom_command(
TARGET userapps TARGET userapps
POST_BUILD POST_BUILD
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --cyan "[INFO] user elf apps ready" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO"
"-DLOG_TEXT=user elf apps ready"
-P "${CL_LOG_EMIT_SCRIPT}"
) )
file(GLOB_RECURSE RAMDISK_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/ramdisk/*") file(GLOB_RECURSE RAMDISK_FILES CONFIGURE_DEPENDS "${CMAKE_SOURCE_DIR}/ramdisk/*")
@@ -493,7 +493,15 @@ add_custom_target(setup-limine
add_dependencies(setup-limine setup-tools) add_dependencies(setup-limine setup-tools)
add_custom_target(setup DEPENDS setup-tools setup-limine) add_custom_target(setup DEPENDS setup-tools setup-limine)
add_custom_command(TARGET setup POST_BUILD COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --cyan "[INFO] environment ready") add_custom_command(
TARGET setup
POST_BUILD
COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO"
"-DLOG_TEXT=environment ready"
-P "${CL_LOG_EMIT_SCRIPT}"
)
add_custom_command( add_custom_command(
OUTPUT "${ISO_IMAGE}" OUTPUT "${ISO_IMAGE}"
@@ -506,7 +514,11 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios-cd.bin" "${ISO_ROOT}/boot/limine/limine-bios-cd.bin" COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-bios-cd.bin" "${ISO_ROOT}/boot/limine/limine-bios-cd.bin"
COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-uefi-cd.bin" "${ISO_ROOT}/boot/limine/limine-uefi-cd.bin" COMMAND ${CMAKE_COMMAND} -E copy "${LIMINE_BIN_DIR_ABS}/limine-uefi-cd.bin" "${ISO_ROOT}/boot/limine/limine-uefi-cd.bin"
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/build" COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_SOURCE_DIR}/build"
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] building iso -> ${ISO_IMAGE}" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=building iso -> ${ISO_IMAGE}"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${XORRISO} -as mkisofs COMMAND ${XORRISO} -as mkisofs
-b boot/limine/limine-bios-cd.bin -b boot/limine/limine-bios-cd.bin
-no-emul-boot -no-emul-boot
@@ -518,9 +530,17 @@ add_custom_command(
--protective-msdos-label --protective-msdos-label
"${ISO_ROOT}" "${ISO_ROOT}"
-o "${ISO_IMAGE}" -o "${ISO_IMAGE}"
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] installing limine boot sectors" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=installing limine boot sectors"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}" COMMAND "${LIMINE_BIN_DIR_ABS}/limine" bios-install "${ISO_IMAGE}"
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --cyan "[INFO] iso ready: ${ISO_IMAGE}" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO"
"-DLOG_TEXT=iso ready: ${ISO_IMAGE}"
-P "${CL_LOG_EMIT_SCRIPT}"
DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf" DEPENDS "${KERNEL_ELF}" "${RAMDISK_IMAGE}" "${CMAKE_SOURCE_DIR}/configs/limine.conf"
VERBATIM VERBATIM
) )
@@ -529,29 +549,53 @@ add_custom_target(iso ALL DEPENDS "${ISO_IMAGE}")
add_dependencies(iso setup-tools setup-limine kernel ramdisk) add_dependencies(iso setup-tools setup-limine kernel ramdisk)
add_custom_target(run add_custom_target(run
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] launching qemu run" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu run"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} -M q35 -m 1024M -cdrom "${ISO_IMAGE}" -serial stdio COMMAND ${QEMU_X86_64} -M q35 -m 1024M -cdrom "${ISO_IMAGE}" -serial stdio
DEPENDS iso DEPENDS iso
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(debug add_custom_target(debug
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] launching qemu debug (-s -S)" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=launching qemu debug (-s -S)"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${QEMU_X86_64} -M q35 -m 1024M -cdrom "${ISO_IMAGE}" -serial stdio -s -S COMMAND ${QEMU_X86_64} -M q35 -m 1024M -cdrom "${ISO_IMAGE}" -serial stdio -s -S
DEPENDS iso DEPENDS iso
USES_TERMINAL USES_TERMINAL
) )
add_custom_target(clean-x86 add_custom_target(clean-x86
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] cleaning ${BUILD_ROOT}" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=cleaning ${BUILD_ROOT}"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${BUILD_ROOT}" COMMAND ${CMAKE_COMMAND} -E rm -rf "${BUILD_ROOT}"
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --cyan "[INFO] clean done" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO"
"-DLOG_TEXT=clean done"
-P "${CL_LOG_EMIT_SCRIPT}"
) )
add_custom_target(clean-all add_custom_target(clean-all
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --magenta "[STEP] cleaning build" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=STEP"
"-DLOG_TEXT=cleaning build"
-P "${CL_LOG_EMIT_SCRIPT}"
COMMAND ${CMAKE_COMMAND} -E rm -rf "${CMAKE_SOURCE_DIR}/build" COMMAND ${CMAKE_COMMAND} -E rm -rf "${CMAKE_SOURCE_DIR}/build"
COMMAND ${CMAKE_COMMAND} -E cmake_echo_color ${BUILD_LOG_COLOR_OPT} --cyan "[INFO] clean-all done" COMMAND ${CMAKE_COMMAND}
"-DNO_COLOR=${NO_COLOR}"
"-DLOG_LEVEL=INFO"
"-DLOG_TEXT=clean-all done"
-P "${CL_LOG_EMIT_SCRIPT}"
) )
add_custom_target(cleonos-help add_custom_target(cleonos-help

View File

@@ -1,21 +1,46 @@
#include <clks/framebuffer.h> #include <clks/framebuffer.h>
#include <clks/string.h>
#include <clks/types.h> #include <clks/types.h>
#include "font8x8.h" #include "psf_font.h"
struct clks_fb_state { struct clks_fb_state {
volatile u8 *address; volatile u8 *address;
struct clks_framebuffer_info info; struct clks_framebuffer_info info;
const struct clks_psf_font *font;
struct clks_psf_font external_font;
clks_bool external_font_active;
u32 glyph_width;
u32 glyph_height;
clks_bool ready; clks_bool ready;
}; };
static struct clks_fb_state clks_fb = { static struct clks_fb_state clks_fb = {
.address = CLKS_NULL, .address = CLKS_NULL,
.info = {0, 0, 0, 0}, .info = {0, 0, 0, 0},
.font = CLKS_NULL,
.external_font = {0, 0, 0, 0, CLKS_NULL},
.external_font_active = CLKS_FALSE,
.glyph_width = 8U,
.glyph_height = 8U,
.ready = CLKS_FALSE, .ready = CLKS_FALSE,
}; };
static void clks_fb_apply_font(const struct clks_psf_font *font) {
clks_fb.font = font;
clks_fb.glyph_width = 8U;
clks_fb.glyph_height = 8U;
if (font != CLKS_NULL) {
if (font->width != 0U) {
clks_fb.glyph_width = font->width;
}
if (font->height != 0U) {
clks_fb.glyph_height = font->height;
}
}
}
static void clks_fb_put_pixel(u32 x, u32 y, u32 rgb) { static void clks_fb_put_pixel(u32 x, u32 y, u32 rgb) {
volatile u8 *row; volatile u8 *row;
volatile u32 *pixel; volatile u32 *pixel;
@@ -33,7 +58,7 @@ static void clks_fb_put_pixel(u32 x, u32 y, u32 rgb) {
} }
row = clks_fb.address + ((usize)y * (usize)clks_fb.info.pitch); row = clks_fb.address + ((usize)y * (usize)clks_fb.info.pitch);
pixel = (volatile u32 *)(row + ((usize)x * 4)); pixel = (volatile u32 *)(row + ((usize)x * 4U));
*pixel = rgb; *pixel = rgb;
} }
@@ -48,6 +73,10 @@ void clks_fb_init(const struct limine_framebuffer *fb) {
clks_fb.info.height = (u32)fb->height; clks_fb.info.height = (u32)fb->height;
clks_fb.info.pitch = (u32)fb->pitch; clks_fb.info.pitch = (u32)fb->pitch;
clks_fb.info.bpp = fb->bpp; clks_fb.info.bpp = fb->bpp;
clks_fb.external_font_active = CLKS_FALSE;
clks_fb_apply_font(clks_psf_default_font());
clks_fb.ready = CLKS_TRUE; clks_fb.ready = CLKS_TRUE;
} }
@@ -67,8 +96,8 @@ void clks_fb_clear(u32 rgb) {
return; return;
} }
for (y = 0; y < clks_fb.info.height; y++) { for (y = 0U; y < clks_fb.info.height; y++) {
for (x = 0; x < clks_fb.info.width; x++) { for (x = 0U; x < clks_fb.info.width; x++) {
clks_fb_put_pixel(x, y, rgb); clks_fb_put_pixel(x, y, rgb);
} }
} }
@@ -78,18 +107,58 @@ void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb) {
const u8 *glyph; const u8 *glyph;
u32 row; u32 row;
u32 col; u32 col;
u32 cols;
u32 rows;
if (clks_fb.ready == CLKS_FALSE) { if (clks_fb.ready == CLKS_FALSE || clks_fb.font == CLKS_NULL) {
return; return;
} }
glyph = clks_font8x8_get(ch); glyph = clks_psf_glyph(clks_fb.font, (u32)(u8)ch);
for (row = 0; row < 8; row++) { cols = clks_fb.glyph_width;
for (col = 0; col < 8; col++) { rows = clks_fb.glyph_height;
if (cols == 0U) {
cols = 8U;
}
if (rows == 0U) {
rows = 8U;
}
if (cols > 8U) {
cols = 8U;
}
for (row = 0U; row < rows; row++) {
u8 bits = glyph[row];
for (col = 0U; col < cols; col++) {
u8 mask = (u8)(1U << (7U - col)); u8 mask = (u8)(1U << (7U - col));
u32 color = (glyph[row] & mask) != 0 ? fg_rgb : bg_rgb; u32 color = (bits & mask) != 0U ? fg_rgb : bg_rgb;
clks_fb_put_pixel(x + col, y + row, color); clks_fb_put_pixel(x + col, y + row, color);
} }
} }
} }
clks_bool clks_fb_load_psf_font(const void *blob, u64 blob_size) {
struct clks_psf_font parsed = {0, 0, 0, 0, CLKS_NULL};
if (clks_psf_parse_font(blob, blob_size, &parsed) == CLKS_FALSE) {
return CLKS_FALSE;
}
clks_fb.external_font = parsed;
clks_fb.external_font_active = CLKS_TRUE;
clks_fb_apply_font(&clks_fb.external_font);
return CLKS_TRUE;
}
u32 clks_fb_cell_width(void) {
return clks_fb.glyph_width == 0U ? 8U : clks_fb.glyph_width;
}
u32 clks_fb_cell_height(void) {
return clks_fb.glyph_height == 0U ? 8U : clks_fb.glyph_height;
}

View File

@@ -0,0 +1,193 @@
#include "psf_font.h"
#include <clks/string.h>
#include <clks/types.h>
#define CLKS_PSF1_MAGIC0 0x36U
#define CLKS_PSF1_MAGIC1 0x04U
#define CLKS_PSF1_HEADER_SIZE 4U
#define CLKS_PSF1_GLYPH_COUNT 256U
#define CLKS_PSF1_GLYPH_BYTES 8U
#define CLKS_PSF1_BLOB_SIZE (CLKS_PSF1_HEADER_SIZE + (CLKS_PSF1_GLYPH_COUNT * CLKS_PSF1_GLYPH_BYTES))
struct clks_psf1_header {
u8 magic[2];
u8 mode;
u8 charsize;
};
struct clks_psf_seed_glyph {
u8 code;
u8 rows[CLKS_PSF1_GLYPH_BYTES];
};
static const u8 clks_psf_unknown[CLKS_PSF1_GLYPH_BYTES] = {
0x3C, 0x42, 0x02, 0x0C, 0x10, 0x00, 0x10, 0x00
};
static const struct clks_psf_seed_glyph clks_psf_seed_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 u8 clks_psf_default_blob[CLKS_PSF1_BLOB_SIZE];
static struct clks_psf_font clks_psf_default = {8U, 8U, 0U, 0U, 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) {
const struct clks_psf1_header *hdr;
u32 glyph_count;
u32 glyph_bytes;
usize payload_size;
if (blob == CLKS_NULL || out_font == CLKS_NULL) {
return CLKS_FALSE;
}
if (blob_size < CLKS_PSF1_HEADER_SIZE) {
return CLKS_FALSE;
}
hdr = (const struct clks_psf1_header *)blob;
if (hdr->magic[0] != CLKS_PSF1_MAGIC0 || hdr->magic[1] != CLKS_PSF1_MAGIC1) {
return CLKS_FALSE;
}
glyph_count = (hdr->mode & 0x01U) != 0U ? 512U : 256U;
glyph_bytes = (u32)hdr->charsize;
if (glyph_bytes == 0U) {
return CLKS_FALSE;
}
payload_size = (usize)glyph_count * (usize)glyph_bytes;
if (blob_size < (usize)CLKS_PSF1_HEADER_SIZE + payload_size) {
return CLKS_FALSE;
}
out_font->width = 8U;
out_font->height = glyph_bytes;
out_font->glyph_count = glyph_count;
out_font->bytes_per_glyph = glyph_bytes;
out_font->glyphs = blob + CLKS_PSF1_HEADER_SIZE;
return CLKS_TRUE;
}
static void clks_psf_seed_default_blob(void) {
struct clks_psf1_header *hdr;
u32 i;
clks_memset(clks_psf_default_blob, 0, sizeof(clks_psf_default_blob));
hdr = (struct clks_psf1_header *)clks_psf_default_blob;
hdr->magic[0] = CLKS_PSF1_MAGIC0;
hdr->magic[1] = CLKS_PSF1_MAGIC1;
hdr->mode = 0x00U;
hdr->charsize = (u8)CLKS_PSF1_GLYPH_BYTES;
for (i = 0U; i < CLKS_PSF1_GLYPH_COUNT; i++) {
u8 *dst = clks_psf_default_blob + CLKS_PSF1_HEADER_SIZE + ((usize)i * CLKS_PSF1_GLYPH_BYTES);
clks_memcpy(dst, clks_psf_unknown, CLKS_PSF1_GLYPH_BYTES);
}
for (i = 0U; i < (u32)(sizeof(clks_psf_seed_table) / sizeof(clks_psf_seed_table[0])); i++) {
const struct clks_psf_seed_glyph *seed = &clks_psf_seed_table[i];
u8 *dst = clks_psf_default_blob + CLKS_PSF1_HEADER_SIZE + ((usize)seed->code * CLKS_PSF1_GLYPH_BYTES);
clks_memcpy(dst, seed->rows, CLKS_PSF1_GLYPH_BYTES);
}
for (i = (u32)'A'; i <= (u32)'Z'; i++) {
const u8 *upper = clks_psf_default_blob + CLKS_PSF1_HEADER_SIZE + ((usize)i * CLKS_PSF1_GLYPH_BYTES);
u8 *lower = clks_psf_default_blob + CLKS_PSF1_HEADER_SIZE + ((usize)(i + ('a' - 'A')) * CLKS_PSF1_GLYPH_BYTES);
clks_memcpy(lower, upper, CLKS_PSF1_GLYPH_BYTES);
}
}
const struct clks_psf_font *clks_psf_default_font(void) {
if (clks_psf_default_ready == CLKS_FALSE) {
clks_psf_seed_default_blob();
if (clks_psf_parse_psf1(clks_psf_default_blob, sizeof(clks_psf_default_blob), &clks_psf_default) == CLKS_FALSE) {
clks_psf_default.width = 8U;
clks_psf_default.height = 8U;
clks_psf_default.glyph_count = 1U;
clks_psf_default.bytes_per_glyph = CLKS_PSF1_GLYPH_BYTES;
clks_psf_default.glyphs = clks_psf_unknown;
}
clks_psf_default_ready = CLKS_TRUE;
}
return &clks_psf_default;
}
const u8 *clks_psf_glyph(const struct clks_psf_font *font, u32 codepoint) {
u32 index = codepoint;
if (font == CLKS_NULL || font->glyphs == CLKS_NULL || font->bytes_per_glyph == 0U) {
return clks_psf_unknown;
}
if (index >= font->glyph_count) {
index = (u32)'?';
if (index >= font->glyph_count) {
index = 0U;
}
}
return font->glyphs + ((usize)index * (usize)font->bytes_per_glyph);
}
clks_bool clks_psf_parse_font(const void *blob, u64 blob_size, struct clks_psf_font *out_font) {
if (blob_size == 0ULL) {
return CLKS_FALSE;
}
return clks_psf_parse_psf1((const u8 *)blob, (usize)blob_size, out_font);
}

View File

@@ -0,0 +1,18 @@
#ifndef CLKS_PSF_FONT_H
#define CLKS_PSF_FONT_H
#include <clks/types.h>
struct clks_psf_font {
u32 width;
u32 height;
u32 glyph_count;
u32 bytes_per_glyph;
const u8 *glyphs;
};
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

View File

@@ -16,5 +16,8 @@ clks_bool clks_fb_ready(void);
struct clks_framebuffer_info clks_fb_info(void); struct clks_framebuffer_info clks_fb_info(void);
void clks_fb_clear(u32 rgb); void clks_fb_clear(u32 rgb);
void clks_fb_draw_char(u32 x, u32 y, char ch, u32 fg_rgb, u32 bg_rgb); 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);
u32 clks_fb_cell_width(void);
u32 clks_fb_cell_height(void);
#endif #endif

View File

@@ -1,3 +1,5 @@
// Kernel main function
#include <clks/boot.h> #include <clks/boot.h>
#include <clks/cpu.h> #include <clks/cpu.h>
#include <clks/driver.h> #include <clks/driver.h>
@@ -76,6 +78,8 @@ void clks_kernel_main(void) {
void *heap_probe = CLKS_NULL; void *heap_probe = CLKS_NULL;
u64 syscall_ticks; u64 syscall_ticks;
u64 fs_root_children; u64 fs_root_children;
const void *tty_psf_blob = CLKS_NULL;
u64 tty_psf_size = 0ULL;
clks_serial_init(); clks_serial_init();
@@ -153,6 +157,18 @@ void clks_kernel_main(void) {
clks_cpu_halt_forever(); clks_cpu_halt_forever();
} }
if (boot_fb != CLKS_NULL) {
tty_psf_blob = clks_fs_read_all("/system/tty.psf", &tty_psf_size);
if (tty_psf_blob != CLKS_NULL && clks_fb_load_psf_font(tty_psf_blob, tty_psf_size) == CLKS_TRUE) {
clks_tty_init();
clks_log(CLKS_LOG_INFO, "TTY", "EXTERNAL PSF LOADED /SYSTEM/TTY.PSF");
clks_log_hex(CLKS_LOG_INFO, "TTY", "PSF_SIZE", tty_psf_size);
} else {
clks_log(CLKS_LOG_WARN, "TTY", "EXTERNAL PSF LOAD FAILED, USING BUILTIN");
}
}
clks_exec_init(); clks_exec_init();
clks_keyboard_init(); clks_keyboard_init();

View File

@@ -17,6 +17,8 @@ static u32 clks_tty_cursor_col[CLKS_TTY_COUNT];
static u32 clks_tty_rows = 0; static u32 clks_tty_rows = 0;
static u32 clks_tty_cols = 0; static u32 clks_tty_cols = 0;
static u32 clks_tty_active_index = 0; static u32 clks_tty_active_index = 0;
static u32 clks_tty_cell_width = 8U;
static u32 clks_tty_cell_height = 8U;
static clks_bool clks_tty_is_ready = CLKS_FALSE; static clks_bool clks_tty_is_ready = CLKS_FALSE;
static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) { static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
@@ -28,7 +30,7 @@ static void clks_tty_fill_row(u32 tty_index, u32 row, char ch) {
} }
static void clks_tty_draw_cell(u32 row, u32 col, char 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); clks_fb_draw_char(col * clks_tty_cell_width, row * clks_tty_cell_height, ch, CLKS_TTY_FG, CLKS_TTY_BG);
} }
static void clks_tty_redraw_active(void) { static void clks_tty_redraw_active(void) {
@@ -81,8 +83,19 @@ void clks_tty_init(void) {
} }
info = clks_fb_info(); info = clks_fb_info();
clks_tty_rows = info.height / 8U; clks_tty_cell_width = clks_fb_cell_width();
clks_tty_cols = info.width / 8U; clks_tty_cell_height = clks_fb_cell_height();
if (clks_tty_cell_width == 0U) {
clks_tty_cell_width = 8U;
}
if (clks_tty_cell_height == 0U) {
clks_tty_cell_height = 8U;
}
clks_tty_rows = info.height / clks_tty_cell_height;
clks_tty_cols = info.width / clks_tty_cell_width;
if (clks_tty_rows > CLKS_TTY_MAX_ROWS) { if (clks_tty_rows > CLKS_TTY_MAX_ROWS) {
clks_tty_rows = CLKS_TTY_MAX_ROWS; clks_tty_rows = CLKS_TTY_MAX_ROWS;
@@ -92,7 +105,7 @@ void clks_tty_init(void) {
clks_tty_cols = CLKS_TTY_MAX_COLS; clks_tty_cols = CLKS_TTY_MAX_COLS;
} }
if (clks_tty_rows == 0 || clks_tty_cols == 0) { if (clks_tty_rows == 0U || clks_tty_cols == 0U) {
clks_tty_is_ready = CLKS_FALSE; clks_tty_is_ready = CLKS_FALSE;
return; return;
} }
@@ -217,4 +230,3 @@ u32 clks_tty_count(void) {
clks_bool clks_tty_ready(void) { clks_bool clks_tty_ready(void) {
return clks_tty_is_ready; return clks_tty_is_ready;
} }

29
cmake/log_emit.cmake Normal file
View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.20)
if(NOT DEFINED NO_COLOR)
set(NO_COLOR 0)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/log.cmake")
if(NOT DEFINED LOG_LEVEL)
set(LOG_LEVEL "INFO")
endif()
if(NOT DEFINED LOG_TEXT)
set(LOG_TEXT "")
endif()
string(TOUPPER "${LOG_LEVEL}" _log_level)
if(_log_level STREQUAL "STEP")
cl_log_step("${LOG_TEXT}")
elseif(_log_level STREQUAL "INFO")
cl_log_info("${LOG_TEXT}")
elseif(_log_level STREQUAL "WARN")
cl_log_warn("${LOG_TEXT}")
elseif(_log_level STREQUAL "ERROR")
cl_log_error("${LOG_TEXT}")
else()
cl_log_info("${LOG_TEXT}")
endif()

BIN
ramdisk/system/tty.psf Normal file

Binary file not shown.