ci: use libc-free probe as FreeMiNT startup shell #286
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: qualification | |
| on: | |
| push: | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| infrastructure: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build atari-runtime image | |
| run: docker build -t atari-runtime:m2 -f Containerfile . | |
| - name: Runtime metadata | |
| run: docker run --rm atari-runtime:m2 tools/runtime-info.sh | |
| - name: Hatari CLI capabilities | |
| run: docker run --rm atari-runtime:m2 sh -c 'hatari --help 2>&1 | tee /tmp/hatari-help.txt; grep -Ei "auto|run|program|gemdos|harddrive" /tmp/hatari-help.txt || true' | |
| - name: Hatari + EmuTOS smoke | |
| run: docker run --rm atari-runtime:m2 tools/smoke.sh | |
| - name: Verify M2 helper | |
| run: docker run --rm atari-runtime:m2 sh -n tools/qualify-m2.sh | |
| m2-emulator: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| profile: [st, ste, tt] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Build atari-runtime image | |
| run: docker build -t atari-runtime:m2 -f Containerfile . | |
| - name: Install floppy image tools | |
| run: sudo apt-get update && sudo apt-get install -y dosfstools mtools | |
| - name: Download canonical atari-dev M2 artifact | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| mkdir -p artifacts | |
| curl --fail --location \ | |
| -H "Authorization: Bearer $GH_TOKEN" \ | |
| -H "Accept: application/vnd.github+json" \ | |
| -o /tmp/atari-dev-m2.zip \ | |
| https://api.github.com/repos/Ploos-AS/atari-dev/actions/artifacts/10600359653/zip | |
| unzip -q /tmp/atari-dev-m2.zip -d artifacts | |
| test -s artifacts/HELLO.TOS | |
| test -s artifacts/MINIMAL.PRG | |
| sha256sum artifacts/HELLO.TOS artifacts/MINIMAL.PRG | |
| - name: Prove EmuTOS reaches video boot | |
| run: | | |
| rm -f artifacts/xvfb-${{ matrix.profile }}.log artifacts/boot-hatari-${{ matrix.profile }}.log | |
| docker run --rm \ | |
| -v "$PWD/artifacts:/runtime/artifacts" atari-runtime:m2 \ | |
| sh -c 'set -eu; Xvfb :99 -screen 0 1024x768x24 >/tmp/xvfb.log 2>&1 & x=$!; export DISPLAY=:99; sleep 1; timeout --signal=TERM --kill-after=2s 8s hatari --machine "${{ matrix.profile }}" --memsize ${{ matrix.profile == 'tt' && '4' || '1' }} --tos /runtime/roms/emutos.img >/tmp/hatari.log 2>&1 || rc=$?; rc=${rc:-0}; cp /tmp/xvfb.log /runtime/artifacts/xvfb-${{ matrix.profile }}.log; cp /tmp/hatari.log /runtime/artifacts/boot-hatari-${{ matrix.profile }}.log; kill "$x" 2>/dev/null || true; wait "$x" 2>/dev/null || true; case "$rc" in 0|124|137) exit 0 ;; *) exit "$rc" ;; esac' | |
| cat artifacts/xvfb-${{ matrix.profile }}.log || true | |
| cat artifacts/boot-hatari-${{ matrix.profile }}.log || true | |
| test -e artifacts/boot-hatari-${{ matrix.profile }}.log | |
| if grep -Eqi 'fatal|cannot open.*tos|no tos|failed to.*tos' artifacts/boot-hatari-${{ matrix.profile }}.log; then | |
| echo "ERROR: Hatari reported a fatal TOS boot error" >&2 | |
| exit 1 | |
| fi | |
| printf 'EmuTOS boot window %s: PASS\n' "${{ matrix.profile }}" | |
| - name: Execute canonical probe from GEMDOS drive | |
| run: | | |
| rm -f artifacts/MINPASS.TXT | |
| test -s artifacts/MINIMAL.PRG | |
| set +e | |
| docker run --rm \ | |
| -v "$PWD/artifacts:/runtime/artifacts" atari-runtime:m2 \ | |
| sh -c 'set +e; Xvfb :99 -screen 0 1024x768x24 >/tmp/xvfb.log 2>&1 & x=$!; export DISPLAY=:99; sleep 1; timeout --signal=TERM --kill-after=2s 45s hatari --machine "${{ matrix.profile }}" --memsize ${{ matrix.profile == 'tt' && '4' || '1' }} --tos /runtime/roms/emutos.img --harddrive /runtime/artifacts --gemdos-drive C --auto MINIMAL.PRG --trace os_base,gemdos --trace-file /runtime/artifacts/hatari-boot-trace-${{ matrix.profile }}.log --log-level debug --log-file /runtime/artifacts/hatari-boot-debug-${{ matrix.profile }}.log --run-vbls 1500 >/runtime/artifacts/hatari-stdout-${{ matrix.profile }}.log 2>/runtime/artifacts/hatari-stderr-${{ matrix.profile }}.log; rc=$?; kill "$x" 2>/dev/null || true; wait "$x" 2>/dev/null || true; exit "$rc"' | |
| rc=$? | |
| set -e | |
| cat "artifacts/hatari-stderr-${{ matrix.profile }}.log" || true | |
| cat "artifacts/hatari-stdout-${{ matrix.profile }}.log" || true | |
| grep -Ei 'MINIMAL|PRG|Pexec|Fcreate|Fwrite|Fclose|GEMDOS|boot' "artifacts/hatari-boot-trace-${{ matrix.profile }}.log" 2>/dev/null | tail -n 300 || true | |
| if [ "$rc" -ne 0 ] && [ ! -s artifacts/MINPASS.TXT ]; then | |
| echo "ERROR: Hatari ended without guest marker (rc=$rc)" >&2 | |
| exit 1 | |
| fi | |
| test -s artifacts/MINPASS.TXT | |
| grep -F 'Ploos-AS atari-runtime minimal GEMDOS execution PASS' artifacts/MINPASS.TXT | |
| printf 'Canonical GEMDOS execution probe %s: PASS\n' "${{ matrix.profile }}" | |
| - name: Discover FreeMiNT TT snapshot payload | |
| if: matrix.profile == 'tt' | |
| run: | | |
| set -eux | |
| curl --fail --location --retry 3 https://atari.joska.no/snapshots/freemint/bootable/freemint-latest-aranym.zip -o /tmp/freemint-tt.zip | |
| unzip -l /tmp/freemint-tt.zip | tee artifacts/freemint-tt-snapshot-inventory.txt | |
| unzip -q /tmp/freemint-tt.zip -d artifacts/freemint-tt | |
| find artifacts/freemint-tt -type f \( -iname 'mint*.prg' -o -iname 'mint.cnf' -o -iname 'xaaes.km' \) -print | tee artifacts/freemint-tt-candidates.txt | |
| test -s artifacts/freemint-tt-candidates.txt | |
| - name: Build FreeMiNT 68030 kernel for TT | |
| if: matrix.profile == 'tt' | |
| run: | | |
| set -eux | |
| sudo apt-get update | |
| sudo apt-get install -y make bzip2 wget build-essential libc6-dev | |
| git clone --depth 1 https://github.com/freemint/freemint.git /tmp/freemint-src | |
| cd /tmp/freemint-src | |
| export CROSS_TOOL=m68k-atari-mint | |
| export PATH="/usr/${CROSS_TOOL}/bin:$PATH" | |
| SYSROOT_DIR=/tmp/mint-toolchain ./.scripts/install-freemint.sh binutils gcc mintbin mintlib libcmini | |
| compiler="$(find /tmp/mint-toolchain \( -type f -o -type l \) -name m68k-atari-mint-gcc -print -quit)" | |
| if [ -z "$compiler" ]; then | |
| echo "ERROR: m68k-atari-mint-gcc not found after toolchain install" >&2 | |
| find /tmp/mint-toolchain -maxdepth 4 \( -type f -o -type l \) -print | sort | tail -n 300 | |
| exit 1 | |
| fi | |
| toolbin="$(dirname "$compiler")" | |
| export PATH="$toolbin:$PATH" | |
| mint_include="$(find /tmp/mint-toolchain -type f -path '*/include/mint/mintbind.h' -printf '%h\n' | sed 's#/mint$##' | head -n1)" | |
| test -n "$mint_include" | |
| echo "MiNT toolchain compiler: $compiler" | |
| echo "MiNT include root: $mint_include" | |
| "$compiler" --version | |
| test -s "$mint_include/mint/mintbind.h" | |
| cd sys | |
| make 030 M68K_ATARI_MINT_CFLAGS="-isystem $mint_include" | |
| test -s .compile_030/mint030.prg | |
| cp .compile_030/mint030.prg "$GITHUB_WORKSPACE/artifacts/mint030.prg" | |
| file "$GITHUB_WORKSPACE/artifacts/mint030.prg" | |
| sha256sum "$GITHUB_WORKSPACE/artifacts/mint030.prg" | |
| { | |
| echo 'milestone=M4.3' | |
| echo 'profile=tt-freemint' | |
| echo 'emulator=Hatari' | |
| echo 'machine=tt' | |
| echo 'kernel=mint030.prg' | |
| echo 'kernel_build=PASS' | |
| } | tee "$GITHUB_WORKSPACE/artifacts/hatari-m4-3-tt-freemint-build.txt" | |
| - name: Boot FreeMiNT 68030 on Hatari TT | |
| if: matrix.profile == 'tt' | |
| run: | | |
| set -eux | |
| # Use a real FAT12 Atari disk image. Once FreeMiNT takes over, | |
| # Hatari GEMDOS host-directory emulation is no longer a valid | |
| # filesystem qualification path for the kernel. | |
| rm -f artifacts/tt-freemint.st | |
| dd if=/dev/zero of=artifacts/tt-freemint.st bs=1024 count=1440 | |
| mkfs.fat -F 12 -n MINTTT artifacts/tt-freemint.st | |
| mmd -i artifacts/tt-freemint.st ::/AUTO | |
| mmd -i artifacts/tt-freemint.st ::/MINT | |
| mmd -i artifacts/tt-freemint.st ::/MINT/1-19-CUR | |
| mcopy -i artifacts/tt-freemint.st artifacts/mint030.prg ::/AUTO/MINT030.PRG | |
| cat > /tmp/mint.cnf <<'EOF' | |
| # Ploos-AS atari-runtime M4.3 minimal TT FreeMiNT qualification. | |
| # The EXEC line is intentionally guest-side and runs only after | |
| # the FreeMiNT kernel has mounted its own FAT filesystem. | |
| # Keep the default FreeMiNT startup path; sh.tos below is our | |
| # libc-free guest execution probe. | |
| EOF | |
| cat > /tmp/ploosprobe.S <<'EOF' | |
| .text | |
| .globl _start | |
| _start: | |
| /* GEMDOS Fcreate("A:\\PLOOSPASS.TXT", 0) */ | |
| clr.w -(sp) | |
| pea filename | |
| move.w #0x3c,-(sp) | |
| trap #1 | |
| addq.l #8,sp | |
| tst.l d0 | |
| bmi.s fail | |
| move.w d0,d2 | |
| /* GEMDOS Fwrite(handle, length, marker) */ | |
| pea marker | |
| move.l #marker_end-marker,-(sp) | |
| move.w d2,-(sp) | |
| move.w #0x40,-(sp) | |
| trap #1 | |
| lea 12(sp),sp | |
| tst.l d0 | |
| bmi.s close_fail | |
| /* GEMDOS Fclose(handle) */ | |
| move.w d2,-(sp) | |
| move.w #0x3e,-(sp) | |
| trap #1 | |
| addq.l #4,sp | |
| /* GEMDOS Pterm0 */ | |
| clr.w -(sp) | |
| trap #1 | |
| close_fail: | |
| move.w d2,-(sp) | |
| move.w #0x3e,-(sp) | |
| trap #1 | |
| addq.l #4,sp | |
| fail: | |
| move.w #20,-(sp) | |
| move.w #0x4c,-(sp) | |
| trap #1 | |
| .data | |
| filename: | |
| .asciz "A:\\PLOOSPASS.TXT" | |
| marker: | |
| .ascii "Ploos-AS atari-runtime FreeMiNT Hatari TT execution PASS\\r\\n" | |
| marker_end: | |
| EOF | |
| assembler="$(find /tmp/mint-toolchain \( -type f -o -type l \) -name m68k-atari-mint-as -print -quit)" | |
| linker="$(find /tmp/mint-toolchain \( -type f -o -type l \) -name m68k-atari-mint-ld -print -quit)" | |
| test -n "$assembler" | |
| test -n "$linker" | |
| "$assembler" -m68030 -o /tmp/ploosprobe.o /tmp/ploosprobe.S | |
| "$linker" -s -e _start -o /tmp/PLOOSPRG.TOS /tmp/ploosprobe.o | |
| test -s /tmp/PLOOSPRG.TOS | |
| file /tmp/PLOOSPRG.TOS | |
| mcopy -i artifacts/tt-freemint.st /tmp/mint.cnf ::/MINT/1-19-CUR/MINT.CNF | |
| mcopy -i artifacts/tt-freemint.st /tmp/PLOOSPRG.TOS ::/MINT/1-19-CUR/sh.tos | |
| mdir -i artifacts/tt-freemint.st -/ :: | tee artifacts/hatari-m4-3-tt-freemint-disk.txt | |
| set +e | |
| docker run --rm \ | |
| -v "$PWD/artifacts:/runtime/artifacts" atari-runtime:m2 \ | |
| sh -c 'set +e; Xvfb :99 -screen 0 1024x768x24 >/tmp/xvfb.log 2>&1 & x=$!; export DISPLAY=:99; sleep 1; timeout --signal=TERM --kill-after=3s 90s hatari --machine tt --memsize 4 --tos /runtime/roms/emutos.img --disk-a /runtime/artifacts/tt-freemint.st --fastfdc yes --trace os_base,gemdos --trace-file /runtime/artifacts/hatari-m4-3-tt-freemint-trace.log --log-level debug --log-file /runtime/artifacts/hatari-m4-3-tt-freemint-debug.log >/runtime/artifacts/hatari-m4-3-tt-freemint-stdout.log 2>/runtime/artifacts/hatari-m4-3-tt-freemint-stderr.log; rc=$?; cp /tmp/xvfb.log /runtime/artifacts/hatari-m4-3-tt-freemint-xvfb.log; kill "$x" 2>/dev/null || true; wait "$x" 2>/dev/null || true; exit "$rc"' | |
| rc=$? | |
| set -e | |
| cat artifacts/hatari-m4-3-tt-freemint-stderr.log || true | |
| grep -Ei 'FreeMiNT|MiNT|PLOOS|panic|fatal|error' artifacts/hatari-m4-3-tt-freemint-{stdout,stderr,debug,trace}.log 2>/dev/null | tail -n 400 | tee artifacts/hatari-m4-3-tt-freemint-visible.log || true | |
| rm -f /tmp/PLOOSPASS.TXT | |
| mcopy -i artifacts/tt-freemint.st ::/PLOOSPASS.TXT /tmp/PLOOSPASS.TXT | |
| test -s /tmp/PLOOSPASS.TXT | |
| tr -d '\r' < /tmp/PLOOSPASS.TXT | grep -Fxq 'Ploos-AS atari-runtime FreeMiNT Hatari TT execution PASS' | |
| cp /tmp/PLOOSPASS.TXT artifacts/hatari-m4-3-tt-freemint-PLOOSPASS.TXT | |
| grep -Fq 'This is FreeMiNT v1.19.0-ALPHA' artifacts/hatari-m4-3-tt-freemint-stdout.log | |
| { | |
| echo 'milestone=M4.3' | |
| echo 'profile=tt-freemint' | |
| echo 'emulator=Hatari' | |
| echo 'machine=tt' | |
| echo 'cpu=68030' | |
| echo 'boot_media=FAT12-floppy' | |
| echo 'kernel=mint030.prg' | |
| echo 'kernel_build=PASS' | |
| echo 'kernel_boot=PASS' | |
| echo 'guest_exec=PASS' | |
| echo 'guest_marker=PASS' | |
| echo "hatari_exit=$rc" | |
| } | tee artifacts/hatari-m4-3-tt-freemint-result.txt | |
| - name: Verify Atari-side GEMDOS execution evidence | |
| run: | | |
| test -s artifacts/MINPASS.TXT | |
| grep -F 'Ploos-AS atari-runtime minimal GEMDOS execution PASS' artifacts/MINPASS.TXT | |
| file artifacts/MINIMAL.PRG |