#!/usr/bin/env python3 """s06 - inject a service: add an RM engine without rebuilding the firmware. Real scenario (Handoff-vGPU-IO.md PART 92 ADDENDUM 5-11, 2026-10-02): the P6 work wired guest-originated CE copies through the real engine; every change to the service/wiring path cost a kernel rebuild plus a supervised physical boot cycle (P6a/b/c, ~5-8 min each, one device-write experiment per cycle) and was only accepted after guest smoke ``ALL OK 64/64``. docs/12-INJECTION-SDK.md defines the in-simulator equivalent: load a position-independent service blob and register it with the firmware's dispatch table (commands 16..23). Analog: load ``sdk/build/injected_demo.elf`` into slot 6, invoke it directly (Frida NativeFunction) and through the firmware mailbox, and record the ``service_injected`` evidence event. No kernel rebuild, no hardware. """ from __future__ import annotations import os try: # package import (tests) or direct script execution (run_all) from . import _common as C except ImportError: import sys as _sys _sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import _common as C def run() -> dict: import greeneye as ge from greeneye.inject import invoke_remote, invoke_via_firmware, load_service backend = C.choose_backend("native") out = C.artifact_dir("s06_inject_service") commands = [ 'load_service(s, "sdk/build/injected_demo.elf", slot=6)', "invoke_remote(s, svc, cmd=1, a0=0x41) # debugger-side call", "invoke_via_firmware(s, svc, cmd=1, a0=0x41) # mailbox cmd=16", "read gsp_ctrl.result / handlers[6]", ] scenario = C.scenario( ids=[ "Handoff-vGPU-IO.md PART 92 ADDENDUM 5-11 (2026-10-02): P6 service/wiring rungs", "PART 92 ADDENDUM 6 (2026-10-02): p6run7 first real engine copy after service wiring", "docs/12-INJECTION-SDK.md: blob/ABI contract for injecting RM services", ], baseline=( "each P6 rung was a kernel rebuild plus a supervised physical cycle " "(~5-8 min boots; P6a->P6c spanned ~02:20-08:30) with fail-safe " "release discipline after every run" ), projection=( "on real GSP-RM the registry is the RM service table (M5), gated on " "H2.2; the load/register/invoke/observe shape is identical to the " "demo handler-table slot" ), blocked=True, device="H2.2 device model + M5 RM service registry", ) C.render_banner( "s06_inject_service", "Can a new service be loaded, registered and invoked without rebuilding the firmware?", "guest-originated CE service wiring (P6a-P6c): kernel rebuild + supervised boot per rung", scenario["static_baseline"], commands, ) if not os.path.isfile(C.SDK_ELF): payload = { "success": False, "skipped": True, "failure": "sdk/build/injected_demo.elf not built (run: make sdk)", "backend": backend, "real_case": scenario, } C.write_json(os.path.join(out, "inject.json"), payload) return payload session_dir = C.session_dir(out) session = ge.launch(kernel=C.DEMO_ELF, backend=backend, record=session_dir, name="vd-s06") try: ctrl = session.symbols.lookup("gsp_ctrl") session.run(duration=0.25) service = load_service(session, C.SDK_ELF, slot=C.SERVICE_SLOT) remote_ping = invoke_remote(session, service, 1, 0x41) remote_sum = invoke_remote(session, service, 2, 0x10, 0x20) via_fw_ping = invoke_via_firmware(session, service, 1, 0x41) via_fw_sum = invoke_via_firmware(session, service, 2, 0x10, 0x20) handlers7 = session.memory.read_u64(ctrl + 0x150 + 8 * C.SERVICE_SLOT) payload = { "success": remote_ping == (0x41 ^ C.PING_XOR) and remote_sum == 0x30 and via_fw_ping == remote_ping and via_fw_sum == remote_sum, "backend": backend, "service": service.summary(), "service_sha256": C.sha256_file(C.SDK_ELF), "handlers_slot6": f"{handlers7:#x}", "remote": {"ping": remote_ping, "sum": remote_sum}, "via_firmware": {"ping": via_fw_ping, "sum": via_fw_sum}, "mailbox_command": C.INJECT_CMD_BASE + C.SERVICE_SLOT, "session": os.path.relpath(session_dir, C.TOOL_ROOT), "question": "load/register/invoke a service blob end-to-end, both routes", "answer": ( f"service loaded at {service.load_addr:#x}, slot {service.slot} " f"(handlers[{service.slot}]={handlers7:#x}); remote ping={remote_ping:#x} " f"sum={remote_sum:#x}; via mailbox cmd={C.INJECT_CMD_BASE + C.SERVICE_SLOT} " f"ping={via_fw_ping:#x} sum={via_fw_sum:#x} - both paths agree, one session" ), "success_criteria": { "pass": "remote and firmware-mailbox invocations return the SDK ABI values and agree", "fail": "a route disagrees, the slot is not registered, or the blob cannot load", }, "real_case": scenario, } C.write_json(os.path.join(out, "inject.json"), payload) finally: session.close() return payload def main() -> int: return 0 if C.timed_demo(run, C.artifact_dir("s06_inject_service"))["success"] else 1 if __name__ == "__main__": raise SystemExit(main())