Skip to content

Add support for booting ELFs from HDD (PFS) boot paths#18

Open
oMrRexD wants to merge 2 commits into
israpps:masterfrom
oMrRexD:hdd-boot-path-support
Open

Add support for booting ELFs from HDD (PFS) boot paths#18
oMrRexD wants to merge 2 commits into
israpps:masterfrom
oMrRexD:hdd-boot-path-support

Conversation

@oMrRexD

@oMrRexD oMrRexD commented Jul 7, 2026

Copy link
Copy Markdown

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 recognizes hdd0:partition:pfs: boot paths, validates them with getMountInfo(), remounts pfs0: 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.
  • Added 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 calls ExecPS2() with the original hdd0: path as argv[0]. This matches the convention used by uLaunchELF, allowing applications such as OPL to determine their own location correctly.
  • Booting from PFS requires the HDD build to have been started from the HDD, since that's when dev9, atad, ps2hdd, and ps2fs are 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)

  • OPL launches applications through ps2sdk's elf-loader, which builds argv[0] in the form hdd0:+OPL:pfs0:APPS/CheatDevice-HDD.ELF. CheatDevice only recognized the uLaunchELF-style :pfs: format, so booting_from_hdd remained false, the HDD modules were never loaded, and mounting pfs0: later failed with the misleading err:-19 (ENODEV).
  • Added 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 mount pfs0: unless the application was actually started from the HDD, avoiding unnecessary errors when the HDD build is launched from mc: or mass:.
  • loadModules() now propagates DEV9 initialization failures and HDD status errors so the actual error is reported instead of a later mount failure.
  • Fixed an incorrect declaration in util.c, where extern char *error referred to char error[255] from main.c. Any sprintf() 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 __common partition.

  • Booting OPL through Start Game using hdd0:__common:pfs:/APPS/OPNPS2LD.ELF
  • Launching CheatDevice-HDD.ELF from OPL's APPS tab (+OPL partition) ✔
  • Launching from uLaunchELF still works as before ✔

Both make and make HDD=1 build successfully using the root670/ps2dev-docker image.

Notes

This PR was developed with assistance from Claude Code.

oMrRexD and others added 2 commits July 5, 2026 11:14
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant