5.2 KiB
Development
This document describes how to build and deploy the Payload Manager.
How to Build
1. Build the Frontend
You must build the React UI first. This converts the JSX into the dist/index.html file that gets embedded.
make frontend-build
2. Build the SDK Docker Image
If you haven't already, build the SDK environment:
docker build -t ps5-payload-sdk -f Dockerfile.sdk .
3. Build the ELF
Use the Docker container to compile the Payload Manager. It is recommended to run make clean if you updated the frontend.
docker run --rm -v $(pwd):/src -w /src ps5-payload-sdk make clean all
The resulting pldmgr.elf will be created in the root directory.
Automated Deploy
For a quick build & deploy cycle, use the deploy.sh script. It will automatically call /shutdown on the PS5, run the docker build, and send the new ELF via socat.
./deploy.sh [PS5_IP]
(Requires PS5 IP as the first argument).
Manual Deploy
- Upload
pldmgr.elfto your PS5 (e.g., via port 9021). - The menu will be available at
http://[PS5_IP]:8084.
Automated Verification
The HTTP response suite compiles the actual src/http_server.c with stubbed
PS5 services and real libmicrohttpd response objects. It injects response-buffer,
response-creation, CORS-header, queue, reallocation, and file I/O failures, then
sends 10,000 requests through a real loopback HTTP server. It also checks
disconnected/chunked requests, concurrent uploads, and server-stop cleanup in
thread-per-connection mode. ASan (including leak detection) and UBSan
are enabled by default. Test files, storage paths, and binaries are temporary;
the suite does not connect to a console or launch payloads.
On a host with Clang, its sanitizer runtime, Python 3, pkg-config, and libmicrohttpd/libcurl development files installed:
make test-host
make test-frontend
The container option builds libmicrohttpd 1.0.1, matching build_deps.sh:
docker build -f tests/Dockerfile -t ps5-payload-manager-tests .
docker run --rm --network=none -v "$(pwd):/src:ro" ps5-payload-manager-tests make test-host
The build downloads test dependencies; the test container itself has external
networking disabled. Linux sanitizer support is included in the image. The
optional --no-sanitize argument is for hosts without sanitizer support; use
the default sanitizer run for verification.
The JSON encoder suite compiles actual src/utils.c and checks its output with
Python's independent JSON and UTF-8 decoders. It covers Unicode, all non-NUL
control bytes, invalid UTF-8 replacement, every small escape/scalar boundary,
truncation status, and guarded destination bounds, with ASan/UBSan enabled.
C strings cannot represent embedded NUL. The decoder rejects decoded NUL in the
requested value, while accepting valid escaped NUL in unrelated fields.
The decoder suite passes exact, non-NUL-terminated buffers to actual
src/json_helpers.c; it checks bounds, direct-member selection, all escapes,
UTF-8, surrogate pairs, malformed input, and strict/prefix overflow contracts.
Objects are validated completely with a nesting limit of 64. Strict extraction
clears the result on overflow; descriptions/release notes explicitly opt into
UTF-8-safe prefixes. The backend suite uses real repository, source save/load,
and slot metadata read/write code inside temporary storage. It parses their
results independently with Python. Unused network/PS5 code is discarded at
link time, and no download or payload launch occurs. make test-host runs all
four host suites with sanitizers.
.github/workflows/verify.yml runs all host suites, existing frontend tests,
and frontend build without publishing or deploying. Frontend lint still reports existing errors. The host suite tests response
ownership/status handling, request cleanup, and autoload-list bounds. Storage
transactions, autoload worker concurrency, and PS5 firmware behavior remain
separate validation scopes. Backend storage/service calls in the HTTP tests are
stubbed; successful mock imports move actual files inside temporary fixtures.
The HTTP server accepts config/source bodies up to 1 MiB and streamed uploads
up to 512 MiB. Larger declared or accumulated bodies return HTTP 413; empty
request bodies return HTTP 400. Upload staging files use private, unique
.upload-* names and are removed by request teardown if uncommitted. This does
not purge older orphan files or guarantee cleanup after power loss/SIGKILL.
Autoload CSV responses currently allow 4,095 bytes; larger/unreadable lists return
HTTP 500 with JSON rather than a truncated list.
Native compilation remains a separate gate. To preserve the previous ELF,
build a candidate under scratch/ rather than run make clean:
mkdir -p scratch
docker run --rm --network=none -v "$(pwd):/src" -w /src \
ps5-payload-sdk-pldmgr make ELF=scratch/pldmgr-candidate.elf
This command assumes the SDK image, frontend distribution, and embedded CA header already exist. For a new checkout, follow the normal build setup first. The ELF target currently does not track ordinary header dependencies; use a new candidate filename or force the ELF target to rebuild after header-only edits.