Compare commits
8 Commits
15e8aedfd2
..
mouse
Vendored
-1
@@ -4,7 +4,6 @@
|
|||||||
"name": "Linux",
|
"name": "Linux",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"gnu-efi/inc/",
|
|
||||||
"include/"
|
"include/"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
|
|||||||
Vendored
-9
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"makefile.launchConfigurations": [
|
|
||||||
{
|
|
||||||
"cwd": "/home/patrick/Sylva/build",
|
|
||||||
"binaryPath": "/home/patrick/Sylva/build/Kernel.elf",
|
|
||||||
"binaryArgs": []
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -50,9 +50,26 @@ All `string_utils.h` helpers are `static inline` — header-only, no link issues
|
|||||||
|
|
||||||
## Conventions
|
## Conventions
|
||||||
|
|
||||||
- **Commits:** `[type] message` — types: `feat`, `fix`, `chore`, `docs`, `refactor` (see `git log`).
|
- **Commits:** `[type] message` — types: `feat`, `fix`, `chore`, `docs`, `refactor`, `optm` (see `git log`).
|
||||||
- **Languages:** C17 (`boot.c`), C++17 (`kernel/`) — `-ffreestanding -fno-stack-protector -fshort-wchar -mno-red-zone -fcf-protection=none`. Kernel adds `-DGNU_EFI_USE_MS_ABI -fno-pic`.
|
- **Languages:** C17 (`boot.c`), C++17 (`kernel/`) — `-ffreestanding -fno-stack-protector -fshort-wchar -mno-red-zone -fcf-protection=none`. Kernel adds `-DGNU_EFI_USE_MS_ABI -fno-pic`.
|
||||||
- **`kernel_main` must be `extern "C"`** — `boot.c` (C) calls into C++ (`kernel/entry.cpp:6`).
|
- **`kernel_main` must be `extern "C"`** — `boot.c` (C) calls into C++ (`kernel/entry.cpp:6`).
|
||||||
- **All UEFI protocol calls must use `uefi_call_wrapper`** — calling the member fn directly page-faults in long mode. See `kernel/main.cpp:23-24` and throughout.
|
- **All UEFI protocol calls must use `uefi_call_wrapper`** — calling the member fn directly page-faults in long mode. See `kernel/main.cpp:23-24` and throughout.
|
||||||
- **Kernel linked at `0x100000`** (`kernel/kernel.ld`); `.bss` start/end symbols exposed as `__bss_start` / `__bss_end`.
|
- **Kernel linked at `0x100000`** (`kernel/kernel.ld`); `.bss` start/end symbols exposed as `__bss_start` / `__bss_end`.
|
||||||
- **No tests, no CI, no lint config** — `make` is the only verification step. Boot by hand in QEMU to confirm kernel output in `serial.log`.
|
- **No tests, no CI, no lint config** — `make` is the only verification step. Boot by hand in QEMU to confirm kernel output in `serial.log`.
|
||||||
|
|
||||||
|
## Global state
|
||||||
|
|
||||||
|
| Symbol | File | Type |
|
||||||
|
|--------|------|------|
|
||||||
|
| `ST` | `kernel/entry.cpp` | `EFI_SYSTEM_TABLE*` — saved from UEFI boot |
|
||||||
|
| `g_gfx` | `include/graphics/context.h` | `gfx_context` — GOP framebuffer info |
|
||||||
|
| `g_draw_target` | `include/graphics/context.h` | `draw_target` — current draw surface |
|
||||||
|
| `g_pmm` | `include/memory/pmm.h` | `pmm_t` — physical page allocator state |
|
||||||
|
| `g_serial` | `kernel/serial.cpp` | `serial_context` — serial protocol handle |
|
||||||
|
|
||||||
|
## Gotchas
|
||||||
|
|
||||||
|
- **No paging** — kernel runs in physical memory, identity-mapped.
|
||||||
|
- **No libc** — all string/memory ops go through `string_utils.h` (header-only, `static inline`).
|
||||||
|
- **Window switching** uses Shift+F10 (hardcoded PS/2 scan codes in `kernel/graphics/layer.cpp`).
|
||||||
|
- **`third_party/`** is empty — no external deps beyond bundled gnu-efi in `efi/`.
|
||||||
|
|||||||
@@ -15,17 +15,14 @@ EFI_CFLAGS = -Iefi/inc -Iefi/inc/x86_64 -Iefi/inc/protocol \
|
|||||||
|
|
||||||
BOOT_OBJ = build/boot.o
|
BOOT_OBJ = build/boot.o
|
||||||
|
|
||||||
KERNEL_CPP = kernel/entry.cpp kernel/main.cpp kernel/serial.cpp kernel/fs.cpp \
|
KERNEL_ASMFLAGS = -Iinclude -Iefi/inc -ffreestanding -fno-stack-protector -fno-stack-check \
|
||||||
kernel/memory/heap.cpp kernel/memory/pmm.cpp \
|
-fshort-wchar -mno-red-zone -fcf-protection=none -g
|
||||||
kernel/scheduler/scheduler.cpp \
|
|
||||||
kernel/interrupt/gdt.cpp kernel/interrupt/idt.cpp \
|
KERNEL_CPP := $(shell find kernel graphics fonts devices -name '*.cpp' -type f)
|
||||||
kernel/interrupt/pic.cpp kernel/interrupt/pit.cpp \
|
KERNEL_ASM := $(shell find kernel -name '*.S' -type f)
|
||||||
kernel/graphics/layer.cpp \
|
|
||||||
graphics/context.cpp graphics/draw.cpp \
|
KERNEL_OBJ := $(KERNEL_CPP:%.cpp=build/%.o) $(KERNEL_ASM:%.S=build/%.o)
|
||||||
fonts/pixel_font.cpp \
|
KERNEL_DIRS := $(sort $(dir $(KERNEL_OBJ)))
|
||||||
fonts/ttf/ttf.cpp fonts/ttf/ttf_parse.cpp fonts/ttf/ttf_render.cpp
|
|
||||||
KERNEL_ASM = kernel/scheduler/context_switch.S kernel/interrupt/isr.S kernel/interrupt/idt_helpers.S
|
|
||||||
KERNEL_OBJ = $(KERNEL_CPP:%.cpp=build/%.o) $(KERNEL_ASM:%.S=build/%.o)
|
|
||||||
|
|
||||||
EFI_TOP_C = $(wildcard efi/lib/*.c)
|
EFI_TOP_C = $(wildcard efi/lib/*.c)
|
||||||
EFI_TOP_S = $(wildcard efi/lib/*.S)
|
EFI_TOP_S = $(wildcard efi/lib/*.S)
|
||||||
@@ -49,9 +46,7 @@ all: _bd $(EFI_OBJ) $(BOOT_OBJ) $(KERNEL_OBJ)
|
|||||||
@echo "Done."
|
@echo "Done."
|
||||||
|
|
||||||
_bd:
|
_bd:
|
||||||
@mkdir -p build/graphics build/kernel build/fonts build/fonts/ttf build/kernel/memory \
|
@mkdir -p $(KERNEL_DIRS) build/efi/gnuefi build/efi/lib build/efi/lib/x86_64 build/efi/lib/runtime
|
||||||
build/kernel/scheduler build/kernel/interrupt build/kernel/graphics \
|
|
||||||
build/efi/lib build/efi/lib/x86_64 build/efi/lib/runtime build/efi/gnuefi
|
|
||||||
|
|
||||||
$(EFI_CRT0_OBJ): efi/gnuefi/crt0-efi-x86_64.S | _bd
|
$(EFI_CRT0_OBJ): efi/gnuefi/crt0-efi-x86_64.S | _bd
|
||||||
@echo "Compile AS $<"
|
@echo "Compile AS $<"
|
||||||
@@ -85,43 +80,13 @@ build/%.o: %.c
|
|||||||
@echo "Compile C $<"
|
@echo "Compile C $<"
|
||||||
@gcc $(CFLAGS) -c $< -o $@
|
@gcc $(CFLAGS) -c $< -o $@
|
||||||
|
|
||||||
build/kernel/%.o: kernel/%.cpp | _bd
|
build/%.o: %.cpp | _bd
|
||||||
@echo "Compile CPP $<"
|
@echo "Compile CPP $<"
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
build/kernel/memory/%.o: kernel/memory/%.cpp | _bd
|
build/%.o: %.S | _bd
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
build/kernel/scheduler/%.o: kernel/scheduler/%.cpp | _bd
|
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
build/kernel/scheduler/%.o: kernel/scheduler/%.S | _bd
|
|
||||||
@echo "Compile AS $<"
|
@echo "Compile AS $<"
|
||||||
@gcc -Iinclude -Iefi/inc -ffreestanding -fno-stack-protector -fno-stack-check \
|
@gcc $(KERNEL_ASMFLAGS) -c $< -o $@
|
||||||
-fshort-wchar -mno-red-zone -fcf-protection=none -g -c $< -o $@
|
|
||||||
|
|
||||||
build/kernel/interrupt/%.o: kernel/interrupt/%.cpp | _bd
|
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
build/kernel/interrupt/%.o: kernel/interrupt/%.S | _bd
|
|
||||||
@echo "Compile AS $<"
|
|
||||||
@gcc -Iinclude -Iefi/inc -ffreestanding -fno-stack-protector -fno-stack-check \
|
|
||||||
-fshort-wchar -mno-red-zone -fcf-protection=none -g -c $< -o $@
|
|
||||||
|
|
||||||
build/graphics/%.o: graphics/%.cpp | _bd
|
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
build/fonts/%.o: fonts/%.cpp | _bd
|
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
build/fonts/ttf/%.o: fonts/ttf/%.cpp | _bd
|
|
||||||
@echo "Compile CPP $<"
|
|
||||||
@g++ $(KERNEL_CXXFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
vdir: all
|
vdir: all
|
||||||
@mkdir -p vdir/EFI/BOOT vdir/sys
|
@mkdir -p vdir/EFI/BOOT vdir/sys
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
#include <devices/cursor.h>
|
||||||
|
#include <devices/mouse.h>
|
||||||
|
#include <graphics/draw.h>
|
||||||
|
#include <graphics/context.h>
|
||||||
|
#include <memory/heap.h>
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
// 经典箭头光标位图 (12x16)
|
||||||
|
// 0=透明, 1=白色填充, 2=黑色轮廓
|
||||||
|
static const SUINT8 g_cursor_bitmap[CURSOR_H][CURSOR_W] = {
|
||||||
|
{2,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{2,2,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
{2,1,2,0,0,0,0,0,0,0,0,0},
|
||||||
|
{2,1,1,2,0,0,0,0,0,0,0,0},
|
||||||
|
{2,1,1,1,2,0,0,0,0,0,0,0},
|
||||||
|
{2,1,1,1,1,2,0,0,0,0,0,0},
|
||||||
|
{2,1,1,1,1,1,2,0,0,0,0,0},
|
||||||
|
{2,1,1,1,1,1,1,2,0,0,0,0},
|
||||||
|
{2,1,1,1,1,1,1,1,2,0,0,0},
|
||||||
|
{2,1,1,1,1,1,1,1,1,2,0,0},
|
||||||
|
{2,1,1,1,1,1,2,2,2,2,2,0},
|
||||||
|
{2,1,1,2,1,2,0,0,0,0,0,0},
|
||||||
|
{2,1,2,0,0,2,0,0,0,0,0,0},
|
||||||
|
{2,2,0,0,0,0,2,0,0,0,0,0},
|
||||||
|
{2,0,0,0,0,0,2,0,0,0,0,0},
|
||||||
|
{0,0,0,0,0,0,0,0,0,0,0,0},
|
||||||
|
};
|
||||||
|
|
||||||
|
static layer_t* g_cursor_layer = NULL;
|
||||||
|
|
||||||
|
void cursor_init(void) {
|
||||||
|
g_cursor_layer = layer_create("cursor", LAYER_TYPE_MOUSE, CURSOR_W, CURSOR_H);
|
||||||
|
if (!g_cursor_layer) return;
|
||||||
|
|
||||||
|
layer_set_z(g_cursor_layer, 9999);
|
||||||
|
|
||||||
|
// 将位图写入图层缓冲区,Reserved 用作 alpha(0=透明, 255=不透明)
|
||||||
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* buf = g_cursor_layer->buffer;
|
||||||
|
for (UINT32 y = 0; y < CURSOR_H; y++) {
|
||||||
|
for (UINT32 x = 0; x < CURSOR_W; x++) {
|
||||||
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* dst = &buf[y * CURSOR_W + x];
|
||||||
|
SUINT8 px = g_cursor_bitmap[y][x];
|
||||||
|
if (px == 1) {
|
||||||
|
dst->Blue = 255; dst->Green = 255; dst->Red = 255; dst->Reserved = 255;
|
||||||
|
} else if (px == 2) {
|
||||||
|
dst->Blue = 0; dst->Green = 0; dst->Red = 0; dst->Reserved = 255;
|
||||||
|
} else {
|
||||||
|
dst->Blue = 0; dst->Green = 0; dst->Red = 0; dst->Reserved = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始位置:屏幕中心
|
||||||
|
layer_set_pos(g_cursor_layer,
|
||||||
|
(SSINT32)(g_gfx.hr / 2),
|
||||||
|
(SSINT32)(g_gfx.vr / 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void cursor_update(void) {
|
||||||
|
if (!g_cursor_layer) return;
|
||||||
|
|
||||||
|
SSINT32 cx = (SSINT32)(g_gfx.hr / 2) + mouse_get_x();
|
||||||
|
SSINT32 cy = (SSINT32)(g_gfx.vr / 2) + mouse_get_y();
|
||||||
|
|
||||||
|
if (cx < 0) cx = 0;
|
||||||
|
if (cy < 0) cy = 0;
|
||||||
|
if (cx + (SSINT32)CURSOR_W > (SSINT32)g_gfx.hr) cx = (SSINT32)g_gfx.hr - CURSOR_W;
|
||||||
|
if (cy + (SSINT32)CURSOR_H > (SSINT32)g_gfx.vr) cy = (SSINT32)g_gfx.vr - CURSOR_H;
|
||||||
|
|
||||||
|
layer_set_pos(g_cursor_layer, cx, cy);
|
||||||
|
}
|
||||||
|
|
||||||
|
layer_t* cursor_get_layer(void) {
|
||||||
|
return g_cursor_layer;
|
||||||
|
}
|
||||||
@@ -0,0 +1,170 @@
|
|||||||
|
#include <devices/mouse.h>
|
||||||
|
#include <interrupt/idt.h>
|
||||||
|
#include <interrupt/pic.h>
|
||||||
|
#include <serial.h>
|
||||||
|
|
||||||
|
static inline void outb(UINT16 port, UINT8 val) {
|
||||||
|
ASM("outb %0, %1" : : "a"(val), "Nd"(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline UINT8 inb(UINT16 port) {
|
||||||
|
UINT8 ret;
|
||||||
|
ASM("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待 PS/2 控制器输入缓冲区清空
|
||||||
|
static void ps2_wait_input(void) {
|
||||||
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
if (!(inb(PS2_STATUS_PORT) & PS2_STAT_IBF)) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待 PS/2 控制器输出缓冲区有数据
|
||||||
|
static void ps2_wait_output(void) {
|
||||||
|
for (int i = 0; i < 100000; i++) {
|
||||||
|
if (inb(PS2_STATUS_PORT) & PS2_STAT_OBF) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向 PS/2 控制器发送命令
|
||||||
|
static void ps2_write_cmd(UINT8 cmd) {
|
||||||
|
ps2_wait_input();
|
||||||
|
outb(PS2_CMD_PORT, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 读取 PS/2 控制器返回的数据
|
||||||
|
static UINT8 ps2_read_data(void) {
|
||||||
|
ps2_wait_output();
|
||||||
|
return inb(PS2_DATA_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 向辅助端口(鼠标)发送数据
|
||||||
|
static void ps2_write_mouse(UINT8 data) {
|
||||||
|
ps2_write_cmd(0xD4); // Write to Auxiliary Device
|
||||||
|
ps2_wait_input();
|
||||||
|
outb(PS2_DATA_PORT, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 鼠标 3 字节数据包状态
|
||||||
|
static int g_pkt_phase = 0; // 0=byte0, 1=byte1, 2=byte2
|
||||||
|
static UINT8 g_pkt_byte0 = 0;
|
||||||
|
static UINT8 g_pkt_byte1 = 0;
|
||||||
|
|
||||||
|
// 鼠标光标位置(相对于屏幕中心)
|
||||||
|
static volatile SSINT32 g_mouse_x = 0;
|
||||||
|
static volatile SSINT32 g_mouse_y = 0;
|
||||||
|
static volatile bool g_mouse_btn_l = false;
|
||||||
|
static volatile bool g_mouse_btn_r = false;
|
||||||
|
static volatile bool g_mouse_btn_m = false;
|
||||||
|
|
||||||
|
// IRQ12 处理函数
|
||||||
|
static void mouse_irq_handler(trap_frame* frame) {
|
||||||
|
(void)frame;
|
||||||
|
pic_send_eoi(PS2_MOUSE_IRQ);
|
||||||
|
|
||||||
|
// 读取状态寄存器,检查输出缓冲区是否有数据
|
||||||
|
UINT8 status = inb(PS2_STATUS_PORT);
|
||||||
|
if (!(status & PS2_STAT_OBF)) return;
|
||||||
|
|
||||||
|
UINT8 data = inb(PS2_DATA_PORT);
|
||||||
|
|
||||||
|
// 解析 3 字节数据包
|
||||||
|
switch (g_pkt_phase) {
|
||||||
|
case 0: // byte 0: 按钮 + 标志
|
||||||
|
if (!(data & PS2_MOUSE_ALWAYS1)) return; // 无效字节,重新同步
|
||||||
|
g_pkt_byte0 = data;
|
||||||
|
g_pkt_phase = 1;
|
||||||
|
break;
|
||||||
|
case 1: // byte 1: X delta
|
||||||
|
g_pkt_byte1 = data;
|
||||||
|
g_pkt_phase = 2;
|
||||||
|
break;
|
||||||
|
case 2: // byte 2: Y delta
|
||||||
|
g_pkt_byte0 = g_pkt_byte0; // 确保编译器不优化
|
||||||
|
g_pkt_byte1 = g_pkt_byte1;
|
||||||
|
|
||||||
|
// 解析按钮状态
|
||||||
|
g_mouse_btn_l = (g_pkt_byte0 & PS2_MOUSE_LEFT) != 0;
|
||||||
|
g_mouse_btn_r = (g_pkt_byte0 & PS2_MOUSE_RIGHT) != 0;
|
||||||
|
g_mouse_btn_m = (g_pkt_byte0 & PS2_MOUSE_MIDDLE) != 0;
|
||||||
|
|
||||||
|
// 解析 X delta
|
||||||
|
SSINT32 dx = (SSINT32)(SSINT8)g_pkt_byte1;
|
||||||
|
if (g_pkt_byte0 & PS2_MOUSE_X_SIGN) dx |= 0xFFFFFF00;
|
||||||
|
|
||||||
|
// 解析 Y delta
|
||||||
|
SSINT32 dy = (SSINT32)(SSINT8)data;
|
||||||
|
if (g_pkt_byte0 & PS2_MOUSE_Y_SIGN) dy |= 0xFFFFFF00;
|
||||||
|
|
||||||
|
// 更新光标位置(Y 轴在屏幕上向下为正)
|
||||||
|
g_mouse_x += dx;
|
||||||
|
g_mouse_y -= dy;
|
||||||
|
|
||||||
|
g_pkt_phase = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 丢弃输出缓冲区中的残留数据
|
||||||
|
static void ps2_flush_output(void) {
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
inb(PS2_DATA_PORT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mouse_init(void) {
|
||||||
|
// 1. 控制器自检(必须在命令字节写入之前,因为自检会重置命令字节)
|
||||||
|
ps2_write_cmd(PS2_CMD_SELF_TEST);
|
||||||
|
UINT8 self_test = ps2_read_data();
|
||||||
|
if (self_test != 0x55) {
|
||||||
|
serial_write("MOUSE: self-test FAILED\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 丢弃自检可能产生的残留数据
|
||||||
|
ps2_flush_output();
|
||||||
|
|
||||||
|
// 3. 启用辅助端口(鼠标)
|
||||||
|
ps2_write_cmd(PS2_CMD_ENABLE_A2);
|
||||||
|
|
||||||
|
// 4. 读取当前命令字节
|
||||||
|
ps2_write_cmd(PS2_CMD_READ_MB);
|
||||||
|
UINT8 cmd = ps2_read_data();
|
||||||
|
|
||||||
|
// 5. 启用 IRQ12 + IRQ1
|
||||||
|
cmd |= PS2_CMD_IRQ12 | PS2_CMD_IRQ1;
|
||||||
|
|
||||||
|
// 6. 写入修改后的命令字节(在自检之后,不会被重置)
|
||||||
|
ps2_write_cmd(PS2_CMD_WRITE_MB);
|
||||||
|
ps2_wait_input();
|
||||||
|
outb(PS2_DATA_PORT, cmd);
|
||||||
|
|
||||||
|
// 7. 验证命令字节已写入
|
||||||
|
ps2_write_cmd(PS2_CMD_READ_MB);
|
||||||
|
UINT8 verify = ps2_read_data();
|
||||||
|
if (verify != cmd) {
|
||||||
|
serial_write("MOUSE: cmd verify mismatch\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重置鼠标
|
||||||
|
ps2_write_mouse(PS2_MOUSE_RESET);
|
||||||
|
UINT8 ack = ps2_read_data();
|
||||||
|
if (ack == 0xFA) {
|
||||||
|
ps2_read_data(); // 丢弃第二字节
|
||||||
|
}
|
||||||
|
|
||||||
|
// 启用鼠标数据上报
|
||||||
|
ps2_write_mouse(PS2_MOUSE_ENABLE);
|
||||||
|
ps2_read_data();
|
||||||
|
|
||||||
|
// 注册 IRQ12 处理函数并取消屏蔽
|
||||||
|
idt_set_handler(PS2_MOUSE_VECTOR, mouse_irq_handler);
|
||||||
|
pic_unmask_irq(2); // 取消主片级联屏蔽
|
||||||
|
pic_unmask_irq(PS2_MOUSE_IRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
SSINT32 mouse_get_x(void) { return g_mouse_x; }
|
||||||
|
SSINT32 mouse_get_y(void) { return g_mouse_y; }
|
||||||
|
bool mouse_get_btn_left(void) { return g_mouse_btn_l; }
|
||||||
|
bool mouse_get_btn_right(void) { return g_mouse_btn_r; }
|
||||||
|
bool mouse_get_btn_middle(void) { return g_mouse_btn_m; }
|
||||||
@@ -3,5 +3,6 @@
|
|||||||
本系统引用了下列字体:
|
本系统引用了下列字体:
|
||||||
|
|
||||||
- Hankaku
|
- Hankaku
|
||||||
|
- 霞鹜文楷 Light
|
||||||
|
|
||||||
并在相关协议下使用。
|
并在相关协议下使用。
|
||||||
@@ -8,13 +8,7 @@ void pf_print_char(char c, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT
|
|||||||
for (SUINT32 y = 0; y < 16; y++) {
|
for (SUINT32 y = 0; y < 16; y++) {
|
||||||
SUINT8 data = hankaku_pixels[c][y];
|
SUINT8 data = hankaku_pixels[c][y];
|
||||||
for (SSINT32 x = 7; x >= 0; x--) {
|
for (SSINT32 x = 7; x >= 0; x--) {
|
||||||
// 解码Hankaku字体
|
// Hankaku 字体解码:每个字节代表一行,低位在右
|
||||||
/*
|
|
||||||
既然都在这了,就讲一下Hankaku字体是如何解码的
|
|
||||||
比如一个
|
|
||||||
{0x00, 0x82, 0x82, 0x44, 0x44, 0x44, 0x28, 0x28, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x00}
|
|
||||||
每一个Hex代表一行,比如0x82就是一行,转换成Bin得到10000010,1代表有像素,0代表没像素
|
|
||||||
*/
|
|
||||||
SUINT32 current = data & 1;
|
SUINT32 current = data & 1;
|
||||||
data >>= 1;
|
data >>= 1;
|
||||||
if (current)
|
if (current)
|
||||||
@@ -26,6 +20,6 @@ void pf_print_char(char c, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT
|
|||||||
void pf_print(const char* text, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) {
|
void pf_print(const char* text, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color) {
|
||||||
for (SUINT32 i = 0; i < str_len(text); i++) {
|
for (SUINT32 i = 0; i < str_len(text); i++) {
|
||||||
char c = text[i];
|
char c = text[i];
|
||||||
pf_print_char(c, basex + i * 8, basey, color); // 只要 字数 * 8 + basex 不爆hr就没事
|
pf_print_char(c, basex + i * 8, basey, color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-5
@@ -4,14 +4,12 @@
|
|||||||
#include <memory/heap.h>
|
#include <memory/heap.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
// Per-glyph scratch — kept static to avoid stack pressure for big Chinese glyphs
|
// 逐字形临时缓冲区 — 静态分配以避免大中文字形的栈压力
|
||||||
static ttf_outline_t s_outline;
|
static ttf_outline_t s_outline;
|
||||||
static ttf_seg_t s_segs[4096];
|
static ttf_seg_t s_segs[4096];
|
||||||
static SUINT8 s_coverage[256 * 256];
|
static SUINT8 s_coverage[256 * 256];
|
||||||
|
|
||||||
// Render one glyph bitmap at screen (px, py) where py is the glyph TOP
|
// 在屏幕 (px, py) 处渲染单个字形位图,py 为字形顶部(已从基线转换)
|
||||||
// (already converted from baseline). (px, py) may be negative — caller
|
|
||||||
// must have clipped into the visible region.
|
|
||||||
static void blit_glyph(SSINT32 px, SSINT32 py, SUINT32 w, SUINT32 h,
|
static void blit_glyph(SSINT32 px, SSINT32 py, SUINT32 w, SUINT32 h,
|
||||||
const SUINT8* coverage, SUINT32 N,
|
const SUINT8* coverage, SUINT32 N,
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
|
||||||
@@ -31,7 +29,7 @@ static void blit_glyph(SSINT32 px, SSINT32 py, SUINT32 w, SUINT32 h,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render a single codepoint at (x, y) = baseline. Returns advance (26.6).
|
// 在基线 (x, y) 处渲染单个码点,返回进宽(26.6 定点数)
|
||||||
static f26_6 render_codepoint(ttf_face_t* face, SSINT32 cp,
|
static f26_6 render_codepoint(ttf_face_t* face, SSINT32 cp,
|
||||||
SSINT32 x, SSINT32 y, SUINT32 pixel_size,
|
SSINT32 x, SSINT32 y, SUINT32 pixel_size,
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color)
|
||||||
|
|||||||
+35
-35
@@ -3,7 +3,7 @@
|
|||||||
#include <memory/heap.h>
|
#include <memory/heap.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
// ---- Big-endian readers (TTF is big-endian) ----
|
// 大端读取器(TTF 为大端格式)
|
||||||
static inline SUINT16 rd16(const SUINT8* p) {
|
static inline SUINT16 rd16(const SUINT8* p) {
|
||||||
return ((SUINT16)p[0] << 8) | p[1];
|
return ((SUINT16)p[0] << 8) | p[1];
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,7 @@ static const SUINT8* find_table(ttf_face_t* face, const char tag[4]) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- UTF-8 ----
|
// UTF-8 解码
|
||||||
SSINT32 ttf_utf8_decode(const char** p) {
|
SSINT32 ttf_utf8_decode(const char** p) {
|
||||||
const SUINT8* s = (const SUINT8*)*p;
|
const SUINT8* s = (const SUINT8*)*p;
|
||||||
SUINT8 b0 = s[0];
|
SUINT8 b0 = s[0];
|
||||||
@@ -39,7 +39,7 @@ SSINT32 ttf_utf8_decode(const char** p) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- cmap ----
|
// cmap 子表查找
|
||||||
static const SUINT8* find_cmap_subtable(ttf_face_t* face) {
|
static const SUINT8* find_cmap_subtable(ttf_face_t* face) {
|
||||||
const SUINT8* cmap = face->cmap;
|
const SUINT8* cmap = face->cmap;
|
||||||
SUINT16 num = rd16(cmap + 2);
|
SUINT16 num = rd16(cmap + 2);
|
||||||
@@ -85,7 +85,7 @@ static SUINT16 cmap4_lookup(const SUINT8* sub, SSINT32 cp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SUINT16 cmap12_lookup(const SUINT8* sub, SSINT32 cp) {
|
static SUINT16 cmap12_lookup(const SUINT8* sub, SSINT32 cp) {
|
||||||
// Format 12 header: format(2) reserved(2) length(4) language(4) nGroups(4)
|
// Format 12 头:format(2) reserved(2) length(4) language(4) nGroups(4)
|
||||||
SUINT32 nGroups = rd32(sub + 12);
|
SUINT32 nGroups = rd32(sub + 12);
|
||||||
const SUINT8* g = sub + 16;
|
const SUINT8* g = sub + 16;
|
||||||
for (SUINT32 i = 0; i < nGroups; i++) {
|
for (SUINT32 i = 0; i < nGroups; i++) {
|
||||||
@@ -108,14 +108,14 @@ SUINT16 ttf_cmap_lookup(ttf_face_t* face, SSINT32 cp) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Glyf decode ----
|
// glyf 解码
|
||||||
bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
||||||
SUINT32 pixel_size_px, ttf_outline_t* out)
|
SUINT32 pixel_size_px, ttf_outline_t* out)
|
||||||
{
|
{
|
||||||
mem_set(out, 0, sizeof(*out));
|
mem_set(out, 0, sizeof(*out));
|
||||||
if (glyph_id >= face->num_glyphs) return false;
|
if (glyph_id >= face->num_glyphs) return false;
|
||||||
|
|
||||||
// Loca
|
// Loca 索引
|
||||||
SUINT32 off0, off1;
|
SUINT32 off0, off1;
|
||||||
if (face->index_to_loc_format == 0) {
|
if (face->index_to_loc_format == 0) {
|
||||||
off0 = ((SUINT32)rd16(face->loca + glyph_id * 2)) * 2;
|
off0 = ((SUINT32)rd16(face->loca + glyph_id * 2)) * 2;
|
||||||
@@ -126,7 +126,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
}
|
}
|
||||||
if (off0 >= face->glyf_len) return false;
|
if (off0 >= face->glyf_len) return false;
|
||||||
|
|
||||||
// Advance width (always readable from hmtx regardless of glyf presence)
|
// 进宽(始终从 hmtx 读取,无论 glyf 是否存在)
|
||||||
{
|
{
|
||||||
SUINT16 aw;
|
SUINT16 aw;
|
||||||
if (glyph_id < face->num_long_hor_metrics) {
|
if (glyph_id < face->num_long_hor_metrics) {
|
||||||
@@ -138,21 +138,21 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (off0 == off1) {
|
if (off0 == off1) {
|
||||||
// Empty glyph (e.g. space)
|
// 空白字形(如空格)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUINT8* g = face->glyf + off0;
|
const SUINT8* g = face->glyf + off0;
|
||||||
SSINT16 numContours = rd16s(g + 0);
|
SSINT16 numContours = rd16s(g + 0);
|
||||||
if (numContours < 0) {
|
if (numContours < 0) {
|
||||||
// Composite glyph — parse component records and merge outlines
|
// 复合字形 — 解析组件记录并合并轮廓
|
||||||
const SUINT8* cp = g + 10;
|
const SUINT8* cp = g + 10;
|
||||||
SSINT32 all_xmin = 0x7FFFFFFF, all_ymin = 0x7FFFFFFF;
|
SSINT32 all_xmin = 0x7FFFFFFF, all_ymin = 0x7FFFFFFF;
|
||||||
SSINT32 all_xmax = -0x7FFFFFFF, all_ymax = -0x7FFFFFFF;
|
SSINT32 all_xmax = -0x7FFFFFFF, all_ymax = -0x7FFFFFFF;
|
||||||
|
|
||||||
// Composite glyph flags (OpenType spec):
|
// 复合字形标志(OpenType 规范):
|
||||||
// 0x0001 = ARG_1_AND_2_ARE_WORDS (16-bit args; else 8-bit)
|
// 0x0001 = ARG_1_AND_2_ARE_WORDS(16 位参数;否则 8 位)
|
||||||
// 0x0002 = ARGS_ARE_XY_VALUES (offsets; else point indices)
|
// 0x0002 = ARGS_ARE_XY_VALUES(偏移量;否则点索引)
|
||||||
// 0x0008 = WE_HAVE_A_SCALE
|
// 0x0008 = WE_HAVE_A_SCALE
|
||||||
// 0x0040 = WE_HAVE_A_2x2
|
// 0x0040 = WE_HAVE_A_2x2
|
||||||
// 0x0080 = WE_HAVE_AN_X_AND_Y_SCALE
|
// 0x0080 = WE_HAVE_AN_X_AND_Y_SCALE
|
||||||
@@ -162,41 +162,41 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
SUINT16 comp_flags = rd16(cp); cp += 2;
|
SUINT16 comp_flags = rd16(cp); cp += 2;
|
||||||
SUINT16 comp_glyph = rd16(cp); cp += 2;
|
SUINT16 comp_glyph = rd16(cp); cp += 2;
|
||||||
|
|
||||||
// Read arguments (size depends on ARG_1_AND_2_ARE_WORDS)
|
// 读取参数(大小取决于 ARG_1_AND_2_ARE_WORDS)
|
||||||
SSINT32 arg1, arg2;
|
SSINT32 arg1, arg2;
|
||||||
if (comp_flags & 0x0001) {
|
if (comp_flags & 0x0001) {
|
||||||
// 16-bit signed words
|
// 16 位有符号字
|
||||||
arg1 = rd16s(cp); cp += 2;
|
arg1 = rd16s(cp); cp += 2;
|
||||||
arg2 = rd16s(cp); cp += 2;
|
arg2 = rd16s(cp); cp += 2;
|
||||||
} else {
|
} else {
|
||||||
// 8-bit signed bytes
|
// 8 位有符号字节
|
||||||
arg1 = (SSINT8)cp[0];
|
arg1 = (SSINT8)cp[0];
|
||||||
arg2 = (SSINT8)cp[1];
|
arg2 = (SSINT8)cp[1];
|
||||||
cp += 2;
|
cp += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read transform scale if present
|
// 如果存在则读取缩放比例
|
||||||
f26_6 scale = F26_ONE;
|
f26_6 scale = F26_ONE;
|
||||||
if (comp_flags & 0x0008) {
|
if (comp_flags & 0x0008) {
|
||||||
// WE_HAVE_A_SCALE: 16.16 fixed-point
|
// WE_HAVE_A_SCALE:16.16 定点数
|
||||||
SSINT16 s16 = rd16s(cp); cp += 2;
|
SSINT16 s16 = rd16s(cp); cp += 2;
|
||||||
scale = (f26_6)s16; // already in f26.6 from 16.16
|
scale = (f26_6)s16; // already in f26.6 from 16.16
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read x/y scale if present
|
// 如果存在则读取 x/y 缩放
|
||||||
f26_6 scaleX = F26_ONE, scaleY = F26_ONE;
|
f26_6 scaleX = F26_ONE, scaleY = F26_ONE;
|
||||||
if (comp_flags & 0x0080) {
|
if (comp_flags & 0x0080) {
|
||||||
// WE_HAVE_AN_X_AND_Y_SCALE: two 16.16 values
|
// WE_HAVE_AN_X_AND_Y_SCALE:两个 16.16 值
|
||||||
SSINT16 sx16 = rd16s(cp); cp += 2;
|
SSINT16 sx16 = rd16s(cp); cp += 2;
|
||||||
SSINT16 sy16 = rd16s(cp); cp += 2;
|
SSINT16 sy16 = rd16s(cp); cp += 2;
|
||||||
scaleX = (f26_6)sx16;
|
scaleX = (f26_6)sx16;
|
||||||
scaleY = (f26_6)sy16;
|
scaleY = (f26_6)sy16;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read 2x2 matrix if present
|
// 如果存在则读取 2x2 矩阵
|
||||||
f26_6 m00 = F26_ONE, m01 = 0, m10 = 0, m11 = F26_ONE;
|
f26_6 m00 = F26_ONE, m01 = 0, m10 = 0, m11 = F26_ONE;
|
||||||
if (comp_flags & 0x0040) {
|
if (comp_flags & 0x0040) {
|
||||||
// WE_HAVE_A_2x2: four 2.14 values
|
// WE_HAVE_A_2x2:四个 2.14 值
|
||||||
SSINT16 a = rd16s(cp); cp += 2;
|
SSINT16 a = rd16s(cp); cp += 2;
|
||||||
SSINT16 b = rd16s(cp); cp += 2;
|
SSINT16 b = rd16s(cp); cp += 2;
|
||||||
SSINT16 c = rd16s(cp); cp += 2;
|
SSINT16 c = rd16s(cp); cp += 2;
|
||||||
@@ -207,36 +207,36 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
m11 = (f26_6)(d >> 8);
|
m11 = (f26_6)(d >> 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load component glyph
|
// 加载组件字形
|
||||||
ttf_outline_t comp;
|
ttf_outline_t comp;
|
||||||
if (!ttf_load_glyph(face, comp_glyph, pixel_size_px, &comp))
|
if (!ttf_load_glyph(face, comp_glyph, pixel_size_px, &comp))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Determine if args are offsets (XY values) or point indices
|
// 判断参数是偏移量(XY 值)还是点索引
|
||||||
SSINT32 offset_x = 0, offset_y = 0;
|
SSINT32 offset_x = 0, offset_y = 0;
|
||||||
if (comp_flags & 0x0002) {
|
if (comp_flags & 0x0002) {
|
||||||
// ARGS_ARE_XY_VALUES: args are pixel offsets (already scaled)
|
// ARGS_ARE_XY_VALUES:参数是像素偏移量(已缩放)
|
||||||
// Scale from font units to pixel space like simple glyphs
|
// 从字体单位缩放到像素空间
|
||||||
offset_x = (SSINT32)(((SSINT64)arg1 * (SSINT64)pixel_size_px * 64 / face->units_per_em));
|
offset_x = (SSINT32)(((SSINT64)arg1 * (SSINT64)pixel_size_px * 64 / face->units_per_em));
|
||||||
offset_y = (SSINT32)(((SSINT64)arg2 * (SSINT64)pixel_size_px * 64 / face->units_per_em));
|
offset_y = (SSINT32)(((SSINT64)arg2 * (SSINT64)pixel_size_px * 64 / face->units_per_em));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform and merge component points
|
// 变换并合并组件点
|
||||||
for (SUINT16 i = 0; i < comp.num_points; i++) {
|
for (SUINT16 i = 0; i < comp.num_points; i++) {
|
||||||
f26_6 fx = comp.x[i];
|
f26_6 fx = comp.x[i];
|
||||||
f26_6 fy = comp.y[i];
|
f26_6 fy = comp.y[i];
|
||||||
f26_6 tx, ty;
|
f26_6 tx, ty;
|
||||||
|
|
||||||
if (comp_flags & 0x0040) {
|
if (comp_flags & 0x0040) {
|
||||||
// 2x2 matrix transform
|
// 2x2 矩阵变换
|
||||||
tx = f26_mul(m00, fx) + f26_mul(m01, fy);
|
tx = f26_mul(m00, fx) + f26_mul(m01, fy);
|
||||||
ty = f26_mul(m10, fx) + f26_mul(m11, fy);
|
ty = f26_mul(m10, fx) + f26_mul(m11, fy);
|
||||||
} else if (comp_flags & 0x0008) {
|
} else if (comp_flags & 0x0008) {
|
||||||
// Uniform scale
|
// 均匀缩放
|
||||||
tx = f26_mul(scale, fx);
|
tx = f26_mul(scale, fx);
|
||||||
ty = f26_mul(scale, fy);
|
ty = f26_mul(scale, fy);
|
||||||
} else if (comp_flags & 0x0080) {
|
} else if (comp_flags & 0x0080) {
|
||||||
// X/Y scale
|
// x/y 独立缩放
|
||||||
tx = f26_mul(scaleX, fx);
|
tx = f26_mul(scaleX, fx);
|
||||||
ty = f26_mul(scaleY, fy);
|
ty = f26_mul(scaleY, fy);
|
||||||
} else {
|
} else {
|
||||||
@@ -295,7 +295,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
SUINT16 instrLen = rd16(p); p += 2;
|
SUINT16 instrLen = rd16(p); p += 2;
|
||||||
p += instrLen;
|
p += instrLen;
|
||||||
|
|
||||||
// Decode flags (with REPEAT)
|
// 解码标志(含 REPEAT)
|
||||||
SUINT8 flags[1024];
|
SUINT8 flags[1024];
|
||||||
SUINT16 pi = 0;
|
SUINT16 pi = 0;
|
||||||
while (pi < numPoints) {
|
while (pi < numPoints) {
|
||||||
@@ -308,7 +308,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode x-coords into x_raw[]
|
// 解码 x 坐标到 x_raw[]
|
||||||
SSINT32 x_raw[1024];
|
SSINT32 x_raw[1024];
|
||||||
{
|
{
|
||||||
SSINT32 x = 0;
|
SSINT32 x = 0;
|
||||||
@@ -324,7 +324,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
x_raw[i] = x;
|
x_raw[i] = x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Decode y-coords into y_raw[]
|
// 解码 y 坐标到 y_raw[]
|
||||||
SSINT32 y_raw[1024];
|
SSINT32 y_raw[1024];
|
||||||
{
|
{
|
||||||
SSINT32 y = 0;
|
SSINT32 y = 0;
|
||||||
@@ -341,7 +341,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale to pixel space (f26_6)
|
// 缩放到像素空间(f26_6)
|
||||||
SUINT64 scale_num = (SUINT64)pixel_size_px * 64;
|
SUINT64 scale_num = (SUINT64)pixel_size_px * 64;
|
||||||
for (SUINT16 i = 0; i < numPoints; i++) {
|
for (SUINT16 i = 0; i < numPoints; i++) {
|
||||||
out->x[i] = (f26_6)(((SSINT64)x_raw[i] * (SSINT64)scale_num) / face->units_per_em);
|
out->x[i] = (f26_6)(((SSINT64)x_raw[i] * (SSINT64)scale_num) / face->units_per_em);
|
||||||
@@ -365,7 +365,7 @@ bool ttf_load_glyph(ttf_face_t* face, SUINT16 glyph_id,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Open / close ----
|
// 打开 / 关闭
|
||||||
ttf_face_t* ttf_open(const void* data, UINTN size) {
|
ttf_face_t* ttf_open(const void* data, UINTN size) {
|
||||||
if (!data || size < 12) return NULL;
|
if (!data || size < 12) return NULL;
|
||||||
const SUINT8* d = (const SUINT8*)data;
|
const SUINT8* d = (const SUINT8*)data;
|
||||||
@@ -449,7 +449,7 @@ void ttf_close(ttf_face_t* face) {
|
|||||||
if (face) kfree(face);
|
if (face) kfree(face);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Metrics (scaled to pixel_size, returned as 26.6 fp) ----
|
// 度量值(缩放到 pixel_size,返回 26.6 定点数)
|
||||||
SSINT32 ttf_ascender (ttf_face_t* face, SUINT32 px) {
|
SSINT32 ttf_ascender (ttf_face_t* face, SUINT32 px) {
|
||||||
return (SSINT32)(((SSINT64)face->os2_ascender * (SSINT64)px * 64) / face->units_per_em);
|
return (SSINT32)(((SSINT64)face->os2_ascender * (SSINT64)px * 64) / face->units_per_em);
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-17
@@ -1,13 +1,12 @@
|
|||||||
#include "ttf_internal.h"
|
#include "ttf_internal.h"
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
|
||||||
// ---- Outline -> segments ----
|
// 轮廓 → 线段转换
|
||||||
//
|
//
|
||||||
// TrueType contour walk: for each pair of consecutive points, emit either
|
// TrueType 轮廓遍历:对每对连续点,发射直线或二次贝塞尔曲线。
|
||||||
// a line or a quadratic bezier. Two consecutive off-curve points trigger
|
// 两个连续的非曲线点会触发合成一个曲线中点。
|
||||||
// synthesis of an on-curve midpoint.
|
|
||||||
//
|
//
|
||||||
// All coordinates remain in 26.6 fp throughout.
|
// 所有坐标全程使用 26.6 定点数。
|
||||||
void ttf_outline_to_segments(const ttf_outline_t* outline,
|
void ttf_outline_to_segments(const ttf_outline_t* outline,
|
||||||
ttf_seg_t* segs, SUINT32* num_segs)
|
ttf_seg_t* segs, SUINT32* num_segs)
|
||||||
{
|
{
|
||||||
@@ -79,7 +78,11 @@ void ttf_outline_to_segments(const ttf_outline_t* outline,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pending >= 0) PUSH_QUAD(anchor, pending, start);
|
if (pending >= 0) {
|
||||||
|
PUSH_QUAD(anchor, pending, start);
|
||||||
|
} else if (anchor != start) {
|
||||||
|
PUSH_LINE(anchor, start);
|
||||||
|
}
|
||||||
|
|
||||||
#undef GET_X
|
#undef GET_X
|
||||||
#undef GET_Y
|
#undef GET_Y
|
||||||
@@ -88,7 +91,7 @@ void ttf_outline_to_segments(const ttf_outline_t* outline,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Integer sqrt (Newton) ----
|
// 整数平方根(牛顿法)
|
||||||
static SUINT32 isqrt_u64(SUINT64 n) {
|
static SUINT32 isqrt_u64(SUINT64 n) {
|
||||||
if (n == 0) return 0;
|
if (n == 0) return 0;
|
||||||
SUINT32 x = (n > 0xFFFFFFFFu) ? 0xFFFFu : (SUINT32)n;
|
SUINT32 x = (n > 0xFFFFFFFFu) ? 0xFFFFu : (SUINT32)n;
|
||||||
@@ -97,19 +100,19 @@ static SUINT32 isqrt_u64(SUINT64 n) {
|
|||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Scanline fill with subpixel supersampling ----
|
// 扫描线填充 + 子像素超采样
|
||||||
//
|
//
|
||||||
// For each output row, run N sub-scanlines at offsets (k+0.5)/N. For each
|
// 对每个输出行,运行 N 条子扫描线,偏移为 (k+0.5)/N。
|
||||||
// sub-scanline y, collect all x-intersections, sort, fill alternating
|
// 对每条子扫描线 y,收集所有 x 交点,排序后交替填充 x 对。
|
||||||
// x-pairs. Sum over N subsamples yields per-pixel coverage in [0, N].
|
// 对 N 个子采样求和得到每个像素的覆盖率 [0, N]。
|
||||||
void ttf_rasterize(const ttf_seg_t* segs, SUINT32 num_segs,
|
void ttf_rasterize(const ttf_seg_t* segs, SUINT32 num_segs,
|
||||||
SSINT32 x0, SSINT32 y0, SUINT32 w, SUINT32 h,
|
SSINT32 x0, SSINT32 y0, SUINT32 w, SUINT32 h,
|
||||||
SUINT8* coverage, SUINT32 N)
|
SUINT8* coverage, SUINT32 N)
|
||||||
{
|
{
|
||||||
// Clear coverage
|
// 清空覆盖率缓冲区
|
||||||
for (SUINT32 i = 0; i < w * h; i++) coverage[i] = 0;
|
for (SUINT32 i = 0; i < w * h; i++) coverage[i] = 0;
|
||||||
|
|
||||||
// Intersection x-buf (per scanline, max possible = num_segs)
|
// 交点 x 缓冲区(每扫描线,最大可能数 = num_segs)
|
||||||
f26_6 xs[2048];
|
f26_6 xs[2048];
|
||||||
if (num_segs > 2048) num_segs = 2048;
|
if (num_segs > 2048) num_segs = 2048;
|
||||||
|
|
||||||
@@ -193,11 +196,10 @@ void ttf_rasterize(const ttf_seg_t* segs, SUINT32 num_segs,
|
|||||||
while (j > 0 && xs[j-1] > v) { xs[j] = xs[j-1]; j--; }
|
while (j > 0 && xs[j-1] > v) { xs[j] = xs[j-1]; j--; }
|
||||||
xs[j] = v;
|
xs[j] = v;
|
||||||
}
|
}
|
||||||
// Deduplicate: merge intersections within 1 pixel (64 in 26.6)
|
// Deduplicate: merge intersections within 1/16 pixel (4 in 26.6)
|
||||||
SUINT32 nxd = 0;
|
SUINT32 nxd = 0;
|
||||||
for (SUINT32 i = 0; i < nxs; i++) {
|
for (SUINT32 i = 0; i < nxs; i++) {
|
||||||
if (nxd > 0 && (xs[i] - xs[nxd - 1]) < 64) {
|
if (nxd > 0 && (xs[i] - xs[nxd - 1]) < 4) {
|
||||||
// Near-duplicate — skip to avoid spurious fill slivers
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
xs[nxd++] = xs[i];
|
xs[nxd++] = xs[i];
|
||||||
@@ -219,6 +221,6 @@ void ttf_rasterize(const ttf_seg_t* segs, SUINT32 num_segs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// (Alpha conversion happens at the caller via N.)
|
// 覆盖率转换在调用端通过 N 完成
|
||||||
(void)x0; (void)y0;
|
(void)x0; (void)y0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
// GFX 存在的意义是什么?
|
// GFX 全局图形上下文,避免每次绘制都传递 GOP 参数
|
||||||
// 每一次想要draw pixel,都需要传入GOP的各种参数,
|
|
||||||
// 加入 GFX 后,GOP 的context就是全局的,可以直接用
|
|
||||||
// 而不用显示传递参数到draw的函数里
|
|
||||||
|
|
||||||
#include <graphics/context.h>
|
#include <graphics/context.h>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
#include <graphics/layer.h>
|
||||||
|
|
||||||
|
#define CURSOR_W 12
|
||||||
|
#define CURSOR_H 16
|
||||||
|
|
||||||
|
void cursor_init(void);
|
||||||
|
void cursor_update(void);
|
||||||
|
|
||||||
|
layer_t* cursor_get_layer(void);
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <common.h>
|
||||||
|
|
||||||
|
#define PS2_MOUSE_IRQ 12
|
||||||
|
#define PS2_MOUSE_VECTOR (PIC_IRQ_BASE + PS2_MOUSE_IRQ)
|
||||||
|
|
||||||
|
// PS/2 controller ports
|
||||||
|
#define PS2_DATA_PORT 0x60
|
||||||
|
#define PS2_STATUS_PORT 0x64
|
||||||
|
#define PS2_CMD_PORT 0x64
|
||||||
|
|
||||||
|
// PS/2 controller commands
|
||||||
|
#define PS2_CMD_READ_MB 0x20 // Read command byte
|
||||||
|
#define PS2_CMD_WRITE_MB 0x60 // Write command byte
|
||||||
|
#define PS2_CMD_ENABLE_A2 0xA8 // Enable auxiliary (second) port
|
||||||
|
#define PS2_CMD_SELF_TEST 0xAA // Controller self-test
|
||||||
|
|
||||||
|
// PS/2 command byte bits
|
||||||
|
#define PS2_CMD_IRQ12 0x02 // Enable IRQ12 (auxiliary device)
|
||||||
|
#define PS2_CMD_IRQ1 0x01 // Enable IRQ1 (keyboard)
|
||||||
|
|
||||||
|
// PS/2 controller status bits
|
||||||
|
#define PS2_STAT_OBF 0x01 // Output buffer full (data ready)
|
||||||
|
#define PS2_STAT_IBF 0x02 // Input buffer full (controller busy)
|
||||||
|
|
||||||
|
// PS/2 mouse commands
|
||||||
|
#define PS2_MOUSE_ENABLE 0xF4 // Enable data reporting
|
||||||
|
#define PS2_MOUSE_DISABLE 0xF5 // Disable data reporting
|
||||||
|
#define PS2_MOUSE_RESET 0xFF // Reset mouse
|
||||||
|
|
||||||
|
// Mouse packet byte 0 flags
|
||||||
|
#define PS2_MOUSE_LEFT 0x01
|
||||||
|
#define PS2_MOUSE_RIGHT 0x02
|
||||||
|
#define PS2_MOUSE_MIDDLE 0x04
|
||||||
|
#define PS2_MOUSE_ALWAYS1 0x08
|
||||||
|
#define PS2_MOUSE_X_SIGN 0x10
|
||||||
|
#define PS2_MOUSE_Y_SIGN 0x20
|
||||||
|
#define PS2_MOUSE_X_OVER 0x40
|
||||||
|
#define PS2_MOUSE_Y_OVER 0x80
|
||||||
|
|
||||||
|
void mouse_init(void);
|
||||||
|
|
||||||
|
SSINT32 mouse_get_x(void);
|
||||||
|
SSINT32 mouse_get_y(void);
|
||||||
|
bool mouse_get_btn_left(void);
|
||||||
|
bool mouse_get_btn_right(void);
|
||||||
|
bool mouse_get_btn_middle(void);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
// Hankaku 字体,不动
|
// Hankaku 8x16 点阵字体数据
|
||||||
static SUINT8 hankaku_pixels[256][16] = {
|
static SUINT8 hankaku_pixels[256][16] = {
|
||||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||||
{0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00},
|
{0x10, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x7c, 0x7c, 0x38, 0x38, 0x10, 0x10, 0x00, 0x00},
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include <graphics/context.h>
|
#include <graphics/context.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
|
||||||
|
// 打印单个字符
|
||||||
void pf_print_char(char c, SUINT32 basex, SUINT32 basey,
|
void pf_print_char(char c, SUINT32 basex, SUINT32 basey,
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); // Pixel Font 打印字符
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255});
|
||||||
void pf_print(String text, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255}); // Pixel Font 打印string
|
// 打印字符串
|
||||||
|
void pf_print(String text, SUINT32 basex, SUINT32 basey, EFI_GRAPHICS_OUTPUT_BLT_PIXEL color = {255, 255, 255, 255});
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
// 这个文件存在的目的是让graphics的draw功能不用每次传 GOP hr vr base
|
|
||||||
|
|
||||||
#include <efi.h>
|
#include <efi.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
|
|
||||||
|
|||||||
+12
-6
@@ -4,14 +4,20 @@
|
|||||||
#include <efiser.h>
|
#include <efiser.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
|
||||||
struct serial_context { // 串行内容结构体
|
// 串行通信上下文
|
||||||
|
struct serial_context {
|
||||||
EFI_SERIAL_IO_PROTOCOL *SerialIo;
|
EFI_SERIAL_IO_PROTOCOL *SerialIo;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern serial_context g_serial;
|
extern serial_context g_serial;
|
||||||
|
|
||||||
void serial_init(EFI_SERIAL_IO_PROTOCOL *SerialIo); // 初始化串行驱动
|
// 初始化串行驱动
|
||||||
void serial_write(String str); // 往串行写string
|
void serial_init(EFI_SERIAL_IO_PROTOCOL *SerialIo);
|
||||||
void serial_write_char(char c); // 往串行写char(不推荐使用)
|
// 写字符串到串行
|
||||||
void serial_write_hex(UINTN val); // 往串行写十六进制数字
|
void serial_write(String str);
|
||||||
char serial_read_char(); // 读串行
|
// 写单个字符到串行(不推荐直接使用)
|
||||||
|
void serial_write_char(char c);
|
||||||
|
// 写十六进制数字到串行
|
||||||
|
void serial_write_hex(UINTN val);
|
||||||
|
// 从串行读取一个字符
|
||||||
|
char serial_read_char();
|
||||||
+2
-1
@@ -8,7 +8,8 @@ extern "C" void kernel_main();
|
|||||||
extern "C" void _start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
extern "C" void _start(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
|
||||||
(void)ImageHandle;
|
(void)ImageHandle;
|
||||||
ST = SystemTable;
|
ST = SystemTable;
|
||||||
ASM("cli"); // disable interrupts until IDT is ready
|
// 在 IDT 就绪前禁用中断
|
||||||
|
ASM("cli");
|
||||||
kernel_main();
|
kernel_main();
|
||||||
while (1) ASM ("hlt");
|
while (1) ASM ("hlt");
|
||||||
}
|
}
|
||||||
|
|||||||
+25
-42
@@ -5,40 +5,40 @@
|
|||||||
#include <memory/pmm.h>
|
#include <memory/pmm.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
#include <idt.h>
|
#include <devices/cursor.h>
|
||||||
#include <pic.h>
|
#include <interrupt/idt.h>
|
||||||
|
#include <interrupt/pic.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
|
|
||||||
// --- Layer list (sorted by z, lowest first) ---
|
// 图层列表(按 z 排序,最低在前)
|
||||||
|
|
||||||
static layer_t g_layers[LAYER_MAX];
|
static layer_t g_layers[LAYER_MAX];
|
||||||
static UINT32 g_layer_count = 0;
|
static UINT32 g_layer_count = 0;
|
||||||
static layer_t* g_layer_list = NULL;
|
static layer_t* g_layer_list = NULL;
|
||||||
|
|
||||||
// Compositor back buffer
|
// 合成器后台缓冲区
|
||||||
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL* g_back_buffer = NULL;
|
static EFI_GRAPHICS_OUTPUT_BLT_PIXEL* g_back_buffer = NULL;
|
||||||
|
|
||||||
// Focus tracking
|
// 焦点追踪
|
||||||
static layer_t* g_focused = NULL;
|
static layer_t* g_focused = NULL;
|
||||||
|
|
||||||
// Shift+F10 state (set by IRQ handler, consumed by compositor)
|
// Shift+F10 状态(由 IRQ 处理函数设置,合成器消费)
|
||||||
static volatile bool g_shift_held = false;
|
static volatile bool g_shift_held = false;
|
||||||
static volatile bool g_switch_pending = false;
|
static volatile bool g_switch_pending = false;
|
||||||
static volatile layer_t* g_switch_target = NULL;
|
static volatile layer_t* g_switch_target = NULL;
|
||||||
|
|
||||||
// PS/2 scan code set 1
|
// PS/2 扫描码集 1
|
||||||
#define PS2_F10 0x44
|
#define PS2_F10 0x44
|
||||||
#define PS2_LSHIFT 0x2A
|
#define PS2_LSHIFT 0x2A
|
||||||
#define PS2_RSHIFT 0x36
|
#define PS2_RSHIFT 0x36
|
||||||
#define PS2_BREAK_BIT 0x80
|
#define PS2_BREAK_BIT 0x80
|
||||||
|
|
||||||
// Forward declare
|
// 前向声明
|
||||||
static void layer_insert_sorted(layer_t* layer);
|
static void layer_insert_sorted(layer_t* layer);
|
||||||
static void layer_remove(layer_t* layer);
|
static void layer_remove(layer_t* layer);
|
||||||
static layer_t* find_next_window(layer_t* from);
|
static layer_t* find_next_window(layer_t* from);
|
||||||
|
|
||||||
// --- PS/2 keyboard IRQ handler ---
|
// PS/2 键盘 IRQ 处理
|
||||||
|
|
||||||
static void ps2_irq_handler(trap_frame* frame) {
|
static void ps2_irq_handler(trap_frame* frame) {
|
||||||
(void)frame;
|
(void)frame;
|
||||||
pic_send_eoi(1);
|
pic_send_eoi(1);
|
||||||
@@ -63,8 +63,7 @@ static void ps2_irq_handler(trap_frame* frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Layer management ---
|
// 图层管理
|
||||||
|
|
||||||
layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h) {
|
layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h) {
|
||||||
if (g_layer_count >= LAYER_MAX) {
|
if (g_layer_count >= LAYER_MAX) {
|
||||||
serial_write("LAYER: limit reached\n");
|
serial_write("LAYER: limit reached\n");
|
||||||
@@ -104,12 +103,6 @@ layer_t* layer_create(const char* name, layer_type_t type, UINT32 w, UINT32 h) {
|
|||||||
|
|
||||||
layer_insert_sorted(layer);
|
layer_insert_sorted(layer);
|
||||||
|
|
||||||
serial_write("LAYER: created '");
|
|
||||||
serial_write(name);
|
|
||||||
serial_write("' id=");
|
|
||||||
serial_write_hex(id);
|
|
||||||
serial_write("\n");
|
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,10 +121,6 @@ void layer_destroy(layer_t* layer) {
|
|||||||
g_switch_target = NULL;
|
g_switch_target = NULL;
|
||||||
g_switch_pending = false;
|
g_switch_pending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
serial_write("LAYER: destroyed '");
|
|
||||||
serial_write(layer->name);
|
|
||||||
serial_write("'\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
layer_t* layer_get_by_id(UINT32 id) {
|
layer_t* layer_get_by_id(UINT32 id) {
|
||||||
@@ -162,8 +151,7 @@ void layer_set_visible(layer_t* layer, bool visible) {
|
|||||||
layer->visible = visible;
|
layer->visible = visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Sorted insert/remove ---
|
// 有序插入/移除
|
||||||
|
|
||||||
static void layer_insert_sorted(layer_t* layer) {
|
static void layer_insert_sorted(layer_t* layer) {
|
||||||
layer->next = NULL;
|
layer->next = NULL;
|
||||||
|
|
||||||
@@ -216,8 +204,7 @@ static layer_t* find_next_window(layer_t* from) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Initialization ---
|
// 初始化
|
||||||
|
|
||||||
void layer_init(void) {
|
void layer_init(void) {
|
||||||
UINT32 hr = g_gfx.hr;
|
UINT32 hr = g_gfx.hr;
|
||||||
UINT32 vr = g_gfx.vr;
|
UINT32 vr = g_gfx.vr;
|
||||||
@@ -235,44 +222,37 @@ void layer_init(void) {
|
|||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register keyboard IRQ and unmask
|
// 注册键盘 IRQ 并取消屏蔽
|
||||||
idt_set_handler(PIC_IRQ_BASE + 1, ps2_irq_handler);
|
idt_set_handler(PIC_IRQ_BASE + 1, ps2_irq_handler);
|
||||||
pic_unmask_irq(1);
|
pic_unmask_irq(1);
|
||||||
|
|
||||||
serial_write("LAYER: compositor init OK (back buffer = ");
|
|
||||||
serial_write_hex(buf_size);
|
|
||||||
serial_write(" bytes)\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Compositor task ---
|
// 合成器任务
|
||||||
|
|
||||||
void layer_compositor_task(void) {
|
void layer_compositor_task(void) {
|
||||||
serial_write("LAYER: compositor task running\n");
|
|
||||||
|
|
||||||
UINT32 hr = g_gfx.hr;
|
UINT32 hr = g_gfx.hr;
|
||||||
UINT32 vr = g_gfx.vr;
|
UINT32 vr = g_gfx.vr;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// Process deferred Shift+F10 switch (safe: not inside IRQ)
|
// 处理延迟的 Shift+F10 窗口切换
|
||||||
if (g_switch_pending) {
|
if (g_switch_pending) {
|
||||||
g_switch_pending = false;
|
g_switch_pending = false;
|
||||||
layer_t* target = (layer_t*)g_switch_target;
|
layer_t* target = (layer_t*)g_switch_target;
|
||||||
if (target && target->visible && target->type == LAYER_TYPE_WINDOW) {
|
if (target && target->visible && target->type == LAYER_TYPE_WINDOW) {
|
||||||
g_focused = target;
|
g_focused = target;
|
||||||
layer_set_z(target, 99);
|
layer_set_z(target, 99);
|
||||||
serial_write("LAYER: Shift+F10 -> '");
|
|
||||||
serial_write(target->name);
|
|
||||||
serial_write("'\n");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear back buffer
|
// 更新光标位置
|
||||||
|
cursor_update();
|
||||||
|
|
||||||
|
// 清除后台缓冲区
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL black = {0, 0, 0, 0};
|
||||||
draw_set_target(g_back_buffer, hr, vr);
|
draw_set_target(g_back_buffer, hr, vr);
|
||||||
draw_rect(0, 0, hr, vr, black);
|
draw_rect(0, 0, hr, vr, black);
|
||||||
draw_set_default_target();
|
draw_set_default_target();
|
||||||
|
|
||||||
// Composite layers from lowest z to highest
|
// 按 z 从低到高合成图层
|
||||||
layer_t* cur = g_layer_list;
|
layer_t* cur = g_layer_list;
|
||||||
while (cur) {
|
while (cur) {
|
||||||
if (cur->visible && cur->buffer) {
|
if (cur->visible && cur->buffer) {
|
||||||
@@ -286,14 +266,17 @@ void layer_compositor_task(void) {
|
|||||||
if (dy + (SSINT32)sh > (SSINT32)vr) sh = vr - dy;
|
if (dy + (SSINT32)sh > (SSINT32)vr) sh = vr - dy;
|
||||||
if (sw == 0 || sh == 0) { cur = cur->next; continue; }
|
if (sw == 0 || sh == 0) { cur = cur->next; continue; }
|
||||||
|
|
||||||
|
bool use_alpha = (cur->type == LAYER_TYPE_MOUSE);
|
||||||
for (UINT32 row = 0; row < sh; row++) {
|
for (UINT32 row = 0; row < sh; row++) {
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* src = cur->buffer + ((UINTN)cur->w * (sy + row)) + sx;
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* src = cur->buffer + ((UINTN)cur->w * (sy + row)) + sx;
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* dst = g_back_buffer + ((UINTN)hr * (dy + row)) + dx;
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL* dst = g_back_buffer + ((UINTN)hr * (dy + row)) + dx;
|
||||||
for (UINT32 col = 0; col < sw; col++) {
|
for (UINT32 col = 0; col < sw; col++) {
|
||||||
|
if (!use_alpha || src->Reserved != 0) {
|
||||||
dst->Blue = src->Blue;
|
dst->Blue = src->Blue;
|
||||||
dst->Green = src->Green;
|
dst->Green = src->Green;
|
||||||
dst->Red = src->Red;
|
dst->Red = src->Red;
|
||||||
dst->Reserved = src->Reserved;
|
dst->Reserved = src->Reserved;
|
||||||
|
}
|
||||||
src++;
|
src++;
|
||||||
dst++;
|
dst++;
|
||||||
}
|
}
|
||||||
@@ -302,7 +285,7 @@ void layer_compositor_task(void) {
|
|||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Blit to screen
|
// Blit 到屏幕
|
||||||
uefi_call_wrapper(g_gfx.GOP->Blt, 10,
|
uefi_call_wrapper(g_gfx.GOP->Blt, 10,
|
||||||
g_gfx.GOP,
|
g_gfx.GOP,
|
||||||
g_back_buffer,
|
g_back_buffer,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include <gdt.h>
|
#include <interrupt/gdt.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|||||||
+10
-10
@@ -1,10 +1,10 @@
|
|||||||
#include <idt.h>
|
#include <interrupt/idt.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <pic.h>
|
#include <interrupt/pic.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
// Defined in isr.S — 256 ISR stubs
|
// isr.S 中定义的 256 个 ISR 桩函数
|
||||||
extern "C" void* isr_stub_table[256];
|
extern "C" void* isr_stub_table[256];
|
||||||
|
|
||||||
static idt_entry g_idt[256];
|
static idt_entry g_idt[256];
|
||||||
@@ -15,7 +15,7 @@ void idt_set_handler(UINT8 vector, isr_handler_t handler) {
|
|||||||
g_handlers[vector] = handler;
|
g_handlers[vector] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called from isr.S common handler
|
// 由 isr.S 通用处理函数调用
|
||||||
extern "C" void isr_dispatch(trap_frame* frame) {
|
extern "C" void isr_dispatch(trap_frame* frame) {
|
||||||
UINT8 vector = (UINT8)frame->vector;
|
UINT8 vector = (UINT8)frame->vector;
|
||||||
|
|
||||||
@@ -31,14 +31,14 @@ extern "C" void isr_dispatch(trap_frame* frame) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IDT helpers (defined in idt_helpers.S)
|
// IDT 辅助函数(定义在 idt_helpers.S)
|
||||||
extern "C" void idt_load(UINT64 base, UINT16 limit);
|
extern "C" void idt_load(UINT64 base, UINT16 limit);
|
||||||
|
|
||||||
static void idt_set_entry(UINT8 vector, UINT64 handler_addr) {
|
static void idt_set_entry(UINT8 vector, UINT64 handler_addr) {
|
||||||
g_idt[vector].offset_low = handler_addr & 0xFFFF;
|
g_idt[vector].offset_low = handler_addr & 0xFFFF;
|
||||||
g_idt[vector].selector = 0x08; // kernel code segment
|
g_idt[vector].selector = 0x08; // 内核代码段
|
||||||
g_idt[vector].ist = 0;
|
g_idt[vector].ist = 0;
|
||||||
g_idt[vector].type_attr = 0x8E; // present, DPL=0, 64-bit interrupt gate
|
g_idt[vector].type_attr = 0x8E; // 存在,DPL=0,64 位中断门
|
||||||
g_idt[vector].offset_mid = (handler_addr >> 16) & 0xFFFF;
|
g_idt[vector].offset_mid = (handler_addr >> 16) & 0xFFFF;
|
||||||
g_idt[vector].offset_high = (handler_addr >> 32) & 0xFFFFFFFF;
|
g_idt[vector].offset_high = (handler_addr >> 32) & 0xFFFFFFFF;
|
||||||
g_idt[vector].reserved = 0;
|
g_idt[vector].reserved = 0;
|
||||||
@@ -47,18 +47,18 @@ static void idt_set_entry(UINT8 vector, UINT64 handler_addr) {
|
|||||||
void idt_init(void) {
|
void idt_init(void) {
|
||||||
serial_write("IDT: initializing 256 entries\n");
|
serial_write("IDT: initializing 256 entries\n");
|
||||||
|
|
||||||
// Clear IDT
|
// 清空 IDT
|
||||||
for (SSINT32 i = 0; i < 256; i++) {
|
for (SSINT32 i = 0; i < 256; i++) {
|
||||||
g_idt[i] = {0};
|
g_idt[i] = {0};
|
||||||
g_handlers[i] = NULL;
|
g_handlers[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Install all 256 ISR stubs
|
// 安装所有 256 个 ISR 桩函数
|
||||||
for (SSINT32 i = 0; i < 256; i++) {
|
for (SSINT32 i = 0; i < 256; i++) {
|
||||||
idt_set_entry(i, (UINT64)isr_stub_table[i]);
|
idt_set_entry(i, (UINT64)isr_stub_table[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load IDT
|
// 加载 IDT
|
||||||
g_idt_ptr.limit = sizeof(g_idt) - 1;
|
g_idt_ptr.limit = sizeof(g_idt) - 1;
|
||||||
g_idt_ptr.base = (UINT64)&g_idt[0];
|
g_idt_ptr.base = (UINT64)&g_idt[0];
|
||||||
idt_load(g_idt_ptr.base, g_idt_ptr.limit);
|
idt_load(g_idt_ptr.base, g_idt_ptr.limit);
|
||||||
|
|||||||
+12
-12
@@ -1,4 +1,4 @@
|
|||||||
#include <pic.h>
|
#include <interrupt/pic.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
@@ -13,37 +13,37 @@ static inline UINT8 inb(UINT16 port) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 慢速 PIC 的小延迟
|
||||||
static void pic_wait(void) {
|
static void pic_wait(void) {
|
||||||
// Small delay for slow PICs
|
|
||||||
ASM("jmp 1f\n\t1: jmp 1f\n\t1:");
|
ASM("jmp 1f\n\t1: jmp 1f\n\t1:");
|
||||||
}
|
}
|
||||||
|
|
||||||
void pic_init(void) {
|
void pic_init(void) {
|
||||||
serial_write("PIC: remapping 8259 PIC\n");
|
serial_write("PIC: remapping 8259 PIC\n");
|
||||||
|
|
||||||
// Save masks
|
// 保存掩码
|
||||||
UINT8 mask1 = inb(PIC1_DATA);
|
UINT8 mask1 = inb(PIC1_DATA);
|
||||||
UINT8 mask2 = inb(PIC2_DATA);
|
UINT8 mask2 = inb(PIC2_DATA);
|
||||||
|
|
||||||
// ICW1: begin initialization, ICW4 needed
|
// ICW1:开始初始化,需要 ICW4
|
||||||
outb(PIC1_CMD, 0x11); pic_wait();
|
outb(PIC1_CMD, 0x11); pic_wait();
|
||||||
outb(PIC2_CMD, 0x11); pic_wait();
|
outb(PIC2_CMD, 0x11); pic_wait();
|
||||||
|
|
||||||
// ICW2: vector offset
|
// ICW2:向量偏移
|
||||||
outb(PIC1_DATA, PIC_IRQ_BASE); // IRQ 0-7 → vector 0x20-0x27
|
outb(PIC1_DATA, PIC_IRQ_BASE); // IRQ 0-7 → 向量 0x20-0x27
|
||||||
pic_wait();
|
pic_wait();
|
||||||
outb(PIC2_DATA, PIC_IRQ_BASE + 8); // IRQ 8-15 → vector 0x28-0x2F
|
outb(PIC2_DATA, PIC_IRQ_BASE + 8); // IRQ 8-15 → 向量 0x28-0x2F
|
||||||
pic_wait();
|
pic_wait();
|
||||||
|
|
||||||
// ICW3: cascading
|
// ICW3:级联
|
||||||
outb(PIC1_DATA, 0x04); pic_wait(); // slave on IRQ 2
|
outb(PIC1_DATA, 0x04); pic_wait(); // 从片在 IRQ 2
|
||||||
outb(PIC2_DATA, 0x02); pic_wait(); // cascade identity
|
outb(PIC2_DATA, 0x02); pic_wait(); // 级联标识
|
||||||
|
|
||||||
// ICW4: 8086 mode
|
// ICW4:8086 模式
|
||||||
outb(PIC1_DATA, 0x01); pic_wait();
|
outb(PIC1_DATA, 0x01); pic_wait();
|
||||||
outb(PIC2_DATA, 0x01); pic_wait();
|
outb(PIC2_DATA, 0x01); pic_wait();
|
||||||
|
|
||||||
// Restore masks
|
// 恢复掩码
|
||||||
outb(PIC1_DATA, mask1);
|
outb(PIC1_DATA, mask1);
|
||||||
outb(PIC2_DATA, mask2);
|
outb(PIC2_DATA, mask2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <pit.h>
|
#include <interrupt/pit.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <string_utils.h>
|
#include <string_utils.h>
|
||||||
#include <pic.h>
|
#include <interrupt/pic.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
static inline void outb(UINT16 port, UINT8 val) {
|
static inline void outb(UINT16 port, UINT8 val) {
|
||||||
@@ -25,14 +25,14 @@ void pit_init(void) {
|
|||||||
|
|
||||||
UINT32 divisor = PIT_BASE_FREQ / PIT_TICK_HZ;
|
UINT32 divisor = PIT_BASE_FREQ / PIT_TICK_HZ;
|
||||||
|
|
||||||
// Command byte: channel 0, lobyte/hibyte, rate generator, binary
|
// 命令字节:通道 0,低/高字节,速率生成器,二进制
|
||||||
outb(PIT_COMMAND_PORT, 0x36);
|
outb(PIT_COMMAND_PORT, 0x36);
|
||||||
|
|
||||||
// Send divisor (low byte first, then high byte)
|
// 发送除数(先低字节后高字节)
|
||||||
outb(PIT_CHANNEL0_DATA, (UINT8)(divisor & 0xFF));
|
outb(PIT_CHANNEL0_DATA, (UINT8)(divisor & 0xFF));
|
||||||
outb(PIT_CHANNEL0_DATA, (UINT8)((divisor >> 8) & 0xFF));
|
outb(PIT_CHANNEL0_DATA, (UINT8)((divisor >> 8) & 0xFF));
|
||||||
|
|
||||||
// Unmask IRQ 0 (timer)
|
// 取消屏蔽 IRQ 0(定时器)
|
||||||
pic_unmask_irq(0);
|
pic_unmask_irq(0);
|
||||||
|
|
||||||
serial_write("PIT: divisor = ");
|
serial_write("PIT: divisor = ");
|
||||||
|
|||||||
+30
-22
@@ -11,10 +11,12 @@
|
|||||||
#include <memory/heap.h>
|
#include <memory/heap.h>
|
||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
#include <fs.h>
|
#include <fs.h>
|
||||||
#include <gdt.h>
|
#include <interrupt/gdt.h>
|
||||||
#include <idt.h>
|
#include <interrupt/idt.h>
|
||||||
#include <pic.h>
|
#include <interrupt/pic.h>
|
||||||
#include <pit.h>
|
#include <interrupt/pit.h>
|
||||||
|
#include <devices/mouse.h>
|
||||||
|
#include <devices/cursor.h>
|
||||||
|
|
||||||
extern EFI_SYSTEM_TABLE *ST;
|
extern EFI_SYSTEM_TABLE *ST;
|
||||||
|
|
||||||
@@ -50,16 +52,15 @@ inline void init_serial() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// External: PIT IRQ handler defined in pit.cpp
|
// 外部 PIT 中断处理函数,定义在 pit.cpp
|
||||||
extern "C" void pit_irq_handler(void);
|
extern "C" void pit_irq_handler(void);
|
||||||
|
|
||||||
// PIC IRQ handler — dispatches IRQ 0 (timer)
|
// PIC 中断处理 — 分发 IRQ 0(定时器)
|
||||||
static void irq_handler(trap_frame* frame) {
|
static void irq_handler(trap_frame* frame) {
|
||||||
UINT8 vector = (UINT8)frame->vector;
|
UINT8 vector = (UINT8)frame->vector;
|
||||||
UINT8 irq = vector - PIC_IRQ_BASE;
|
UINT8 irq = vector - PIC_IRQ_BASE;
|
||||||
|
|
||||||
// Send EOI BEFORE handling, so PIC can deliver new interrupts
|
// 先发送 EOI 再处理,这样上下文切换后 PIC 可以立即投递新中断
|
||||||
// immediately after a context switch inside the handler.
|
|
||||||
pic_send_eoi(irq);
|
pic_send_eoi(irq);
|
||||||
|
|
||||||
switch (irq) {
|
switch (irq) {
|
||||||
@@ -81,7 +82,7 @@ extern "C" void kernel_main() {
|
|||||||
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
uefi_call_wrapper(ST->ConOut->ClearScreen, 1, ST->ConOut);
|
||||||
serial_write("\n\n");
|
serial_write("\n\n");
|
||||||
|
|
||||||
// init memory managers
|
// 初始化内存管理器
|
||||||
serial_write("Sylva: init PMM...\n");
|
serial_write("Sylva: init PMM...\n");
|
||||||
EFI_STATUS st = pmm_init();
|
EFI_STATUS st = pmm_init();
|
||||||
if (EFI_ERROR(st)) {
|
if (EFI_ERROR(st)) {
|
||||||
@@ -96,7 +97,7 @@ extern "C" void kernel_main() {
|
|||||||
serial_write("Sylva: init heap...\n");
|
serial_write("Sylva: init heap...\n");
|
||||||
init_heap();
|
init_heap();
|
||||||
|
|
||||||
// test kmalloc/kfree
|
// 测试 kmalloc/kfree
|
||||||
serial_write("Sylva: kmalloc test...\n");
|
serial_write("Sylva: kmalloc test...\n");
|
||||||
void* p1 = kmalloc(64);
|
void* p1 = kmalloc(64);
|
||||||
void* p2 = kmalloc(128);
|
void* p2 = kmalloc(128);
|
||||||
@@ -134,7 +135,7 @@ extern "C" void kernel_main() {
|
|||||||
// pf_print("Welcome to Sylva OS!\n");
|
// pf_print("Welcome to Sylva OS!\n");
|
||||||
serial_write(" Kernel prepared well.\n");
|
serial_write(" Kernel prepared well.\n");
|
||||||
|
|
||||||
// --- Interrupt infrastructure ---
|
// 初始化中断基础设施
|
||||||
serial_write("Sylva: init GDT...\n");
|
serial_write("Sylva: init GDT...\n");
|
||||||
gdt_init();
|
gdt_init();
|
||||||
|
|
||||||
@@ -144,24 +145,31 @@ extern "C" void kernel_main() {
|
|||||||
serial_write("Sylva: init PIC...\n");
|
serial_write("Sylva: init PIC...\n");
|
||||||
pic_init();
|
pic_init();
|
||||||
|
|
||||||
// Register IRQ handler (vector 0x20 = PIC_IRQ_BASE + 0)
|
// 注册 IRQ 处理函数(向量 0x20 = PIC_IRQ_BASE + 0)
|
||||||
idt_set_handler(PIC_IRQ_BASE + 0, irq_handler);
|
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");
|
serial_write("Sylva: init PIT...\n");
|
||||||
pit_init();
|
pit_init();
|
||||||
pit_set_tick_handler(scheduler_tick);
|
pit_set_tick_handler(scheduler_tick);
|
||||||
|
|
||||||
// Enable interrupts
|
// 启用中断
|
||||||
ASM("sti");
|
ASM("sti");
|
||||||
serial_write("Sylva: interrupts enabled\n");
|
serial_write("Sylva: interrupts enabled\n");
|
||||||
|
|
||||||
// --- Multitasking demo ---
|
// 创建多任务演示
|
||||||
serial_write("Sylva: creating tasks...\n");
|
serial_write("Sylva: creating tasks...\n");
|
||||||
|
|
||||||
// Init compositor (allocates back buffer, registers keyboard handler)
|
// 初始化合成器(分配后台缓冲区,注册键盘处理)
|
||||||
layer_init();
|
layer_init();
|
||||||
|
|
||||||
// Create desktop layer (full screen, z=0)
|
// 初始化鼠标光标
|
||||||
|
cursor_init();
|
||||||
|
|
||||||
|
// 创建桌面图层(全屏,z=0)
|
||||||
layer_t* desktop = layer_create("desktop", LAYER_TYPE_DESKTOP, g_gfx.hr, g_gfx.vr);
|
layer_t* desktop = layer_create("desktop", LAYER_TYPE_DESKTOP, g_gfx.hr, g_gfx.vr);
|
||||||
if (desktop) {
|
if (desktop) {
|
||||||
layer_set_z(desktop, 0);
|
layer_set_z(desktop, 0);
|
||||||
@@ -172,7 +180,7 @@ extern "C" void kernel_main() {
|
|||||||
layer_set_pos(desktop, 0, 0);
|
layer_set_pos(desktop, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create window 1 (centered)
|
// 创建窗口 1(居中)
|
||||||
layer_t* win1 = layer_create("window_1", LAYER_TYPE_WINDOW, 300, 200);
|
layer_t* win1 = layer_create("window_1", LAYER_TYPE_WINDOW, 300, 200);
|
||||||
if (win1) {
|
if (win1) {
|
||||||
layer_set_pos(win1, (SSINT32)(g_gfx.hr / 2) - 150, (SSINT32)(g_gfx.vr / 2) - 100);
|
layer_set_pos(win1, (SSINT32)(g_gfx.hr / 2) - 150, (SSINT32)(g_gfx.vr / 2) - 100);
|
||||||
@@ -183,7 +191,7 @@ extern "C" void kernel_main() {
|
|||||||
draw_set_default_target();
|
draw_set_default_target();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create window 2 (offset from center)
|
// 创建窗口 2(偏离中心)
|
||||||
layer_t* win2 = layer_create("window_2", LAYER_TYPE_WINDOW, 250, 180);
|
layer_t* win2 = layer_create("window_2", LAYER_TYPE_WINDOW, 250, 180);
|
||||||
if (win2) {
|
if (win2) {
|
||||||
layer_set_pos(win2, (SSINT32)(g_gfx.hr / 2) - 50, (SSINT32)(g_gfx.vr / 2) - 40);
|
layer_set_pos(win2, (SSINT32)(g_gfx.hr / 2) - 50, (SSINT32)(g_gfx.vr / 2) - 40);
|
||||||
@@ -194,7 +202,7 @@ extern "C" void kernel_main() {
|
|||||||
draw_set_default_target();
|
draw_set_default_target();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compositor task (replaces the old demo tasks)
|
// 合成器任务
|
||||||
task_create("compositor", layer_compositor_task);
|
task_create("compositor", layer_compositor_task);
|
||||||
|
|
||||||
serial_write("Sylva: disk read benchmark...\n");
|
serial_write("Sylva: disk read benchmark...\n");
|
||||||
@@ -220,7 +228,7 @@ extern "C" void kernel_main() {
|
|||||||
serial_write_hex(kbps);
|
serial_write_hex(kbps);
|
||||||
serial_write(" KiB/s)\n");
|
serial_write(" KiB/s)\n");
|
||||||
|
|
||||||
// --- TTF demo ---
|
// TTF 渲染演示
|
||||||
serial_write("Sylva: ttf_open...\n");
|
serial_write("Sylva: ttf_open...\n");
|
||||||
ttf_face_t* face = ttf_open(ttf_buf, ttf_size);
|
ttf_face_t* face = ttf_open(ttf_buf, ttf_size);
|
||||||
if (!face) {
|
if (!face) {
|
||||||
@@ -228,7 +236,7 @@ extern "C" void kernel_main() {
|
|||||||
} else {
|
} else {
|
||||||
serial_write("Sylva: ttf_open OK\n");
|
serial_write("Sylva: ttf_open OK\n");
|
||||||
|
|
||||||
// Create an overlay layer for TTF output (sits above the two demo windows)
|
// 创建 TTF 文本覆盖图层
|
||||||
const UINT32 TL_W = 500, TL_H = 200;
|
const UINT32 TL_W = 500, TL_H = 200;
|
||||||
layer_t* text_layer = layer_create("ttf_text", LAYER_TYPE_WINDOW, TL_W, TL_H);
|
layer_t* text_layer = layer_create("ttf_text", LAYER_TYPE_WINDOW, TL_W, TL_H);
|
||||||
if (text_layer) {
|
if (text_layer) {
|
||||||
@@ -238,7 +246,7 @@ extern "C" void kernel_main() {
|
|||||||
draw_set_target(text_layer->buffer, TL_W, TL_H);
|
draw_set_target(text_layer->buffer, TL_W, TL_H);
|
||||||
draw_rect(0, 0, TL_W - 1, TL_H - 1, clear);
|
draw_rect(0, 0, TL_W - 1, TL_H - 1, clear);
|
||||||
|
|
||||||
// Render at 4 sizes + mixed CJK
|
// 渲染多种字号和中日韩字符
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL white = {255, 255, 255, 0};
|
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 yellow = {255, 240, 80, 0};
|
||||||
EFI_GRAPHICS_OUTPUT_BLT_PIXEL cyan = {80, 220, 255, 0};
|
EFI_GRAPHICS_OUTPUT_BLT_PIXEL cyan = {80, 220, 255, 0};
|
||||||
|
|||||||
+14
-14
@@ -42,7 +42,7 @@ static void heap_expand(UINTN min_size) {
|
|||||||
new_block->size = pages * PAGE_SIZE;
|
new_block->size = pages * PAGE_SIZE;
|
||||||
new_block->next = NULL;
|
new_block->next = NULL;
|
||||||
|
|
||||||
// Add to free list (sorted by address for coalescing)
|
// 添加到空闲链表(按地址排序以便合并)
|
||||||
struct heap_block** prev = &g_heap_free_list;
|
struct heap_block** prev = &g_heap_free_list;
|
||||||
while (*prev && (UINT8*)*prev < (UINT8*)new_block) {
|
while (*prev && (UINT8*)*prev < (UINT8*)new_block) {
|
||||||
prev = &(*prev)->next;
|
prev = &(*prev)->next;
|
||||||
@@ -50,7 +50,7 @@ static void heap_expand(UINTN min_size) {
|
|||||||
new_block->next = *prev;
|
new_block->next = *prev;
|
||||||
*prev = new_block;
|
*prev = new_block;
|
||||||
|
|
||||||
// Try to merge with the previous free block if adjacent
|
// 尝试与前一个空闲块合并(如果相邻)
|
||||||
if (prev != &g_heap_free_list) {
|
if (prev != &g_heap_free_list) {
|
||||||
struct heap_block* prev_block = g_heap_free_list;
|
struct heap_block* prev_block = g_heap_free_list;
|
||||||
while (prev_block->next != new_block) {
|
while (prev_block->next != new_block) {
|
||||||
@@ -104,21 +104,21 @@ void* kmalloc(UINTN size) {
|
|||||||
while (*prev) {
|
while (*prev) {
|
||||||
UINTN block_sz = BLOCK_SIZE(*prev);
|
UINTN block_sz = BLOCK_SIZE(*prev);
|
||||||
if (block_sz >= alloc_size) {
|
if (block_sz >= alloc_size) {
|
||||||
// Found a suitable block
|
// 找到合适的块
|
||||||
struct heap_block* block = *prev;
|
struct heap_block* block = *prev;
|
||||||
|
|
||||||
// Split if remaining space is useful
|
// 如果剩余空间足够则分割
|
||||||
if (block_sz >= alloc_size + MIN_BLOCK_SIZE) {
|
if (block_sz >= alloc_size + MIN_BLOCK_SIZE) {
|
||||||
struct heap_block* split = (struct heap_block*)((UINT8*)block + alloc_size);
|
struct heap_block* split = (struct heap_block*)((UINT8*)block + alloc_size);
|
||||||
split->size = block_sz - alloc_size;
|
split->size = block_sz - alloc_size;
|
||||||
// Insert split into free list
|
// 将分割后的块插入空闲链表
|
||||||
split->next = block->next;
|
split->next = block->next;
|
||||||
block->size = alloc_size | 1;
|
block->size = alloc_size | 1;
|
||||||
*prev = split;
|
*prev = split;
|
||||||
} else {
|
} else {
|
||||||
// Use the whole block
|
// 使用整个块
|
||||||
*prev = block->next;
|
*prev = block->next;
|
||||||
block->size = block_sz | 1; // mark used
|
block->size = block_sz | 1; // 标记为已使用
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > 1024) {
|
if (size > 1024) {
|
||||||
@@ -134,11 +134,11 @@ void* kmalloc(UINTN size) {
|
|||||||
prev = &(*prev)->next;
|
prev = &(*prev)->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Out of memory in current heap — expand
|
// 当前堆空间不足,扩展堆
|
||||||
UINTN expand_size = alloc_size > PAGE_SIZE ? alloc_size : PAGE_SIZE;
|
UINTN expand_size = alloc_size > PAGE_SIZE ? alloc_size : PAGE_SIZE;
|
||||||
heap_expand(expand_size);
|
heap_expand(expand_size);
|
||||||
|
|
||||||
// Retry after expansion
|
// 扩展后重试
|
||||||
return kmalloc(size);
|
return kmalloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +151,14 @@ void kfree(void* ptr) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark as free
|
// 标记为空闲
|
||||||
block->size &= ~(UINTN)1;
|
block->size &= ~(UINTN)1;
|
||||||
|
|
||||||
// Merge with next block if it's free
|
// 与下一个空闲块合并
|
||||||
struct heap_block* next = next_block(block);
|
struct heap_block* next = next_block(block);
|
||||||
if ((UINT8*)next < (UINT8*)g_heap_end) {
|
if ((UINT8*)next < (UINT8*)g_heap_end) {
|
||||||
if (IS_FREE(next)) {
|
if (IS_FREE(next)) {
|
||||||
// Remove next from free list and merge
|
// 从空闲链表中移除 next 并合并
|
||||||
block->size += next->size;
|
block->size += next->size;
|
||||||
struct heap_block** prev = &g_heap_free_list;
|
struct heap_block** prev = &g_heap_free_list;
|
||||||
while (*prev && *prev != next) {
|
while (*prev && *prev != next) {
|
||||||
@@ -168,7 +168,7 @@ void kfree(void* ptr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert block into free list
|
// 将块插入空闲链表
|
||||||
struct heap_block** prev = &g_heap_free_list;
|
struct heap_block** prev = &g_heap_free_list;
|
||||||
while (*prev && (UINT8*)*prev < (UINT8*)block) {
|
while (*prev && (UINT8*)*prev < (UINT8*)block) {
|
||||||
prev = &(*prev)->next;
|
prev = &(*prev)->next;
|
||||||
@@ -201,7 +201,7 @@ void* krealloc(void* ptr, UINTN new_size) {
|
|||||||
UINTN old_size = BLOCK_SIZE(block) - HEADER_SIZE;
|
UINTN old_size = BLOCK_SIZE(block) - HEADER_SIZE;
|
||||||
|
|
||||||
if (old_size >= new_size) {
|
if (old_size >= new_size) {
|
||||||
// Can we split the shrinkage?
|
// 能否分割缩小的部分?
|
||||||
UINTN shrink = old_size - new_size;
|
UINTN shrink = old_size - new_size;
|
||||||
if (shrink >= MIN_BLOCK_SIZE) {
|
if (shrink >= MIN_BLOCK_SIZE) {
|
||||||
block->size = (new_size + HEADER_SIZE) | 1;
|
block->size = (new_size + HEADER_SIZE) | 1;
|
||||||
|
|||||||
+11
-11
@@ -19,7 +19,7 @@ static inline BOOLEAN bitmap_test(UINTN idx) {
|
|||||||
return (g_pmm.bitmap[idx / 8] >> (idx % 8)) & 1;
|
return (g_pmm.bitmap[idx / 8] >> (idx % 8)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean stale entries from free list head
|
// 清理空闲链表头部的过期条目
|
||||||
static void clean_free_list() {
|
static void clean_free_list() {
|
||||||
while (g_pmm.free_list_head != NULL &&
|
while (g_pmm.free_list_head != NULL &&
|
||||||
bitmap_test((UINTN)g_pmm.free_list_head / PAGE_SIZE)) {
|
bitmap_test((UINTN)g_pmm.free_list_head / PAGE_SIZE)) {
|
||||||
@@ -58,7 +58,7 @@ EFI_STATUS pmm_init() {
|
|||||||
|
|
||||||
UINTN entry_count = map_size / desc_size;
|
UINTN entry_count = map_size / desc_size;
|
||||||
|
|
||||||
// First pass: count total pages and find max physical address
|
// 第一遍:统计总页数并找到最大物理地址
|
||||||
UINT64 max_addr = 0;
|
UINT64 max_addr = 0;
|
||||||
UINT64 total_free = 0;
|
UINT64 total_free = 0;
|
||||||
for (UINTN i = 0; i < entry_count; i++) {
|
for (UINTN i = 0; i < entry_count; i++) {
|
||||||
@@ -73,16 +73,16 @@ EFI_STATUS pmm_init() {
|
|||||||
g_pmm.base_addr = 0;
|
g_pmm.base_addr = 0;
|
||||||
g_pmm.max_addr = max_addr;
|
g_pmm.max_addr = max_addr;
|
||||||
|
|
||||||
// How many pages does the bitmap cover?
|
// 位图覆盖的页数
|
||||||
UINTN total_pages = (UINTN)(max_addr / PAGE_SIZE);
|
UINTN total_pages = (UINTN)(max_addr / PAGE_SIZE);
|
||||||
g_pmm.total_pages = total_pages;
|
g_pmm.total_pages = total_pages;
|
||||||
|
|
||||||
// Bitmap size in bytes, rounded up to page boundary
|
// 位图大小(字节),向上取整到页边界
|
||||||
g_pmm.bitmap_size = ((total_pages + 7) / 8);
|
g_pmm.bitmap_size = ((total_pages + 7) / 8);
|
||||||
UINTN bitmap_pages = (g_pmm.bitmap_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
UINTN bitmap_pages = (g_pmm.bitmap_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
g_pmm.bitmap_size = bitmap_pages * PAGE_SIZE; // round to full pages
|
g_pmm.bitmap_size = bitmap_pages * PAGE_SIZE; // round to full pages
|
||||||
|
|
||||||
// Place bitmap at the end of the highest free conventional memory region
|
// 将位图放在最高空闲常规内存区域的末尾
|
||||||
UINT64 bitmap_addr = 0;
|
UINT64 bitmap_addr = 0;
|
||||||
for (UINTN i = 0; i < entry_count; i++) {
|
for (UINTN i = 0; i < entry_count; i++) {
|
||||||
EFI_MEMORY_DESCRIPTOR* desc = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)mem_map + i * desc_size);
|
EFI_MEMORY_DESCRIPTOR* desc = (EFI_MEMORY_DESCRIPTOR*)((UINT8*)mem_map + i * desc_size);
|
||||||
@@ -105,12 +105,12 @@ EFI_STATUS pmm_init() {
|
|||||||
|
|
||||||
g_pmm.bitmap = (UINT8*)(UINTN)bitmap_addr;
|
g_pmm.bitmap = (UINT8*)(UINTN)bitmap_addr;
|
||||||
|
|
||||||
// Init bitmap: mark ALL pages as used (0xFF)
|
// 初始化位图:将所有页标记为已使用
|
||||||
for (UINTN i = 0; i < g_pmm.bitmap_size; i++) {
|
for (UINTN i = 0; i < g_pmm.bitmap_size; i++) {
|
||||||
g_pmm.bitmap[i] = 0xFF;
|
g_pmm.bitmap[i] = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark free pages (EfiConventionalMemory) as free in bitmap
|
// 将空闲页(EfiConventionalMemory)在位图中标记为空闲
|
||||||
g_pmm.free_pages = 0;
|
g_pmm.free_pages = 0;
|
||||||
UINT64 bm_start_page = bitmap_addr / PAGE_SIZE;
|
UINT64 bm_start_page = bitmap_addr / PAGE_SIZE;
|
||||||
UINT64 bm_end_page = (bitmap_addr + g_pmm.bitmap_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
UINT64 bm_end_page = (bitmap_addr + g_pmm.bitmap_size + PAGE_SIZE - 1) / PAGE_SIZE;
|
||||||
@@ -123,19 +123,19 @@ EFI_STATUS pmm_init() {
|
|||||||
UINT64 end_page = start_page + desc->NumberOfPages;
|
UINT64 end_page = start_page + desc->NumberOfPages;
|
||||||
|
|
||||||
for (UINT64 p = start_page; p < end_page; p++) {
|
for (UINT64 p = start_page; p < end_page; p++) {
|
||||||
// Skip bitmap pages
|
// 跳过位图占用的页
|
||||||
if (p >= bm_start_page && p < bm_end_page) continue;
|
if (p >= bm_start_page && p < bm_end_page) continue;
|
||||||
bitmap_clear((UINTN)p);
|
bitmap_clear((UINTN)p);
|
||||||
g_pmm.free_pages++;
|
g_pmm.free_pages++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark bitmap pages as used
|
// 将位图占用的页标记为已使用
|
||||||
for (UINT64 p = bm_start_page; p < bm_end_page; p++) {
|
for (UINT64 p = bm_start_page; p < bm_end_page; p++) {
|
||||||
bitmap_set((UINTN)p);
|
bitmap_set((UINTN)p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reserve low memory (first 4 MB) — UEFI firmware may use it during BS calls
|
// 保留低内存(前 4MB)— 固件可能在 Boot Services 调用期间使用
|
||||||
UINT64 low_reserve_pages = 0x400;
|
UINT64 low_reserve_pages = 0x400;
|
||||||
for (UINT64 p = 0; p < low_reserve_pages && p < g_pmm.total_pages; p++) {
|
for (UINT64 p = 0; p < low_reserve_pages && p < g_pmm.total_pages; p++) {
|
||||||
if (!bitmap_test((UINTN)p)) {
|
if (!bitmap_test((UINTN)p)) {
|
||||||
@@ -144,7 +144,7 @@ EFI_STATUS pmm_init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build free list by linking free pages
|
// 通过链接空闲页构建空闲链表
|
||||||
g_pmm.free_list_head = NULL;
|
g_pmm.free_list_head = NULL;
|
||||||
void* prev = NULL;
|
void* prev = NULL;
|
||||||
for (UINTN i = 0; i < entry_count; i++) {
|
for (UINTN i = 0; i < entry_count; i++) {
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
#include <scheduler.h>
|
#include <scheduler.h>
|
||||||
#include <idt.h>
|
#include <interrupt/idt.h>
|
||||||
#include <pic.h>
|
#include <interrupt/pic.h>
|
||||||
#include <memory/heap.h>
|
#include <memory/heap.h>
|
||||||
#include <memory/pmm.h>
|
#include <memory/pmm.h>
|
||||||
#include <common.h>
|
#include <common.h>
|
||||||
#include <serial.h>
|
#include <serial.h>
|
||||||
|
|
||||||
// Assembly: context_switch(UINT64* old_rsp, UINT64 new_rsp)
|
// 汇编函数:context_switch(UINT64* old_rsp, UINT64 new_rsp)
|
||||||
extern "C" void context_switch(UINT64* old_rsp, UINT64 new_rsp);
|
extern "C" void context_switch(UINT64* old_rsp, UINT64 new_rsp);
|
||||||
|
|
||||||
static task_t g_tasks[TASK_MAX];
|
static task_t g_tasks[TASK_MAX];
|
||||||
static UINT32 g_task_count = 0;
|
static UINT32 g_task_count = 0;
|
||||||
static task_t* g_current = NULL;
|
static task_t* g_current = NULL;
|
||||||
static task_t* g_task_list = NULL; // circular linked list head
|
static task_t* g_task_list = NULL; // 循环链表头
|
||||||
|
|
||||||
// Trampoline: first thing a new task runs after context_switch.
|
// 跳板函数:新任务在 context_switch 后首先执行的函数
|
||||||
static void (*g_task_entries[TASK_MAX])(void);
|
static void (*g_task_entries[TASK_MAX])(void);
|
||||||
|
|
||||||
extern "C" void task_entry_trampoline() {
|
extern "C" void task_entry_trampoline() {
|
||||||
@@ -37,7 +37,7 @@ task_t* task_create(const char* name, void (*entry)(void)) {
|
|||||||
|
|
||||||
g_task_entries[id] = entry;
|
g_task_entries[id] = entry;
|
||||||
|
|
||||||
// Allocate kernel stack
|
// 分配内核栈
|
||||||
UINTN stack_pages = TASK_STACK_SIZE / PAGE_SIZE;
|
UINTN stack_pages = TASK_STACK_SIZE / PAGE_SIZE;
|
||||||
void* stack = pmm_alloc_pages(stack_pages);
|
void* stack = pmm_alloc_pages(stack_pages);
|
||||||
if (!stack) {
|
if (!stack) {
|
||||||
@@ -52,24 +52,21 @@ task_t* task_create(const char* name, void (*entry)(void)) {
|
|||||||
task->stack_base = stack;
|
task->stack_base = stack;
|
||||||
task->time_slice = TIME_SLICE_DEFAULT;
|
task->time_slice = TIME_SLICE_DEFAULT;
|
||||||
|
|
||||||
// Copy name
|
// 复制任务名称
|
||||||
str_copy(task->name, name, TASK_NAME_LEN);
|
str_copy(task->name, name, TASK_NAME_LEN);
|
||||||
|
|
||||||
// Set up initial stack for first context_switch into this task.
|
// 设置首次 context_switch 时的初始栈
|
||||||
// Stack grows downward. context_switch will pop 6 regs then ret.
|
// 栈向下增长。context_switch 会弹出 6 个寄存器然后 ret。
|
||||||
//
|
//
|
||||||
// Layout (high addr -> low addr):
|
// 布局(高地址 → 低地址):
|
||||||
// [stack + TASK_STACK_SIZE] <- top
|
// [stack + TASK_STACK_SIZE] <- 栈顶
|
||||||
// return addr = task_entry_trampoline (ret goes here)
|
// 返回地址 = task_entry_trampoline(ret 跳转到这里)
|
||||||
// rbx = 0
|
// rbx = 0
|
||||||
// rbp = 0
|
// rbp = 0
|
||||||
// r12 = 0
|
// r12 = 0
|
||||||
// r13 = 0
|
// r13 = 0
|
||||||
// r14 = 0
|
// r14 = 0
|
||||||
// r15 = 0 <- RSP points here initially
|
// r15 = 0 <- RSP 初始指向这里
|
||||||
//
|
|
||||||
// When preempted by timer IRQ, the ISR stub saves a full trap_frame
|
|
||||||
// on the task's stack — that layout is only created by hardware+ISR.
|
|
||||||
//
|
//
|
||||||
UINT64* sp = (UINT64*)((UINT8*)stack + TASK_STACK_SIZE);
|
UINT64* sp = (UINT64*)((UINT8*)stack + TASK_STACK_SIZE);
|
||||||
|
|
||||||
@@ -84,7 +81,7 @@ task_t* task_create(const char* name, void (*entry)(void)) {
|
|||||||
|
|
||||||
task->rsp = (UINT64)sp;
|
task->rsp = (UINT64)sp;
|
||||||
|
|
||||||
// Insert into circular linked list
|
// 插入循环链表
|
||||||
if (g_task_list == NULL) {
|
if (g_task_list == NULL) {
|
||||||
task->next = task;
|
task->next = task;
|
||||||
g_task_list = task;
|
g_task_list = task;
|
||||||
@@ -103,7 +100,7 @@ task_t* task_create(const char* name, void (*entry)(void)) {
|
|||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next READY task in the circular list, starting from g_current->next
|
// 在循环链表中查找下一个就绪任务
|
||||||
static task_t* find_next_ready(void) {
|
static task_t* find_next_ready(void) {
|
||||||
if (g_current == NULL || g_task_list == NULL) return NULL;
|
if (g_current == NULL || g_task_list == NULL) return NULL;
|
||||||
|
|
||||||
@@ -117,7 +114,7 @@ static task_t* find_next_ready(void) {
|
|||||||
next = next->next;
|
next = next->next;
|
||||||
} while (next != start);
|
} while (next != start);
|
||||||
|
|
||||||
return NULL; // no READY tasks
|
return NULL; // 没有就绪任务
|
||||||
}
|
}
|
||||||
|
|
||||||
void yield(void) {
|
void yield(void) {
|
||||||
@@ -137,27 +134,27 @@ void yield(void) {
|
|||||||
context_switch(&cur->rsp, next->rsp);
|
context_switch(&cur->rsp, next->rsp);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer tick handler — called from PIT IRQ 0
|
// 定时器 tick 处理 — 由 PIT IRQ 0 调用
|
||||||
void scheduler_tick(void) {
|
void scheduler_tick(void) {
|
||||||
if (g_current == NULL) return;
|
if (g_current == NULL) return;
|
||||||
|
|
||||||
// Decrement time slice
|
// 递减时间片
|
||||||
if (g_current->time_slice > 0) {
|
if (g_current->time_slice > 0) {
|
||||||
g_current->time_slice--;
|
g_current->time_slice--;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If time slice expired, preempt
|
// 时间片用完则抢占
|
||||||
if (g_current->time_slice == 0) {
|
if (g_current->time_slice == 0) {
|
||||||
task_t* cur = g_current;
|
task_t* cur = g_current;
|
||||||
task_t* next = find_next_ready();
|
task_t* next = find_next_ready();
|
||||||
|
|
||||||
if (next == NULL || next == cur) {
|
if (next == NULL || next == cur) {
|
||||||
// No other task ready, or only this task — reload time slice
|
// 没有其他就绪任务,或仅此一个 — 重置时间片
|
||||||
cur->time_slice = TIME_SLICE_DEFAULT;
|
cur->time_slice = TIME_SLICE_DEFAULT;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preempt
|
// 抢占
|
||||||
cur->state = TASK_STATE_READY;
|
cur->state = TASK_STATE_READY;
|
||||||
cur->time_slice = TIME_SLICE_DEFAULT;
|
cur->time_slice = TIME_SLICE_DEFAULT;
|
||||||
next->state = TASK_STATE_RUNNING;
|
next->state = TASK_STATE_RUNNING;
|
||||||
@@ -174,7 +171,7 @@ void scheduler_run(void) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find first READY task
|
// 查找第一个就绪任务
|
||||||
task_t* start = g_task_list->next;
|
task_t* start = g_task_list->next;
|
||||||
task_t* t = start;
|
task_t* t = start;
|
||||||
do {
|
do {
|
||||||
@@ -197,12 +194,12 @@ void scheduler_run(void) {
|
|||||||
serial_write(t->name);
|
serial_write(t->name);
|
||||||
serial_write("'\n");
|
serial_write("'\n");
|
||||||
|
|
||||||
// First context switch — switch to the task's stack
|
// 首次上下文切换 — 切换到任务栈
|
||||||
// This will never return (until all tasks terminate)
|
// 此后不会返回(直到所有任务终止)
|
||||||
UINT64 dummy_rsp;
|
UINT64 dummy_rsp;
|
||||||
context_switch(&dummy_rsp, t->rsp);
|
context_switch(&dummy_rsp, t->rsp);
|
||||||
|
|
||||||
// We only return here when ALL tasks are terminated
|
// 只有所有任务终止后才会返回到这里
|
||||||
serial_write("SCHED: all tasks finished\n");
|
serial_write("SCHED: all tasks finished\n");
|
||||||
while (1) ASM ("hlt");
|
while (1) ASM ("hlt");
|
||||||
}
|
}
|
||||||
@@ -216,10 +213,10 @@ void task_exit(void) {
|
|||||||
|
|
||||||
g_current->state = TASK_STATE_TERMINATED;
|
g_current->state = TASK_STATE_TERMINATED;
|
||||||
|
|
||||||
// Yield to next task — we won't come back
|
// 让出 CPU 给下一个任务 — 不会回来
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
// Should never reach here
|
// 不应到达此处
|
||||||
while (1) ASM ("hlt");
|
while (1) ASM ("hlt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ void serial_write_hex(UINTN val) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char serial_read_char() {
|
char serial_read_char() {
|
||||||
// 后面可能用的上,比如远程调试?
|
|
||||||
if (!g_serial.SerialIo) return 0;
|
if (!g_serial.SerialIo) return 0;
|
||||||
char c = 0;
|
char c = 0;
|
||||||
UINTN size = 1;
|
UINTN size = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user