Editing Iplloader
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
The PRE-IPL, called "Lib-PSP iplloader" internally by sony, is the first code to run in PSP MIPS32 main CPU. Its role is to load the [[Initial Program Loader]]. PRE-IPL is where the routines to boot into service mode are and loads & decrypts the encrypted IPL from the nand/MS). | |||
Its role is to load | |||
= Location = | = Location = | ||
On retail PSP units | On retail PSP units PRE-IPL is read from the Tachyon (Allegrex MIPS R4000 based SOC) boot rom. On DTP-T1000 it is loaded externally. | ||
The PSP main CPU is a custom-made Sony CPU with a MIPS32 core and has an embedded mask rom device (like most embedded systems do) which is exactly 4KB in size. This device holds the | The PSP main CPU is a custom-made Sony CPU with a MIPS32 core and has an embedded mask rom device (like most embedded systems do) which is exactly 4KB in size. This device holds the PRE-IPL. This PRE-IPL mask rom device is mapped to physical address 0x1FC00000 (this is the address of reset exception vector on MIPS CPUs), and this is where the CPU starts executing from coldboot. | ||
= Structure = | = Structure = | ||
The | The PRE-IPL is made up of 2 parts, the "loader", and the "payload". | ||
TODO | |||
A few | = PRE-IPL Versions = | ||
A few example of PRE-IPL payload sizes and hashes are: | |||
{| class="wikitable" style="text-align: center" | {| class="wikitable" style="text-align: center" | ||
! SDK Version | |||
! SDK Version | |||
! Date (DD-MM-YYYY) | ! Date (DD-MM-YYYY) | ||
! Payload Size | ! Payload Size | ||
! Hash | ! Hash | ||
|- | |- | ||
| Tachyon 0x00140000-0x00300000 | |||
| 20-04-2004 (build date in ROM) | |||
| 0xAF8 | |||
| SHA-256: 48F4F11C383621C8569EC07273AE0AF6AD79681CF5B77263A69CF908EEFE4A53 (ROM) | |||
|- | |- | ||
| 0.4.0 | |||
| 23-07-2004 (or older/last modified date for kbooti.bin) | |||
| n/a | |||
| SHA-256: 18B5BF7AEFE956D99B397AAAAC94DC965ADFDBC2BE0532096BBC1F8F8C5B7C34 (Full Binary) | |||
|- | |- | ||
| 0.6.0 | |||
| 08-09-2004 (or older/last modified date for kbooti.bin) | |||
| n/a | |||
| SHA-256: 5CDEDDEBE11807DDAEB17BAC03945A0B828E8057C9587652CA207E3BB959AC96 (Full Binary) | |||
|- | |- | ||
| 0.7.0 | |||
| 18-09-2004 (build date in the payload) | |||
| 0x894 | |||
| SHA-256: 351ECD64C945489999D477ECAFBFBB8FE769C2484636D2F7323557F7EEFD54A2 (payload only) | |||
SHA-256: 388FA1DB87973A2A37D576AAAB785D840CA4D883AB5111781DA2D0AF59CFE667 (Full decrypted binary) | |||
SHA-256: 388FA1DB87973A2A37D576AAAB785D840CA4D883AB5111781DA2D0AF59CFE667 (Full | |||
|- | |- | ||
| 0.9.0 | |||
| 15-10-2004 (build date in the payload) | |||
| 0x894 | |||
| SHA-256: 4F794E4FF32D5267AEAEDBA362D005EF0B7E93E29CF7C8209E0D9DBB0144F4DB (payload only) | |||
SHA-256: E415198C16E29D96C9232FF78272EE639D0630A56E370ED18A33D358FEF7CA95 (Full decrypted binary) | |||
SHA-256: E415198C16E29D96C9232FF78272EE639D0630A56E370ED18A33D358FEF7CA95 (Full | |||
|- | |- | ||
| Tachyon 0x00400000-0x00500000 | |||
| 04-01-2005 (build date in ROM) | |||
| 0xB30 | |||
| SHA-256: 41B2578F84BDE33E09356F0170FF99E2417EA7B1D02BD9163A41AE61FE74C3A5 (ROM) | |||
|- | |- | ||
| 2.6.0 | |||
| 22-10-2005 (build date in the payload) | |||
| 0xBF4 | |||
| SHA-256: 8821D96F5FB35C55DF649A97F5703F8A705362C2F54665B5EE4221E686B5578A (payload only) | |||
SHA-256: 0A83CB36F1FE7C2A9A53BD46E6FFD915D4D1BB97EED3D1EF336960DB752C3446 (Full decrypted binary) | |||
SHA-256: 0A83CB36F1FE7C2A9A53BD46E6FFD915D4D1BB97EED3D1EF336960DB752C3446 (Full | |||
|- | |- | ||
| 2.7.1 | |||
| 14-02-2006 (build date in the payload) | |||
| 0xBF4 | |||
| SHA-256: F9160C03EC6174F54F1C1EB645CFBBDB65B3DA47DA1A5478BE30E5EB2B0852B4 (payload only) | |||
SHA-256: 7DDFF7093906C10BA11D7402E9939763173F1ADEA59A38B4006484FD18EA21EA (Full decrypted binary) | |||
SHA-256: 7DDFF7093906C10BA11D7402E9939763173F1ADEA59A38B4006484FD18EA21EA (Full | |||
|- | |- | ||
| 3.5.0 | |||
| 12-02-2007 (build date in the payload) | |||
| 0xC74 | |||
| SHA-256: 0F9B33F693704F21AAF481CEBF6FCEBE68E6637E1CB243E2316F3D580DCB4362 (payload only) | |||
|- | |- | ||
| | | 0.931-0.995 (inside PSVita Compatibility Secure Module) | ||
| | | 11-17-2010 (last modified date for 0.940I compat_sm.self) | ||
| 0x2C0 | |||
| | | SHA-256: 6D75EC720739C53228B1CA1AFF6CE073AE542BBB38FCC9B8710EC5EB3889B942 (Full Binary) | ||
|- | |- | ||
| | | 0.996.070-0.996.090 (inside PSVita Compatibility Secure Module) | ||
| 07-22-2011 (last modified date for compat_sm.self) | |||
| | | 0xD34 | ||
| | | SHA-256: E09B36DE655A441D2C94D39EF7BBC505EAB1722E9380EBE73E9E6A7DC88D9731 (Full Binary) | ||
|- | |- | ||
| | | 1.000.041-1.06 (inside PSVita Compatibility Secure Module) | ||
| 08-30-2011 (last modified date for compat_sm.self) | |||
| 0xDB4 | |||
| | | SHA-256: C2AE6939BC4B06CB4A81415E27EB1E7129C561B9C16C3AAFF6FDEBBAB48EBD09 (Full Binary) | ||
|- | |- | ||
| | | 1.50-1.81 (inside PSVita Compatibility Secure Module) | ||
| 12-14-2011 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| | | SHA-256: 522851781DD82F89D69EBFE0F25C3E7CFE5899A53E850F2F979AD1B0E53376F9 (Full Binary) | ||
|- | |- | ||
| | | 2.00-2.05 (inside PSVita Compatibility Secure Module) | ||
| 11-16-2012 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| | | SHA-256: A9A097ED8925B83A210202AA4C943011C05FE48028BA6E05E85E1494143B0100 (Full Binary) | ||
|- | |- | ||
| | | 2.06-2.12 (inside PSVita Compatibility Secure Module) | ||
| 02-22-2013 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 25E22C1D988609AA948F103E1312297F9533CA689B3C1BDC2CECBBC43997D566 (Full Binary) | |||
|- | |- | ||
| 2.50-3.01 (inside PSVita Compatibility Secure Module) | |||
| 06-27-2013 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 187DD28ADAD4167F3849392D570CA5A56DEEC608156D0EC6F2453958B1DB9672 (Full Binary) | |||
|- | |- | ||
| | | 3.10-3.20 (inside PSVita Compatibility Secure Module) | ||
| 12-05-2013 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: EF7D498295E416CCBD79FED78656E683DA1DCBC7B88C521DF0A1E00F5EC450FE (Full Binary) | |||
|- | |- | ||
| | | 3.30-3.35 (inside PSVita Compatibility Secure Module) | ||
| 09-25-2014 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 7DF591C05BF66292B6868CE4331A1DC11B7A0E421D082971E9CA65C7236B6843 (Full Binary) | |||
|- | |- | ||
| 3.36-3.50 (inside PSVita Compatibility Secure Module) | |||
| 01-09-2015 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 7E66976C311F5D3797A30B09DC608A0FA2E67EAA060097423CFD2E5FC89A57D9 (Full Binary) | |||
|- | |- | ||
| 3.51-3.55 (inside PSVita Compatibility Secure Module) | |||
| 05-12-2015 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 6E869E08CCE41E0AA0D386DE8936F81F66CABB20B964C3EF2159548852F39F30 (Full Binary) | |||
|- | |- | ||
| 3.57-3.63 (inside PSVita Compatibility Secure Module) | |||
| 11-25-2015 (last modified date for compat_sm.self) | |||
| | | 0xE34 | ||
| SHA-256: 047366634210449C62FD813B3BFDA6267A1FA8683BA17901A214FC32E473A35F (Full Binary) | |||
|- | |- | ||
| 3.65-3.70 ?3.73? (inside PSVita Compatibility Secure Module) | |||
| 03-17-2017 (last modified date for compat_sm.self) | |||
| 0xE34 | |||
| SHA-256: B5EF4FB2C84D629B2BDC9A70A4B8E5A7EC31CD9EA330E309361C80A9A96B65C5 (Full Binary) | |||
|} | |} | ||
= Behaviour = | = Behaviour = | ||
== | == PRE-IPL Boot Sequence == | ||
=== | === Part1 PRE-IPL (the loader) === | ||
Because the | Because the PRE-IPL is stored in non-volatile read-only memory it cannot use variables, so the Part1 PRE-IPL code (the loader) copies the Part2 PRE-IPL (the payload) to the CPU's scratchpad RAM (the only RAM available at this time, along with another 4KB block of RAM and the 2MB EDRAM - normal DDR SDRAM hasnt been initialised yet). The scratchpad RAM is mapped to physical address 0x00010000, and after Part1 has finished copying Part2 to it, it jumps to this new address. | ||
=== Part2 PRE-IPL (the payload) === | |||
Now the CPU is executing from the scratchpad RAM (the PRE-IPL payload). The PRE-IPL payload inits the nand hardware and reads the IPL nand-block-table (a table with the physical block numbers of the encrypted IPL's location on the nand). The table is located at the 4th physical block of the nand (offset 0x10000), and is repeated for the next 7 blocks. This is so that if a bad block occurs in any of these blocks, the table can still be read. Though if all 8 blocks become bad blocks, its a non-recoverable brick as the PRE-IPL can no longer locate the IPL's location (the only solution to this problem is to either boot from MS instead, or use a custom IPL to patch the PRE-IPL to remap the table - both of which would still require Pandora). | |||
The entire raw IPL is stored on the nand encrypted. The PRE-IPL payload uses a 4KB RAM (this RAM is mapped to physical address 0x1FD00000, but will later be remapped to 0x1FC00000 to be used for the ME CPU reset exception vector) as a temporary location to load & decrypt each encrypted IPL block. Because this RAM is only 4KB in size, the encrypted IPL is organised as 4KB blocks on the nand. As the PRE-IPL decrypts each of the 4KB IPL blocks, it loads the decrypted blocks to the IPL entry address 0x040F0000 (this address is located in the 2MB EDRAM which is normally used as VRAM, normal DDR RAM still has not been initialised yet). When the PRE-IPL has finished decrypting and loading all the encrypted IPL blocks, it jumps to the IPL entry address. | |||
The entire raw IPL is stored on the | |||
== Memory mapping == | == Memory mapping == | ||
The | The PRE-IPL is mapped to 0xBFC00000 which is the reset vector of PSP's MIPS R4000 CPU. | ||
0.7.0 | 0.7.0 PRE-IPL and onward are composed of two parts: a loader from 0xBFC00000 to 0xBFC0027F and a payload from 0xBFC00280 and ending at the size specified at 0xBFC000034 (little endian 0x2 bytes). | ||
PSVita's PRE-IPL from version 0.996 and onward's payload starts at 0xbfc00180, rather than 0xbfc00280 on previous and PSP hardware versions. | |||
== | == Devkit behaviour == | ||
=== bloadp === | === bloadp === | ||
bloadp is used to send kbooti binaries (encrypted | bloadp is used to send kbooti binaries (encrypted PRE-IPL data from 0x0 to 0x1000 and IPL blocks at 0x1000) to the DTP-T1000. | ||
bloadp (through tachsm) | bloadp will (through tachsm) initialize the 0x1D600000 memory (from /dev/mem or 0x00000000 from /dev/tachsm0 ; /dev/tachsm1 is mapped from 0x1D400000 to 0x1D5FFFFF) on the [http://www.psdevwiki.com/ps3/Communication_Processor Communication Processor] side (0x200000 in size, 0x100000 on the tachsm0 device) which is the DTP-T1000 PSP Shared memory, on the psp/tachyon side it is mapped to 0xBFE00000, it will then write the kbooti binary at 0x1D600000, however on SDK 0.5.0 and below dstdb (which bloadp was originally a part of), it was possible to specify the address to which kbooti would be loaded (default address to be specified was 0xbfc00000, the allowed range was 0xbfc00000-0xbfc10000), this in effect would write kbooti to 0x1D600000/0xBFE00000 + the address specific in the range -0xbfc00000, so for instance if 0xbfc02000 was specified, this would write kbooti to 0xBFE02000, keep in mind that the actual 0xBFC00000 memory mirrors itself every 0x1000 segments. | ||
If bloadp is never invoked, 0x1D700000 to 0x1D7FFFFF is uninitialized memory. It is cleared out as soon as bloadp is invoked. | If bloadp is never invoked, 0x1D700000 to 0x1D7FFFFF is uninitialized memory. It is cleared out as soon as bloadp is invoked. | ||
Line 214: | Line 172: | ||
=== Prototype 0.4.0-0.6.0 (23-07-2004 or older) === | === Prototype 0.4.0-0.6.0 (23-07-2004 or older) === | ||
Prototype PRE-IPL will read the IPL blocks in place from 0xBFE01000 and decrypts them to 0x88400000 before jumping there. IPL blocks have no metadata in prototype IPLs. Instead PRE-IPL uses 0x88400000 as a hardcoded entry point (see code samples below). In fact the IPL payload/part3, nested inside current IPL revisions and loaded by main.bin are using the prototype format, so the prototype PRE-IPL loads the IPL part 3/payload directly. | |||
It is also worthy of note that | It is also worthy of note that prototype PRE-IPL for DEM-1000 (for 0.4.0 and 0.6.0 firmwares) does not make use of paddr 0xa0010000 as their payload location. The PRE-IPL payload is instead executed in place at 0xBFC00000. As such the PRE-IPL data is not wiped and can be dumped in its entirety using a custom IPL (please note that the IPL format is different than later revision IPLs: prototype IPLs are loaded in a single raw KIRK commmand 1 block). | ||
<pre> | <pre> | ||
// 0.4 | // 0.4 PRE-IPL | ||
} | } | ||
// 0xbfc00138 | // 0xbfc00138 | ||
Line 235: | Line 193: | ||
<pre> | <pre> | ||
// 0.6 | // 0.6 PRE-IPL | ||
// 0xbfc00168 | // 0xbfc00168 | ||
function_bfc001b0(100); | function_bfc001b0(100); | ||
Line 251: | Line 209: | ||
=== 0.7.0-2.50 (18-09-2004) === | === 0.7.0-2.50 (18-09-2004) === | ||
The 0.7.0+ | The 0.7.0+ PRE-IPL will copy its PRE-IPL payload (stored at 0xBFC000280) to 0x80010000 (physical address 0xa0010000) and jump there. Because on DTP-T1000 0xBFC00000 is writable during PRE-IPL execution and because 0xBFD00000 is an invalid range on DTP-T1000, the payload will use the 0xBFC00000 memory (which originally contains the whole PRE-IPL loader+payload) as work ram. It will however not wipe itself so you can dump the important part (the payload) from 0xa0010000 (assuming you gain execution at IPL time). | ||
IPL blocks are then loaded from 0xBFE01000 by | IPL blocks are then loaded from 0xBFE01000 by PRE-IPL and copied to 0xBFC00000 where they are decrypted in place and copied to the location of load address specified in the metadata. | ||
=== 2.60+ (22-10-2005) === | === 2.60+ (22-10-2005) === | ||
Because a hash of the data stored between | Because a hash of the data stored between 0xbfc00040 and 0xbfc002c0 is used in an additional step by 2.60+ IPLs to decrypt main.bin, from 2.60 and onward the payload will overwrite 0xbfc00000 with an identical copy of first 0x2C0 bytes of the original psp-1000(01g) PRE-IPL rom data (stored at 0xBFC00BB0 in the 2.60 and 2.71 kbooti, 0x80010930 in the payload) and wipe everything after 0xbfc002C0 with 00 before jumping to the IPL entrypoint, if bootstrapping the 1.50 firmware using the 2.60/2.71 PRE-IPL part, data from the retail rom addresses 0xBFC00200 to 0xBFC002C0 is retrievable, please note that this would not have been enough to generate the hash required to decrypt 2.60+ main.bin in any case and dumping using a custom IPL would be required to retrieve enough of the data even on a DTP-T1000. | ||
2.6.0 kbooti also appears to fix one of the | 2.6.0 kbooti also appears to fix one of the PRE-IPL flaws that allowed to load the Pandora time attacked block. It likely either checks for the entrypoint not to be in the 0xb* range or prevents the use of IPL blocks with 0x0 set as a load address (or both), it does not however check for the data size of the block. | ||
The code that copies 0x2C0 bytes from 0x80010930 to | The code that copies 0x2C0 bytes from 0x80010930 to 0xbfc0 verbatim from the 2.6.0 PRE-IPL payload. | ||
<pre> | <pre> | ||
0x800100c4: 19 00 20 13 beq 0x8001012c <entry_point+0x12c>, $zero, 0x8001012c <entry_point+0x12c> | 0x800100c4: 19 00 20 13 beq 0x8001012c <entry_point+0x12c>, $zero, 0x8001012c <entry_point+0x12c> | ||
Line 284: | Line 240: | ||
</pre> | </pre> | ||
Please note that neither the 0xbfc00000 (on DTP-T1000) nor 0xa0010000 memory locations survive reboots. | |||
=== 3.50 (12-02-2007) === | === 3.50 (12-02-2007) === | ||
PRE-IPL adds a step using a 0x40 bytes xor key to decrypt the CMAC hash and data keys from the IPL block headers. As a result you cannot decrypt using KIRK command 1 the IPL blocks meant for the new PRE-IPL. | |||
=== JIG Memory Stick Test Mode === | |||
Starting from kbooti 0.7.0, a special JIG test mode exists, it will read an IPL block at 0x2000 on the Memory Stick instead of address 0xBFE01000 if the specific condition is met: | |||
if ( MEMORY[0xBFEFFFFC] < 0 ) use MS | |||
Writing 0xFFFFFFFF at 0xBFEFFFFC does indeed enable the pseudo service mode and reads the block from the Memory stick, it is speculated that this mode is used by Sony Engineers to debug JIG Memory sticks by writing a kbooti using a specific build of bloadp/dstdb which writes at 0xBFEFFFFC. Kbooti remains loaded in memory until the main unit is turned off, allowing then to cycle through different memory stick. | |||
In kbooti revision 3.5.0 this mode skips the XOR step on the kirk header, allowing to use a regular IPL block to achieve code execution and dump the payload. | |||
== Retail behaviour == | |||
pseucode from Tachyon 0x00140000-0x00300000 PRE-IPL payload: | |||
<pre> | |||
int iplBlockNumber = 0; | |||
u32 checksum = 0; | |||
// load/decrypt all encrypted ipl blocks | |||
while(1) | |||
{ | |||
// copy an encrypted ipl block to 0xBFD00000-0xBFD01000 (4KB embedded cpu ram) | |||
if (LoadIplBlock(iplBlockNum ber, block) < 0) | |||
while(1); | |||
// decrypt the ipl block in place (uh oh...) | |||
if (DecryptIplBlock(block, block)) | |||
while(1); | |||
// first block will have zero as its checksum since there is no previous block (another uh oh...) | |||
if (block->checksum != checksum) | |||
while(1); | |||
= | // load the 'data' section of the ipl block to the specified address (0x040Fxxxx range) | ||
if (block->loadaddr) | |||
checksum = memcpy(block->loadaddr, block->data, block->blocksize); | |||
// reached the end of the ipl, jump to the entry address (0x040F0000) | |||
if (block->entry) | |||
{ | |||
// clear caches | |||
Dcache(); | |||
Icache(); | |||
// jump to ipl - do not return | |||
block->entry(); | |||
} | |||
iplBlockNumber++; | |||
} | } | ||
</pre> | </pre> | ||
Tachyon revisions 0x00140000 to 0x00300000 PRE-IPL pseudo code: | |||
<pre> | |||
PSP Disassembler Ver.0.20 Copyright(c)2005,2006 BOOSTER | |||
incl. elf-lib 0.1r2 copyright (c) 2005 djhuevo | |||
:file name '0x80010000.bin',size = 4096 | |||
Load 3684 NID's name | |||
:Disasm | |||
;copied by pre-ipl bootcode, from 0xbfc00280-0xbfc00d78 | |||
;here code is 0x80010000 to 0x80010af8 | |||
; | |||
;$bfd00000-$bfd00fff : sector read buffer | |||
; | |||
;------------------------------------------------------- | |||
;recovery mode selector | |||
;be240004 GPIO READ REG. | |||
; bit4 : device select ,0=NAND Flash, 1= rec-dev | |||
; | |||
;------------------------------------------------------- | |||
;------------------------------------------------------- | |||
;recovery boot device (rec-dev) HW assign | |||
; | |||
;bd200030 command register | |||
00009007 : read request (write size = 8) | |||
00002200 : read sector buffer (read size=200) | |||
00008004 : ? status (write size = 8 , read size=8) | |||
00004000 : ? status (read size=8) | |||
00007001 : ? (data size=8?) | |||
;bd200034 data register (read / write) | |||
;bd200038 status register | |||
; bit14:read data ready | |||
; bit13:parameter wirte ready | |||
; bit12:transmit finish ? | |||
; bit 9:???? error | |||
; bit 8:read data error | |||
; | |||
;bd20003c ??? | |||
bit15:reset device ? | |||
; | |||
;------------------------------------------------------- | |||
if ( | ;--------------------------------------------------------------------------- | ||
;entry | |||
;--------------------------------------------------------------------------- | |||
L80010000: | |||
; | |||
;reset I/O | |||
$800106B0(L80010a80) | |||
; | |||
lui r8,$bc10 ;80010010[3C08BC10,'...<'] | |||
; | |||
if(r8[$68]>>16 == 0) $80010034 | |||
; | |||
r9 = r8[$78] | |||
ori r9,r9,$0800 ;80010028[35290800,'..)5'] | |||
b $80010040 ;8001002C[10000004,'....'] | |||
sw r9,$78(r8) ;80010030[AD090078,'x...'] | |||
; | |||
;80010034 | |||
lw r9,$7c(r8) ;80010034[8D09007C,'|...'] | |||
ori r9,r9,$0010 ;80010038[35290010,'..)5'] | |||
sw r9,$7c(r8) ;8001003C[AD09007C,'|...'] | |||
addiu r4,0,$a ;80010040[2404000A,'...$'] | |||
jal $80010768 ;80010044[0C0041DA,'.A..'] | |||
sync ;80010048[0000000F,'....'] | |||
;80010768 | |||
; | |||
;check recovery boot mode switch | |||
; | |||
r8 = [$be240004] & 0x10 // GPIO bit 4 | |||
; | |||
r9 = $80010194 // NAND read BLOCK entry | |||
r10= $80010130 // NAND initialize(read FAT) entry | |||
; | |||
if(r8!=0)// $80010080 | |||
{ | |||
r9 = $80010248 // rec-dev read BLOCK entry | |||
r10= $80010240 // rec-dev initialize entry | |||
} | |||
;80010080 | |||
[$80010808] = r9 | |||
[$8001080c] = 0x000000000 | |||
; | |||
;call read FAT | |||
; | |||
(r10)() | |||
; | |||
r23 = 0 ; check sum of last block | |||
; | |||
;READ BLOCK LOOP | |||
; | |||
L80010098 | |||
r25 = [$80010808] ; read BLOCK entry | |||
r4 = [$8001080c] ; block num of read | |||
; | |||
;call read body function | |||
; | |||
r2 = (r25)(r4,$bfd000000); | |||
if(r2<0) $80010128 | |||
; | |||
;decrypt 1000H block | |||
; | |||
r2 = $80010620($bfd00000,$bfd00000) | |||
if(r2<0) $80010128 | |||
; | |||
;+000c : check sum of last block ? | |||
; | |||
if( [$bfd0000c] != r23) $80010128 | |||
; | |||
;+0000 : distination address | |||
;+0004 : block size | |||
; | |||
r4 = [$bfd00000] ; +0000 : top pointer | |||
r6 = [$bfd00004] ; +0004 : size | |||
if(r4!=0) | |||
{ | |||
;transmit BLOCK body | |||
r23 = $80010688(r4,r16 + $10 , r6) | |||
} | |||
; | |||
;+0008 : entry point or continue MARK check | |||
; | |||
r25 = r16[8] | |||
if(r25==0) //$80010114 | |||
{ | |||
;L80010114: | |||
[$8001080c]++ ; next block | |||
goto $80010098 | |||
} | |||
; | |||
;cache ? | |||
$800102D8() | |||
; | |||
;cache ? | |||
$800102A0() | |||
; | |||
;goto IPL entry point | |||
; | |||
jalr r25 ;8001010C[0320F809,'.. .'] | |||
; | |||
;80010128 | |||
while(1); // HALT | |||
; | |||
;--------------------------------------------------------------------------- | |||
;read IPL FAT | |||
;--------------------------------------------------------------------------- | |||
L80010130: | |||
r16 =r31 | |||
; | |||
;80010134 | |||
;NAND reset | |||
$80010308() | |||
; | |||
;8001013C | |||
r17 = $80 // top of IPL-FAT sector | |||
;80010140 | |||
;read IPL FAT | |||
r2 = $80010334(r17,8001081c,80010810) | |||
if(r2<0) $8001018c | |||
;80010164 | |||
r8 = r6[0] | |||
r9 = r6[4] | |||
r10= r6[8] | |||
;ECC signature | |||
if(r9 != $6dc64a38) // $8001018c | |||
{ | |||
r17 += $20 // next IPL sector | |||
goto $80010140 | |||
} | |||
; jr r16 ;80010184[02000008,'....'] | |||
return | |||
;------------------------------------------------------------------------ | |||
} | ;NAND read body | ||
; | |||
;r4 : fat logical ptr (400H bytes lba? ) | |||
; | |||
;------------------------------------------------------------------------ | |||
L80010194: | |||
[$80010800] = r31 | |||
[$80010804] = r4 | |||
; | |||
r17 = r5 | |||
;get FAT location | |||
r8 = $8001081c ; FAT table | |||
r9 = (r4>>2)<<1 | |||
r8 += r9 | |||
r9 = (u16)r8[0] | |||
; | |||
r8 = (r9<<2) | (r4 & 3) | |||
; | |||
r16 = r8 << 3 ; * 8 | |||
r18 = 0 | |||
;800101CC | |||
do | |||
{ | |||
;read body one | |||
r2 = $80010334(r16+r18,r17 + (r18<<9),80010810) | |||
if(r2<0) $80010230 | |||
r8 = r6[0] | |||
r9 = r6[4] | |||
r10= r6[8] | |||
;ECC signature | |||
if(r9 != $6dc64a38) $80010230 | |||
r18++ | |||
}while(r18<8); | |||
;80010220 | |||
r31 = [$80010800] | |||
return r0 | |||
= | L80010230: | ||
r31 = [$80010800] | |||
return -1 | |||
;------------------------------------------------------------------------ | |||
;rec-dev initialize | |||
;------------------------------------------------------------------------ | |||
L80010240: | |||
return $800103B4() | |||
;------------------------------------------------------------------------ | |||
;rec-dev read 1000H block | |||
;------------------------------------------------------------------------ | |||
L80010248: | |||
[$80010$800] = r31 | |||
; | |||
r16 = r4 | |||
r17 = r5 | |||
r18 = 0 | |||
;8001025C | |||
do{ | |||
r2 = $80010418(r18+0x10+r16<<3 ,r17 + r18<<9) | |||
if(r2<0) $8001025c | |||
r18++ | |||
}while(r18<8); | |||
; | |||
r31 = [$80010$800] | |||
return r2 | |||
;------------------------------------------------------------------------ | |||
;cache ? | |||
;------------------------------------------------------------------------ | |||
L800102A0: | |||
mfc0 r8,Config ;800102A0[40088000,'...@'] | |||
addiu r9,0,$1000 ;800102A4[24091000,'...$'] | |||
dc.l $7d081240 [invalid] ;800102A8[7D081240,'@..}'] | |||
sllv r9,r9,r8 ;800102AC[01094804,'.H..'] | |||
mtc0 0,TagLo ;800102B0[4080E000,'...@'] | |||
mtc0 0,TagHi ;800102B4[4080E800,'...@'] | |||
addu r8,0,0 ;800102B8[00004021,'!@..'] | |||
; | |||
cache $01,r8($0) ;800102BC[BD010000,'....'] | |||
cache $03,r8($0) ;800102C0[BD030000,'....'] | |||
addiu r8,r8,$40 ;800102C4[25080040,'@..%'] | |||
bne r8,r9,$800102bc ;800102C8[1509FFFC,'....'] | |||
nop ;800102CC[00000000,'....'] | |||
jr r31 ;800102D0[03E00008,'....'] | |||
nop ;800102D4[00000000,'....'] | |||
;------------------------------------------------------------------------ | |||
;cache ? | |||
;------------------------------------------------------------------------ | |||
L800102D8: | |||
mfc0 r8,Config ;800102D8[40088000,'...@'] | |||
addiu r9,0,$800 ;800102DC[24090800,'...$'] | |||
dc.l $7d081180 [invalid] ;800102E0[7D081180,'...}'] | |||
sllv r9,r9,r8 ;800102E4[01094804,'.H..'] | |||
addu r8,0,0 ;800102E8[00004021,'!@..'] | |||
; | |||
cache $14,r8($0) ;800102EC[BD140000,'....'] | |||
cache $14,r8($0) ;800102F0[BD140000,'....'] | |||
addiu r8,r8,$40 ;800102F4[25080040,'@..%'] | |||
bne r8,r9,$800102ec ;800102F8[1509FFFC,'....'] | |||
nop ;800102FC[00000000,'....'] | |||
jr r31 ;80010300[03E00008,'....'] | |||
sync ;80010304[0000000F,'....'] | |||
=== | ;---------------------------------------------------------------------------- | ||
;NAND reset CMD | |||
;---------------------------------------------------------------------------- | |||
L80010308: | |||
;nand cmd | |||
[$bd101008] = 0xff | |||
;nand sts | |||
while( [$bd101004] & 1 ==0); | |||
; | |||
[$bd101014] = 0x01 | |||
return | |||
;---------------------------------------------------------------------------- | |||
;NAND Read Sector | |||
; | |||
;r4 : sector | |||
;r5 : data buffer | |||
;r6 : Extra buffer | |||
; | |||
;---------------------------------------------------------------------------- | |||
L80010334: | |||
;nand sts | |||
while([$bd101004] & 1 == 0); | |||
; | |||
[$bd101020] = r4 << 10 | |||
[$bd101024] = $301 | |||
;80010354 | |||
while([$bd101024] & 1 == 0); | |||
;80010364 | |||
if([$bd101028] != 0) return -1 | |||
; | |||
lui r8,$bff0 ;80010370[3C08BFF0,'...<'] | |||
; | |||
r9 = r8[$900] | |||
r10 = r8[$904] | |||
r2 = r8[$908] | |||
; | |||
r6[0] = r9 | |||
r6[4] = r10 | |||
r6[8] = r2 | |||
; | |||
r9 = r5 | |||
r2 = $200 | |||
L80010394: | |||
do | |||
{ | |||
r10 = r8[0] | |||
r2 -= 4 | |||
r8 += 4 | |||
r9[0] = r10 | |||
r9 += 4 | |||
}while(r2); | |||
;800103AC | |||
return 0 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev initialize | |||
;---------------------------------------------------------------------------- | |||
L800103B4: | |||
r24 = r31 | |||
; | |||
;rec-dev I/O init : device & clock enable ? | |||
$800106B0(L80010ad4) | |||
; | |||
;reset device ? | |||
; | |||
[$bd20003c] = $8000 | |||
;800103D4 | |||
while( [$bd20003c] & 0x8000); | |||
; | |||
$80010530() | |||
$80010508() | |||
; | |||
;800103F4 | |||
do{ | |||
r2 = $800105B8() | |||
if(r2<0) continue // $800103f4 | |||
; | |||
}while(r2 & $0080 == 0); // $800103f4 | |||
; | |||
; jr r24 ;80010410[03000008,'....'] | |||
return 0 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev read sector one | |||
; | |||
;a1:sector address | |||
;a2:buffer | |||
; | |||
;---------------------------------------------------------------------------- | |||
L80010418: | |||
r14 = r5 | |||
; r24 = r31 | |||
; lui r25,$bd20 | |||
; | |||
;read sector COMMAND ? | |||
[$bd200030] = $00009007 | |||
; | |||
dc.l $7c0428e0 [invalid] ;8001042C[7C0428E0,'.(.|'] | |||
; | |||
r5 >>= 8 | |||
r9 = (r4 >> 24) << 24 | |||
; | |||
r4 = $00010020 | |||
r4 |= r9 | |||
; | |||
;write parameter | |||
r2 = $800104C0(r4,r5) | |||
if(r2<0) return -1 | |||
;busy wait | |||
$80010608() | |||
; | |||
;$8001045c | |||
do{ | |||
r2 = $800105B8() | |||
if(r2<0) return -1 | |||
r2 = r2 & $0020 | |||
}while((r2 & $0020)==0); | |||
; | |||
if(r2 & $0040) return -1 | |||
; | |||
;read buffer COMMAND ? | |||
[$bd200030] = $00002200 | |||
; | |||
;read sector data | |||
r2 = $800104CC(r14,$200) // r14 == r5 | |||
if(r2<0) return -1 | |||
;wait finish | |||
r2 = $80010508() | |||
if(r2<0) return -1 | |||
;busy wait | |||
$80010608() | |||
; | |||
goto $800103f4 | |||
; | |||
;800104B8 | |||
; jr r24 ;800104B8[03000008,'....'] | |||
return -1 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev : commmand output ? | |||
; | |||
;a1:1st write data | |||
;a2:2nd write data | |||
;---------------------------------------------------------------------------- | |||
L800104C0: | |||
[$bd200034] = r4 | |||
[$bd200034] = r5 | |||
goto $80010508 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev read data block | |||
; | |||
;a1:distination pointer | |||
;a2:transmit size | |||
; | |||
;---------------------------------------------------------------------------- | |||
L800104CC: | |||
do{ | |||
do{ | |||
r9 = [$bd200038] | |||
if(r9 & $0100) return -1; | |||
}while(r9 & $4000 == 0); | |||
; | |||
r2 = [$bd200034] | |||
r5 -= 4 | |||
r4[0] = r2 | |||
r4 += 4 | |||
}while(r5 >=0); | |||
; | |||
return 0; | |||
;---------------------------------------------------------------------------- | |||
;wait for TX finish ? | |||
;---------------------------------------------------------------------------- | |||
L80010508: | |||
do{ | |||
r9 = [$bd200038] | |||
}while(r9 & $1000 == 0); | |||
; | |||
if(r9 & $0300) return -1// $80010528 | |||
; | |||
return 0 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev read status ? | |||
;---------------------------------------------------------------------------- | |||
L80010530: | |||
; addu r15,r31,0 ;80010530[03E07821,'!x..'] | |||
; lui r25,$bd20 ;80010534[3C19BD20,' ..<'] | |||
; | |||
[$bd200030] = $00008004 | |||
[$bd200034] = $06100800 | |||
[$bd200034] = 0 | |||
r2 = $80010508() | |||
if(r2<0) return -1 | |||
; | |||
$800105A4($80010a1c,8); | |||
; | |||
;get status ? | |||
; | |||
r4 = [$80010a1c] | |||
r5 = [$80010a20] | |||
; | |||
if( (r4>>16)&0x15 != 0) return -1 | |||
; | |||
return 0 | |||
;---------------------------------------------------------------------------- | |||
;rec-dev read status ? | |||
; | |||
;a1:buffer | |||
;a2:size | |||
; | |||
;---------------------------------------------------------------------------- | |||
L800105A4: | |||
[$bd200030] = $00004000 | |||
;read sector body | |||
return $800104cc(r4,r5) | |||
;----------------------------------------------------------------------------- | |||
;rec-dev device ready check? | |||
;----------------------------------------------------------------------------- | |||
L800105B8: | |||
;r25 = $bd200000 | |||
[$bd200030] = $00007001 | |||
;wait | |||
do | |||
{ | |||
r9 = [$bd200038] | |||
}while(r9 & $0100); | |||
if((r9 & $4000)==0) $800105c0 | |||
; | |||
r2 = [$bd200034] | |||
r0 = [$bd200034] // ? | |||
;800105E0 | |||
do{ | |||
r9 = [$bd200038] | |||
if(r9 & $0100) //$80010600 | |||
{ | |||
L80010600: | |||
return -1 | |||
} | |||
}while( (r9 & $1000)==0); | |||
; | |||
return r2 & 0xff; | |||
;---------------------------------------------------------------------------- | |||
;wait for rec-dev busy | |||
;---------------------------------------------------------------------------- | |||
L80010608: | |||
do | |||
{ | |||
r9 = [$bd200038] | |||
}while( (r9 & $2000) == 0); | |||
return | |||
;----------------------------------------------------------------------------- | |||
;decrypt 1000H block | |||
;----------------------------------------------------------------------------- | |||
L80010620: | |||
; lui r25,$bde0 ;80010620[3C19BDE0,'...<'] | |||
; | |||
[$bde00010] = $00000001 | |||
;r8 = r4 | |||
dc.l $7ca8e000 [invalid] ;8001062C[7CA8E000,'...|'] | |||
[$bde0002c] = r8 | |||
; | |||
;r8 = r5 | |||
dc.l $7c88e000 [invalid] ;80010634[7C88E000,'...|'] | |||
[$bde00030] = r8 | |||
; | |||
[$bde0000c] = $00000001 | |||
;$80010644 | |||
do{ | |||
r8 = [$bde0001c] | |||
}while(r8 & $0011 == 0) | |||
; | |||
[$bde00028] = r8 | |||
if(r8&$0010) // $80010664 | |||
{ | |||
L80010664: | |||
[$bde0000c] = $00000002 | |||
;$8001066C | |||
do{ | |||
r8 = [$bde0001c] | |||
}while(r8 & $0002 == 0) | |||
; | |||
[$bde00028] = r8 | |||
sync | |||
return -1 | |||
} | |||
; | |||
return [$bde00014] | |||
;---------------------------------------------------------------------------- | |||
;transmit data with calc check sum | |||
; | |||
;arg1: source | |||
;arg2: distination | |||
;arg1: size | |||
; | |||
;return : 32bit check sum (add) | |||
; | |||
;---------------------------------------------------------------------------- | |||
L80010688: | |||
r2 = 0 ; clear check sum | |||
do{ | |||
r3 = r5[0] | |||
r5 += 4 | |||
r6 -= 4 | |||
r4[0] = r3 | |||
r2 += r3 ; check sum | |||
r4 += 4 | |||
}while(r6>=0); | |||
return | |||
* | ;--------------------------------------------------------------------------- | ||
;script executer | |||
; | |||
;a1:script pointer | |||
; | |||
;2 word command | |||
; | |||
;+00[31:28] : CMD | |||
;+00[27: 0] : OFFSET | |||
;+04[31: 0] : VALUE | |||
; | |||
;CMD : command : | |||
; 0 : store | [$b0000000 + OFFSET] = VALUE | |||
; 1 : or | [$b0000000 + OFFSET] |= VALUE | |||
; 2 : and | [$b0000000 + OFFSET] &= VALUE | |||
; 3 : wait toL| while( ( [$b0000000 + OFFSET] &= VALUE) != 0) | |||
;(4) : wait toH| while( (~[$b0000000 + OFFSET] &= VALUE) != 0) | |||
; 5 : delay | for(cnt=VALUE*96;cnt;cnt--) | |||
; F : end | return | |||
; | |||
;--------------------------------------------------------------------------- | |||
L800106B0: | |||
r8 = r4 | |||
;addu r25,r31,0 | |||
; | |||
;800106b8 | |||
do{ | |||
// read CMD:offset + VALUE | |||
r4 = r8[0] | |||
r9 = r4 >> 28 | |||
r4 = ( (r4 << 4)>>4 ) | $b0000000 | |||
r5 = r4[4] | |||
; | |||
if(r9==0) //$80010724 | |||
{ | |||
;80010724 | |||
r4[0]=r5 | |||
goto $8001071c | |||
} | |||
if(r9==1)// $8001072c | |||
{ | |||
;8001072C | |||
r4[0] = r4[0] | r5 | |||
goto $8001071c | |||
} | |||
if(r9==2) // $8001073c | |||
{ | |||
r4[0] = r4[0] & r5 | |||
goto $8001071c | |||
} | |||
r1 = 0 | |||
if(r9==3) $8001074c | |||
; | |||
r1 = $ffffffff ; nor r1,0,0 | |||
;!!!!! buggy code !!!!! | |||
; addiu r10,r10,-$4 | |||
; if(r9==4) $8001074c | |||
if(r9==7) $8001074c | |||
;!!!!! buggy code !!!!! | |||
==== | ; if(r9==5) //$80010714 | ||
{ | |||
L80010714: | |||
$80010768(r5); | |||
goto L8001071C | |||
} | |||
;default: | |||
; jr r25 ;8001070C[03200008,'.. .'] | |||
return; | |||
; | |||
;case end | |||
L8001071C: | |||
// next script point | |||
r8 += 8 | |||
}while(1); | |||
; | |||
;4,7 | |||
L8001074C: | |||
{ | |||
do{ | |||
r9 = (r4[0] ^ r1) & r5 | |||
}while(r9!=0); | |||
goto $8001071c | |||
} | |||
;-------------------------------------------------------------------------- | |||
;delay | |||
;-------------------------------------------------------------------------- | |||
L80010768: | |||
r1 = ((r4 << 1) + r4)<<5 // * 96 | |||
while(r1) r1--; | |||
return | |||
;-------------------------------------------------------------------------- | |||
;-------------------------------------------------------------------------- | |||
L80010784: | |||
nop ;80010784[00000000,'....'] | |||
nop ;80010788[00000000,'....'] | |||
nop ;8001078C[00000000,'....'] | |||
nop ;80010790[00000000,'....'] | |||
nop ;80010794[00000000,'....'] | |||
nop ;80010798[00000000,'....'] | |||
nop ;8001079C[00000000,'....'] | |||
nop ;800107A0[00000000,'....'] | |||
nop ;800107A4[00000000,'....'] | |||
nop ;800107A8[00000000,'....'] | |||
nop ;800107AC[00000000,'....'] | |||
nop ;800107B0[00000000,'....'] | |||
nop ;800107B4[00000000,'....'] | |||
nop ;800107B8[00000000,'....'] | |||
nop ;800107BC[00000000,'....'] | |||
nop ;800107C0[00000000,'....'] | |||
nop ;800107C4[00000000,'....'] | |||
nop ;800107C8[00000000,'....'] | |||
nop ;800107CC[00000000,'....'] | |||
nop ;800107D0[00000000,'....'] | |||
nop ;800107D4[00000000,'....'] | |||
nop ;800107D8[00000000,'....'] | |||
nop ;800107DC[00000000,'....'] | |||
nop ;800107E0[00000000,'....'] | |||
nop ;800107E4[00000000,'....'] | |||
nop ;800107E8[00000000,'....'] | |||
nop ;800107EC[00000000,'....'] | |||
nop ;800107F0[00000000,'....'] | |||
nop ;800107F4[00000000,'....'] | |||
nop ;800107F8[00000000,'....'] | |||
nop ;800107FC[00000000,'....'] | |||
;----------------------------------------------------------------------------- | |||
; | |||
;r31 save buffer | |||
; | |||
L80010800: | |||
dl 800100B0 | |||
; | |||
;r4 save buffer | |||
; | |||
L80010804: | |||
dl 0000002E | |||
; | |||
;read sector function entry | |||
; | |||
L80010808: | |||
dl L80010194 | |||
; | |||
;read block number | |||
; | |||
L8001080C: | |||
dl L0000002E | |||
; | |||
;NAND Extra buffer | |||
; | |||
L80010810: | |||
dl FFFFFFFF | |||
dl 6DC64A38 | |||
dl FFFFFD89 | |||
; | |||
;NAND Data buffer (IPL FAT) | |||
; | |||
L8001081c | |||
mfhi 0 ;8001081C[00110010,'....'] | |||
mflo 0 ;80010820[00130012,'....'] | |||
dsllv 0,r21,0 ;80010824[00150014,'....'] | |||
dsrlv 0,r23,0 ;80010828[00170016,'....'] | |||
mult 0,r25 ;8001082C[00190018,'....'] | |||
div 0,r27 ;80010830[001B001A,'....'] | |||
nop ;80010834[00000000,'....'] | |||
nop ;80010838[00000000,'....'] | |||
nop ;8001083C[00000000,'....'] | |||
nop ;80010840[00000000,'....'] | |||
nop ;80010844[00000000,'....'] | |||
nop ;80010848[00000000,'....'] | |||
nop ;8001084C[00000000,'....'] | |||
nop ;80010850[00000000,'....'] | |||
nop ;80010854[00000000,'....'] | |||
nop ;80010858[00000000,'....'] | |||
nop ;8001085C[00000000,'....'] | |||
nop ;80010860[00000000,'....'] | |||
nop ;80010864[00000000,'....'] | |||
nop ;80010868[00000000,'....'] | |||
nop ;8001086C[00000000,'....'] | |||
nop ;80010870[00000000,'....'] | |||
nop ;80010874[00000000,'....'] | |||
nop ;80010878[00000000,'....'] | |||
nop ;8001087C[00000000,'....'] | |||
nop ;80010880[00000000,'....'] | |||
nop ;80010884[00000000,'....'] | |||
nop ;80010888[00000000,'....'] | |||
nop ;8001088C[00000000,'....'] | |||
nop ;80010890[00000000,'....'] | |||
nop ;80010894[00000000,'....'] | |||
nop ;80010898[00000000,'....'] | |||
nop ;8001089C[00000000,'....'] | |||
nop ;800108A0[00000000,'....'] | |||
nop ;800108A4[00000000,'....'] | |||
nop ;800108A8[00000000,'....'] | |||
nop ;800108AC[00000000,'....'] | |||
nop ;800108B0[00000000,'....'] | |||
nop ;800108B4[00000000,'....'] | |||
nop ;800108B8[00000000,'....'] | |||
nop ;800108BC[00000000,'....'] | |||
nop ;800108C0[00000000,'....'] | |||
nop ;800108C4[00000000,'....'] | |||
nop ;800108C8[00000000,'....'] | |||
nop ;800108CC[00000000,'....'] | |||
nop ;800108D0[00000000,'....'] | |||
nop ;800108D4[00000000,'....'] | |||
nop ;800108D8[00000000,'....'] | |||
nop ;800108DC[00000000,'....'] | |||
nop ;800108E0[00000000,'....'] | |||
nop ;800108E4[00000000,'....'] | |||
nop ;800108E8[00000000,'....'] | |||
nop ;800108EC[00000000,'....'] | |||
nop ;800108F0[00000000,'....'] | |||
nop ;800108F4[00000000,'....'] | |||
nop ;800108F8[00000000,'....'] | |||
nop ;800108FC[00000000,'....'] | |||
nop ;80010900[00000000,'....'] | |||
nop ;80010904[00000000,'....'] | |||
nop ;80010908[00000000,'....'] | |||
nop ;8001090C[00000000,'....'] | |||
nop ;80010910[00000000,'....'] | |||
nop ;80010914[00000000,'....'] | |||
nop ;80010918[00000000,'....'] | |||
nop ;8001091C[00000000,'....'] | |||
nop ;80010920[00000000,'....'] | |||
nop ;80010924[00000000,'....'] | |||
nop ;80010928[00000000,'....'] | |||
nop ;8001092C[00000000,'....'] | |||
nop ;80010930[00000000,'....'] | |||
nop ;80010934[00000000,'....'] | |||
nop ;80010938[00000000,'....'] | |||
nop ;8001093C[00000000,'....'] | |||
nop ;80010940[00000000,'....'] | |||
nop ;80010944[00000000,'....'] | |||
nop ;80010948[00000000,'....'] | |||
nop ;8001094C[00000000,'....'] | |||
nop ;80010950[00000000,'....'] | |||
nop ;80010954[00000000,'....'] | |||
nop ;80010958[00000000,'....'] | |||
nop ;8001095C[00000000,'....'] | |||
nop ;80010960[00000000,'....'] | |||
nop ;80010964[00000000,'....'] | |||
nop ;80010968[00000000,'....'] | |||
nop ;8001096C[00000000,'....'] | |||
nop ;80010970[00000000,'....'] | |||
nop ;80010974[00000000,'....'] | |||
nop ;80010978[00000000,'....'] | |||
nop ;8001097C[00000000,'....'] | |||
nop ;80010980[00000000,'....'] | |||
nop ;80010984[00000000,'....'] | |||
nop ;80010988[00000000,'....'] | |||
nop ;8001098C[00000000,'....'] | |||
nop ;80010990[00000000,'....'] | |||
nop ;80010994[00000000,'....'] | |||
nop ;80010998[00000000,'....'] | |||
nop ;8001099C[00000000,'....'] | |||
nop ;800109A0[00000000,'....'] | |||
nop ;800109A4[00000000,'....'] | |||
nop ;800109A8[00000000,'....'] | |||
nop ;800109AC[00000000,'....'] | |||
nop ;800109B0[00000000,'....'] | |||
nop ;800109B4[00000000,'....'] | |||
nop ;800109B8[00000000,'....'] | |||
nop ;800109BC[00000000,'....'] | |||
nop ;800109C0[00000000,'....'] | |||
nop ;800109C4[00000000,'....'] | |||
nop ;800109C8[00000000,'....'] | |||
nop ;800109CC[00000000,'....'] | |||
nop ;800109D0[00000000,'....'] | |||
nop ;800109D4[00000000,'....'] | |||
nop ;800109D8[00000000,'....'] | |||
nop ;800109DC[00000000,'....'] | |||
nop ;800109E0[00000000,'....'] | |||
nop ;800109E4[00000000,'....'] | |||
nop ;800109E8[00000000,'....'] | |||
nop ;800109EC[00000000,'....'] | |||
nop ;800109F0[00000000,'....'] | |||
nop ;800109F4[00000000,'....'] | |||
nop ;800109F8[00000000,'....'] | |||
nop ;800109FC[00000000,'....'] | |||
nop ;80010A00[00000000,'....'] | |||
nop ;80010A04[00000000,'....'] | |||
nop ;80010A08[00000000,'....'] | |||
nop ;80010A0C[00000000,'....'] | |||
nop ;80010A10[00000000,'....'] | |||
nop ;80010A14[00000000,'....'] | |||
nop ;80010A18[00000000,'....'] | |||
; | |||
;rec-dev status read buffer ? | |||
L80010A1C: | |||
dl 00000000,00000000 | |||
; | |||
nop ;80010A24[00000000,'....'] | |||
nop ;80010A28[00000000,'....'] | |||
nop ;80010A2C[00000000,'....'] | |||
nop ;80010A30[00000000,'....'] | |||
nop ;80010A34[00000000,'....'] | |||
nop ;80010A38[00000000,'....'] | |||
nop ;80010A3C[00000000,'....'] | |||
nop ;80010A40[00000000,'....'] | |||
nop ;80010A44[00000000,'....'] | |||
nop ;80010A48[00000000,'....'] | |||
nop ;80010A4C[00000000,'....'] | |||
nop ;80010A50[00000000,'....'] | |||
nop ;80010A54[00000000,'....'] | |||
nop ;80010A58[00000000,'....'] | |||
nop ;80010A5C[00000000,'....'] | |||
nop ;80010A60[00000000,'....'] | |||
nop ;80010A64[00000000,'....'] | |||
nop ;80010A68[00000000,'....'] | |||
nop ;80010A6C[00000000,'....'] | |||
nop ;80010A70[00000000,'....'] | |||
nop ;80010A74[00000000,'....'] | |||
nop ;80010A78[00000000,'....'] | |||
nop ;80010A7C[00000000,'....'] | |||
; | |||
; | |||
;script command : I/O init | |||
; | |||
L80010A80: | |||
dl 1C100058,00800000 ; [$bc100058] |= 00800000 | |||
dl 1C100050,0000608E ; [$bc100050] |= 0000608E | |||
dl 2C10004C,FFFFFBF7 ; [$bc10004C] &= FFFFFBF7 | |||
dl 1C100078,00000002 ; [$bc100078] |= 00000002 | |||
dl 2E240000,FFFFFFEF ; [$be240000] &= FFFFFFEF : GPIO bit4 direction read? | |||
dl 1E240040,00000010 ; [$be240040] |= 00000010 : GPIO bit4 pullup enable ? | |||
dl 50000000,00000001 ; delay 1 | |||
dl 0D500010,00000001 ; [$bd500010] = 00000001 | |||
dl 3D500010,00000001 ; while( [$bd500010] & 1) | |||
dl 0D500040,00000001 ; [$bd500040] = 00000001 | |||
dl F0000000 ; end | |||
; | |||
;script command : rec-dev I/O init | |||
; | |||
L80010AD4: | |||
dl 3D500010,00000001 ; while( [$bd500010] & 1) | |||
dl 1C100054,00000100 ; [$bc100054] |= 00000100 | |||
dl 1C100050,00000400 ; [$bc100050] |= 00000400 | |||
dl 1C100078,00000010 ; [$bc100078] |= 00000010 | |||
dl 2C10004C,FFFFFEFF ; [$bc10004C] &= FFFFFEFF | |||
dl F0000000 ; end | |||
; | |||
;------------------------------------------------------------------------------ | |||
;code end | |||
;------------------------------------------------------------------------------ | |||
</pre> | |||
== | == PSVita Compatibility mode behavior == | ||
PRE-IPL is sent by the compatibility secure module (os0:sm/compat_sm.self) to the non-secure kernel which writes it to 0xE8100000 (named CompatSharedSram and mapped to the 0xBFC00000 reset vector on the emulated PSP/Tachyon side). | |||
compat_sm will then send a specific 0x40 bytes key to be used for by the PSVita's PRE-IPL as a 0x40 bytes XOR mask against the IPL header (the IPL is stored in the pcbc.skprx kernel module). | |||
KIRK command 1 will then be used on the result. Unlike on actual PSP units, the IPL is decrypted in a single large block rather than in multiple blocks. | |||
The 0x40 bytes key gets updated depending on the firmware version in use. | The 0x40 bytes key gets updated depending on the firmware version in use. | ||
A 0x40 bytes XOR mask is also | A 0x40 bytes XOR mask is also presumably how the PSP-3000 (and newer), as well as the 3.50+ DTP-T1000 security, is most likely handled (see PSP PRE-IPL section). | ||
= Dumper = | = Dumper = | ||
As of March 21st 2018, a dumper for DTP-T1000 | As of March 21st 2018, a dumper for DTP-T1000 PRE-IPL has been made available on github by mathieulh: | ||
* [https://github.com/mathieulh/DTP-T1000-Pre-IPL-dumper] | |||
= | = See also = | ||
* [https://web.archive.org/web/20090826053327/http://silverspring.lan.st/NPSPTD_01.txt PRE-IPL and IPL description by SilverSpring] | |||
* [https://web.archive.org/web/20090826053327/http://silverspring.lan.st/NPSPTD_01.txt |