#!/usr/bin/env python3 # SPDX-License-Identifier: GPL-3.0-or-later """Validate Phase-1.0Q public VideoOut evidence and fail-closed decision.""" from __future__ import annotations import argparse import hashlib import json from pathlib import Path import subprocess from typing import Any PHASE = "PHASE_1_0Q_PUBLIC_VIDEOOUT_EVIDENCE" STATUS = "PUBLIC_VIDEOOUT_EVIDENCE_INSUFFICIENT_PARAMETER_CHANGE_BLOCKED" SDK_COMMIT = "d2e2e585740362976a39fdd5ccf390f199a7bc37" SDL_COMMIT = "0baf4ac49382b537ba449901b5b6d0d189bb1fbb" AUTHORIZATION_FIELDS = ( "target_build_authorized", "ps5_connection_authorized", "device_transfer_authorized", "device_execution_authorized", "result_receive_authorized", "installation_authorized", "autoload_authorized", "device_write_authorized", "automatic_retry", ) def load_json(path: Path) -> dict[str, Any]: value = json.loads(path.read_text(encoding="utf-8")) if not isinstance(value, dict): raise ValueError("evidence manifest is not an object") return value def sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as stream: for chunk in iter(lambda: stream.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def all_false(record: dict[str, Any], fields: tuple[str, ...]) -> bool: return all(record.get(field) is False for field in fields) def network_scope_is_bounded(record: dict[str, Any]) -> bool: return ( record.get("github_metadata") is True and record.get("official_source_archives") is True and record.get("arbitrary_mirrors") is False and record.get("downloaded_code_executed") is False and record.get("ps5_address_used") is False and record.get("ps5_connected") is False ) def sdk_evidence_is_symbol_only(record: dict[str, Any]) -> bool: return ( record.get("repository") == "https://github.com/ps5-payload-dev/sdk" and record.get("release") == "v0.41" and record.get("release_commit") == SDK_COMMIT and record.get("latest_release_during_audit") is True and record.get("master_commit_inspected") == "a0d2bc60bdcc0a5ee9e790fa3b02fe5051a152d0" and record.get("videoout_stub_size") == 25199 and record.get("videoout_stub_sha256") == "da6cff9b3255e9ccb0440790f73e0265696ca47724cf8fe5950b579702940016" and record.get("exports_only") is True and record.get("public_videoout_header") is False and record.get("signatures_or_layouts") is False and record.get("return_semantics") is False ) def sdl_lineage_is_single(record: dict[str, Any]) -> bool: return ( record.get("repository") == "https://github.com/ps5-payload-dev/SDL" and record.get("pinned_commit") == SDL_COMMIT and record.get("initial_ps5_video_commit") == "2682a5e31e8aee888538b0fb7253d8cadf2797a1" and record.get("initial_source_size") == 7873 and record.get("initial_source_sha256") == "1b9f917cac4e00ba1eccb22093e3ca079238f91c9a44ceefa9e23570ca9abab3" and record.get("declaration_move_commit") == "fdfa470a0fa33215c677193982dfe3651ac1321a" and record.get("uint32_cleanup_commit") == "14ac2ec2ab5889af47218a957e3456e613b13d3d" and record.get("pinned_header_size") == 2878 and record.get("pinned_header_sha256") == "e60766e0b43c2a7fceba2ada0c030e7f7b05e63885590092f2f8f5b9da34ed75" and record.get("pinned_source_size") == 12162 and record.get("pinned_source_sha256") == "44124546da132ea6e12b1f06a1808d61690c73460a65c3161e8453e8108684b6" and record.get("independent_abi_source_cited") is False and record.get("opaque_buffer_member_name") == "junk0" and record.get("opaque_attribute_member_name") == "junk0" and record.get("single_lineage_only") is True ) def archives_do_not_corroborate(records: Any) -> bool: expected = { "ps5-payload-dev/libcross2d": ("829b167262d3567a048b6e69416f8e3be399c098", 1838927, "eb952a041396ba01224a890d14d41662b017488f487ddd4c4018ffddd4a59ae2", "SDL_CONSUMER"), "ps5-payload-dev/pemu": ("4136088e13e825f33c9d0cc43ff9a8c8f749dcb0", 7540449, "9ed14a1ea432638992b614f9946bcbc9770f70b6f18ded5778fd6809a927eaeb", "SDL_CONSUMER"), "ps5-payload-dev/FBNeo": ("ca4222ca2cd52215a673c565a5eae3589b352ba2", 15318689, "824d6e5b6b61555f5ecc598204052dcb4b1cf16d28be29b9594a44866e726ef3", "NO_DIRECT_IMPLEMENTATION"), "ps5-payload-dev/LakeSnes": ("a2db690123649c7ffbc68a663af31efb3a41bf3f", 413067, "253a08957a68461a8535a4727ee1242c21b2dc40c8eb8c99bdb85af799ac3ca6", "SDL_CONSUMER"), "ps5-payload-dev/yquake2": ("9e233b6a601c393be4ff1dcb1c003750346b8bbb", 2914919, "01ef41608b2be0ace119019901a6ea22f304542972bace714d1177cb7f567978", "SDL_CONSUMER"), "ps5-payload-dev/pacbrew-repo": ("c2abcfcb60f569128abd0e8e70ad03a67bee5ea7", 143496, "17be50219ce41772cfc50ea9274b0a62a2259162556b6eeecfaed4a691822872", "REFERENCES_SAME_SDL_FORK"), } if not isinstance(records, list) or len(records) != 6: return False if {item.get("repository") for item in records} != set(expected): return False for item in records: repository = item["repository"] commit, size, digest, relationship = expected[repository] if item.get("direct_videoout_hits") != 0: return False if item.get("relationship") != relationship: return False if item.get("commit") != commit or item.get("size") != size: return False if item.get("sha256") != digest: return False return True def ps4_analogue_is_not_promoted(record: dict[str, Any]) -> bool: return ( record.get("repository") == "https://github.com/OpenOrbis/OpenOrbis-PS4-Toolchain" and record.get("commit") == "0a1aaf9dd4a92695538bdeb09fb056d06dd11725" and record.get("four_argument_submit") is True and record.get("mode_one_documented_as_vsync") is True and record.get("classification") == "PS4_ANALOG_ONLY" and record.get("accepted_as_ps5_abi") is False ) def evidence_matrix_is_fail_closed(record: dict[str, Any]) -> bool: return record == { "submit_signature": "PARTIAL_SINGLE_LINEAGE", "argument_positions": "PARTIAL_SINGLE_LINEAGE", "mode_one_semantics": "UNPROVEN_ON_PS5", "frame_zero_validity": "UNPROVEN_ON_PS5", "video_buffer_layout": "UNPROVEN", "video_attribute_layout": "UNPROVEN", "format_constant_semantics": "UNPROVEN", "register_return_semantics": "PARTIAL_RUNTIME_ONLY", "submit_error_semantics": "UNPROVEN", "flip_master_or_active_app_requirement": "UNPROVEN", "status_query_signatures_and_layouts": "UNPROVEN", } def decision_is_blocked(record: dict[str, Any]) -> bool: return ( record.get("independent_ps5_abi_corroboration_found") is False and record.get("root_cause_resolved") is False and record.get("parameter_change_allowed") is False and record.get("new_videoout_call_allowed") is False and record.get("phase10r_target_artifact_allowed") is False and record.get("phase10r_device_action_allowed") is False and record.get("safe_next_steps") == [ "OFFLINE_LAUNCH_CONTEXT_COMPARISON", "HOST_OR_SOFTWARE_ONLY_INTEGRATION", ] ) def git(root: Path, *args: str) -> str: result = subprocess.run( ["git", *args], cwd=root, capture_output=True, text=True, check=False) if result.returncode: raise RuntimeError(result.stderr.strip() or "git failed") return result.stdout def validate(root: Path, sdk_root: Path, sdl_root: Path) -> list[str]: errors: list[str] = [] try: record = load_json( root / "manifests/retroarch/phase-1.0q-public-videoout-evidence.json") except (OSError, ValueError, json.JSONDecodeError) as error: return [str(error)] if record.get("phase") != PHASE or record.get("status") != STATUS: errors.append("phase/status mismatch") if record.get("start_commit") != "df470c691f375b73768fd0d4a51dc2d35523e71d": errors.append("start commit mismatch") if not network_scope_is_bounded(record.get("network_scope", {})): errors.append("network scope is broadened") if not all_false(record.get("authorizations", {}), AUTHORIZATION_FIELDS): errors.append("authorization remains active") if not sdk_evidence_is_symbol_only(record.get("sdk", {})): errors.append("SDK evidence was promoted") if not sdl_lineage_is_single(record.get("sdl_lineage", {})): errors.append("SDL lineage is incomplete or promoted") if not archives_do_not_corroborate(record.get("official_project_archives")): errors.append("official archive inventory mismatch") storage = record.get("temporary_research_storage", {}) if storage != { "archive_count": 6, "downloaded_bytes": 28169547, "retained_in_git": False, "cleaned_after_static_scan": False, "cleanup_status": "RETAINED_TEMP_LOCAL_DELETE_POLICY_BLOCKED", }: errors.append("temporary research storage boundary mismatch") additional = record.get("additional_ps5_source", {}) if not ( additional.get("repository") == "https://github.com/PS5Dev/PS5SDK" and additional.get("commit") == "a2e03a2a0231a3a3397fa6cd087a01ca6d04f273" and additional.get("videoout_implementation_found") is False and additional.get("classification") == "NO_CORROBORATION" ): errors.append("additional PS5 source was promoted") if not ps4_analogue_is_not_promoted(record.get("ps4_analogue", {})): errors.append("PS4 analogue was promoted to PS5 ABI") if not evidence_matrix_is_fail_closed(record.get("evidence_matrix", {})): errors.append("evidence matrix mismatch") if not decision_is_blocked(record.get("decision", {})): errors.append("parameter or device path is not blocked") performed = record.get("performed_actions", {}) if not all(value is False for value in performed.values()) or set(performed) != { "target_source_changed", "target_artifact_created", "ps5_connected", "device_transfer_performed", "target_execution_performed", "result_received_from_device", }: errors.append("performed-action boundary mismatch") tests = record.get("tests", {}) if not ( tests.get("chimera_gfx_ctest") == "62_OF_62_PASS" and tests.get("phase10q_guardrails") == 20 and tests.get("network_required_by_tests") is False and tests.get("hardware_claim_from_host_test") is False ): errors.append("test evidence mismatch") try: if git(sdk_root, "rev-parse", "HEAD").strip() != SDK_COMMIT: errors.append("local SDK release commit mismatch") if git(sdl_root, "rev-parse", "HEAD").strip() != SDL_COMMIT: errors.append("local SDL commit mismatch") if git(sdk_root, "status", "--porcelain"): errors.append("local SDK tree is dirty") if git(sdl_root, "status", "--porcelain"): errors.append("local SDL tree is dirty") stub = sdk_root / "sce_stubs/libSceVideoOut.c" header = sdl_root / "src/video/ps5/SDL_ps5video.h" source = sdl_root / "src/video/ps5/SDL_ps5video.c" if stub.stat().st_size != 25199 or sha256(stub) != record["sdk"]["videoout_stub_sha256"]: errors.append("local VideoOut stub identity mismatch") if header.stat().st_size != 2878 or sha256(header) != record["sdl_lineage"]["pinned_header_sha256"]: errors.append("local SDL header identity mismatch") if source.stat().st_size != 12162 or sha256(source) != record["sdl_lineage"]["pinned_source_sha256"]: errors.append("local SDL source identity mismatch") header_text = header.read_text(encoding="utf-8") if "uint64_t junk0[3]" not in header_text or "uint8_t junk0[80]" not in header_text: errors.append("opaque SDL declarations changed") tracked = git(root, "ls-files").splitlines() if any(path.lower().endswith((".elf", ".self", ".sprx", ".pkg", ".zip")) for path in tracked): errors.append("target or downloaded archive is tracked") except (OSError, RuntimeError, KeyError) as error: errors.append(str(error)) return errors def main() -> int: parser = argparse.ArgumentParser() parser.add_argument("--root", type=Path, required=True) parser.add_argument("--sdk-root", type=Path, required=True) parser.add_argument("--sdl-root", type=Path, required=True) args = parser.parse_args() errors = validate(args.root.resolve(), args.sdk_root.resolve(), args.sdl_root.resolve()) if errors: for error in errors: print(f"ERROR: {error}") return 1 print("Phase-1.0Q public VideoOut evidence validation passed") return 0 if __name__ == "__main__": raise SystemExit(main())