diff --git a/doc/source/build_system.rst b/doc/source/build_system.rst index ecda494f2..f5d8019cd 100644 --- a/doc/source/build_system.rst +++ b/doc/source/build_system.rst @@ -71,8 +71,8 @@ Everything is anchored on the repository root. Source ``env.sh`` once per shell: This exports ``IB_ROOT_DIR``, sets ``BBPATH``/``BUILDDIR`` to ``build/``, and prepends ``scripts/`` and the bundled ``bitbake`` to ``PATH`` so the active tree -wins. From then on the ``build.sh`` / ``deploy.sh`` / ``st.sh`` / ``stg.sh`` -commands are on the path. See :ref:`user_guide` for the end-to-end walkthrough. +wins. From then on the ``build.sh`` / ``deploy.sh`` / ``st.sh`` commands are on +the path. See :ref:`user_guide` for the end-to-end walkthrough. Meta-layers =========== diff --git a/doc/source/display_input.rst b/doc/source/display_input.rst index de5e88b00..3825f7477 100644 --- a/doc/source/display_input.rst +++ b/doc/source/display_input.rst @@ -143,25 +143,23 @@ it once per refresh through the ``GET_STATE`` ioctl, and the driver scales the r relative PL050 mouse (``kmi1.c``) is kept in the tree but its dts node is ``status = "disabled"`` so there is a single ``/dev/mouse``. -The host GTK window (``stg.sh``) -================================ +The host GTK window (``st.sh -d``) +================================== -The graphical launcher ``stg.sh`` starts QEMU with the **GTK** display -backend (``-display gtk,zoom-to-fit=off``): +By default ``st.sh`` is headless (``-display none``): no window, serial console +only, used for non-graphical work and CI. Pass **-d** to open the QEMU **GTK** +window that presents the guest PL111 CLCD (``-display gtk,zoom-to-fit=off``): * **GTK, not SDL** — the SDL backend does not present the PL111 console surface (the window stays black even though the framebuffer is rendered correctly); GTK shows it, and its *View* menu lists every console. -* **XWayland for HiDPI** — ``stg.sh`` exports ``GDK_BACKEND=x11`` (plus - ``GDK_SCALE=1``). On a fractionally-scaled HiDPI **Wayland** panel, GTK reports - pointer coordinates in a different scale than the framebuffer surface, so the - absolute mapping comes out *offset* (host and guest cursors shifted) — fine on a - 1× external monitor, wrong on the laptop panel. Routing GTK through XWayland - gives a uniform pointer-to-surface mapping, so the cursors coincide on every - monitor. It is harmless on a native X11 session. - -``st.sh`` is the headless sibling (``-display none``): no window, console -only, used for non-graphical work and CI. +* **XWayland for HiDPI** — with ``-d``, ``st.sh`` exports ``GDK_BACKEND=x11`` + (plus ``GDK_SCALE=1``). On a fractionally-scaled HiDPI **Wayland** panel, GTK + reports pointer coordinates in a different scale than the framebuffer surface, + so the absolute mapping comes out *offset* (host and guest cursors shifted) — + fine on a 1× external monitor, wrong on the laptop panel. Routing GTK through + XWayland gives a uniform pointer-to-surface mapping, so the cursors coincide on + every monitor. It is harmless on a native X11 session. .. _console_sigint: diff --git a/doc/source/img/gen_so3_diagrams.py b/doc/source/img/gen_so3_diagrams.py index 2492ccb10..bac953b92 100644 --- a/doc/source/img/gen_so3_diagrams.py +++ b/doc/source/img/gen_so3_diagrams.py @@ -348,7 +348,7 @@ def xml(self): dep = p.box(420, 420, 250, 64, "scripts/deploy.sh bsp-so3\n→ sdcard FAT (+ flash0.img)", WHITE, 10) run = p.box(770, 420, 270, 64, - "scripts/st.sh / stg.sh\n→ QEMU (EL1 / EL2 / ATF)", WHITE, 10) + "scripts/st.sh [-d]\n→ QEMU (EL1 / EL2 / ATF)", WHITE, 10) # the band feeds do_itb: drop from the band's lower-left border straight down. p.edge(rec, itb, "", ARR + "exitX=0.15;exitY=1;entryX=0.5;entryY=0;") p.edge(itb, dep, "", ARR + "exitX=1;exitY=0.5;entryX=0;entryY=0.5;") @@ -379,7 +379,7 @@ def xml(self): qmsd = p.box(430, 320, 280, 44, "pl050 mouse @ 0x08802000 (disabled)", NONE, 9) quart= p.box(430, 380, 280, 46, "pl011 UART @ 0x09000000 (SPI 1)", HW, 9) # Host column -p.box(780, 60, 300, 470, "Host (scripts/stg.sh)", CONT, 12, 1) +p.box(780, 60, 300, 470, "Host (scripts/st.sh -d)", CONT, 12, 1) hwin = p.box(810, 110, 240, 80, "GTK window\n-display gtk,zoom-to-fit=off\nGDK_BACKEND=x11 (HiDPI/Wayland)", NEUTRAL, 9) hptr = p.box(810, 250, 240, 64, "host pointer → absolute\n1:1 mapping, no grab / no warp", NEUTRAL, 9) hterm= p.box(810, 380, 240, 46, "terminal (-serial mon:stdio)", NEUTRAL, 9) diff --git a/doc/source/img/so3.drawio b/doc/source/img/so3.drawio index f2fdfecc5..3dcfb561f 100644 --- a/doc/source/img/so3.drawio +++ b/doc/source/img/so3.drawio @@ -1,2 +1,2 @@ \ No newline at end of file +(guest-boot x0/x1)" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;endArrow=block;strokeColor=#444444;fontSize=10;" edge="1" parent="1" source="c4" target="c5"> \ No newline at end of file diff --git a/doc/source/img/so3_build.png b/doc/source/img/so3_build.png index f273c77f3..06c516b5a 100644 Binary files a/doc/source/img/so3_build.png and b/doc/source/img/so3_build.png differ diff --git a/doc/source/img/so3_io.png b/doc/source/img/so3_io.png index e2904b638..aeef57ba2 100644 Binary files a/doc/source/img/so3_io.png and b/doc/source/img/so3_io.png differ diff --git a/doc/source/lvgl.rst b/doc/source/lvgl.rst index bc4d32133..7d4d45d8d 100644 --- a/doc/source/lvgl.rst +++ b/doc/source/lvgl.rst @@ -83,12 +83,12 @@ Running LVGL under QEMU ======================= Build the user space with the LVGL applications and a framebuffer-enabled kernel -configuration, then launch the **graphical** emulator (the framebuffer needs a -real window): +configuration, then launch the emulator in **graphical** mode with ``-d`` (the +framebuffer needs a real window): .. code-block:: bash - stg.sh + st.sh -d QEMU opens a GTK window that shows the PL111 framebuffer; launch an LVGL application from the ``so3%`` prompt to draw into it, for example:: diff --git a/doc/source/user_guide.rst b/doc/source/user_guide.rst index 79b417afc..e62eb2c43 100644 --- a/doc/source/user_guide.rst +++ b/doc/source/user_guide.rst @@ -34,7 +34,7 @@ The most relevant top-level directories are:: so3/ # the SO3 kernel (so3/so3) and user space (so3/usr), plus dts build/ # the Infrabase build: meta-* layers, conf/local.conf, bitbake work tree - scripts/ # build.sh, deploy.sh, st.sh, stg.sh, updiff.sh, … + scripts/ # build.sh, deploy.sh, st.sh, updiff.sh, … filesystem/ # the virtual SD-card image used by QEMU u-boot/ # fetched U-Boot (patched) qemu/ # fetched QEMU (patched) -> qemu/build/qemu-system-* @@ -105,12 +105,12 @@ Launch scripts :header-rows: 1 :widths: 16 84 - * - Script + * - Command - Use * - ``st.sh`` - **headless** run (``-display none``) — serial console only. The default for non-graphical work and CI. - * - ``stg.sh`` + * - ``st.sh -d`` - **graphical** run — a GTK window for the PL111 framebuffer (LVGL, ``fb_test``). See :ref:`display_input`. diff --git a/docker/scripts/run.sh b/docker/scripts/run.sh index a593c4abe..fdab44468 100755 --- a/docker/scripts/run.sh +++ b/docker/scripts/run.sh @@ -40,8 +40,8 @@ fi # This launcher boots a STANDALONE SO3 image at EL1 (plain -M virt). It cannot # boot an AVZ (EL2 hypervisor) or an ATF/flash0 (EL3) deployment — those need -# QEMU started with virtualization=on / secure=on, which scripts/st.sh and -# scripts/stg.sh select from the deployed ITS. The lv_perf images deploy a +# QEMU started with virtualization=on / secure=on, which scripts/st.sh selects +# from the deployed ITS. The lv_perf images deploy a # standalone ITS, so this guard only ever trips when run by hand on a host tree # configured for AVZ/ATF. SO3_ITS=$(grep -E "^IB_TARGET_ITS:so3:${PLATFORM}\b" build/conf/local.conf 2>/dev/null \ @@ -55,7 +55,7 @@ if [ -n "$why" ]; then echo "Error: the deployment is not standalone — $why." >&2 echo " run.sh boots SO3 standalone at EL1 only. For an AVZ (EL2) or ATF" >&2 echo " (EL3) build, use the host launchers instead, which select the EL" >&2 - echo " from the ITS: scripts/st.sh (headless) / scripts/stg.sh (GTK)." >&2 + echo " from the ITS: scripts/st.sh (headless) / scripts/st.sh -d (GTK)." >&2 exit 1 fi diff --git a/scripts/st.sh b/scripts/st.sh index 707cedc80..7b581e21b 100755 --- a/scripts/st.sh +++ b/scripts/st.sh @@ -12,6 +12,23 @@ QEMU_AUDIO_DRV="none" GDB_PORT_BASE=1234 + +# Parse our own options (currently just -d) out of the argument list before +# what's left is forwarded to QEMU as USR_OPTION. +WITH_DISPLAY=0 +POSARGS=() +for _a in "$@"; do + case "$_a" in + -d) WITH_DISPLAY=1 ;; + -h|--help) + echo "Usage: $(basename "$0") [-d] [qemu-option]" + echo " -d graphical: open the QEMU GTK window showing the guest PL111/LVGL screen" + echo " (default: headless, serial console only)" + exit 0 ;; + *) POSARGS+=("$_a") ;; + esac +done +set -- "${POSARGS[@]}" USR_OPTION=$1 # QEMU_BIN is selected per IB_PLATFORM below (qemu-system-aarch64 for # virt64, qemu-system-arm for virt32). @@ -46,6 +63,24 @@ launch_qemu() { SO3_ITS=$(grep -E "^IB_TARGET_ITS:so3:${IB_PLATFORM}\b" build/conf/local.conf | awk -F'"' '{print $2}' | tail -1) LINUX_ITS=$(grep -E "^IB_TARGET_ITS:linux:${IB_PLATFORM}\b" build/conf/local.conf | awk -F'"' '{print $2}' | tail -1) + # Display mode. Default: headless (serial console only, -display none). With + # -d: open the QEMU GTK window that presents the guest PL111 CLCD (the LVGL + # screen). SO3 drives PL111 + PL050 (wired unconditionally into '-M virt' by + # the so3 QEMU patch) and has no virtio-gpu, so no extra device flags are + # needed — just switch the display backend. Use GTK, not SDL: SDL leaves the + # PL111 console black, GTK presents it (and its View menu lists every + # console). On a fractionally-scaled HiDPI Wayland panel, route GTK through + # XWayland (GDK_BACKEND=x11) so the so3,absmouse absolute pointer maps 1:1 + # onto the guest surface; harmless on a real X11 session. + if [ "$WITH_DISPLAY" == "1" ]; then + DISPLAY_OPT="-display gtk,zoom-to-fit=off" + export GDK_BACKEND=x11 + export GDK_SCALE=1 + export GDK_DPI_SCALE=1 + else + DISPLAY_OPT="-display none" + fi + if [ "$IB_PLATFORM" == "virt64" ]; then QEMU_BIN="$IB_ROOT_DIR/qemu/build/qemu-system-aarch64" echo Starting on virt64 @@ -97,7 +132,7 @@ launch_qemu() { -device virtio-blk-device,drive=hd0 \ -drive if=none,file=filesystem/sdcard.img.virt64,id=hd0,format=raw,file.locking=off \ -m 1024 \ - -display none \ + ${DISPLAY_OPT} \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-device,netdev=n1,mac=${QEMU_MAC_ADDR} \ -gdb tcp::${GDB_PORT} @@ -120,7 +155,7 @@ launch_qemu() { -device virtio-blk-device,drive=hd0 \ -drive if=none,file=filesystem/sdcard.img.virt32,id=hd0,format=raw,file.locking=off \ -m 1024 \ - -display none \ + ${DISPLAY_OPT} \ -netdev user,id=n1,hostfwd=tcp::2222-:22 \ -device virtio-net-device,netdev=n1,mac=${QEMU_MAC_ADDR} \ -gdb tcp::${GDB_PORT} diff --git a/scripts/stg.sh b/scripts/stg.sh deleted file mode 100755 index 31a59244f..000000000 --- a/scripts/stg.sh +++ /dev/null @@ -1,142 +0,0 @@ -#!/bin/bash - -# Copyright (c) 2025-2026 EDGEMTech SA - -# Resolve project root from this script's own location, cd there, and -# source env.sh — prompting the user first if the parent shell points -# at a different tree. Every relative path below (filesystem/..., -# build/conf/local.conf) is anchored on that root. See -# scripts/common/setup_env.sh. - -. "$(cd "$(dirname "$(command -v -- "$0")")" && pwd)/common/setup_env.sh" - -QEMU_AUDIO_DRV="none" -GDB_PORT_BASE=1234 -USR_OPTION=$1 -# QEMU_BIN is selected per IB_PLATFORM below (qemu-system-aarch64 for -# virt64, qemu-system-arm for virt32). - -N_QEMU_INSTANCES=`ps -A | grep qemu-system | wc -l` - -launch_qemu() { - QEMU_MAC_ADDR="$(printf 'DE:AD:BE:EF:%02X:%02X\n' $((N_QEMU_INSTANCES)) $((N_QEMU_INSTANCES)))" - - GDB_PORT=$((${GDB_PORT_BASE} + ${N_QEMU_INSTANCES})) - - echo -e "\033[01;36mMAC addr: " ${QEMU_MAC_ADDR} "\033[0;37m" - echo -e "\033[01;36mGDB port: " ${GDB_PORT} "\033[0;37m" - - while IFS= read -r line; do - # Check if the line starts with "IB_PLATFORM" - if [[ $line == IB_PLATFORM* ]]; then - # Extract the value between the quotes - value=$(echo "$line" | awk -F'"' '{print $2}') - - # Set the IB_PLATFORM variable to the extracted value - IB_PLATFORM="$value" - break - fi - done < build/conf/local.conf - - # Detect a SO3-on-AVZ boot from the selected (uncommented) so3 ITS — AVZ - # is an EL2 hypervisor, so QEMU must expose EL2 (virtualization=on). - SO3_ITS=$(grep -E "^IB_TARGET_ITS:so3:${IB_PLATFORM}\b" build/conf/local.conf | awk -F'"' '{print $2}' | tail -1) - - if [ "$IB_PLATFORM" != "virt64" ] && [ "$IB_PLATFORM" != "virt32" ]; then - echo "ERROR: stg.sh only supports IB_PLATFORM=virt64 or virt32, but" >&2 - echo " build/conf/local.conf has IB_PLATFORM=\"$IB_PLATFORM\"." >&2 - echo "" >&2 - echo " Edit build/conf/local.conf to set" >&2 - echo " IB_PLATFORM ?= \"virt64\" (or \"virt32\")" >&2 - echo " then rebuild+redeploy before retrying stg.sh." >&2 - exit 1 - fi - - # SO3 now uses the ABSOLUTE pointer (so3,absmouse — see the so3 QEMU patch - # and devices/input/absmouse.c), so QEMU runs in absolute pointer mode: the - # host pointer maps 1:1 onto the guest with NO grab and NO warp. This sheds - # the relative-mouse grab workaround (grab-on-hover) entirely. - # - # GDK_BACKEND=x11 is still needed on a FRACTIONALLY-SCALED HiDPI Wayland - # panel: there QEMU's GTK reports pointer coordinates in a different scale - # than the framebuffer surface, so the absolute mapping comes out OFFSET - # (host vs guest cursor shifted) — fine on a 1x external monitor, shifted - # on the laptop. Routing GTK through XWayland gives a uniform pointer-to- - # surface mapping, so the cursors line up on every monitor. (GDK_SCALE just - # keeps the window native-sized; not load-bearing for the mapping.) - # Harmless on a real X11 session. - export GDK_BACKEND=x11 - export GDK_SCALE=1 - export GDK_DPI_SCALE=1 - - if [ "$IB_PLATFORM" == "virt64" ]; then - QEMU_BIN="$IB_ROOT_DIR/qemu/build/qemu-system-aarch64" - echo Starting on virt64 - # See st.sh for rationale and for the flash0.img-presence boot-mode - # heuristic (AVZ chain vs bare U-Boot). - # Like virt32, SO3 drives the PL111 CLCD + PL050 keyboard/mouse that the - # so3 QEMU patch wires unconditionally into '-M virt' (virt64.dts has the - # clcd@08800000 / pl050 nodes). It has NO virtio-gpu driver, so we do not - # add virtio-gpu/keyboard/mouse here. Use the GTK backend: SDL does not - # present the PL111 console's surface (the window stays black even though - # the framebuffer is rendered); GTK shows it and its View menu lists every - # console. - - if [ -f filesystem/flash0.img ]; then - # ATF/OP-TEE chain (flash0/FIP): EL3 (secure=on) + EL2. - MACHINE_OPT="-M virt,virtualization=on,gic-version=2,secure=on" - BOOT_OPT="-drive if=pflash,format=raw,file=filesystem/flash0.img" - elif [[ "$SO3_ITS" == *avz* ]]; then - # SO3-on-AVZ via the ITS, no ATF: AVZ runs at EL2, so QEMU must - # expose it (virtualization=on). U-Boot here is virt64_defconfig - # (EL2-aware) and hands off to AVZ at EL2. - echo "AVZ guest (ITS=$SO3_ITS) — enabling EL2 (virtualization=on)" - MACHINE_OPT="-M virt,gic-version=2,virtualization=on" - BOOT_OPT="-kernel u-boot/u-boot" - else - MACHINE_OPT="-M virt,gic-version=2" - BOOT_OPT="-kernel u-boot/u-boot" - fi - ${QEMU_BIN} $@ ${USR_OPTION} \ - -smp 4 \ - -serial mon:stdio \ - ${MACHINE_OPT} -cpu cortex-a72 \ - ${BOOT_OPT} \ - -device virtio-blk-device,drive=hd0 \ - -drive if=none,file=filesystem/sdcard.img.virt64,id=hd0,format=raw,file.locking=off \ - -display gtk,zoom-to-fit=off \ - -m 1024 \ - -netdev user,id=n1,hostfwd=tcp::2222-:22 \ - -device virtio-net-device,netdev=n1,mac=${QEMU_MAC_ADDR} \ - -gdb tcp::${GDB_PORT} - fi - - if [ "$IB_PLATFORM" == "virt32" ]; then - QEMU_BIN="$IB_ROOT_DIR/qemu/build/qemu-system-arm" - echo Starting on virt32 - # Graphical sibling of st.sh's virt32 branch: bare U-Boot chain - # (no ATF / flash on this platform), cortex-a15. - # NOTE: SO3 drives the PL111 CLCD + PL050 keyboard/mouse that the - # so3 QEMU patch wires unconditionally into '-M virt' (see boot log: - # pl111_init / pl050_init_*). It has NO virtio-gpu driver, so we must - # NOT add virtio-gpu/keyboard/mouse here. - # Use the GTK backend: its View menu lists every graphic console, so the - # PL111 panel is reachable even if QEMU registers more than one console. - ${QEMU_BIN} $@ ${USR_OPTION} \ - -smp 4 \ - -serial mon:stdio \ - -M virt -cpu cortex-a15 \ - -kernel u-boot/u-boot \ - -device virtio-blk-device,drive=hd0 \ - -drive if=none,file=filesystem/sdcard.img.virt32,id=hd0,format=raw,file.locking=off \ - -display gtk,zoom-to-fit=off \ - -m 1024 \ - -netdev user,id=n1,hostfwd=tcp::2222-:22 \ - -device virtio-net-device,netdev=n1,mac=${QEMU_MAC_ADDR} \ - -gdb tcp::${GDB_PORT} - fi - - QEMU_RESULT=$? -} - -launch_qemu