Boot0
This is an old revision of this page, as edited by Randomdude (talk | contribs) at 06:27, 22 August 2010. It may differ significantly from the current revision. |
boot0 is the first-stage bootloader in the Starlet ARM core on board the Hollywood; it's contained in 4K of Mask ROM (only 1.5K of which is actually used).
It contains code to read the first 48 pages of the attached NAND flash, decrypt them with a fixed AES key, hash them with SHA1, and compare the hash with a value read from OTP memory. If the hashes do not match. The system will refuse to boot. If the hash in OTP is all zeroes, then the system will always boot -- this is true of development consoles and probably also during the manufacturing process. For more discussion on this subject, see bushing's HackMii post.
The division between boot0/boot1 allows the RSA signature verification to be done using trusted code loaded from flash. It would not have fit into the 4K of space available. It is coded in a mixture of C and assembly.
; reset vectors FFFF0000 LDR PC, =_start FFFF0004 LDR PC, =__arm_undefined_handler FFFF0008 LDR PC, =__arm_syscall_handler FFFF000C LDR PC, =__arm_prefetch_abort_handler FFFF0010 LDR PC, =__arm_data_abort_handler FFFF0014 LDR PC, =__arm_reserved_handler FFFF0018 LDR PC, =__arm_irq_handler FFFF001C LDR PC, =__arm_fiq_handler FFFF001C ; --------------------------------------------------------------------------- FFFF0020 off_FFFF0020 DCD _start ; DATA XREF: FFFF0000 FFFF0024 off_FFFF0024 DCD __arm_undefined ; DATA XREF: FFFF0004 FFFF0028 off_FFFF0028 DCD __arm_syscall ; DATA XREF: FFFF0008 FFFF002C off_FFFF002C DCD __arm_prefetch_abort ; DATA XREF: FFFF000C FFFF0030 off_FFFF0030 DCD __arm_data_abort ; DATA XREF: FFFF0010 FFFF0034 off_FFFF0034 DCD __arm_reserved ; DATA XREF: FFFF0014 FFFF0038 off_FFFF0038 DCD __arm_irq ; DATA XREF: FFFF0018 FFFF003C off_FFFF003C DCD __arm_fiq ; DATA XREF: FFFF001C FFFF0040 ; =============== S U B R O U T I N E ======================================= FFFF0040 _start ; CODE XREF: FFFF0000 FFFF001C FFFF0040 ; DATA XREF: off_FFFF0020 FFFF0040 MOV R1, #0 FFFF0044 MOV R4, #0 FFFF0048 MOV R11, #0 FFFF004C MOV R11, #0 FFFF0050 MOV LR, #0 FFFF0054 LDR SP, =0xD417C00 ; set stack pointer to top of SRAM FFFF0058 BL _main FFFF005C BL panic ; should never be reached FFFF005C ; End of function _start ; All of the other vector handlers just hang FFFF0060 __arm_undefined_handler FFFF0060 B __arm_undefined_handler FFFF0064 __arm_syscall_handler FFFF0064 B __arm_syscall_handler FFFF0068 __arm_prefetch_abort_handler FFFF0068 B __arm_prefetch_abort_handler FFFF006C __arm_data_abort_handler FFFF006C B __arm_data_abort_handler FFFF0070 __arm_reserved_handler FFFF0070 B __arm_reserved_handler FFFF0074 __arm_irq_handler FFFF0074 B __arm_irq_handler FFFF0078 __arm_fiq_handler FFFF0078 B __arm_fiq_handler FFFF007C _main ; CODE XREF: _start+18 FFFF007C B main FFFF0080 boot0_stack DCD 0xD417C00 ; DATA XREF: _start+14 FFFF0084 ; =============== S U B R O U T I N E ======================================= FFFF0084 debug_port_output ; CODE XREF: panic+14 panic+28 main+170 ... FFFF0084 MOV R3, #0xD800000 FFFF0088 LDR R2, [R3,#0xE0] FFFF008C MOV R0, R0,LSL#16 FFFF0090 BIC R2, R2, #0xFF0000 FFFF0094 AND R0, R0, #0xFF0000 FFFF0098 ORR R2, R2, R0 FFFF009C STR R2, [R3,#0xE0] ; output 8 bits to the 8 GPIOs at 0xD8000E0 FFFF00A0 BX LR FFFF00A0 ; End of function debug_port_output FFFF00A4 ; =============== S U B R O U T I N E ======================================= FFFF00A4 ; int __stdcall panic(unsigned __int8 error) FFFF00A4 panic ; CODE XREF: _start+1C main+3B8 main+3D4 FFFF00A4 MOV R12, SP FFFF00A8 STMFD SP!, {R4,R11,R12,LR,PC} FFFF00AC SUB R11, R12, #4 FFFF00B0 MOV R4, R0 FFFF00B4 loc_FFFF00B4 ; CODE XREF: panic+38 FFFF00B4 MOV R0, R4 ; alternate between 0 and the error code FFFF00B8 BL debug_port_output FFFF00BC MOVL R0, 1000000 FFFF00C4 BL delay FFFF00C8 MOV R0, #0 FFFF00CC BL debug_port_output FFFF00D0 MOVL R0, 1000000 FFFF00D8 BL delay FFFF00DC B loc_FFFF00B4 ; infinite loop FFFF00DC ; End of function panic FFFF00E0 ; =============== S U B R O U T I N E ======================================= FFFF00E0 init_gpio_direction ; CODE XREF: main+104 FFFF00E0 MOV R3, #0xD800000 ; configure GPIO direction registers FFFF00E4 LDR R2, [R3,#0xDC] FFFF00E8 AND R2, R2, #0xFF000000 FFFF00EC ORR R2, R2, #0xFF0000 FFFF00F0 STR R2, [R3,#0xDC] ; D8000DC = (D8000DC & 0xff000000) | 0x00ff0000 FFFF00F4 LDR R2, [R3,#0xE4] FFFF00F8 AND R2, R2, #0xFF000000 FFFF00FC ORR R2, R2, #0xFF0000 FFFF0100 STR R2, [R3,#0xE4] ; D8000E4 = (D8000E4 & 0xff000000) | 0x00ff0000 FFFF0104 BX LR FFFF0104 ; End of function init_gpio_direction FFFF0108 ; =============== S U B R O U T I N E ======================================= FFFF0108 main ; CODE XREF: _main FFFF0108 MOV R12, SP FFFF010C STMFD SP!, {R4-R12,LR,PC} FFFF0110 MOV R3, #0xD000000 FFFF0114 SUB R11, R12, #4 FFFF0118 ADD R3, R3, #0x20000 ; R3 = 0D020000 = AES command reg FFFF011C MOV R9, #0 FFFF0120 MOV R1, #7 FFFF0124 MOV R2, #0xD800000 FFFF0128 SUB SP, SP, #0x2C FFFF012C STR R1, [R2,#0x60] ; 0D800060 = 7 FFFF0130 SUB R2, R11, #0x54 FFFF0134 STR R9, [R3] ; write 0 to AES command reg FFFF0138 LDR R1, =boot1_key FFFF013C STR R9, [R2] FFFF0140 MOV R0, R3 FFFF0144 MOV LR, #0xD400000 FFFF0148 MOV R2, #3 FFFF014C set_AES_key ; CODE XREF: main+50 FFFF014C LDR R3, [R1],#4 ; use hardcoded boot1 key FFFF0150 SUBS R2, R2, #1 FFFF0154 STR R3, [R0,#0xC] FFFF0158 BPL set_AES_key FFFF015C MOV R12, #0xD000000 FFFF0160 LDR R1, =boot1_iv ; boot1_iv is all zeroes FFFF0164 ADD R12, R12, #0x20000 FFFF0168 MOV R2, #3 FFFF016C set_AES_iv ; CODE XREF: main+70 FFFF016C LDR R3, [R1],#4 FFFF0170 SUBS R2, R2, #1 FFFF0174 STR R3, [R12,#0x10] FFFF0178 BPL set_AES_iv FFFF017C LDR R3, =0x67452301 ; set initial SHA context FFFF0180 MOVL R1, 0xD030000 FFFF0188 MOV R0, #0 FFFF018C LDR R2, =0xEFCDAB89 FFFF0190 STR LR, [R12,#4] FFFF0194 STR LR, [R12,#8] FFFF0198 STR R0, [R1] FFFF019C STR R3, [R1,#8] FFFF01A0 LDR R3, =0x98BADCFE FFFF01A4 STR R2, [R1,#0xC] FFFF01A8 LDR R2, =0x10325476 FFFF01AC STR R3, [R1,#0x10] FFFF01B0 LDR R3, =0xC3D2E1F0 FFFF01B4 STR R2, [R1,#0x14] FFFF01B8 MOV R2, #0xD400000 FFFF01BC STR R3, [R1,#0x18] FFFF01C0 STR R2, [R1,#4] FFFF01C4 MOVL R3, 0xD010000 FFFF01CC LDR R2, [R3,#4] FFFF01D0 MOVL R1, 0x80FF0000 FFFF01D8 ORR R2, R2, #0x8000000 FFFF01DC ADD R1, R1, #0x8000 FFFF01E0 STR R2, [R3,#4] FFFF01E4 MOV R4, #0xD800000 FFFF01E8 STR R0, [R3,#0x10] FFFF01EC STR R0, [R3,#0x14] FFFF01F0 STR R0, [R3,#8] FFFF01F4 STR R0, [R3,#0xC] FFFF01F8 STR R1, [R3] FFFF01FC MOV R3, #0x80000000 FFFF0200 MOV R6, R0 FFFF0204 STR R3, [R4,#0x1EC] ; 0D8001EC = 0x80000000 FFFF0208 SUB R5, R11, #0x3C FFFF020C BL init_gpio_direction FFFF0210 MOV R1, R6 ; c FFFF0214 MOV R0, R5 ; dest FFFF0218 MOV R2, #20 ; len FFFF021C BL memset ; zero out hash buffer FFFF0220 MOV R1, #16 ; read 20 bytes of OTP data into *R5 FFFF0224 get_otp_hash ; CODE XREF: main+138 FFFF0224 AND R3, R6, #0x1F FFFF0228 ORR R3, R3, #0x80000000 FFFF022C STR R3, [R4,#0x1EC] ; *starlet_otp_addr = (R6 & 0x1f) | 0x80000000; FFFF0230 LDR R2, [R4,#0x1F0] ; R2 = *starlet_otp_data FFFF0234 SUBS R1, R1, #4 FFFF0238 STR R2, [R5],#4 FFFF023C ADD R6, R6, #1 ; R6++ FFFF0240 BPL get_otp_hash FFFF0244 MOV R1, #0 FFFF0248 SUB R2, R11, #0x28 FFFF024C is_otp_hash_empty? ; CODE XREF: main+15C FFFF024C LDR R3, [R2,#-0x14] ; if OTP hash is all zeroes, then we're still FFFF0250 CMP R3, #0 ; in the factory with a blank OTP, so FFFF0254 ADD R1, R1, #1 ; don't verify the hash against boot1 FFFF0258 ADD R2, R2, #4 FFFF025C BNE otp_hash_not_empty FFFF0260 CMP R1, #4 FFFF0264 BLS is_otp_hash_empty? FFFF0268 loc_FFFF0268 ; CODE XREF: main+3CC FFFF0268 MOVL R8, 0xD010000 FFFF0270 MOV R4, #0 ; R4 = flash page number FFFF0274 boot1_read_loop ; CODE XREF: main+2F0 FFFF0274 MOV R0, R4 ; as we read in the flash pages, output FFFF0278 BL debug_port_output ; each page number to the debug port FFFF027C ORR R0, R4, #0x80 ; hi bit is a strobe bit FFFF0280 BL debug_port_output FFFF0284 loc_FFFF0284 ; CODE XREF: main+184 FFFF0284 LDR R3, [R8] ; R3 = *0D100000 = NAND status FFFF0288 CMP R3, #0 FFFF028C BLT loc_FFFF0284 ; wait for command to complete FFFF0290 CMP R4, #47 ; pageno > 47? FFFF0294 BCS done_reading_flash FFFF0298 MOV R3, #0x9F000000 FFFF029C STR R4, [R8,#0xC] FFFF02A0 STR R3, [R8] FFFF02A4 MOVL R0, 0xD010000 ; D010000 = NAND Flash HW FFFF02AC read_flash_page ; CODE XREF: main+1AC FFFF02AC LDR R3, [R0] ; wait for non-busy status from NAND flash FFFF02B0 CMP R3, #0 FFFF02B4 BLT read_flash_page FFFF02B8 AND R3, R4, #1 FFFF02BC MOV R3, R3,LSL#7 FFFF02C0 MOV R1, #0x80000000 FFFF02C4 ADD R3, R3, #0xD400000 FFFF02C8 ADD R1, R1, #0x308000 ; 0x30 = READ PAGE FFFF02CC MOV R2, R4,LSL#11 FFFF02D0 ADD R2, R2, #0xD400000 FFFF02D4 ADD R3, R3, #0x17800 ; read into 0xD417800 FFFF02D8 ADD R1, R1, #0x3840 FFFF02DC STR R2, [R0,#0x10] FFFF02E0 STR R3, [R0,#0x14] FFFF02E4 STR R1, [R0] ; send flash command FFFF02E8 done_reading_flash ; CODE XREF: main+18C FFFF02E8 MOVL R2, 0xD020000 ; D020000 = AES hw FFFF02F0 loc_FFFF02F0 ; CODE XREF: main+1F0 FFFF02F0 LDR R3, [R2] FFFF02F4 CMP R3, #0 ; wait for non-busy status from AES FFFF02F8 BLT loc_FFFF02F0 FFFF02FC CMP R4, #0 FFFF0300 BEQ loc_FFFF03D0 FFFF0304 CMP R4, #47 FFFF0308 BHI loc_FFFF03D0 FFFF030C SUB R2, R4, #1 FFFF0310 AND R3, R2, #1 FFFF0314 MOV R3, R3,LSL#7 FFFF0318 ADD R6, R3, #0xD400000 FFFF031C MOV R2, R2,LSL#11 FFFF0320 MOV R10, #0xFF0 FFFF0324 ADD R6, R6, #0x17800 FFFF0328 ADD R10, R10, #0xF FFFF032C ADD R5, R2, #0xD400000 FFFF0330 MOV R7, #0 FFFF0334 calc_ecc ; CODE XREF: main+2A4 FFFF0334 MOV R2, R7,LSL#2 ; this code takes the hardware-generated ECC syndrome FFFF0338 ADD R3, R6, #0x30 ; from the NAND flash interface, and uses it to try to FFFF033C LDR R12, [R3,R2] ; correct single-bit errors in boot1. FFFF0340 ADD R0, R6, R2 ; If we hit more than one error per 512 bytes, we're screwed. FFFF0344 AND R1, R12, #0xFF0000 FFFF0348 LDR R2, [R0,#0x40] FFFF034C MOV R1, R1,LSR#8 FFFF0350 AND R3, R12, #0xFF00 FFFF0354 ORR R1, R1, R12,LSR#24 FFFF0358 ORR R1, R1, R3,LSL#8 FFFF035C AND R3, R2, #0xFF0000 FFFF0360 MOV R3, R3,LSR#8 FFFF0364 ORR R3, R3, R2,LSR#24 FFFF0368 AND R0, R2, #0xFF00 FFFF036C ORR R3, R3, R0,LSL#8 FFFF0370 CMP R12, R2 FFFF0374 ORR R12, R1, R12,LSL#24 FFFF0378 ORR R2, R3, R2,LSL#24 FFFF037C EOR R12, R12, R2 FFFF0380 SUB R1, R12, #1 FFFF0384 BEQ loc_FFFF03A0 FFFF0388 MOV R3, R12,LSL#20 FFFF038C MOV R3, R3,LSR#20 FFFF0390 MOV R2, R12,LSR#16 FFFF0394 TST R1, R12 FFFF0398 EOR R3, R2, R3 FFFF039C BNE uncorrectable_ecc_error FFFF03A0 loc_FFFF03A0 ; CODE XREF: main+27C main+3B4 main+3BC FFFF03A0 ADD R7, R7, #1 FFFF03A4 CMP R7, #4 FFFF03A8 ADD R5, R5, #0x200 FFFF03AC BCC calc_ecc FFFF03B0 MOV R1, #0x98000000 FFFF03B4 ADD R2, R1, #0x1040 FFFF03B8 MOV R3, #0xD000000 FFFF03BC CMP R4, #1 FFFF03C0 ADD R2, R2, #0x3F FFFF03C4 ADD R3, R3, #0x20000 FFFF03C8 ADDEQ R2, R1, #0x7F FFFF03CC STR R2, [R3] FFFF03D0 loc_FFFF03D0 ; CODE XREF: main+1F8 main+200 FFFF03D0 MOVL R2, 0xD030000 ; D030000 = SHA1 HW FFFF03D8 loc_FFFF03D8 ; CODE XREF: main+2D8 FFFF03D8 LDR R3, [R2] FFFF03DC CMP R3, #0 ; wait for SHA1 non-busy status FFFF03E0 BLT loc_FFFF03D8 FFFF03E4 CMP R4, #1 FFFF03E8 MOVHI R3, #0x8000001F FFFF03EC ADD R4, R4, #1 FFFF03F0 STRHI R3, [R2] ; update SHA1 context FFFF03F4 CMP R4, #48 FFFF03F8 BLS boot1_read_loop FFFF03FC MOVL R2, 0xD030000 FFFF0404 done_reading_boot1 ; CODE XREF: main+304 FFFF0404 LDR R3, [R2] FFFF0408 CMP R3, #0 ; wait for SHA1 non-busy status FFFF040C BLT done_reading_boot1 FFFF0410 SUB R3, R11, #0x54 ; Was OTP hash zero? FFFF0414 LDR R3, [R3] FFFF0418 CMP R3, #0 FFFF041C BEQ jump_boot1 FFFF0420 MOVL R0, 0xD030000 FFFF0428 ADD R0, R0, #8 FFFF042C MOV R1, #0 FFFF0430 SUB R2, R11, #0x28 FFFF0434 loc_FFFF0434 ; CODE XREF: main+340 FFFF0434 LDR R3, [R0,R1,LSL#2] FFFF0438 ADD R1, R1, #1 FFFF043C CMP R1, #4 FFFF0440 STR R3, [R2,#-0x28] FFFF0444 ADD R2, R2, #4 FFFF0448 BLS loc_FFFF0434 FFFF044C SUB R0, R11, #0x28 FFFF0450 MOV R1, #4 FFFF0454 compare_hashes ; CODE XREF: main+364 FFFF0454 LDR R2, [R0,#-0x14] FFFF0458 LDR R3, [R0,#-0x28] FFFF045C CMP R2, R3 FFFF0460 MOVNE R9, #1 FFFF0464 SUBS R1, R1, #1 FFFF0468 ADD R0, R0, #4 FFFF046C BPL compare_hashes FFFF0470 CMP R9, #0 FFFF0474 BNE hash_fail FFFF0478 jump_boot1 ; CODE XREF: main+314 main+3D8 FFFF0478 MOV R0, #0xA FFFF047C BL debug_port_output ; output 0x0A FFFF0480 MOV R0, #0x88 FFFF0484 BL debug_port_output ; output 0x88 FFFF0488 LDR PC, =0xFFF00000 ; jump to BOOT1 (this is aliased to 0x0D400000) FFFF048C ; --------------------------------------------------------------------------- FFFF048C SUB SP, R11, #0x28 ; return code generated by compiler FFFF0490 LDMFD SP, {R4-R11,SP,PC}; (unreachable) FFFF0494 ; --------------------------------------------------------------------------- FFFF0494 uncorrectable_ecc_error ; CODE XREF: main+294 FFFF0494 BIC R1, R2, #7 FFFF0498 MOV R1, R1,LSL#20 FFFF049C CMP R3, R10 FFFF04A0 MOV R1, R1,LSR#20 FFFF04A4 AND R12, R2, #7 FFFF04A8 LDREQB R2, [R5,R1,ASR#3] FFFF04AC MOVEQ R3, #1 FFFF04B0 EOREQ R2, R2, R3,LSL R12 FFFF04B4 MOV R0, #0xF1 ; error F1 FFFF04B8 STREQB R2, [R5,R1,ASR#3] FFFF04BC BEQ loc_FFFF03A0 FFFF04C0 BL panic ; panic code F1 = ECC failure FFFF04C4 B loc_FFFF03A0 FFFF04C8 ; --------------------------------------------------------------------------- FFFF04C8 otp_hash_not_empty ; CODE XREF: main+154 FFFF04C8 MOV R2, #1 FFFF04CC SUB R3, R11, #0x54 FFFF04D0 STR R2, [R3] ; set a flag indicating that the otp hash is valid FFFF04D4 B loc_FFFF0268 FFFF04D8 ; --------------------------------------------------------------------------- FFFF04D8 hash_fail ; CODE XREF: main+36C FFFF04D8 MOV R0, #0xF2 ; error F2 = OTP mismatch FFFF04DC BL panic FFFF04E0 B jump_boot1 FFFF04E0 ; --------------------------------------------------------------------------- FFFF04E4 off_FFFF04E4 DCD boot1_key ; DATA XREF: main+30 FFFF04E8 off_FFFF04E8 DCD boot1_iv ; DATA XREF: main+58 FFFF04EC kSHA1_0 DCD 0x67452301 ; DATA XREF: main+74 FFFF04F0 kSHA1_1 DCD 0xEFCDAB89 ; DATA XREF: main+84 FFFF04F4 kSHA1_2 DCD 0x98BADCFE ; DATA XREF: main+98 FFFF04F8 kSHA1_3 DCD 0x10325476 ; DATA XREF: main+A0 FFFF04FC kSHA1_4 DCD 0xC3D2E1F0 ; DATA XREF: main+A8 FFFF0500 boot1_entrypt DCD 0xFFF00000 ; DATA XREF: main+380 FFFF0504 DCB 0 FFFF0505 a_GCCGNU3_4_3 DCB "GCC: (GNU) 3.4.3",0 ; garbage inserted by compiler lol? FFFF0516 DCB 0, 0 FFFF0518 ; =============== S U B R O U T I N E ======================================= FFFF0518 unused1 FFFF0518 BIC R0, R0, #0x35000000 FFFF051C BIC R0, R0, #0x10000 FFFF0520 MOVL R3, 0xFFFFFFC FFFF0524 SUB R3, R3, #0x2BC0000 FFFF0528 ORR R0, R0, #0xCA000000 FFFF052C SUB R3, R3, #0x28000 FFFF0530 ORR R0, R0, #0xFE0000 FFFF0534 STR R0, [R3] FFFF0538 MOV R0, #0 FFFF053C B unused11 FFFF053C ; End of function unused1 FFFF0540 ; =============== S U B R O U T I N E ======================================= FFFF0540 unused2 FFFF0540 BIC R0, R0, #0x45000000 FFFF0544 BIC R0, R0, #0x2F0000 FFFF0548 MOVL R3, 0xFFFFFFC FFFF054C SUB R3, R3, #0x2BC0000 FFFF0550 ORR R0, R0, #0xBA000000 FFFF0554 SUB R3, R3, #0x28000 FFFF0558 ORR R0, R0, #0xD00000 FFFF055C STR R0, [R3] FFFF0560 MOV R0, #1 FFFF0564 B unused12 FFFF0564 ; End of function unused2 FFFF0568 ; =============== S U B R O U T I N E ======================================= FFFF0568 unused3 FFFF0568 STR R1, [R0] FFFF056C BX LR FFFF056C ; End of function unused3 FFFF0570 ; =============== S U B R O U T I N E ======================================= FFFF0570 unused4 FFFF0570 LDR R0, [R0] FFFF0574 BX LR FFFF0574 ; End of function unused4 FFFF0578 ; =============== S U B R O U T I N E ======================================= FFFF0578 unused5 FFFF0578 STRH R1, [R0] FFFF057C BX LR FFFF057C ; End of function unused5 FFFF0580 ; =============== S U B R O U T I N E ======================================= FFFF0580 unused6 FFFF0580 LDRH R0, [R0] FFFF0584 BX LR FFFF0584 ; End of function unused6 FFFF0588 ; =============== S U B R O U T I N E ======================================= FFFF0588 delay ; CODE XREF: panic+20 panic+34 FFFF0588 CMP R0, #0 FFFF058C BXEQ LR FFFF0590 loc_FFFF0590 ; CODE XREF: delay+C FFFF0590 SUBS R0, R0, #1 FFFF0594 BNE loc_FFFF0590 FFFF0598 BX LR FFFF0598 ; End of function delay FFFF059C ; =============== S U B R O U T I N E ======================================= FFFF059C unused7 FFFF059C STMFD SP!, {R0-R3} FFFF05A0 ADD SP, SP, #0x10 FFFF05A4 RET FFFF05A4 ; End of function unused7 FFFF05A8 ; =============== S U B R O U T I N E ======================================= FFFF05A8 unused8 FFFF05A8 STMFD SP!, {R0-R3} FFFF05AC ADD SP, SP, #0x10 FFFF05B0 RET FFFF05B0 ; End of function unused8 FFFF05B4 ; =============== S U B R O U T I N E ======================================= FFFF05B4 unused9 FFFF05B4 STMFD SP!, {R0-R3} FFFF05B8 ADD SP, SP, #0x10 FFFF05BC RET FFFF05BC ; End of function unused9 FFFF05C0 ; =============== S U B R O U T I N E ======================================= FFFF05C0 ; int __stdcall memset(void *dest, int c, int len) FFFF05C0 memset ; CODE XREF: main+114 FFFF05C0 SUB R2, R2, #1 FFFF05C4 CMN R2, #1 FFFF05C8 MOV R3, R0 FFFF05CC BXEQ LR FFFF05D0 loc_FFFF05D0 ; CODE XREF: memset+1C FFFF05D0 SUB R2, R2, #1 FFFF05D4 CMN R2, #1 FFFF05D8 STRB R1, [R3],#1 FFFF05DC BNE loc_FFFF05D0 FFFF05E0 BX LR FFFF05E0 ; End of function memset FFFF05E4 ; =============== S U B R O U T I N E ======================================= FFFF05E4 ; Attributes: noreturn FFFF05E4 unused10 ; CODE XREF: unused11+4, unused12+4 FFFF05E4 MCR p15, 0, R0,c7,c0, 4 FFFF05E8 hang ; CODE XREF: unused10:hang FFFF05E8 B hang FFFF05E8 ; End of function unused10 FFFF05EC ; =============== S U B R O U T I N E ======================================= FFFF05EC unused11 ; CODE XREF: unused1+24 FFFF05EC MOV R0, #0 FFFF05F0 BL unused10 FFFF05F0 ; End of function unused11 FFFF05F4 ; =============== S U B R O U T I N E ======================================= FFFF05F4 unused12 ; CODE XREF: unused2+24 FFFF05F4 MOV R0, #1 FFFF05F8 BL unused10 FFFF05F8 ; End of function unused12 FFFF05F8 ; --------------------------------------------------------------------------- FFFF05FC boot1_key DCD 0x9258A752,0x64960D82,0x676F9044,0x56882A73 FFFF05FC ; DATA XREF: main:off_FFFF04E4 FFFF060C boot1_iv DCD 0, 0, 0, 0 ; DATA XREF: main:off_FFFF04E8 FFFF1FFC DCD 0xABAB0101 ; not sure what this is FFFF1FFC ; boot0 ends