#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include 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); // 初始化 PS/2 鼠标驱动 serial_write("Sylva: init mouse...\n"); mouse_init(); 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(); // 初始化鼠标光标 cursor_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 }