Initializing the PS2/PSX

Originally posted here: https://assemblergames.com/threads/initializing-the-playstation-2-from-cold-boot.67794/

Introduction

As promised, I would do a write-up to share about how the PS2 is to be initialized, from within an memory-card update program.

However, I am still reverse-engineering and updating my code from FMCB, so that they'll be more usable for external projects... so I don't really have any code to show at the moment I am writing this. Over time, I will make new posts to elaborate on things that I don't elabore here.

I have decided to consoliate the OSD init stuff into a new library, named libosdinit. It may make things easier for new software to work with the OSD configuration.

Although we have various samples floating around the Internet in the form of the FreeVast and FMCB v1.7 source code, I found that FMCB v1.8 did not quite have an accurate method of initializing the PS2.

I won't get into the basics of initializing SIFRPC/SIFCMD services, as those are the basics required for each project.

Initializing the PS2

Things that need to be done:

//Reboot IOP

while(!SifIopReset("", 0)){};

while(!SifIopSync()){};

//Reboot IOP

while(!SifIopRebootBuffer(psx_ioprp, size_psx_ioprp)){};

while(!SifIopSync()){};

SetMemoryMode(1);

_InitTLB();

Code:

int fd;

char romver[16], RomName[4];

 if((fd = open("rom0:ROMVER", O_RDONLY)) >= 0)

{

       read(fd, romver, sizeof(romver));

       close(fd);

       // E.g. 0160HC = 1,60,'H','C'

       RomName[0]=(romver[0]-'0')*10 + (romver[1]-'0');

       RomName[1]=(romver[2]-'0')*10 + (romver[3]-'0');

       RomName[2]=romver[4];

       RomName[3]=romver[5];


       sceCdBootCertify(RomName);

}

Code:

   do{

       sceCdForbidDVDP(&result);

   }while(result&8);

Code:

InitOsd();

Code:

   int result;

   ConfigParam config;

   Config2Param config2;


   <Load and parse configuration here. config.version is set to 2, as FMCB implements the configuration mechanism from a late ROM>


   SetOsdConfigParam(&config);

   GetOsdConfigParam(&config);

   //Unpatched Protokernels cannot retain values set in the version field, and don't support SetOsdConfigParam2().

   if(config.version) SetOsdConfigParam2(&config2, 4, 0);

Code:

   SetGsVParam(config.videoOutput?1:0);


Compatibility Across PS2 Models

OSD Initialization Libraries + Example

This package contains various files that are related to the initialization of the PlayStation 2 and the launching of the DVD Player. FMCB v1.96 and later use code based on this project.

The package contains various OSD-related files:

Most of the files were based on the OSD from ROM v2.20, which has a late design.

Notes regarding the PSX example

The PSX's OSDSYS differs from the standard PS2's, whereby it isn't a fully-function dashboard on its own. It will also perform the boot certification step, which is why it is not necessary. The PSX's EE has 64MB and its IOP has 8MB. Similar to the TOOL, the memory capacity can be limited to 32MB with the TLB.

It also has a dual-mode CD/DVD drive - by default, it starts up in writer ("Rainbow") mode. In this mode, the usual registers do not work. The PSX also has a "QUIT GAME" button, which must be enabled by "notifying" the MECHACON of the game mode with sceCdNotifyGameStart().

To build the PSX example, set the PSX variable in the Makefile to 1.

Notes regarding disc-booting

The example shows how the browser boots PlayStation and PlayStation 2 game discs. The browser does not parse SYSTEM.CNF to determine what ELF to boot, but uses SYSTEM.CNF to verify that the ID obtained from DRM matches. Your software does not need to do this (it is not even done with FMCB). However, using the same method as the browser for parsing SYSTEM.CNF is good for ensuring that exactly the same behaviour as the official browser is guaranteed. There was also code that directly accessed the hardware, to check that the appopriate type of disc is inserted. Such code has been omitted, as I feel that they were meant to enforce the DRM and increases coupling with the hardware.

Notes regarding the DVD Player

The SCPH-10000 and SCPH-15000 have no DVD Player built in, as no DVD ROM chip is installed.  This is much like the DEX, TOOL and PSX consoles. Starting from the SCPH-75000, the DVD ROM became universal, containing the DVD players from all regions.  However, this requires the code to query the console for the MagicGate region.

Notes regarding the functions within OSDHistory

icon.sys

