diff --git a/backend/app/services/qemu_manager.py b/backend/app/services/qemu_manager.py index 1bc7add8..c8018256 100644 --- a/backend/app/services/qemu_manager.py +++ b/backend/app/services/qemu_manager.py @@ -148,6 +148,31 @@ PI_CONFIGS: dict[str, dict] = { # that still send the legacy "start_pi" message without a board field. DEFAULT_PI_BOARD = 'raspberry-pi-3' +# Every key a profile must carry — the boot path reads exactly these. +_PI_PROFILE_KEYS = frozenset( + {'qemu', 'cpu', 'smp', 'memory', 'image_set', 'kernel', 'initramfs', + 'rootfs', 'bus'} +) + + +def register_pi_board_profile(board_type: str, cfg: dict) -> None: + """Register (or override) a QEMU-Linux board profile at runtime. + + Seam for private overlays to add board profiles (same shape as the + ``PI_CONFIGS`` entries) without the OSS tree carrying their names — + e.g. an ARM64 SBC that boots the generic arm64 image set with a + different -cpu model. Must be called before the board's first + ``start_instance`` (overlay registration time is fine). + """ + missing = _PI_PROFILE_KEYS - cfg.keys() + if missing: + raise ValueError( + f'pi board profile {board_type!r} missing keys: {sorted(missing)}' + ) + PI_CONFIGS[board_type] = dict(cfg) + logger.info('registered QEMU board profile %r (cpu=%s, image_set=%s)', + board_type, cfg['cpu'], cfg['image_set']) + # ── Pluggable I2C/SPI/UART dispatcher ──────────────────────────────────── # diff --git a/frontend/src/lib/proBoardRegistry.ts b/frontend/src/lib/proBoardRegistry.ts index 841d9228..a844a532 100644 --- a/frontend/src/lib/proBoardRegistry.ts +++ b/frontend/src/lib/proBoardRegistry.ts @@ -21,6 +21,7 @@ import { BOARD_KIND_LABELS, BOARD_KIND_FQBN, BOARD_SUPPORTS_MICROPYTHON, + registerPiFamilyKind, type BoardKind, } from '../types/board'; @@ -54,6 +55,10 @@ export interface ProBoardDef { * through the ESP32 bridge path and picks the machine/engine type. Omit for * boards that provide createSimulator (RP2350 class) or AVR/RP2040. */ esp32Family?: 'esp32' | 'esp32-s3' | 'esp32-c3' | 'esp32-c6'; + /** QEMU-Linux run-path routing: route this kind through the Raspberry Pi + * bridge (backend qemu WebSocket, VFS panel, boot terminal). The overlay + * must also register a matching backend profile for the kind. */ + piFamily?: boolean; /** Canvas renderer. Receives the placed board's props; return a React node. * When omitted, the canvas renders ``. */ render?: (props: { id: string; x: number; y: number; running: boolean }) => React.ReactNode; @@ -120,6 +125,7 @@ export function registerProBoards(defs: ProBoardDef[]): void { (BOARD_KIND_LABELS as Record)[kind] = def.label; (BOARD_KIND_FQBN as Record)[kind] = def.fqbn; if (def.supportsMicroPython) BOARD_SUPPORTS_MICROPYTHON.add(kind); + if (def.piFamily) registerPiFamilyKind(def.kind); } version++; for (const l of listeners) l(); diff --git a/frontend/src/types/board.ts b/frontend/src/types/board.ts index dc69f6d1..2eda2385 100644 --- a/frontend/src/types/board.ts +++ b/frontend/src/types/board.ts @@ -32,11 +32,24 @@ export type BoardKind = export type LanguageMode = 'arduino' | 'micropython' | 'espidf'; -/** True for every Raspberry Pi backed by the QEMU bridge (Zero, 1, 2, 3, 4, 5). +/** Extra QEMU-Linux board kinds registered at runtime by a private overlay + * (proBoardRegistry defs with `piFamily: true`). They route through the same + * backend qemu bridge, VFS panel and terminal UX as the Raspberry Pi family. */ +const PI_FAMILY_EXTRA_KINDS = new Set(); + +export function registerPiFamilyKind(kind: string): void { + PI_FAMILY_EXTRA_KINDS.add(kind); +} + +/** True for every Raspberry Pi backed by the QEMU bridge (Zero, 1, 2, 3, 4, 5) + * and any overlay-registered QEMU-Linux board (registerPiFamilyKind). * Excludes the Pico boards (RP2040, browser emulation). */ export function isPiBoardKind(kind: BoardKind | string): boolean { - return typeof kind === 'string' && kind.startsWith('raspberry-pi-') - && kind !== 'raspberry-pi-pico'; + if (typeof kind !== 'string') return false; + return ( + (kind.startsWith('raspberry-pi-') && kind !== 'raspberry-pi-pico') || + PI_FAMILY_EXTRA_KINDS.has(kind) + ); } /** True for STM32 boards backed by the QEMU bridge (libqemu-arm via