-
Notifications
You must be signed in to change notification settings - Fork 1
/
minfirm.asm
218 lines (164 loc) · 6.04 KB
/
minfirm.asm
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
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
.3ds
.create "min.firm",0
.headersize 0x0 + 0x3B00 ; ITCM, at offset where boot9 loads the firm header
; Use the mirror at 0 so we can do PC-relative bl into the bootrom at 0xFFFFXXXX
payloadsector equ (0x0B800000 / 0x200)
nopslide_addr equ 0x1FFFA000 ; nop slide in AXIWRAM generated by a boot11 memset
nopslide_end equ (0x1FFFC000 - arm11stub_size)
arm11stub_size equ (arm11stub_end - arm11stub)
;.notice tohex(nopslide_end - nopslide_addr)
area0maxsize equ (0x30 + 8) ; reserved + section 0 offset, address
area1maxsize equ (4 + 0x20 + 8) ; section 0 copy method + section 0 hash + section 1 offset, address
area2maxsize equ (4 + 0x20 + 8) ; section 1 copy method + section 1 hash + section 2 offset, address
area3maxsize equ (4 + 0x20 + 8) ; section 2 copy method + section 2 hash + section 3 offset, address
area4maxsize equ (4 + 0x20) ; section 3 copy method + section 3 hash
; Firm Header:
.area 0x10
.ascii "FIRM" ; magic
; boot priority (code)
.thumb
Entry:
add sp, #0x1FC ; place stack in unused ITCM, saves space over
; using arm-mode code to put it in fcram or whatever
b Entry1
.word nopslide_addr | 1 ; arm11 entry
.word Entry | 1 ; arm9 entry
.endarea
.orga 0x10
area0:
.area area0maxsize
.skip 0x30 ; stupid known-plaintext XOR things. usually this could be used for code.
.thumb
Entry1:
add r0, =arm11stub
ldr r1, =nopslide_end
mov r2, #arm11stub_size
mov r7, #1
endarea0:
.endarea
.orga 0x48
.word 0 ; section 0 size
.orga 0x4C
area1:
.area area1maxsize
blx 0xFFFF03F0 ; memcpy(src, dst, count)
; sdmmc stuff adapted from https://github.com/yellows8/unprotboot9_sdmmc
lsl r5, r1, #6 ; =0xfff00000
add r5, 0x9c
str r7, [r5, #0x1c]
bl 0xffff1ff8 ; funcptr_boot9init
bl 0xffff56c8 ; funcptr_mmcinit
lsl r0, r7, #9 ; = 0x200
ldr r6, =nopslide_end
lsl r1, r7, #28
ldr r2, [r1, #0x20] ; CFG9_SDMMCCTL
orr r2, r0
bic r2, r7
str r2, [r1, #0x20]
add r0, #1 ; =0x201
ldr r3, =0x10146000 ; HID_PAD
ldrh r3, [r3]
lsr r3, #10
bne use_nand ; if X and Y are pressed, forcibly use SD
use_sd:
str r7, [r6, #arm11stub_size] ; tell arm11 to flash the power LED
endarea1:
.endarea
.orga 0x78
.word 0 ; section 1 size
.orga 0x7C
area2:
.area area2maxsize
lsl r0, r7, #9 ; = 0x200
use_nand:
bl 0xffff5774 ; ub9_initdev
ldr r4, [r5, #0x20]
orr r4, r7
str r4, [r5, #0x20]
ldr r2, =nopslide_end
add r2, #(arm11stub_size + 4) ; load the FIRM header 4 bytes after the ARM11 stub
mov r1, #1
ldr r0, =payloadsector
bl 0xffff55f8 ; ub9_readsectors(sector, size_sectors, address)
ldr r0, [r6, #(arm11stub_size + 4)] ; load magic from loaded FIRM header
ldr r1, =0x4D524946 ; ascii "FIRM"
cmp r0, r1
bne use_sd
mov r4, #4
add r6, #(0x40 + arm11stub_size + 4) ; point r6 to first FIRM section header
firmload_loop:
ldmia r6!, {r0, r2, r3} ; load section offset, load address, size
lsr r1, r3, #9 ; / 0x200 to get size in sectors
beq firmload_skip ; if size is 0, don't do anything for this section
lsr r0, #9 ; convert section offset to sectors
endarea2:
.endarea
.orga 0xA8
.word 0 ; section 2 size
.orga 0xAC
area3:
.area area3maxsize
ldr r3, =payloadsector
add r0, r3
bl 0xffff55f8 ; ub9_readsectors
firmload_skip:
add r6, #0x24 ; advance r6 to point to the next section header
sub r4, #1
bne firmload_loop
ldr r3, =nopslide_end
ldr r4, [r3, #(0xC + arm11stub_size + 4)] ; load arm9 entrypoint from FIRM header
str r3, [r3, #arm11stub_size] ; tell arm11 to jump to its entrypoint
; the specific value written here doesn't matter, just something > 1
mov r0, #0 ; 0 out argc,
mov r1, #0 ; argv, and
mov r2, #0 ; magicWord (luma uses this for entrypoint detection)
bx r4 ; jump to arm9 entrypoint
.pool
endarea3:
.endarea
.orga 0xD8
.word 0 ; section 3 size
.orga 0xDC
area4:
.area area4maxsize
.thumb
.align 4
arm11stub: ; this all gets relocated to AXIWRAM and runs on arm11
ldr r0, [arm11stub_end] ; this will always initially be 0;
; arm9 will write here when it's time to do something
cmp r0, #1 ; 0: loop, 1: set LED, else: jump to entrypoint
blo arm11stub
beq arm11stub_write_reg
ldr r0, [arm11stub_end + 4 + 8] ; load arm11 entrypoint
bx r0
arm11stub_write_reg:
lsl r0, #29 ; =0x20000000
mov sp, r0 ; place stack at the end of axiwram
ldr r3, [boot11_i2c_write_reg]
mov r0, #3
mov r1, #0x29
mov r2, #6
blx r3 ; set power LED to flashing red
b arm11stub ; keep looping
.align 4
boot11_i2c_write_reg:
.word 0x000135CD
.align 4
arm11stub_end:
endarea4:
.endarea
.orga 0x100
.incbin "sig.bin"
.close
area0size equ (endarea0 - area0)
area1size equ (endarea1 - area1)
area2size equ (endarea2 - area2)
area3size equ (endarea3 - area3)
area4size equ (endarea4 - area4)
.notice "Area 0: 0x" + tohex(area0size, 2) + " / 0x" + tohex(area0maxsize, 2) + " bytes used, 0x" + tohex(area0maxsize - area0size, 2) + " bytes free"
.notice "Area 1: 0x" + tohex(area1size, 2) + " / 0x" + tohex(area1maxsize, 2) + " bytes used, 0x" + tohex(area1maxsize - area1size, 2) + " bytes free"
.notice "Area 2: 0x" + tohex(area2size, 2) + " / 0x" + tohex(area2maxsize, 2) + " bytes used, 0x" + tohex(area2maxsize - area2size, 2) + " bytes free"
.notice "Area 3: 0x" + tohex(area3size, 2) + " / 0x" + tohex(area3maxsize, 2) + " bytes used, 0x" + tohex(area3maxsize - area3size, 2) + " bytes free"
.notice "Area 4: 0x" + tohex(area4size, 2) + " / 0x" + tohex(area4maxsize, 2) + " bytes used, 0x" + tohex(area4maxsize - area4size, 2) + " bytes free"
.notice ""
.notice "Total: 0x" + tohex(area0size + area1size + area2size + area3size + area4size, 2) + " / 0x" + tohex(area0maxsize + area1maxsize + area2maxsize + area3maxsize + area4maxsize, 2) + " bytes used"