The icon.sys file generated usually uses "_SCE8" as its icons. "_SCE8" usually refers to an icon that is part of the browser. The icon.sys file for US (icon_A.sys), Japan (icon_J.sys) and China (icon_C.sys) are reproductions of the icons that are found in the browser. While each icon.sys file is assumed to be 964 bytes in length (like normal icon.sys files), the browser always writes 1776 bytes of data when writing icon.sys. The icon is written, along with the data after it. If the correct number of bytes (964) is written, the HDD Browser appears to deem the icon as invalid.

ICOBYSYS

 When the console is not a US/Asian, European or Japanese console, the icon (ICOBYSYS) is written to the memory card as "_SCE8" (along with icon.sys). This leaves the Chinese (SCPH-50009) and DEX consoles (typically have an 'X' for the region) as potential targets for this code, even though these consoles appear to support "_SCE8" without problems.

However, as ICOBYSYS belongs to Sony, it is not part of this package. If you want to have a complete system, you need to provide ICOBYSYS as icons/icobysys.icn and change WRITE_ICOBYSYS in the Makefile to 1.

Known limitations

System Driver Update

The System Driver Update is set of patches for the OSDSYS of ROM v1.0x.

This package contains the source code for clones of the OSDSYS patches, meant for ROM v1.00 and v1.01. As with the OSD update files, these files were meant to be encapsulated as KELFs. But I will not cover that here.

The first PlayStation 2 consoles (SCPH-10000 & SCPH-15000) had a considerably different boot ROM from the expansion-bay consoles. Other than having the earliest-possible IOP and EE kernels, their OSDSYS programs were coded rather differently and had a design flaw that prevented arguments from being passed to memory-card updates.

These are the original update files and their descriptions:

Code:

Model                 ROM             Update File  Description

SCPH-10000            0100JC20000117  osdsys.elf   OSDSYS patch (patch0100).

SCPH-10000/SCPH-15000 0101JC20000217  osd110.elf   System Driver Update + OSDSYS patch (patch0101).

SCPH-18000            0120JC20001027  osd130.elf   System Driver Update + OSDSYS patch (patch0101). Exactly the same in content as osd110.elf.

These patches will copy a small ROM image that contains a replacement EELOAD program, into kernel memory (0x80030000). It will then patch the EE kernel to scan 0x80030000-0x80040000 for the EELOAD, instead of the boot ROM.

The System Driver Update attempts to boot the HDD-based update from the HDD unit. While the SCPH-18000 contained a modern ROM that did not have the same deficiencies as its predecessors, it is incapable of supporting the CXD9566R PCMCIA controller of the SCPH-18000. As a result, it needed extra help to boot updates from the HDD unit.

osd110.elf and osd130.elf are the main executables of the system driver update, which also contain a patch that is similar to the code within osdsys.elf, which install a replacement EELOAD program that will replace rom0:EELOAD. This patch targets OSDSYS from ROM v1.01J, and does nothing for other ROM versions. As a result, its patches are also different from the ones that osdsys.elf applies (see below).

EELOAD Replacement

This EELOAD replacement within osd110.elf and osd130.elf will wait for a request that boots rom0:OSDSYS, before loading rom0:OSDSYS and applying a few fixes to it:

Once the OSDSYS-patching code within EELOAD is run, its effects are binding until the console is hard-reset or powered off.

Modifications for FMCB, which this package has

FMCB sits in for the System Driver Update. To save space, I made osd110.elf similar to osdsys.elf; instead of being a full system driver update, it will patch OSDSYS to boot osd130.elf. The osdsys.elf patch was also made to boot osd130.elf directly, hence allowing only one copy of the system driver update to exist.

Official path of execution:

New (unofficial) path of execution:

Notes for compilation

These patches are split into two parts: The main program and an ROM image that contains EELOAD. It is possible to build the patch without rebuilding EELOAD, by just entering "make".

The EELOAD module is a binary file, built to be loaded at 0x00082000. To build a ROM image, you need a tool (i.e. ROMIMG). If you wish to rebuild EELOAD, you need to:

Other Trivia

MBR Program

This package contains the source code for the homebrew MBR program, which aims to function similarly to the Sony MBR program, which is used for booting HDDOSD installations.

It supports the same integrity checks as the Sony MBR program, and boots one of the following KELF targets:

If the HDD has been deemed to have filesystem corruption, FSCK in one of these locations will be launched, in this order:

Failing to do so, it'll fall back to the OSD.

FSCK is linked to at the bottom of this page. I seem to have provided it from somewhere because it was uploaded in 2016, but I do not remember where. Anyway.

MBR Structure

This MBR is split into two parts: The main program and an embedded EELOAD module, which is used to load the HDDOSD.

The embedded EELOAD module is hardcoded in the MBR program to expect the EELOAD module to run at 0x00084000.

