Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ test-contracts:
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-cocoa-scroll.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-cocoa-iso-keyboard.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-cocoa-injected-text.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-cocoa-no-console.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-hvf-memory-reclaim.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-hvf-mapped-sections.py"
@PYTHONDONTWRITEBYTECODE=1 python3 "$(ROOT)/macos/Tests/test-virtio-pinch.py"
Expand Down
64 changes: 64 additions & 0 deletions macos/Tests/cocoa-no-console-harness.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/* Portable harness for the Cocoa startup console lookup extracted from the QEMU patch. */
#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct { int unused; } DisplaySurface;
typedef struct { DisplaySurface *surface; } QemuConsole;
typedef struct { QemuConsole *con; } QKbdState;
typedef struct { QemuConsole *con; } DisplayChangeListener;

static DisplayChangeListener dcl;
static DisplaySurface *surface;
static QKbdState *kbd;
static QKbdState kbd_state;
static QemuConsole *default_console;

static QemuConsole *qemu_console_lookup_default(void)
{
return default_console;
}

static QKbdState *qkbd_state_init(QemuConsole *con)
{
kbd_state.con = con;
return &kbd_state;
}

static DisplaySurface *qemu_console_surface(QemuConsole *console)
{
/* The patched ui/console.c reads console->surface with no NULL check. */
if (!console) {
fputs("qemu_console_surface() called without a console\n", stderr);
abort();
}
return console->surface;
}

static void cocoa_display_startup(void)
{
/* STARTUP */
}

int main(void)
{
DisplaySurface device_surface = {0};
QemuConsole console = { &device_surface };

/* -nodefaults with no display device: QEMU has no console at all. */
default_console = NULL;
surface = &device_surface;
cocoa_display_startup();
assert(dcl.con == NULL);
assert(surface == NULL);
assert(kbd == &kbd_state && kbd_state.con == NULL);

/* A graphics device: the surface still comes from its console. */
default_console = &console;
cocoa_display_startup();
assert(dcl.con == &console);
assert(surface == &device_surface);
assert(kbd == &kbd_state && kbd_state.con == &console);
return 0;
}
63 changes: 63 additions & 0 deletions macos/Tests/test-cocoa-no-console.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env python3
"""Start the Cocoa display without a console, as pristine QEMU allows."""

import hashlib
import os
from pathlib import Path
import re
import shlex
import subprocess
import tempfile
import unittest


ROOT = Path(__file__).resolve().parents[2]
PATCH = ROOT / "macos/patches/qemu-texture-borrowing-11.1.patch"
START = "dcl.con = qemu_console_lookup_default();"
END = "// Create an Application controller"


def patched_cocoa_hunks():
section = PATCH.read_text().split(
"diff --color -urN pristine/src/ui/cocoa.m trim/src/ui/cocoa.m\n", 1
)[1].split("\ndiff --color ", 1)[0]
return ["\n".join(line[1:] for line in hunk.splitlines()
if line.startswith((" ", "+")))
for hunk in re.split(r"^@@.*@@.*$", section, flags=re.M)[1:]]


class CocoaNoConsoleTests(unittest.TestCase):
def test_build_uses_verified_patch(self):
builder = (ROOT / "macos/build-qemu-gpu-runtime.sh").read_text()
digest = hashlib.sha256(PATCH.read_bytes()).hexdigest()
self.assertIn(f"texture_patch_sha256={digest}", builder)
self.assertIn('"$texture_patch" "$texture_patch_sha256"', builder)
self.assertIn('patch -d "$source_dir" -p1 -f -i "$texture_patch"', builder)

def test_startup_without_console(self):
# Compile the patched statements that run before the controller is
# created. With no console they must not reach qemu_console_surface();
# QEMU's listener registration later shows its placeholder surface.
hunks = patched_cocoa_hunks()
startup = [hunk for hunk in hunks if START in hunk]
self.assertEqual(len(startup), 1, "console lookup must be in one hunk")
startup = START + startup[0].split(START, 1)[1]
self.assertIn(END, startup)
startup = startup.split(END, 1)[0]
source = "\n".join(hunks)
self.assertEqual(source.count("qemu_console_surface("),
startup.count("qemu_console_surface("), "surface read moved")
self.assertIn("qemu_console_register_listener(qemu_console_lookup_default(),",
source)
with tempfile.TemporaryDirectory() as directory:
work = Path(directory)
harness = (ROOT / "macos/Tests/cocoa-no-console-harness.c").read_text()
(work / "test.c").write_text(harness.replace("/* STARTUP */", startup))
compiler = shlex.split(os.environ.get("CC", "cc"))
subprocess.run(compiler + ["-std=c11", "-Wall", "-Wextra", "-Werror",
str(work / "test.c"), "-o", str(work / "test")], check=True)
subprocess.run([str(work / "test")], check=True)


if __name__ == "__main__":
unittest.main()
2 changes: 1 addition & 1 deletion macos/build-qemu-gpu-runtime.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ qemu_archive_name="$qemu_root.tar.gz"
qemu_url="https://gitlab.com/qemu-project/qemu/-/archive/$qemu_commit/$qemu_archive_name"
qemu_sha256=7563781d7dec46f11509801e027f852597235d29ca7afa44a07ed9d8b108b8cd

texture_patch_sha256=b20bdf9a7d7ccda5b86366ad9d09a3bf95308b98a06b1ece281344405bcc7ab9
texture_patch_sha256=b8e107ecd82813854bac7f6bb110722f52937d64b6f98611c4dd02842977fc2f
gpu_fix_patch_sha256=b554e1ef9910d0891d69ee0fe84e479559c057dc28291e36e1524031808fc69f
identity_patch_sha256=5c9358c2858a74d6a678eacaae550a021f3e616c98c4e4e98c0e50bd869a0666
display_patch_sha256=1ce59350b6b8e6842bc0c9ca34c97f54cb75e85e2d7b35e5b483858654c4d693
Expand Down
2 changes: 1 addition & 1 deletion macos/patches/qemu-texture-borrowing-11.1.patch
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ diff --color -urN pristine/src/ui/cocoa.m trim/src/ui/cocoa.m

+ dcl.con = qemu_console_lookup_default();
+ kbd = qkbd_state_init(dcl.con);
+ surface = qemu_console_surface(dcl.con);
+ surface = dcl.con ? qemu_console_surface(dcl.con) : NULL;
+
// Create an Application controller
- QemuCocoaAppController *controller = [[QemuCocoaAppController alloc] init];
Expand Down
Loading