Add support for booting ELFs from HDD (PFS) boot paths#18
Open
oMrRexD wants to merge 2 commits into
Open
Conversation
Boot paths like "hdd0:__common:pfs:/APPS/OPNPS2LD.ELF" previously hung on a red screen: the bootstrap loads ELFs with SifLoadElf and fio, and neither can interpret that path format nor read from pfs, which is an iomanX-only device invisible to rom0:LOADFILE/ioman. startgameExecute now recognizes hdd0:partition:pfs: paths, validates them with getMountInfo, remounts pfs0: on the target partition and checks the ELF exists, showing a proper error menu on failure instead of a red screen. The bootstrap gained LoadElfFromPFS, which loads the ELF manually through the fileXio RPC (still resident since the IOP is not reset on handoff), then performs the usual IOP reset and ExecPS2 with the original hdd0: path as argv[0], matching the uLaunchELF convention. Requires the HDD build and starting Cheat Device from the HDD, since the dev9/atad/ps2hdd/ps2fs modules are only loaded in that case; other configurations now show an explanatory error for hdd0: paths. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
OPL launches apps through ps2sdk's elf-loader, whose loader concatenates the partition and file path into argv[0], producing e.g. "hdd0:+OPL:pfs0:APPS/CheatDevice-HDD.ELF". CheatDevice only recognized the uLaunchELF-style ":pfs:" marker, so booting_from_hdd stayed 0, the dev9/atad/ps2hdd/ps2fs modules were never loaded, and main() still tried to mount the partition, failing with a misleading 'failed to mount partition "hdd0:+OPL" err:-19' (ENODEV, since the pfs device was never registered). The new pfsPathGetFilePart() helper accepts both ":pfs:" and ":pfsN:" markers and is now used for HDD boot detection, for Start Game HDD boot paths, and by the bootstrap's PFS loader, so OPL-style paths work everywhere. Additionally: - main() no longer parses the boot path or mounts pfs0: when not booted from HDD, removing the spurious boot path/mount errors when the HDD build is started from mc/mass. - loadModules() now reports DEV9.IRX load failures and bad HDD status with a nonzero return so the real error is displayed instead of a misleading mount failure later. - util.c declared 'extern char* error' for main.c's 'char error[255]', so any error sprintf in util.c would have written through a garbage pointer; it is now declared with the correct array type. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
I keep both OPL and CheatDevice on my PS2's internal HDD, and while trying to make my setup completely HDD-based I ran into a couple of issues.
First, launching CheatDevice from OPL's APPS tab always failed with
err:-19, forcing me to launch it through the OSD menu launcher or uLaunchELF instead.Second, after enabling cheats, Start Game couldn't boot OPL back from the HDD. It only worked if OPL was on a memory card or USB drive. Even keeping both ELFs in the same partition didn't help because the bootstrap couldn't load ELFs from PFS paths.
This PR fixes both issues, making it possible to launch CheatDevice from OPL, enable cheats, and return directly to OPL without relying on a memory card or USB device.
Changes
Booting ELFs from PFS partitions (
startgame.c,bootstrap/main.c)startgameExecute()now recognizeshdd0:partition:pfs:boot paths, validates them withgetMountInfo(), remountspfs0:on the target partition, and verifies that the target ELF exists before booting. Invalid paths now display an error menu instead of hanging on a red screen.LoadElfFromPFS(), which manually loads the ELF through the fileXio RPC while it is still available (before the IOP reset), then performs the usual IOP reset and callsExecPS2()with the originalhdd0:path asargv[0]. This matches the convention used by uLaunchELF, allowing applications such as OPL to determine their own location correctly.dev9,atad,ps2hdd, andps2fsare loaded. If the application was not started from the HDD, an explanatory error is shown instead of hanging.HDD boot detection when launched from OPL (
main.c,util.c)elf-loader, which buildsargv[0]in the formhdd0:+OPL:pfs0:APPS/CheatDevice-HDD.ELF. CheatDevice only recognized the uLaunchELF-style:pfs:format, sobooting_from_hddremained false, the HDD modules were never loaded, and mountingpfs0:later failed with the misleadingerr:-19(ENODEV).pfsPathGetFilePart(), which accepts both:pfs:and:pfsN:formats. It is now used by HDD boot detection, Start Game boot paths, and the bootstrap so all three components interpret HDD paths consistently.main()no longer attempts to parse HDD paths or mountpfs0:unless the application was actually started from the HDD, avoiding unnecessary errors when the HDD build is launched frommc:ormass:.loadModules()now propagates DEV9 initialization failures and HDD status errors so the actual error is reported instead of a later mount failure.util.c, whereextern char *errorreferred tochar error[255]frommain.c. Anysprintf()through that pointer would have written to an invalid address.Testing
Tested on a real SCPH-50001 PS2 with an internal HDD and OPL installed in the
__commonpartition.hdd0:__common:pfs:/APPS/OPNPS2LD.ELF✔+OPLpartition) ✔Both
makeandmake HDD=1build successfully using theroot670/ps2dev-dockerimage.Notes
This PR was developed with assistance from Claude Code.