Line 1:
Line 1:
−
#REDIRECT [[Hardware/NAND]]
+
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 [http://hackmii.com/2008/05/boot0/ 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. Although it appears to have been hand-coded in assembly, there are some "dead" / unused pieces of code.
+
+
; 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_FFFF04E4o
+
FFFF060C boot1_iv DCD 0, 0, 0, 0 ; DATA XREF: main:off_FFFF04E8o
+
FFFF1FFC DCD 0xABAB0101 ; not sure what this is
+
FFFF1FFC ; boot0 ends