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 mapped to 0xBFC00000 which is the reset vector of PSP's MIPS R4000 CPU, on retail PSP units it is the Tachyon (Allegrex MIPS R4000 based SOC) bootrom, on DTP-T1000 it is loaded externally to volatile memory mapped at 0xBFC00000. | |||
0.7.0 Lib-PSP iplloader and onward are composed of two parts: A loader from 0xbfc00000 to 0xbfc0027F and a payload starting at 0xbfc00280 and ending at the size specified at 0xbfc000034. | |||
A few example of payload sizes and their hashes are: | |||
A few | |||
<pre> | <pre> | ||
From older to newer; | |||
DD-MM-YYYY: | |||
20-04-2004 (Tachyon 0x00140000-0x00300000): 0xAF8 | SHA-256: 48F4F11C383621C8569EC07273AE0AF6AD79681CF5B77263A69CF908EEFE4A53 (ROM) | |||
23-07-2004 or older (0.4.0) : n/a | SHA-256: 18B5BF7AEFE956D99B397AAAAC94DC965ADFDBC2BE0532096BBC1F8F8C5B7C34 (Full Binary) | |||
08-09-2004 or older (0.6.0) : n/a | SHA-256: 5CDEDDEBE11807DDAEB17BAC03945A0B828E8057C9587652CA207E3BB959AC96 (Full Binary) | |||
18-09-2004: 0x894 (0.7.0) | SHA-256: 351ECD64C945489999D477ECAFBFBB8FE769C2484636D2F7323557F7EEFD54A2 (payload only) | |||
15-10-2004: 0x894 (0.9.0) | SHA-256: 4F794E4FF32D5267AEAEDBA362D005EF0B7E93E29CF7C8209E0D9DBB0144F4DB (payload only) | |||
04-01-2005 (Tachyon 0x00400000-0x00500000): 0xB30 | SHA-256: 41B2578F84BDE33E09356F0170FF99E2417EA7B1D02BD9163A41AE61FE74C3A5 (ROM) | |||
22-10-2005: 0xBF4 (2.60) | SHA-256: 8821D96F5FB35C55DF649A97F5703F8A705362C2F54665B5EE4221E686B5578A (payload only) | |||
14-02-2006: 0xBF4 (2.71) | SHA-256: F9160C03EC6174F54F1C1EB645CFBBDB65B3DA47DA1A5478BE30E5EB2B0852B4 (payload only) | |||
</pre> | </pre> | ||
==Devkit behavior== | |||
// | |||
On DTP-T1000 and DEM-1000 a different ROM/hardware and loading process are used, Lib-PSP iplloader will be part of a kbooti/bootdispi/writei... file containing the encrypted Lib-PSP iplloader data from 0x0 to 0x1000 followed by IPL blocks. | |||
these files are loaded externally through the Communication Processor using the bloadp command to the Persistent Boot Storage (0xBFE00000), the hardware checks the Lib-PSP iplloader data size (0x10-0x12) to know how much of the file it needs to check against the data hash, most likely CMAC encrypted (0x0-0x10), (anything over the size range is not checked/loaded), if the hash fails execution halts, it then decrypts the Lib-PSP iplloader data (cryptanalysis strongly suggest the use of a CBC block cipher, either CBC AES or CBC DES, both the CMAC and data are encrypted with a static key) itself and copies it to a memory mapped as 0xBFC00000 on the psp side starts/reset the MIPS cpu which jumps to it, (the regular CPU rom is not mapped, according to Tachyon's revision it is in fact identical to the rom present in TA-079v1 PSPs, it is capable of loading regular IPLs directly from NAND or Memory stick, on DTP-H1500/DTP-L1500 the normal behavior occurs and the IPL is loaded from NAND), on DTP-T1000 0xBFD00000 is an invalid address, trying to read from or write to it at IPL time will trigger a crash, this effectively renders the Lib-PSP iplloader (pre-ipl) dynamic (updatable/downgradable) at will since it is not stored in rom format. | |||
=== 0. | ===Prototype 0.4.0-0.6.0 (23-07-2004 or older) === | ||
Prototype Lib-PSP iplloader 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 Lib-PSP iplloader uses 0x88400000 as an hardcoded entry point, in fact the IPL payload/part3, nested inside current IPL revisions and loaded by main.bin are using the prototype format, so the prototype Lib-PSP iplloader loads the IPL part 3/payload directly. | |||
It is also of worthy of note that prototype Lib-PSP iplloader for DEM-1000 (for 0.4.0 and 0.6.0 firmwares) do not make use of 0xa0010000 as their payload location, the "payload" is instead executed in place at 0xbfc00000, as such the Lib-PSP iplloader 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 cmd0 0x01 block) | |||
The 0.7.0+ iplloader | ===0.7.0-2.50 (18-09-2004) === | ||
The 0.7.0+ pre-ipl will copy it's Lib-PSP iplloader payload (stored at 0xBFC000280) to 0x80010000 (physical address 0xa0010000) and jump there, because on DTP-T1000 0xbfc00000 is writable during Lib-PSP iplloader execution and because 0xBFD00000 is an invalid range on DTP-T1000, the payload will use the 0xBFC00000 memory (which originally contains the whole Lib-PSP iplloader 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), from 2.60 and onward the payload will just overwrite 0xbfc00000 using random data as IPL blocks get loaded. | |||
IPL blocks are then loaded from 0xBFE01000 by | IPL blocks are then loaded from 0xBFE01000 by Lib-PSP iplloader 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 0xbfc00040 and 0xbfc002c0 is used as 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) Lib-PSP iplloader (pre-ipl) rom data (stored at 0xBFC00BB0 in the 2.60 and 2.71 kbooti) 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 Lib-PSP iplloader 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 because every Sony IPL performs "*(u32 *)0xBC100004 = -1;) | |||
Please note that neither the 0xbfc00000 (on DTP-T1000) nor 0xa0010000 memory locations survive reboots. | |||
=== 3.50+ (01-06-2007 or older) === | |||
Lib-PSP iplloader adds a step using an xor key to decrypt the CMAC hash and data keys from the IPL block headers, as a result you cannot decrypt the IPL blocks meant for the new Lib-PSP iplloader using kirk cmd 1. | |||
==Retail behavior== | |||
pseucode from Tachyon 0x00140000-0x00300000 Lib-PSP iplloader payload: | |||
<pre> | <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 Lib-PSP iplloader pseudo code: | |||
<pre> | <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 ? | |||
; | |||
;------------------------------------------------------- | |||
;--------------------------------------------------------------------------- | |||
;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> | </pre> | ||