2017-07-29 13:17:31 +02:00
|
|
|
.section .text
|
|
|
|
.arm
|
|
|
|
.align 4
|
|
|
|
|
2017-08-18 13:45:00 -03:00
|
|
|
#include <arm.h>
|
|
|
|
#include <vram.h>
|
|
|
|
|
|
|
|
.equ ARG_MAGIC, 0x0000BEEF
|
2017-07-29 13:17:31 +02:00
|
|
|
.equ MPCORE_LD, 0x27FFFB00
|
|
|
|
.equ STUB_LOC, 0x27FFFC00
|
2017-08-18 13:45:00 -03:00
|
|
|
.equ ARGV_LOC, 0x27FFFE00
|
|
|
|
.equ FBPTR_LOC, 0x27FFFE08
|
|
|
|
.equ PATH_LOC, 0x27FFFF00
|
2017-07-29 13:17:31 +02:00
|
|
|
|
|
|
|
.cpu mpcore
|
|
|
|
MPCore_stub:
|
2017-08-18 13:45:00 -03:00
|
|
|
cpsid aif, #(SR_SVC_MODE)
|
2017-07-29 13:17:31 +02:00
|
|
|
mov r0, #0x20000000
|
|
|
|
mov r1, #0
|
|
|
|
str r1, [r0, #-4]
|
|
|
|
.Lcheckmpcentry:
|
|
|
|
ldr r1, [r0, #-4]
|
|
|
|
cmp r1, #0
|
|
|
|
beq .Lcheckmpcentry
|
|
|
|
bx r1
|
|
|
|
.pool
|
|
|
|
MPCore_stub_end:
|
|
|
|
|
|
|
|
@ Assume these functions ALWAYS clobber R0-R3 and R12 and don't use the stack
|
|
|
|
.equ MEMCPY, 0xFFFF0374 @ void memcpy32(void *src, void *dest, u32 size)
|
|
|
|
.equ INV_DC, 0xFFFF07F0 @ void invalidate_dcache(void)
|
|
|
|
.equ WB_DC, 0xFFFF07FC @ void writeback_dcache(void)
|
|
|
|
.equ WBINV_DC, 0xFFFF0830 @ void writeback_invalidate_dcache(void)
|
|
|
|
.equ INV_IC, 0xFFFF0AB4 @ void invalidate_icache(void)
|
|
|
|
.equ INITCP15, 0xFFFF0C58 @ void reset_cp15(void)
|
|
|
|
|
|
|
|
.cpu arm946e-s
|
|
|
|
@ void BootFirm_stub(void *firm, char *path)
|
|
|
|
@ r0-r8: scratch registers
|
|
|
|
@ r9: FIRM path
|
|
|
|
@ r10: FIRM header
|
|
|
|
@ r11: current section header
|
|
|
|
BootFirm_stub:
|
|
|
|
mov r10, r0
|
|
|
|
add r11, r0, #0x40
|
|
|
|
mov r9, r1
|
|
|
|
|
|
|
|
mov r4, #4
|
|
|
|
.LBootFirm_stub_copysect:
|
|
|
|
@ Fetch source, destination and length
|
|
|
|
ldmia r11, {r0-r2}
|
|
|
|
|
|
|
|
cmp r2, #0 @ If section is unused/zerolength, don't even bother
|
|
|
|
addne r0, r10 @ Fix source address
|
|
|
|
|
|
|
|
ldrne r3, =MEMCPY
|
|
|
|
blxne r3
|
|
|
|
|
|
|
|
subs r4, #1
|
|
|
|
addne r11, #0x30 @ Advance to the next section
|
|
|
|
bne .LBootFirm_stub_copysect
|
|
|
|
|
|
|
|
@ Boot state
|
|
|
|
@ CPSR:
|
|
|
|
@ ARM, Supervisor, IRQ/FIQs disabled
|
|
|
|
@ Flags are undefined
|
2017-08-18 13:45:00 -03:00
|
|
|
msr cpsr_c, #(SR_SVC_MODE | SR_IRQ | SR_FIQ)
|
2017-07-29 13:17:31 +02:00
|
|
|
|
|
|
|
@ CP15:
|
|
|
|
@ MPU and Caches are off
|
|
|
|
@ TCMs are on (location/configuration is undefined)
|
|
|
|
@ Alternative exception vectors are enabled (0xFFFF0000)
|
|
|
|
ldr r3, =WBINV_DC
|
|
|
|
ldr r4, =INV_IC
|
|
|
|
ldr r5, =INITCP15
|
|
|
|
blx r3
|
|
|
|
blx r4
|
|
|
|
blx r5
|
|
|
|
|
|
|
|
@ Registers:
|
2017-08-18 13:45:00 -03:00
|
|
|
@ R0 = 0x1 or 0x2
|
2017-07-29 13:17:31 +02:00
|
|
|
@ R1 = 0x23FFFE10
|
|
|
|
@ R2 = 0x0000BEEF
|
|
|
|
@ R3-R14 are undefined
|
|
|
|
|
2017-08-12 23:41:51 +02:00
|
|
|
@ Check screen-init flag
|
|
|
|
ldrb r3, [r10, #0x10]
|
|
|
|
tst r3, #1
|
|
|
|
movne r0, #2
|
|
|
|
moveq r0, #1
|
2017-07-29 13:17:31 +02:00
|
|
|
ldr r1, =ARGV_LOC
|
|
|
|
ldr r2, =ARG_MAGIC
|
|
|
|
|
|
|
|
|
|
|
|
@ Setup argv
|
2017-08-12 23:41:51 +02:00
|
|
|
ldrne r3, =FBPTR_LOC
|
2017-08-18 13:45:00 -03:00
|
|
|
str r9, [r1, #0x00] @ FIRM path / argv[0]
|
2017-08-12 23:41:51 +02:00
|
|
|
strne r3, [r1, #0x04] @ Framebuffers / argv[1]
|
2017-07-29 13:17:31 +02:00
|
|
|
|
|
|
|
@ Fetch FIRM entrypoints
|
|
|
|
ldr r3, [r10, #0x08] @ ARM11 entrypoint
|
|
|
|
ldr r4, [r10, #0x0C] @ ARM9 entrypoint
|
|
|
|
|
|
|
|
@ Set the ARM11 entrypoint
|
|
|
|
mov r5, #0x20000000
|
|
|
|
str r3, [r5, #-4]
|
|
|
|
|
|
|
|
@ Branch to the ARM9 entrypoint
|
|
|
|
bx r4
|
|
|
|
|
|
|
|
.pool
|
|
|
|
BootFirm_stub_end:
|
|
|
|
|
|
|
|
@ void BootFirm(void *firm, char *path)
|
|
|
|
@ BootFirm_stub wrapper
|
|
|
|
@ No checks are performed on the data
|
|
|
|
.global BootFirm
|
|
|
|
.type BootFirm, %function
|
|
|
|
BootFirm:
|
|
|
|
mov r10, r0
|
2017-08-18 13:45:00 -03:00
|
|
|
mov r11, r1
|
|
|
|
|
|
|
|
@ Setup the framebuffer struct
|
|
|
|
ldr r0, =FBPTR_LOC
|
|
|
|
ldr r1, =VRAM_TOP_LA
|
|
|
|
ldr r2, =VRAM_TOP_RA
|
|
|
|
ldr r3, =VRAM_BOT_A
|
|
|
|
stmia r0!, {r1,r2,r3}
|
|
|
|
|
|
|
|
ldr r1, =VRAM_TOP_LB
|
|
|
|
ldr r2, =VRAM_TOP_RB
|
|
|
|
ldr r3, =VRAM_BOT_B
|
|
|
|
stmia r0!, {r1,r2,r3}
|
2017-07-29 13:17:31 +02:00
|
|
|
|
|
|
|
@ Copy the FIRM path somewhere safe
|
2017-08-18 13:45:00 -03:00
|
|
|
ldr r0, =PATH_LOC
|
|
|
|
mov r1, r11
|
2017-07-29 13:17:31 +02:00
|
|
|
mov r11, r0
|
|
|
|
blx strcpy
|
|
|
|
|
|
|
|
@ Relocate the MPCore stub binary
|
|
|
|
ldr r4, =MPCORE_LD
|
|
|
|
adr r1, MPCore_stub
|
|
|
|
adr r2, MPCore_stub_end
|
|
|
|
sub r2, r1
|
|
|
|
mov r0, r4
|
|
|
|
blx memcpy
|
|
|
|
|
|
|
|
@ Make the ARM11 run the stub, wait until its done
|
|
|
|
mov r1, #0x20000000
|
|
|
|
mov r0, r4
|
|
|
|
str r0, [r1, #-4]
|
|
|
|
.Lwaitforsi:
|
|
|
|
ldr r0, [r1, #-4]
|
|
|
|
cmp r0, #0
|
|
|
|
bne .Lwaitforsi
|
|
|
|
|
|
|
|
@ Relocate BootFirm
|
|
|
|
ldr r4, =STUB_LOC
|
|
|
|
adr r5, BootFirm_stub
|
|
|
|
adr r6, BootFirm_stub_end
|
|
|
|
sub r7, r6, r5
|
|
|
|
|
|
|
|
mov r0, r4
|
|
|
|
mov r1, r5
|
|
|
|
mov r2, r7
|
|
|
|
blx memcpy
|
|
|
|
|
|
|
|
mov r0, r10
|
|
|
|
mov r1, r11
|
|
|
|
|
|
|
|
bx r4
|
|
|
|
b .
|