refactor: apply newtypes throughout userspace API and display types

Every syscall stub now uses proper types from types/ — CapSlot,
EntryPoint, StackPointer, VirtualAddress, PageCount, ProcessId,
PermissionSet, Ticks. The compiler prevents swapping entry/stack,
passing a ProcessId where a CapSlot is expected, or using an
address as a page count.

New display types in types/display.rs:
  - Color(u32) with rgb() constructor
  - ScreenCoord(u16) for x/y positions
  - Dimension(u16) for width/height

Updated throughout:
  - userspace/syscall.rs: all params typed, returns Option instead
    of sentinel usize::MAX
  - server-framework: endpoint param is CapSlot
  - port-framebuffer: trait uses Color, ScreenCoord, Dimension
  - hw-virtio: DmaAddrs uses PhysicalAddress/VirtualAddress,
    GPU commands use Dimension
  - All servers, drivers, bins, apps updated for new signatures
  - permission-manager: process field uses ProcessId
  - PermissionSet: added bits() accessor

89 tests pass, full QEMU boot verified.
This commit is contained in:
2026-10-18 13:45:40 +02:00
parent 3a0395453b
commit 7c7e3b8748
42 changed files with 416 additions and 307 deletions

View File

@@ -1,14 +1,15 @@
use crate::protocol::{DisplayRequest, DisplayResponse};
use server_framework::{Decode, Encode};
use types::display::{Color, Dimension, ScreenCoord};
#[test]
fn draw_rect_roundtrip() {
let req = DisplayRequest::DrawRect {
x: 10,
y: 20,
w: 100,
h: 50,
color: 0xFF0000,
x: ScreenCoord::new(10),
y: ScreenCoord::new(20),
w: Dimension::new(100),
h: Dimension::new(50),
color: Color::from_raw(0xFF0000),
};
let words = req.encode();
let decoded = DisplayRequest::decode(words).unwrap();
@@ -17,7 +18,7 @@ fn draw_rect_roundtrip() {
#[test]
fn clear_roundtrip() {
let req = DisplayRequest::Clear { color: 0x00FF00 };
let req = DisplayRequest::Clear { color: Color::from_raw(0x00FF00) };
let words = req.encode();
let decoded = DisplayRequest::decode(words).unwrap();
assert_eq!(decoded, req);
@@ -40,8 +41,8 @@ fn get_dimensions_roundtrip() {
#[test]
fn dimensions_response_roundtrip() {
let resp = DisplayResponse::Dimensions {
width: 320,
height: 240,
width: Dimension::new(320),
height: Dimension::new(240),
};
let words = resp.encode();
let decoded = DisplayResponse::decode(words).unwrap();

View File

@@ -2,20 +2,21 @@ use driver_framebuffer_mock::MockFramebuffer;
use crate::protocol::{DisplayRequest, DisplayResponse};
use crate::server::DisplayServer;
use server_framework::Server;
use types::display::{Color, Dimension, ScreenCoord};
fn test_server() -> DisplayServer<MockFramebuffer> {
DisplayServer::new(MockFramebuffer::new(320, 240))
DisplayServer::new(MockFramebuffer::new(Dimension::new(320), Dimension::new(240)))
}
#[test]
fn draw_rect_writes_pixels() {
let mut server = test_server();
let resp = server.handle(DisplayRequest::DrawRect {
x: 0,
y: 0,
w: 4,
h: 3,
color: 0xFF,
x: ScreenCoord::new(0),
y: ScreenCoord::new(0),
w: Dimension::new(4),
h: Dimension::new(3),
color: Color::from_raw(0xFF),
});
assert_eq!(resp, DisplayResponse::Ok);
assert_eq!(server.framebuffer().pixel_count(), 12);
@@ -25,13 +26,13 @@ fn draw_rect_writes_pixels() {
fn clear_resets_pixels() {
let mut server = test_server();
server.handle(DisplayRequest::DrawRect {
x: 0,
y: 0,
w: 10,
h: 10,
color: 0xFF,
x: ScreenCoord::new(0),
y: ScreenCoord::new(0),
w: Dimension::new(10),
h: Dimension::new(10),
color: Color::from_raw(0xFF),
});
server.handle(DisplayRequest::Clear { color: 0 });
server.handle(DisplayRequest::Clear { color: Color::from_raw(0) });
assert_eq!(server.framebuffer().pixel_count(), 0);
}
@@ -50,8 +51,8 @@ fn get_dimensions_returns_size() {
assert_eq!(
resp,
DisplayResponse::Dimensions {
width: 320,
height: 240
width: Dimension::new(320),
height: Dimension::new(240),
}
);
}
@@ -60,16 +61,16 @@ fn get_dimensions_returns_size() {
fn draw_rect_correct_pixel_positions() {
let mut server = test_server();
server.handle(DisplayRequest::DrawRect {
x: 5,
y: 10,
w: 2,
h: 2,
color: 0xAB,
x: ScreenCoord::new(5),
y: ScreenCoord::new(10),
w: Dimension::new(2),
h: Dimension::new(2),
color: Color::from_raw(0xAB),
});
let fb = server.framebuffer();
assert_eq!(fb.pixel_count(), 4);
assert_eq!(fb.pixel_at(0), (5, 10, 0xAB));
assert_eq!(fb.pixel_at(1), (6, 10, 0xAB));
assert_eq!(fb.pixel_at(2), (5, 11, 0xAB));
assert_eq!(fb.pixel_at(3), (6, 11, 0xAB));
assert_eq!(fb.pixel_at(0), (ScreenCoord::new(5), ScreenCoord::new(10), Color::from_raw(0xAB)));
assert_eq!(fb.pixel_at(1), (ScreenCoord::new(6), ScreenCoord::new(10), Color::from_raw(0xAB)));
assert_eq!(fb.pixel_at(2), (ScreenCoord::new(5), ScreenCoord::new(11), Color::from_raw(0xAB)));
assert_eq!(fb.pixel_at(3), (ScreenCoord::new(6), ScreenCoord::new(11), Color::from_raw(0xAB)));
}