Unlike rom0:EELOAD and various other EELOAD programs, the SDK used to build the MBR has the alarm functions patch (which resides at 0x00082000).


The MBR program itself must run from 0x00100000 when decrypted by rom0:HDDLOAD or by a Sony OSD update.


Both programs are headerless, binary blobs of code.

Additional note: this MBR program is not a drop-in replacement for the PSBBN's MBR program. That one has more functionality.

The "MBR" is the first program that the ROM/System Driver Update will boot, when booting a HDD update.


As with any update file, the MBR program is meant to be stored within an appropriate KELF, but that will not be covered here. 

HDDLOAD

The HDDLOAD module is used for loading a bootstrap program from the __mbr partition of the attached HDD unit. The program is expected to be an appropriately-flagged KELF.

Some PlayStation 2 consoles like the SCPH-10000, SCPH-15000 and SCPH-18000 do not support their HDD units, so the Sony HDD Utility Disc may be used to install a "System Driver Update" that adds the ability to boot from the HDD.

While not applied by Sony, it is possible to use this system to boot a HDD update on the SCPH-700xx.

This update will boot a HDDLOAD module, which works similarly to the one found in the boot ROM.


This package contains the source code a clone of the HDDLOAD module, based on a module from the 1.60 ROM. It depends on dev9.irx and atad.irx.


Workflow


Configuration

The IOP side will access the configuration storage area which is set up by EELOAD, which resides at 0x000003c0. This is loaded from the MECHACON's NVRAM storage.

Bits:

1 = Disable ATAD. By default, this is not set.

2 = Disable HDD support. PS2 consoles come with this bit set.  

So if the HDD browser was never installed on the PS2, HDD support is disabled. Which results in HDDLOAD switching off the HDD immediately after the program is loaded.


ATAD check

As described above, the ATAD module from the boot ROM is a combination of DEV9 and ATAD from the Sony PS2 SDK. It will also check whether ATAD is enabled.

This bit is not set by default (ATAD is enabled by default). This is what the ATAD module checks:

static int CheckATADEnabled(void){

return(!((*(*(vu8 **)0x000003c0))&1));

}


Enabling HDD support

As shown in the FMCB Installer, the following can be done from the EE to enable HDD booting on the PS2. This should be done during installation:


static int EnableHDDBooting(void){

int OpResult, result;

unsigned char OSDConfigBuffer[15];


do{

sceCdOpenConfig(0, 0, 1, &OpResult);

}while(OpResult&9);


do{

result=sceCdReadConfig(OSDConfigBuffer, &OpResult);

}while(OpResult&9 || result==0);


do{

result=sceCdCloseConfig(&OpResult);

}while(OpResult&9 || result==0);


if((OSDConfigBuffer[0]&3)!=2){ //If ATAD support and HDD booting are not already activated.

OSDConfigBuffer[0]=(OSDConfigBuffer[0]&~3)|2;


do{

sceCdOpenConfig(0, 1, 1, &OpResult);

}while(OpResult&9);


do{

result=sceCdWriteConfig(OSDConfigBuffer, &OpResult);

}while(OpResult&9 || result==0);


do{

result=sceCdCloseConfig(&OpResult);

}while(OpResult&9 || result==0);


result=0;

}

else result=1;


return result;

}


Downloads/Links

NEW OSD Initialization Libraries + Example (2019/12/07): https://www.mediafire.com/file/d6rfx7qjzz2pk57/%5B191207%5Dosd.7z/file 

OSD Initialization Libraries + Example (2018/08/25): http://www.mediafire.com/file/xpd3qt5p60k4pb6/%5B180825%5Dosd.7z/file 

MBR (2019/01/07 - link corrected on 2023/03/11): https://www.mediafire.com/file/ikf8hy2y0fs5j8j/%255B190107%255Dmbr.7z/file

kpatch (2018/01/29): http://www.mediafire.com/file/0cvbca36fbwv14p/%5B180129%5Dkpatch.7z/file

HDDLOAD (2018/07/09, uploaded on 2023/03/11): https://www.mediafire.com/file/yhngtx1vjcw9dez/%255B180709%255Dhddload.7z/file

FSCK (2016/12/16, link added on 2023/03/11): https://www.mediafire.com/file/33gjpud1kh1pcdf/%255B161216%255DFSCK.7z/file

Note: the latest example (released today on 7th December 2019) was restructured to include code for the PSX, but I have not tested anything. Hence I am keeping the download link to the previous version as well, in case the new bundle doesn't work and doesn't serve well as an example.