Files
Sylva/kernel/main.cpp
T
2026-06-06 10:31:20 +08:00

267 lines
8.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <efi.h>
#include <graphics/context.h>
#include <graphics/draw.h>
#include <graphics/layer.h>
#include <fonts/pixel_font.h>
#include <fonts/ttf.h>
#include <serial.h>
#include <common.h>
#include <string_utils.h>
#include <memory/pmm.h>
#include <memory/heap.h>
#include <scheduler.h>
#include <fs.h>
#include <gdt.h>
#include <idt.h>
#include <pic.h>
#include <pit.h>
extern EFI_SYSTEM_TABLE *ST;
inline void init_gop() {
EFI_GUID gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
EFI_GRAPHICS_OUTPUT_PROTOCOL *GOP;
uefi_call_wrapper(ST->BootServices->SetWatchdogTimer, 4, 0, 0, 0, NULL);
uefi_call_wrapper(ST->BootServices->LocateProtocol, 3, &gop_guid, NULL, (void **)&GOP);
gfx_init(GOP);
}
inline void init_serial() {
EFI_SERIAL_IO_PROTOCOL *SerialIo = NULL;
EFI_GUID gEfiSerialIoProtocolGuid = EFI_SERIAL_IO_PROTOCOL_GUID;
EFI_HANDLE *SerialHandles = NULL;
UINTN NumSerials = 0;
EFI_STATUS status = uefi_call_wrapper(ST->BootServices->LocateHandleBuffer, 5,
ByProtocol,
&gEfiSerialIoProtocolGuid,
NULL,
&NumSerials,
&SerialHandles
);
if (status == EFI_SUCCESS && NumSerials > 0) {
status = uefi_call_wrapper(ST->BootServices->HandleProtocol, 3,
SerialHandles[0], &gEfiSerialIoProtocolGuid, (void **)&SerialIo);
if (status == EFI_SUCCESS) {
serial_init(SerialIo);
}
}
if (SerialHandles) {
ST->BootServices->FreePool(SerialHandles);
}
}
// 外部 PIT 中断处理函数,定义在 pit.cpp
extern "C" void pit_irq_handler(void);
// PIC 中断处理 — 分发 IRQ 0(定时器)
static void irq_handler(trap_frame* frame) {
UINT8 vector = (UINT8)frame->vector;
UINT8 irq = vector - PIC_IRQ_BASE;
// 先发送 EOI 再处理,这样上下文切换后 PIC 可以立即投递新中断
pic_send_eoi(irq);
switch (irq) {
case 0: // PIT timer
pit_irq_handler();
break;
default:
break;
}
}
extern "C" void kernel_main() {
init_gop();
init_serial();
uefi_call_wrapper(ST->ConOut->SetCursorPosition, 3, ST->ConOut, 0, 5);
uefi_call_wrapper(ST->ConOut->OutputString, 2, ST->ConOut, (CHAR16*)L"Kernel is running!\n");
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
serial_write("\n\n");
// 初始化内存管理器
serial_write("Sylva: init PMM...\n");
EFI_STATUS st = pmm_init();
if (EFI_ERROR(st)) {
serial_write("Sylva: PMM init FAILED!\n");
} else {
serial_write("Sylva: PMM init OK\n");
serial_write("Sylva: free pages = ");
serial_write_hex(pmm_get_free_count());
serial_write("\n");
}
serial_write("Sylva: init heap...\n");
init_heap();
// 测试 kmalloc/kfree
serial_write("Sylva: kmalloc test...\n");
void* p1 = kmalloc(64);
void* p2 = kmalloc(128);
void* p3 = kmalloc(256);
serial_write("Sylva: p1 = ");
serial_write_hex((UINTN)p1);
serial_write(" p2 = ");
serial_write_hex((UINTN)p2);
serial_write(" p3 = ");
serial_write_hex((UINTN)p3);
serial_write("\n");
serial_write("Sylva: kfree test...\n");
kfree(p2);
kfree(p1);
kfree(p3);
void* p4 = kmalloc(32);
serial_write("Sylva: realloc p4 = ");
serial_write_hex((UINTN)p4);
serial_write("\n");
kfree(p4);
serial_write("Sylva: memory init done.\n");
serial_write("Sylva: FS init...\n");
EFI_STATUS fs_st = fs_init();
if (EFI_ERROR(fs_st)) {
serial_write("Sylva: FS init FAILED!\n");
} else {
serial_write("Sylva: root directory listing:\n");
fs_list();
}
// pf_print("Welcome to Sylva OS!\n");
serial_write(" Kernel prepared well.\n");
// 初始化中断基础设施
serial_write("Sylva: init GDT...\n");
gdt_init();
serial_write("Sylva: init IDT...\n");
idt_init();
serial_write("Sylva: init PIC...\n");
pic_init();
// 注册 IRQ 处理函数(向量 0x20 = PIC_IRQ_BASE + 0
idt_set_handler(PIC_IRQ_BASE + 0, irq_handler);
serial_write("Sylva: init PIT...\n");
pit_init();
pit_set_tick_handler(scheduler_tick);
// 启用中断
ASM("sti");
serial_write("Sylva: interrupts enabled\n");
// 创建多任务演示
serial_write("Sylva: creating tasks...\n");
// 初始化合成器(分配后台缓冲区,注册键盘处理)
layer_init();
// 创建桌面图层(全屏,z=0
layer_t* desktop = layer_create("desktop", LAYER_TYPE_DESKTOP, g_gfx.hr, g_gfx.vr);
if (desktop) {
layer_set_z(desktop, 0);
EFI_GRAPHICS_OUTPUT_BLT_PIXEL bg = {180, 80, 40, 0};
draw_set_target(desktop->buffer, g_gfx.hr, g_gfx.vr);
draw_rect(0, 0, g_gfx.hr, g_gfx.vr, bg);
draw_set_default_target();
layer_set_pos(desktop, 0, 0);
}
// 创建窗口 1(居中)
layer_t* win1 = layer_create("window_1", LAYER_TYPE_WINDOW, 300, 200);
if (win1) {
layer_set_pos(win1, (SSINT32)(g_gfx.hr / 2) - 150, (SSINT32)(g_gfx.vr / 2) - 100);
layer_set_z(win1, 1);
EFI_GRAPHICS_OUTPUT_BLT_PIXEL win_color = {200, 200, 200, 0};
draw_set_target(win1->buffer, 300, 200);
draw_rect(0, 0, 299, 199, win_color);
draw_set_default_target();
}
// 创建窗口 2(偏离中心)
layer_t* win2 = layer_create("window_2", LAYER_TYPE_WINDOW, 250, 180);
if (win2) {
layer_set_pos(win2, (SSINT32)(g_gfx.hr / 2) - 50, (SSINT32)(g_gfx.vr / 2) - 40);
layer_set_z(win2, 2);
EFI_GRAPHICS_OUTPUT_BLT_PIXEL win2_color = {180, 220, 140, 0};
draw_set_target(win2->buffer, 250, 180);
draw_rect(0, 0, 249, 179, win2_color);
draw_set_default_target();
}
// 合成器任务
task_create("compositor", layer_compositor_task);
serial_write("Sylva: disk read benchmark...\n");
void *ttf_buf = NULL;
UINTN ttf_size = 0;
UINT64 t0 = pit_get_ticks();
EFI_STATUS rd_st = fs_read((WString)L"sys\\resources\\LXGWWenKai-Light.ttf", &ttf_buf, &ttf_size);
UINT64 t1 = pit_get_ticks();
if (EFI_ERROR(rd_st)) {
serial_write("Sylva: fs_read FAILED: ");
serial_write_hex(rd_st);
serial_write("\n");
serial_write("Test done.\n\n");
} else {
UINT64 ticks = t1 - t0;
UINT64 ms = ticks * (1000 / PIT_TICK_HZ);
UINT64 kbps = ms ? (ttf_size * 1000ULL) / (ms * 1024ULL) : 0;
serial_write("Sylva: read ");
serial_write_hex(ttf_size);
serial_write(" bytes in ");
serial_write_hex(ms);
serial_write(" ms (");
serial_write_hex(kbps);
serial_write(" KiB/s)\n");
// TTF 渲染演示
serial_write("Sylva: ttf_open...\n");
ttf_face_t* face = ttf_open(ttf_buf, ttf_size);
if (!face) {
serial_write("Sylva: ttf_open FAILED\n");
} else {
serial_write("Sylva: ttf_open OK\n");
// 创建 TTF 文本覆盖图层
const UINT32 TL_W = 500, TL_H = 200;
layer_t* text_layer = layer_create("ttf_text", LAYER_TYPE_WINDOW, TL_W, TL_H);
if (text_layer) {
layer_set_z(text_layer, 3);
layer_set_pos(text_layer, 100, 300);
EFI_GRAPHICS_OUTPUT_BLT_PIXEL clear = {0, 0, 0, 0};
draw_set_target(text_layer->buffer, TL_W, TL_H);
draw_rect(0, 0, TL_W - 1, TL_H - 1, clear);
// 渲染多种字号和中日韩字符
EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
EFI_GRAPHICS_OUTPUT_BLT_PIXEL yellow = {255, 240, 80, 0};
EFI_GRAPHICS_OUTPUT_BLT_PIXEL cyan = {80, 220, 255, 0};
EFI_GRAPHICS_OUTPUT_BLT_PIXEL pink = {255, 160, 200, 0};
UINT32 ttf_t0 = pit_get_ticks();
ttf_draw_text(face, "Hello, Sylva OS!",
40, 60, 24, white);
ttf_draw_text(face, "欢迎来到Sylva系统!",
40, 110, 32, yellow);
UINT32 ttf_t1 = pit_get_ticks();
draw_set_default_target();
serial_write("Sylva: ttf render in ");
serial_write_hex((UINT64)((ttf_t1 - ttf_t0) * (1000 / PIT_TICK_HZ)));
serial_write(" ms\n");
}
ttf_close(face);
}
kfree(ttf_buf);
}
serial_write("Test done.\n\n");
serial_write("Sylva: starting preemptive scheduler\n");
scheduler_run(); // never returns
}