/*---------------------------------------------------------------------------* Project: CtrBrom - library - init File: crt0_secure.c Copyright 2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: $ $Rev$ $Author$ *---------------------------------------------------------------------------*/ #include #include #define STUPi_HW_DTCM |Image$$DTCM$$Base| void stupInitMMUTable( void ); /*---------------------------------------------------------------------------* Name: STUPi_StartHandler Description: start handler Arguments: None Returns: None. *---------------------------------------------------------------------------*/ asm void STUPi_StartHandler( void ) { PRESERVE8 INASM_EXTERN( STUPi_HW_DTCM ) INASM_EXTERN( BromMain ) INASM_EXTERN( main ) //---- disable cp15 bl stupDisableCP15 //---- initialize MMU bl stupInitMMU //---- enable cp15 bl stupEnableCP15 //---- initialize stack pointer // SVC mode mov r0, #HW_PSR_SVC_MODE msr cpsr_c, r0 ldr sp, =HW_BROM_SVC_STACK_END // IRQ mode mov r0, #HW_PSR_IRQ_MODE msr cpsr_c, r0 ldr r0, =HW_BROM_IRQ_STACK_END mov sp, r0 // System mode mov r0, #HW_PSR_SYS_MODE msr cpsr_csfx, r0 ldr r0, =HW_BROM_SYS_STACK_END mov sp, r0 //---- clear wram // 1KB mov r0, #0 ldr r1, =HW_AXI_WRAM_END mov r2, #0x0400 sub r1, r1, r2 bl STUPi_CpuClear32 //---- lnitialize sections bl stupInitSections //---- start (to 16bit code) ldr r1, =BromMain adr lr, terminate bx r1 terminate b terminate } /*---------------------------------------------------------------------------* Name: stupDisableCP15 Description: Disable Coprocessor 15 Arguments: None Returns: None *---------------------------------------------------------------------------*/ ASM void stupDisableCP15( void ) { // MMU/Caches/BranchPrediction disable mrc p15, 0, r0, c1, c0, 0 ldr r1, =HW_C1_IC_ENABLE | HW_C1_DC_ENABLE \ | HW_C1_FORCE_AP_BIT \ | HW_C1_TEX_CB_REMAP \ | HW_C1_NMFI_FIQ \ | HW_C1_EXCEPT_BIG_ENDIAN \ | HW_C1_BR_PREDICT_ENABLE \ | HW_C1_LD_INTERWORK_DISABLE \ | HW_C1_UNALIGN_ACCESS_ENABLE \ | HW_C1_ALIGN_FAULT_ENABLE \ | HW_C1_ROM_PROTECT_ENABLE \ | HW_C1_MMU_PROTECT_ENABLE \ | HW_C1_MMU_ENABLE bic r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 mrc p15, 0, r0, c1, c0, 1 ldr r1, =HW_C1_SMP_MODE \ | HW_C1_EXCLUSIVE_L1C_L2C \ | HW_C1_BR_FOLDING_ENABLE \ | HW_C1_SBR_PREDICT_ENABLE \ | HW_C1_DBR_PREDICT_ENABLE \ | HW_C1_RETURN_STACK_ENABLE bic r0, r0, r1 mcr p15, 0, r0, c1, c0, 1 #if 0 // Invalidate Caches mov r0, #0 mcr p15, 0, r0, c7, c5, 0 // Inst Cache mcr p15, 0, r0, c7, c6, 0 // Data cache #endif // Wait for write buffer empty mcr p15, 0, r0, c7, c10, 4 bx lr } /*---------------------------------------------------------------------------* Name: stupEnableCP15 Description: Enable Coprocessor 15 Arguments: None Returns: None *---------------------------------------------------------------------------*/ ASM void stupEnableCP15( void ) { // // Auxiliary Control // mrc p15, 0, r0, c1, c0, 1 ldr r1, =HW_C1_AMP_MODE \ | HW_C1_BR_FOLDING_ENABLE \ | HW_C1_SBR_PREDICT_ENABLE \ | HW_C1_DBR_PREDICT_ENABLE \ | HW_C1_RETURN_STACK_ENABLE orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 1 // // Master Control // mrc p15, 0, r0, c1, c0, 0 #if 1 // 0 -> 1 miya ldr r1, =HW_C1_EXCEPT_VEC_UPPER \ | HW_C1_FORCE_AP_BIT \ | HW_C1_UNALIGN_ACCESS_ENABLE \ | HW_C1_BR_PREDICT_ENABLE \ | HW_C1_MMU_V6 \ | HW_C1_IC_ENABLE \ | HW_C1_DC_ENABLE \ | HW_C1_MMU_ENABLE #else ldr r1, =HW_C1_0_SB1 \ | HW_C1_EXCEPT_LITTLE_ENDIAN \ | HW_C1_EXCEPT_VEC_UPPER \ | HW_C1_UNALIGN_ACCESS_ENABLE \ | HW_C1_BR_PREDICT_ENABLE \ | HW_C1_MMU_V6 \ | HW_C1_IC_ENABLE \ | HW_C1_DC_ENABLE \ | HW_C1_MMU_ENABLE #endif orr r0, r0, r1 mcr p15, 0, r0, c1, c0, 0 // Invalidate Caches mov r0, #0 mcr p15, 0, r0, c7, c5, 0 // Inst Cache mcr p15, 0, r0, c7, c6, 0 // Data cache // Wait for write buffer empty mcr p15, 0, r0, c7, c10, 4 bx lr } /*---------------------------------------------------------------------------* Name: stupInitMMU Description: Initialize MMU Arguments: None Returns: None *---------------------------------------------------------------------------*/ ASM void stupInitMMU( void ) { stmfd sp!, {r4, lr} // stack requires 8byte alignment // Invalidate ITLB DTLB mov r0, #0 mcr p15, 0, r0, c8, c5, 0 mcr p15, 0, r0, c8, c6, 0 ldr r0, =HW_BROM_MMU_T1 mov r2, #HW_C2_V5_T1_BOUNBRY_16KB // MMU L1 Table Base ldr r1, =HW_C2_0_T1_BASE_MASK_MIN mov r1, r1, ASR r2 and r1 ,r1, r0 orr r1, r1, #HW_C2_WALK_L2C_CA_NC << HW_C2_WALK_L2C_CA_SFT mcr p15, 0, r1, c2, c0, 0 ldr r1, =HW_C2_1_T1_BASE_MASK and r1 ,r1, r0 orr r1, r1, #HW_C2_WALK_L2C_CA_NC << HW_C2_WALK_L2C_CA_SFT mcr p15, 0, r1, c2, c0, 1 // MMU L1 Table Boundary mcr p15, 0, r2, c2, c0, 2 // Domain Access Permission #if 1 // miya ldr r1, =0x00000001 #else ldr r1, = HW_C3_DOMAIN_PACK( \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_CLIENT, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER, \ HW_C3_DM_AP_MANAGER \ ) #endif mcr p15, 0, r1, c3, c0, 0 // VFP Access Permission ldr r1, =HW_C1_VFP_AP_PACK( \ HW_C1_AP_PRIV, HW_C1_AP_PRIV ) mcr p15, 0, r1, c1, c0, 2 // Initialize MMU Table bl __cpp(stupInitMMUTable) ldmfd sp!, {r4, pc} // stack requires 8byte alignment } /*---------------------------------------------------------------------------* Name: stupInitMMUTable Description: Initialize MMU Table Arguments: None Returns: None *---------------------------------------------------------------------------*/ void stupInitMMUTable( void ) { u32* t1Base = (u32* )HW_BROM_MMU_T1; u32* t2Base = (u32* )HW_BROM_MMU_T2; u32* table; u32 paddr = (u32 )NULL; // Initialize as Access Prohibition table = &t1Base[0]; for ( paddr = (u32 )NULL; table < (void *)HW_BROM_MMU_T1_END; ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_APX_NA, HW_MMU6_T1_RGT_STRONG_ORDER, HW_MMU6_T1_GLOBAL, FALSE, HW_MMU6_T1_XN, 0); paddr += HW_MMU6_T1_SEC_SIZE; } #if 0 table = &t2Base[0]; for ( paddr = (u32 )NULL; table < (void *)HW_MAIN_MEM_MMU_T2_END; ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_NA, HW_MMU6_T2_LP_RGT_STRONG_ORDER, HW_MMU6_T2_GLOBAL, FALSE, HW_MMU6_T2_SP_XN); } // EDRAM Region (4MB uncache) table = &t1Base[HW_EDRAM/HW_MMU6_T1_SEC_SIZE]; for ( paddr = HW_EDRAM; paddr < HW_EDRAM_END; ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_NC, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); paddr += HW_MMU6_T1_SEC_SIZE; } // EDRAM Region (4MB cache) table = &t1Base[HW_EDRAM_CACHED/HW_MMU6_T1_SEC_SIZE]; for ( paddr = HW_EDRAM; paddr < HW_EDRAM_END; ) { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_WB_WA, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); paddr += HW_MMU6_T1_SEC_SIZE; } // Main Memory Region (64MB uncache) table = &t1Base[HW_MAIN_MEM/HW_MMU6_T1_SEC_SIZE]; #ifdef MIYA_MMU for ( paddr = HW_MAIN_MEM; paddr < HW_MAIN_MEM_SEC_END; ) #else for ( paddr = HW_MAIN_MEM; paddr < (HW_MAIN_MEM +( 64 * 1024 *1024 )); ) #endif { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_NC, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); paddr += HW_MMU6_T1_SEC_SIZE; } // Main Memory Region (64MB cache) table = &t1Base[HW_MAIN_MEM_CACHED/HW_MMU6_T1_SEC_SIZE]; #ifdef MIYA_MMU for ( paddr = HW_MAIN_MEM; paddr < HW_MAIN_MEM_SEC_END; ) #else for ( paddr = HW_MAIN_MEM; paddr < (HW_MAIN_MEM +( 64 * 1024 *1024 )); ) #endif { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_WB_WA, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); paddr += HW_MMU6_T1_SEC_SIZE; } #ifdef MIYA_MMU *table = HW_MMU6_T1_COURSE_PACK( paddr, 0 ); // T2 for Page table = &t2Base[0]; for ( paddr = HW_MAIN_MEM_LP; paddr < HW_MAIN_MEM_LP_END; ) { *table++ = HW_MMU6_T2_LP_PACK( paddr, HW_MMU6_T2_APX_ALL, //miya HW_MMU6_T2_LP_RGT_L1L2C_WB_WA, HW_MMU6_T2_LP_RGT_L1L2C_NC, HW_MMU6_T2_GLOBAL, FALSE, FALSE); paddr += HW_MMU6_T2_LP_ALIAS_SIZE; } for ( paddr = HW_MAIN_MEM_SP_NA; paddr < HW_MAIN_MEM_SP_NA_END; ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T1_APX_ALL, // miya HW_MMU6_T2_SP_RGT_STRONG_ORDER, HW_MMU6_T2_SP_RGT_L1L2C_NC, HW_MMU6_T2_GLOBAL, FALSE, FALSE); paddr += HW_MMU6_T2_SP_SIZE; } for ( paddr = HW_MAIN_MEM_SP; paddr < HW_MAIN_MEM_SP_END; ) { *table++ = HW_MMU6_T2_SP_PACK( paddr, HW_MMU6_T2_APX_ALL, // HW_MMU6_T2_SP_RGT_STRONG_ORDER, HW_MMU6_T2_SP_RGT_L1L2C_NC, HW_MMU6_T2_GLOBAL, FALSE, FALSE); paddr += HW_MMU6_T2_SP_SIZE; } t2Base += HW_MMU6_T1_CORS_SIZE/sizeof(t2Base[0]); #endif // IO Registers Region (4MB) // IOPIF (4MB) 0x40000000 table = &t1Base[HW_IOPIF/HW_MMU6_T1_SEC_SIZE]; for ( paddr = HW_IOPIF; paddr < (HW_IOPIF + 0x00100000 * 16) ; ) // HW_IOPIF_END { *table++ = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); paddr += HW_MMU6_T1_SEC_SIZE; } // APBIF (64KB) 0x44100000 table = &t1Base[HW_APBIF/HW_MMU6_T1_SEC_SIZE]; paddr = HW_APBIF; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); // GPUIF (64MB) 0x48000000 table = &t1Base[HW_GPUIF/HW_MMU6_T1_SEC_SIZE]; paddr = HW_GPUIF; *table = HW_MMU6_T1_SUSEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, FALSE); // CONFIF (64KB) 0xfe000000 mmio cfg. table = &t1Base[HW_CONFIF/HW_MMU6_T1_SEC_SIZE]; paddr = HW_CONFIF; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); // MPCore Registers Region (8KB) 0xff000000 table = &t1Base[HW_MPCORE_REG/HW_MMU6_T1_SEC_SIZE]; paddr = HW_MPCORE_REG; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_NSHARED_DEV, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); // TCRAM Region (4KB) table = &t1Base[HW_TCRAM/HW_MMU6_T1_SEC_SIZE]; paddr = HW_TCRAM; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_NC, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); // BIOS Region (32KB) 0xffff0000 table = &t1Base[HW_BIOS/HW_MMU6_T1_SEC_SIZE]; paddr = HW_BIOS; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_L1L2C_WB_WA, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); // MSelect Region (4KB) = 0xfdff0000 table = &t1Base[HW_MSEL_VIRTUAL/HW_MMU6_T1_SEC_SIZE]; paddr = HW_BIOS; *table = HW_MMU6_T1_SEC_PACK( paddr, HW_MMU6_T1_APX_ALL, HW_MMU6_T1_RGT_STRONG_ORDER, HW_MMU6_T1_GLOBAL, FALSE, FALSE, 0); #endif } #include <./crt0_misc.c>