Skip to content

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.rspub mod serial;
kernel/core/lib.rsserial_log! macro (#[macro_export]) + Serial::init() أول شيء في kernel_main
kernel/mm/mod.rsscan شامل لجميع Multiboot2 tags + طباعة Framebuffer Tag8 تشخيصياً
tools/build.shUEFI 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/8

GRUB يُعطي 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.rsFB_VIRT_BASE = 0xE000_0000 (3.5GB، PDP[3])، PTE_PCD flag (bit 4)
kernel/core/lib.rsdraw_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.rspub mod font;
kernel/core/lib.rsFbConsole 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 != 0

FbConsole 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 المضافة ​

الرقمالاسمالوظيفة
7SYS_DRAWمحتفظ — VGA text mode (backward compat)
9SYS_GET_FB_INFOيكتب [width, height, pitch, fmt] في ptr userspace
10SYS_DRAW_FBblit raw bytes من userspace → FB مع validate_user_buffer
11SYS_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::MAX

qet4_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

⚠️ تحذيرات تقنية لا تُنسى ​

  1. BIOS legacy = type=2 دائماً — يجب UEFI/OVMF فقط
  2. bpp=24 (3 bytes/pixel) — كل كود يفترض 4 bytes سيكسر pixel alignment
  3. pitch ≠ width × 3 — استخدم pitch دائماً للانتقال بين الصفوف
  4. addr=0x80000000 خارج identity map → لا تقرأ/تكتب إلا عبر virt=0xE0000000
  5. reserved في Mb2FramebufferTag = u16 (2 bytes، offset 12) → Color Info عند offset 31→32
  6. use crate::serial_log; مطلوب في كل موديول منفصل
  7. MAX_PAGES PMM لا يغطي FB frame → لا تستدعي mark_used للـ phys FB
  8. FbConsole.scroll(): core::ptr::copy (يتعامل مع overlap صحيح بعكس memcpy)
  9. 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

تم تطويره بحب بواسطة مجتمع Qtoom.