Milestone: Framebuffer Implementation — Phases 1–4
التاريخ: 2026-09-29 → 2026-09-30
وقت الإنشاء: 2026-09-30 14:54 +03:00
المشروع: QOS / Qet4 Microkernel — Linear Framebuffer (عبر UEFI/OVMF)
🧭 من أين توقفنا؟
آخر milestone كان 2026-09-28_23-35_phase5_techdebt_complete.md:
- اكتمل Phase 5 (Tech Debt): إصلاح ABI، syscall arg clobbering، display_server VGA
- النظام يعمل على VGA text mode (0xB8000) فقط
- لا يوجد framebuffer حقيقي — الهدف التالي هو الانتقال من VGA → Linear Framebuffer
✅ Phase 1 — Serial Logging + MB2 Framebuffer Diagnostic
المشكلة
GRUB كان يُهيئ display mode كـ type=2 (VGA text) عبر Legacy BIOS — لا framebuffer حقيقي.
ما تم
| الملف | التغيير |
|---|---|
kernel/arch/x86_64/serial.rs | جديد — COM1 UART driver (115200 baud, 8N1, loopback test حُذف) |
kernel/arch/x86_64/mod.rs | pub mod serial; |
kernel/core/lib.rs | serial_log! macro (#[macro_export]) + Serial::init() أول شيء في kernel_main |
kernel/mm/mod.rs | scan شامل لجميع Multiboot2 tags + طباعة Framebuffer Tag8 تشخيصياً |
tools/build.sh | UEFI grub.cfg: insmod all_video + gfxmode=auto + terminal_output gfxterm + gfxpayload=keep |
tools/run.sh | -bios /usr/share/ovmf/OVMF.fd + -display gtk (UEFI/OVMF) |
النتيجة
[mm] FB: addr=0x80000000 pitch=2400 800x600 bpp=24 type=1 tag_sz=38
[mm] FB: color r=16/8 g=8/8 b=0/8GRUB يُعطي type=1 (RGB Direct) عبر UEFI/OVMF — خلاف Legacy BIOS
دروس مستخلصة
- BIOS legacy دائماً يعطي type=2 — لازم UEFI/OVMF لـ efifb
use crate::serial_log;مطلوب في كل موديول منفصل (#[macro_export]لا يستورد تلقائياً)- Serial loopback test يُحذف من init — QEMU يتسامح لكن hardware حقيقي قد يفشل
✅ Phase 2 — Framebuffer Memory Mapping
المشكلة الحرجة
reservedفيMb2FramebufferTag=u16(2 bytes) وليسu8— Color Info عند offset 32 وليس 31- FB عند
phys=0x80000000(2GB) خارج identity map (0–2GB) - MAX_PAGES = 32768 (128MB فقط) — لا يغطي frame 131072
ما تم
| الملف | التغيير |
|---|---|
kernel/mm/mod.rs | إصلاح reserved: u8 → u16، Color Info offset صحيح، FramebufferInfo struct، apply_framebuffer_map()، get_framebuffer() |
kernel/mm/vmm.rs | FB_VIRT_BASE = 0xE000_0000 (3.5GB، PDP[3])، PTE_PCD flag (bit 4) |
kernel/core/lib.rs | draw_test_square() — مربع 64×64 أحمر اختباري |
النتيجة المؤكدة
[mm] FB mapped: phys=0x80000000 → virt=0xe0000000 pages=352 bpp=24 800x600
color r=16/8 g=8/8 b=0/8 → r_byte=2, g_byte=1, b_byte=0 (RGB24)
[qet4] FB test square drawn at virt=0xe0000000بيانات تقنية مهمة
phys_addr = 0x80000000 (حافة identity map بالضبط)
pitch = 2400 (800 × 3 bytes/pixel)
bpp = 24 (NOT 32!)
format = BGR24 في الذاكرة (R=byte[2], G=byte[1], B=byte[0])
virt_base = 0xE000_0000 (PDP[3]: 3.5GB kernel virtual)
pages = 352 (352 × 4KB = 1,441,792 bytes = 1.44MB)
PTE flags = PRESENT | WRITABLE | PTE_PCD✅ Phase 3 — Bitmap Font Renderer (FbConsole)
ما تم
| الملف | التغيير |
|---|---|
kernel/drivers/font_data.psf | جديد — Terminus16 PSF1 (8×16، 256 glyphs، مضغوط 5670 byte → فك ضغط) |
kernel/drivers/font.rs | جديد — PSF1 renderer: draw_char() + FbConsole (scroll، newline، color، clear) |
kernel/drivers/mod.rs | pub mod font; |
kernel/core/lib.rs | FbConsole init + welcome screen متعدد الألوان بدلاً من test square |
كيف يعمل PSF1 Reader
glyph_offset = 4 (header) + char_index * 16
bits = FONT_DATA[glyph_offset + row]
pixel_on = (bits >> (7 - col)) & 1 != 0FbConsole API
rust
let mut console = FbConsole::new(fb);
console.fg = (0x00, 0xD4, 0xFF); // cyan
console.bg = (0x0A, 0x0E, 0x1A); // navy-black
console.clear(); // مسح الشاشة
console.print("text"); // طباعة مع newline + scrollالنتيجة (لقطة شاشة مؤكدة)
Qet4 Microkernel v0.1 | Phase 3: Framebuffer ← cyan
FB: 800x600 bpp=24 virt=0xe0000000 ← white
Kernel booted successfully! ← gold #FFE060
Waiting for userspace services... ← whiteخلفية: #0A0E1A (navy-black)، خط: Terminus16 8×16 ✅
✅ Phase 4 — SYS_DRAW_FB + SYS_GET_FB_INFO + display_server
Syscalls المضافة
| الرقم | الاسم | الوظيفة |
|---|---|---|
| 7 | SYS_DRAW | محتفظ — VGA text mode (backward compat) |
| 9 | SYS_GET_FB_INFO | يكتب [width, height, pitch, fmt] في ptr userspace |
| 10 | SYS_DRAW_FB | blit raw bytes من userspace → FB مع validate_user_buffer |
| 11 | SYS_DRAW_CHAR_FB | رسم حرف ASCII عبر kernel font (Terminus16) |
توقيع السجلات
SYS_GET_FB_INFO (9):
rdi = ptr → [u32; 4]: [width, height, pitch, bytes_pp|r_pos<<8|g_pos<<16|b_pos<<24]
rax ← pitch * height | u64::MAX عند الفشل
SYS_DRAW_FB (10):
rdi = src_ptr (user), rsi = dst_offset, rdx = len
rax ← 0 | u64::MAX | u64::MAX-1 (overflow) | u64::MAX-2 (ENODEV)
SYS_DRAW_CHAR_FB (11):
rdi = ch | (x<<16) | (y<<32)
rsi = fg: R|(G<<8)|(B<<16)
rdx = bg: R|(G<<8)|(B<<16)
rax ← 0 | u64::MAXqet4_api API المضاف
rust
pub struct FbInfo { width, height, pitch, fmt }
impl FbInfo { bytes_pp(), r_pos(), g_pos(), b_pos(), r_byte(), ... }
pub fn get_fb_info(out: &mut FbInfo) -> bool
pub fn draw_fb(src: &[u8], dst_offset: usize) -> u64
pub fn draw_char_fb(ch: u8, x: usize, y: usize, fg: (u8,u8,u8), bg: (u8,u8,u8)) -> u64
pub fn draw_str_fb(s: &str, x: usize, y: usize, ...) -> usize
pub fn fill_fb_row(fb: &FbInfo, row: usize, color: (u8,u8,u8), row_buf: &mut [u8])display_server Phase 4
- يستدعي
get_fb_info()عند الإقلاع - يرسم title bar (أزرق
#005599) + background (#0A0E1A) صف بصف (stack 2400 bytes) - يرسم النص عبر
draw_char_fbبدلاً من VGA - VGA fallback إذا لم يتوفر FB
DISP_PRINT→ pixel coordinates:(col*8, row*16)- VGA color palette → RGB mapping جاهز
📁 الملفات المتأثرة (ملخص)
kernel/arch/x86_64/
serial.rs ← جديد Phase 1
mod.rs ← pub mod serial
kernel/core/
lib.rs ← serial_log!, FbConsole init, draw_test_square (P2→P3)
kernel/mm/
mod.rs ← apply_framebuffer_map, FramebufferInfo, get_framebuffer
vmm.rs ← FB_VIRT_BASE, PTE_PCD
kernel/drivers/
mod.rs ← pub mod font
font.rs ← جديد: PSF1 renderer, FbConsole
font_data.psf ← جديد: Terminus16 8×16
kernel/ipc/
mod.rs ← SYS_GET_FB_INFO(9), SYS_DRAW_FB(10), SYS_DRAW_CHAR_FB(11)
qet4_api/src/
lib.rs ← FbInfo struct, get_fb_info, draw_fb, draw_char_fb, draw_str_fb, fill_fb_row
services/display_server/src/
main.rs ← Phase 4 rewrite: FB UI, VGA fallback, vga_color_to_rgb palette
tools/
build.sh ← UEFI grub.cfg (gfxterm + gfxpayload=keep)
run.sh ← OVMF + GTK display⚠️ تحذيرات تقنية لا تُنسى
- BIOS legacy = type=2 دائماً — يجب UEFI/OVMF فقط
- bpp=24 (3 bytes/pixel) — كل كود يفترض 4 bytes سيكسر pixel alignment
- pitch ≠ width × 3 — استخدم
pitchدائماً للانتقال بين الصفوف - addr=0x80000000 خارج identity map → لا تقرأ/تكتب إلا عبر
virt=0xE0000000 reservedفي Mb2FramebufferTag = u16 (2 bytes، offset 12) → Color Info عند offset 31→32use crate::serial_log;مطلوب في كل موديول منفصل- MAX_PAGES PMM لا يغطي FB frame → لا تستدعي
mark_usedللـ phys FB - FbConsole.scroll():
core::ptr::copy(يتعامل مع overlap صحيح بعكس memcpy) - row_buf على الـ stack (2400 bytes max للـ 800x24bpp) — userspace stack = 16KB كافية
🔮 Phase 5 (التالي)
الهدف: Window Compositor protocol
display_server: يُضيف SYS_MAP_WINDOW
- يسمح لـ app بـ mmap منطقة للرسم
- compositor يدمج المناطق على FB
- Z-order (layering) للنوافذ
أو البديل الأبسط:
display_server: يُضيف DISP_BLIT message
- app يرسل: x, y, w, h, pixel_data_ptr
- display_server يرسمها عبر SYS_DRAW_FB