| .psx | |
| ; BIOS program is ripped from Mr Driller G | |
| .open "bios_program.bin", "bios_program_patched.bin", 0x1fc00000 | |
| .definelabel INPUT_DATA_SIZE_IN_BLOCKS, 0xbc | |
| .definelabel ESCAPED_PAYLOAD_ADDR, 0x80010000-0x800 | |
| .definelabel DECRYPTED_PAYLOAD_ADDR, 0x80010000 | |
| .definelabel CHECKSUM_BUFF_ADDR, 0x80000000 | |
| .org 0x1fc1a000 | |
| ;.dw (0x0000189b * 1) ; Set to 9600 baud | |
| ;.dw (0x0000189b * 6) ; Set to 57600 baud | |
| .dw (0x0000189b * 12) ; Set to 115200 baud | |
| ; Disable some prints which have strings that are being overwritten by code | |
| .org 0x1fc20758 | |
| nop | |
| nop | |
| nop | |
| .org 0x1fc20784 | |
| nop | |
| nop | |
| nop | |
| .org 0x1fc207e4 | |
| nop | |
| nop | |
| nop | |
| .org 0x1fc20884 | |
| ; Patch decryption length | |
| slti v0, s0, INPUT_DATA_SIZE_IN_BLOCKS | |
| .org 0x1fc20860 | |
| b initialize_crypto | |
| nop | |
| initialize_crypto_ret: | |
| .org 0x1fc2081c | |
| b write_decrypted_data_to_serial | |
| nop | |
| .org 0x1fc20038 | |
| CHUNK_START: | |
| .ascii 0x0d,0x0a,"CHUNK " | |
| initialize_crypto: | |
| li a0, 0x8000 | |
| li a1, 0x1f300000 | |
| sh a0, 0(a1) | |
| nop | |
| b initialize_crypto_ret | |
| nop | |
| write_decrypted_data_to_serial: | |
| addiu sp, sp, -0x04 | |
| ; address to read data from to write to NAND | |
| li s4, DECRYPTED_PAYLOAD_ADDR | |
| li s5, INPUT_DATA_SIZE_IN_BLOCKS * 0x20 | |
| CHUNK_WRITER_LOOP: | |
| ; Watchdog | |
| li s2, 0x1fb60000 | |
| sw zero, 0(s2) | |
| beq s5, zero, CHUNK_WRITER_LOOP_END | |
| move s3, zero | |
| li s0, ESCAPED_PAYLOAD_ADDR | |
| li s1, 0x400 | |
| CLEAR_BUFF2: | |
| beq s1, zero, CLEAR_BUF_END2 | |
| nop | |
| sw zero, 0(s0) | |
| nop | |
| addiu s0, s0, 4 | |
| b CLEAR_BUFF2 | |
| subi s1, s1, 4 | |
| CLEAR_BUF_END2: | |
| ; Write data as hex string into payload buffer | |
| move s0, s4 | |
| li s6, ESCAPED_PAYLOAD_ADDR | |
| li s1, 0x200 | |
| WRITE_HEX_STRING_PAYLOAD_LOOP: | |
| beq s1, zero, WRITE_HEX_STRING_PAYLOAD_LOOP_END | |
| nop | |
| lbu a1, 0(s0) | |
| move a0, s6 | |
| jal FUNC_WRITE_HEX_STRING | |
| li a2, 2 | |
| addiu s0, s0, 1 | |
| addiu s6, s6, 2 | |
| b WRITE_HEX_STRING_PAYLOAD_LOOP | |
| subi s1, s1, 1 | |
| WRITE_HEX_STRING_PAYLOAD_LOOP_END: | |
| li a2, CHECKSUM_BUFF_ADDR | |
| li a3, 0x10 | |
| CLEAR_BUFF: | |
| beq a3, zero, CLEAR_BUF_END | |
| nop | |
| sw zero, 0(a2) | |
| nop | |
| addiu a2, a2, 4 | |
| b CLEAR_BUFF | |
| subi a3, a3, 4 | |
| CLEAR_BUF_END: | |
| ; Write current memory addr as hex string | |
| li a0, CHECKSUM_BUFF_ADDR | |
| move a1, s4 | |
| jal FUNC_WRITE_HEX_STRING | |
| li a2, 8 | |
| ; Watchdog | |
| li s2, 0x1fb60000 | |
| sw zero, 0(s2) | |
| ; CALL CHUNKSUM_FUNC on normal payload | |
| li a2, CHECKSUM_BUFF_ADDR + 8 | |
| move a0, s4 | |
| jal CHUNKSUM_FUNC | |
| li a1, 0x200 | |
| sw s3, 4(sp) | |
| ; Write chunk header | |
| li a0, CHUNK_START | |
| jal SERIAL_WRITE_BUFFER | |
| li a1, 0x08 | |
| ; Write chunk checksum | |
| li a0, CHECKSUM_BUFF_ADDR | |
| jal SERIAL_WRITE_BUFFER | |
| li a1, 0x10 | |
| ; Write chunk data | |
| li a0, ESCAPED_PAYLOAD_ADDR | |
| jal SERIAL_WRITE_BUFFER | |
| li a1, 0x400 | |
| addiu s4, s4, 0x200 | |
| b CHUNK_WRITER_LOOP | |
| subi s5, s5, 1 | |
| CHUNK_WRITER_LOOP_END: | |
| ; Finished everything | |
| li v0, DECRYPTED_PAYLOAD_ADDR | |
| jr v0 | |
| nop | |
| CHUNKSUM_FUNC: | |
| addiu sp, sp, -0x14 | |
| sw ra, 0x04(sp) | |
| sw s0, 0x08(sp) | |
| sw s1, 0x0c(sp) | |
| sw s2, 0x10(sp) | |
| sw s3, 0x14(sp) | |
| move s0, a0 | |
| move s1, a1 | |
| CHUNKSUM_LOOP: | |
| beq s1, zero, CHUNKSUM_LOOP_END | |
| lbu s2, 0(s0) | |
| nop | |
| addu s3, s3, s2 | |
| addiu s0, s0, 0x1 | |
| b CHUNKSUM_LOOP | |
| subiu s1, s1, 0x1 | |
| CHUNKSUM_LOOP_END: | |
| move a0, a2 | |
| move a1, s3 | |
| jal FUNC_WRITE_HEX_STRING | |
| li a2, 8 | |
| lw ra, 0x04(sp) | |
| lw s0, 0x08(sp) | |
| lw s1, 0x0c(sp) | |
| lw s2, 0x10(sp) | |
| lw s3, 0x14(sp) | |
| nop | |
| jr ra | |
| addiu sp, sp, 0x14 | |
| nop | |
| FUNC_WRITE_HEX_STRING: | |
| addiu sp, sp, -0x10 | |
| sw ra, 0x04(sp) | |
| sw s1, 0x08(sp) | |
| sw s2, 0x0c(sp) | |
| sw s3, 0x10(sp) | |
| move s1, a2 ; number of bytes to write | |
| add a0, a0, s1 | |
| move s3, a1 ; value to write | |
| CHUNKSUM_WRITE_HEX_STRING_LOOP: | |
| beq s1, zero, CHUNKSUM_WRITE_HEX_STRING_LOOP_END | |
| nop | |
| move s2, s3 ; s3 is the checksum | |
| srl s3, s3, 4 | |
| andi s2, s2, 0x0f | |
| blt s2, 0x0a, HEX_IS_NUMERIC | |
| addiu s2, s2, 0x30 | |
| addiu s2, s2, 0x07 ; +7 to turn it into an uppercase alpha byte | |
| HEX_IS_NUMERIC: | |
| subi a0, a0, 1 | |
| sb s2, 0(a0) | |
| nop | |
| b CHUNKSUM_WRITE_HEX_STRING_LOOP | |
| subi s1, s1, 1 | |
| CHUNKSUM_WRITE_HEX_STRING_LOOP_END: | |
| lw ra, 0x04(sp) | |
| lw s1, 0x08(sp) | |
| lw s2, 0x0c(sp) | |
| lw s3, 0x10(sp) | |
| nop | |
| jr ra | |
| addiu sp, sp, 0x10 | |
| nop | |
| SERIAL_WRITE_BUFFER: | |
| addiu sp, sp, -0x04 | |
| sw ra, 4(sp) | |
| move s0, a0 | |
| move s1, a1 | |
| li s2, 0 | |
| SERIAL_WRITE_BUFFER_LOOP: | |
| beq s1, zero, SERIAL_WRITE_BUFFER_END | |
| lw s2, 0(s0) | |
| nop | |
| addiu s0, s0, 4 | |
| move a0, s2 | |
| jal SERIAL_WRITE_BYTE | |
| andi a0, a0, 0xff | |
| srl s2, s2, 8 | |
| move a0, s2 | |
| jal SERIAL_WRITE_BYTE | |
| andi a0, a0, 0xff | |
| srl s2, s2, 8 | |
| move a0, s2 | |
| jal SERIAL_WRITE_BYTE | |
| andi a0, a0, 0xff | |
| srl s2, s2, 8 | |
| move a0, s2 | |
| jal SERIAL_WRITE_BYTE | |
| andi a0, a0, 0xff | |
| srl s2, s2, 8 | |
| b SERIAL_WRITE_BUFFER_LOOP | |
| subi s1, s1, 4 | |
| SERIAL_WRITE_BUFFER_END: | |
| lw ra, 4(sp) | |
| nop | |
| jr ra | |
| addiu sp, sp, 0x04 | |
| nop | |
| SERIAL_WRITE_BYTE: | |
| li t2, 0x42cc | |
| jr t2 | |
| li t1, 0x3f | |
| nop | |
| .close |