Files
knutwurst--patchdl/scripts/deploy_ps5.sh
T
Knutwurst fb47730d70 Docs: README for 0.0.4 (cross-region install works, UI updates, filename)
README catches up to where the code is:

- The "cross-region install is a known limitation" section is gone. We
  route through sceAppInstUtilAppInstallPkg now, verified end-to-end on
  Dead Island 2 (01.000.001 -> 01.000.011, including the shared-storage
  case where the patch lives under a master title id).
- A Web UI section documents the filter chips (Updatable default,
  Updating separate bucket, All on the right) and Update all.
- Deploy section notes the new filename shape (patchdl_<version>.elf)
  so Payload Manager can parse the version out of it.

deploy_ps5.sh follows: UP_NAME is now patchdl_${VERSION}.elf to match
the released asset naming.
2026-06-24 21:16:31 +02:00

85 lines
3.0 KiB
Bash
Executable File

#!/bin/sh
# Deploy patchdl to the PS5 via the Payload Manager HTTP API (port 8084).
# The uploaded filename carries the version so it is identifiable in the
# Payload Manager UI. Any running instance is killed first (the payload's own
# self-kill is racy when the port is still held), so this is a clean redeploy.
#
# Usage: scripts/deploy_ps5.sh [PS5_HOST]
# PS5_HOST defaults to $PS5_HOST or ps5-slim.fritz.box
set -eu
ROOT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
HOST=${1:-${PS5_HOST:-ps5-slim.fritz.box}}
PM_PORT=${PM_PORT:-8084}
HTTP_PORT=${PATCHDL_HTTP_PORT:-12880}
VERSION=$(sed -n 's/.*PATCHDL_VERSION[^"]*"\([^"]*\)".*/\1/p' "$ROOT_DIR/src/patchdl_version.h")
[ -n "$VERSION" ] || { echo "could not read PATCHDL_VERSION" >&2; exit 1; }
SRC_ELF="$ROOT_DIR/patchdl-ps5.elf"
[ -f "$SRC_ELF" ] || { echo "build first: $SRC_ELF missing" >&2; exit 1; }
UP_NAME="patchdl_${VERSION}.elf"
TMP_ELF="$ROOT_DIR/$UP_NAME"
cp "$SRC_ELF" "$TMP_ELF"
echo "Uploading $UP_NAME to $HOST:$PM_PORT ..."
curl -fsS -m120 -X POST "http://$HOST:$PM_PORT/manage:upload?filename=$UP_NAME" \
-H 'Content-Type: application/octet-stream' --data-binary @"$TMP_ELF" >/dev/null
rm -f "$TMP_ELF"
PAYLOAD_PATH=$(curl -fsS -m15 "http://$HOST:$PM_PORT/list_payloads" | \
UP_NAME="$UP_NAME" python3 -c '
import os, sys, json
want = os.environ["UP_NAME"]
obj = json.load(sys.stdin)
paths = obj.get("payloads", obj) if isinstance(obj, dict) else obj
for p in paths:
if isinstance(p, str) and p.endswith(want):
print(p); break
')
[ -n "$PAYLOAD_PATH" ] || { echo "uploaded payload not found in list_payloads" >&2; exit 1; }
# Kill any running patchdl first so the new instance can bind the port
# deterministically (the in-payload self-kill races on the held socket).
echo "Stopping any running patchdl ..."
curl -fsS -m15 "http://$HOST:$PM_PORT/processes_list" 2>/dev/null | \
HOST="$HOST" PM_PORT="$PM_PORT" python3 -c '
import os, sys, json, urllib.request
obj = json.load(sys.stdin)
procs = obj if isinstance(obj, list) else obj.get("processes", [])
host, port = os.environ["HOST"], os.environ["PM_PORT"]
for p in procs:
if "patchdl" in str(p.get("name", "")).lower():
try:
urllib.request.urlopen("http://%s:%s/process_kill?pid=%d" % (host, port, int(p["pid"])), timeout=10).read()
print(" killed pid %d" % int(p["pid"]))
except Exception as e:
print(" kill pid %s failed: %s" % (p.get("pid"), e))
' || true
i=0
while [ "$i" -lt 8 ]; do
curl -fsS -m4 "http://$HOST:$HTTP_PORT/api/status" >/dev/null 2>&1 || break
sleep 1
i=$((i + 1))
done
echo "Launching $PAYLOAD_PATH ..."
curl -fsS -m20 "http://$HOST:$PM_PORT/loadpayload:$PAYLOAD_PATH" >/dev/null
printf "Waiting for web server on :%s " "$HTTP_PORT"
i=0
while [ "$i" -lt 20 ]; do
if curl -fsS -m4 "http://$HOST:$HTTP_PORT/api/status" >/dev/null 2>&1; then
echo " up."
curl -fsS -m6 "http://$HOST:$HTTP_PORT/api/status"; echo
echo "UI: http://$HOST:$HTTP_PORT/"
exit 0
fi
printf "."
sleep 2
i=$((i + 1))
done
echo " timeout — server did not answer." >&2
exit 1