#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); } } // External: PIT IRQ handler defined in pit.cpp extern "C" void pit_irq_handler(void); // PIC IRQ handler — dispatches IRQ 0 (timer) static void irq_handler(trap_frame* frame) { UINT8 vector = (UINT8)frame->vector; UINT8 irq = vector - PIC_IRQ_BASE; // Send EOI BEFORE handling, so PIC can deliver new interrupts // immediately after a context switch inside the handler. 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"); // init memory managers 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(); // test 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"); // --- Interrupt infrastructure --- serial_write("Sylva: init GDT...\n"); gdt_init(); serial_write("Sylva: init IDT...\n"); idt_init(); serial_write("Sylva: init PIC...\n"); pic_init(); // Register IRQ handler (vector 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); // Enable interrupts ASM("sti"); serial_write("Sylva: interrupts enabled\n"); // --- Multitasking demo --- serial_write("Sylva: creating tasks...\n"); // Init compositor (allocates back buffer, registers keyboard handler) layer_init(); // Create desktop layer (full screen, z=0) layer_t* desktop = layer_create("desktop", LAYER_TYPE_DESKTOP, g_gfx.hr, g_gfx.vr); if (desktop) { layer_set_z(desktop, 0); // Fill with dark blue EFI_GRAPHICS_OUTPUT_BLT_PIXEL bg = {180, 80, 40, 0}; // BGRA: dark blue gfx_fill_rect(desktop->buffer, g_gfx.hr, g_gfx.vr, 0, 0, g_gfx.hr, g_gfx.vr, bg); layer_set_pos(desktop, 0, 0); } // Create window 1 (centered) layer_t* win1 = layer_create("window_1", LAYER_TYPE_WINDOW, 300, 200); if (win1) { layer_set_pos(win1, (int)(g_gfx.hr / 2) - 150, (int)(g_gfx.vr / 2) - 100); layer_set_z(win1, 1); // Fill with gray EFI_GRAPHICS_OUTPUT_BLT_PIXEL win_color = {200, 200, 200, 0}; gfx_fill_rect(win1->buffer, 300, 200, 0, 0, 300, 200, win_color); // White border EFI_GRAPHICS_OUTPUT_BLT_PIXEL border = {255, 255, 255, 0}; gfx_draw_rect(win1->buffer, 300, 200, 0, 0, 300, 200, border); // Title bar (blue strip at top) EFI_GRAPHICS_OUTPUT_BLT_PIXEL title_bar = {180, 100, 30, 0}; gfx_fill_rect(win1->buffer, 300, 200, 0, 0, 300, 30, title_bar); } // Create window 2 (offset from center) layer_t* win2 = layer_create("window_2", LAYER_TYPE_WINDOW, 250, 180); if (win2) { layer_set_pos(win2, (int)(g_gfx.hr / 2) - 50, (int)(g_gfx.vr / 2) - 40); layer_set_z(win2, 2); // Fill with light green EFI_GRAPHICS_OUTPUT_BLT_PIXEL win2_color = {180, 220, 140, 0}; gfx_fill_rect(win2->buffer, 250, 180, 0, 0, 250, 180, win2_color); // Dark border EFI_GRAPHICS_OUTPUT_BLT_PIXEL border2 = {50, 50, 50, 0}; gfx_draw_rect(win2->buffer, 250, 180, 0, 0, 250, 180, border2); // Title bar EFI_GRAPHICS_OUTPUT_BLT_PIXEL title2 = {160, 180, 100, 0}; gfx_fill_rect(win2->buffer, 250, 180, 0, 0, 250, 28, title2); } // Compositor task (replaces the old demo tasks) task_create("compositor", layer_compositor_task); serial_write("Sylva: starting preemptive scheduler\n"); scheduler_run(); // never returns }