diff --git a/Makefile.arm9 b/Makefile.arm9 index cdcf5b5..f3a5de6 100644 --- a/Makefile.arm9 +++ b/Makefile.arm9 @@ -41,7 +41,7 @@ CFLAGS += $(INCLUDE) -DARM9 $(DEFINES) CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11 -ASFLAGS := $(INCLUDE) $(ARCH) $(DEFINES) +ASFLAGS := -g $(INCLUDE) $(ARCH) $(DEFINES) LDFLAGS = -nostartfiles -T../$(LDNAME) $(CFLAGS) -Wl,-Map,$(notdir $*.map),--use-blx,--gc-sections #--------------------------------------------------------------------------------- diff --git a/arm11.ld b/arm11.ld index 7e8e682..d571b2e 100644 --- a/arm11.ld +++ b/arm11.ld @@ -4,7 +4,7 @@ MEMORY { - memregion : ORIGIN = 0x1FF80000, LENGTH = 500K + memregion : ORIGIN = 0x1FF80000, LENGTH = 100K } __memregion_start = ORIGIN(memregion); diff --git a/include/arm9/firm.h b/include/arm9/firm.h index fa34758..d8b807d 100644 --- a/include/arm9/firm.h +++ b/include/arm9/firm.h @@ -1,6 +1,5 @@ #pragma once -#include #include "types.h" #include "mem_map.h" @@ -29,5 +28,10 @@ u8 signature[0x100]; } firm_header; + +extern void (*firmLaunchEntry9)(void); +extern void (*firmLaunchEntry11)(void); + + bool firm_load_verify(void); -void firm_launch(void (*entry)(void)); +void NORETURN firm_launch(void); diff --git a/include/arm9/firm_launch_stub.h b/include/arm9/firm_launch_stub.h deleted file mode 100644 index 59157fd..0000000 --- a/include/arm9/firm_launch_stub.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include "types.h" - - - -void firmLaunchStub(void (*entry)(void)); diff --git a/source/arm11/start.s b/source/arm11/start.s index 49c0a60..03d0d42 100644 --- a/source/arm11/start.s +++ b/source/arm11/start.s @@ -22,7 +22,7 @@ _start: cpsid aif, #0x1F @ Disable all interrupts, system mode - ldr sp, =(A11_STUB_ENTRY-8) + ldr sp, =(A11_STUB_ENTRY) mov r0, #0 mcr p15, 0, r0, c7, c14, 0 @ Clear and invalidate entire data cache diff --git a/source/arm9/debug.c b/source/arm9/debug.c index 5a8eb82..1900211 100644 --- a/source/arm9/debug.c +++ b/source/arm9/debug.c @@ -8,7 +8,7 @@ static u32 debugHash = 0; -void NORETURN guruMeditation(u8 type, u32 *excStack, u32 *stackPointer) +void NORETURN guruMeditation(u8 type, unsigned int *excStack, unsigned int *stackPointer) { const char *typeStr[3] = {"Undefined instruction", "Prefetch abort", "Data abort"}; u32 realPc, instSize = 4; @@ -16,9 +16,9 @@ if(exceptionTriggered) // inception :( while(1); - + exceptionTriggered = true; - + // verify text and rodata u32 prevHash = debugHash; hashCodeRoData(); @@ -45,21 +45,21 @@ excStack[4], excStack[12], excStack[5], excStack[13], excStack[6], excStack[14], - excStack[7], (u32)stackPointer, + excStack[7], (unsigned int)stackPointer, excStack[8], excStack[0], excStack[9], realPc); // make sure we can actually dump the stack without triggering another fault. - if((stackPointer >= A9_RAM_BASE) && (stackPointer < A9_RAM_BASE + A9_RAM_SIZE)) + if((stackPointer >= (unsigned int*)A9_RAM_BASE) && (stackPointer < (unsigned int*)(A9_RAM_BASE + A9_RAM_SIZE))) { puts("Stack dump:"); for(u32 i = 0; i < 15; i++) { - printf("0x%08X: %08X %08X\n", (u32)stackPointer, stackPointer[0], stackPointer[1]); + printf("0x%08X: %08X %08X\n", (unsigned int)stackPointer, stackPointer[0], stackPointer[1]); stackPointer += 2; } } - + if(codeChanged) printf("Attention: RO section data changed!!"); // avoid fs corruptions diff --git a/source/arm9/exception.s b/source/arm9/exception.s index 9d31ed6..3e68118 100644 --- a/source/arm9/exception.s +++ b/source/arm9/exception.s @@ -37,4 +37,4 @@ str lr, [r1, #-4]! @ Save lr on exception stack mov r2, sp mov sp, r1 - blx guruMeditation @ r0 = exception type, r1 = reg dump ptr {lr, cpsr, r0-r12, pc + X}, r2 = sp + b guruMeditation @ r0 = exception type, r1 = reg dump ptr {lr, cpsr, r0-r12, pc + X}, r2 = sp diff --git a/source/arm9/firm.c b/source/arm9/firm.c index 82b687f..34605db 100644 --- a/source/arm9/firm.c +++ b/source/arm9/firm.c @@ -8,10 +8,45 @@ #include "arm9/crypto.h" #include "arm9/ndma.h" #include "arm9/mpu.h" -#include "arm9/firm_launch_stub.h" +void NORETURN firmLaunchStub(void) +{ + firm_header *firm_hdr = (firm_header*)FIRM_LOAD_ADDR; + void (*entry9)(void) = firmLaunchEntry9; + if(firmLaunchEntry9 == NULL) entry9 = (void (*)(void))firm_hdr->entrypointarm9; + void (*entry11)(void) = firmLaunchEntry11; + if(firmLaunchEntry11 == NULL) entry11 = (void (*)(void))firm_hdr->entrypointarm11; + + + for(int i = 0; i < 4; i++) + { + firm_sectionheader *section = &firm_hdr->section[i]; + if(section->size == 0) + continue; + + REG_NDMA_SRC_ADDR(i) = FIRM_LOAD_ADDR + section->offset; + REG_NDMA_DST_ADDR(i) = section->address; + REG_NDMA_WRITE_CNT(i) = section->size>>2; + REG_NDMA_BLOCK_CNT(i) = NDMA_BLOCK_SYS_FREQ; + REG_NDMA_CNT(i) = NDMA_DST_UPDATE_INC | NDMA_SRC_UPDATE_INC | NDMA_IMMEDIATE_MODE | NDMA_ENABLE; + } + + while(REG_NDMA0_CNT & NDMA_ENABLE || REG_NDMA1_CNT & NDMA_ENABLE || REG_NDMA2_CNT & NDMA_ENABLE || REG_NDMA3_CNT & NDMA_ENABLE); + + // Tell ARM11 its entrypoint + *((vu32*)CORE_SYNC_PARAM) = (u32)entry11; + + // Wait for ARM11... + while(*((vu32*)CORE_SYNC_ID) != 0x544F4F42); + + // go for it! + __asm__ __volatile__("mov lr, %[in]\n" : : [in] "r" (firm_hdr->entrypointarm9)); + entry9(); + while(1); +} + bool firm_load_verify(void) { firm_header *firm_hdr = (firm_header*)FIRM_LOAD_ADDR; @@ -43,7 +78,7 @@ return retval; } -void firm_launch(void (*entry)(void)) +void NORETURN firm_launch(void) { *((vu32*)CORE_SYNC_ID) = 0x544F4F42; @@ -54,7 +89,8 @@ NDMA_copy((void*)A9_STUB_ENTRY, (void*)firmLaunchStub, 0x200>>2); //printf("Starting firm launch...\n"); - void (*stub_entry)(void (*)(void)) = (void (*)(void (*)(void)))A9_STUB_ENTRY; + void (*stub)(void) = (void (*)(void))A9_STUB_ENTRY; disableMpu(); - stub_entry(entry); + stub(); + while(1); } diff --git a/source/arm9/firm_launch_stub.c b/source/arm9/firm_launch_stub.c deleted file mode 100644 index 745e358..0000000 --- a/source/arm9/firm_launch_stub.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include "types.h" -#include "mem_map.h" -#include "arm9/firm_launch_stub.h" -#include "arm9/firm.h" -#include "arm9/ndma.h" - - - -void NORETURN firmLaunchStub(void (*entry)(void)) -{ - firm_header *firm_hdr = (firm_header*)FIRM_LOAD_ADDR; - if(entry == NULL) entry = (void (*)(void))firm_hdr->entrypointarm9; - - - for(int i = 0; i < 4; i++) - { - firm_sectionheader *section = &firm_hdr->section[i]; - if(section->size == 0) - continue; - - REG_NDMA_SRC_ADDR(i) = FIRM_LOAD_ADDR + section->offset; - REG_NDMA_DST_ADDR(i) = section->address; - REG_NDMA_WRITE_CNT(i) = section->size>>2; - REG_NDMA_BLOCK_CNT(i) = NDMA_BLOCK_SYS_FREQ; - REG_NDMA_CNT(i) = NDMA_DST_UPDATE_INC | NDMA_SRC_UPDATE_INC | NDMA_IMMEDIATE_MODE | NDMA_ENABLE; - } - - while(REG_NDMA0_CNT & NDMA_ENABLE || REG_NDMA1_CNT & NDMA_ENABLE || REG_NDMA2_CNT & NDMA_ENABLE || REG_NDMA3_CNT & NDMA_ENABLE); - - // Tell ARM11 its entrypoint - *((vu32*)CORE_SYNC_PARAM) = firm_hdr->entrypointarm11; - - // Wait for ARM11... - while(*((vu32*)CORE_SYNC_ID) != 0x544F4F42); - - // go for it! - __asm__ __volatile__("mov lr, %[in]\nbx %[in2]\n" : : [in] "r" (firm_hdr->entrypointarm9), [in2] "r" (entry)); -} diff --git a/source/arm9/main.c b/source/arm9/main.c index 03adceb..90c54ff 100644 --- a/source/arm9/main.c +++ b/source/arm9/main.c @@ -155,8 +155,13 @@ } u8 rng_get_byte() -{ - return *((u32*)0x10011000) & 0xFF; // PRNG reg +{ + u32 tmp = *((u32*)0x10011000); // PRNG reg + for(u32 i = 8; i < 40; i += 8) + { + tmp ^= (u8)(tmp >> i); + } + return (u8)tmp; } static void loadFirmNand(void) diff --git a/source/arm9/menu.c b/source/arm9/menu.c index 8eee1ab..f93c94b 100644 --- a/source/arm9/menu.c +++ b/source/arm9/menu.c @@ -165,7 +165,7 @@ } while(!(keys & KEY_B)); menu_state = STATE_MAIN; } - else firm_launch(NULL); + else goto exitAndLaunchFirm; break; default: printf("OOPS!\n"); break; @@ -174,5 +174,7 @@ } +exitAndLaunchFirm: + return 0; } diff --git a/source/arm9/start.s b/source/arm9/start.s index f7b03db..454f470 100644 --- a/source/arm9/start.s +++ b/source/arm9/start.s @@ -7,6 +7,8 @@ .global _start .global _init +.global firmLaunchEntry9 +.global firmLaunchEntry11 .type _start STT_FUNC .type _init STT_FUNC @@ -15,6 +17,7 @@ .extern __libc_init_array .extern heap_init .extern main +.extern firm_launch .extern __bss_start__ .extern __bss_end__ @@ -23,23 +26,21 @@ _start: b skip_pool - - // - .string "3DS BOOTLOADER " - .word BOOTLOADER_VERSION - .align + + .string "3DS BOOTLOADER " + .word BOOTLOADER_VERSION + .word 0 @ Flags +firmLaunchEntry9: + .word 0 @ Entrypoint override field +firmLaunchEntry11: + .word 0 skip_pool: msr cpsr_c, #0xDF @ Disable all interrupts, system mode - ldr sp, =(A9_STUB_ENTRY-8) + ldr sp, =(A9_STUB_ENTRY) bl setupSystem - ldr r0, =(CORE_SYNC_ID & 0xFFFFFFF0) - mov r1, #0 - str r1, [r0, #0x8] @ Clear arm9 communication fields - str r1, [r0, #0xC] - ldr r0, =__bss_start__ ldr r1, =__bss_end__ sub r1, r1, r0 @@ -52,7 +53,9 @@ blx __libc_init_array blx heap_init blx main - b . @ If main ever returns loop forever + cmp r0, #0 + beq firm_launch + b . @ needed by libc diff --git a/source/arm9/system.s b/source/arm9/system.s index de4e0b6..9818145 100644 --- a/source/arm9/system.s +++ b/source/arm9/system.s @@ -8,8 +8,8 @@ .global disableMpu .type setupSystem STT_FUNC -.type setupTcms STT_FUNC .type setupExceptionVectors STT_FUNC +.type setupTcms STT_FUNC .type setupMpu STT_FUNC .type disableMpu STT_FUNC @@ -20,7 +20,7 @@ setupSystem: - push {r4-r10, lr} + mov r10, lr @ Control register: @ [19] ITCM load mode : disabled @@ -45,34 +45,19 @@ bl setupExceptionVectors @ Setup the vectors in ARM9 mem bootrom vectors jump to bl setupTcms @ Setup and enable DTCM and ITCM bl setupMpu - - pop {r4-r10, pc} - - -setupTcms: - ldr r0, =0xFFF0000A @ Base = 0xFFF00000, size = 16 KB - mcr p15, 0, r0, c9, c1, 0 @ Write DTCM region reg - mov r0, #0x00000024 @ Base = 0x00000000, size = 512 KB (32 KB mirrored) - mcr p15, 0, r0, c9, c1, 1 @ Write ITCM region reg - - mrc p15, 0, r0, c1, c0, 0 @ Read control register - orr r0, r0, #0x50000 @ Enable DTCM and ITCM - mcr p15, 0, r0, c1, c0, 0 @ Write control register - - bx lr + bx r10 #define MAKE_BRANCH(src, dst) (0xEA000000 | (((((dst) - (src)) >> 2) - 2) & 0xFFFFFF)) setupExceptionVectors: - mov r10, lr ldr r0, =_vectorStubs_ mov r1, #A9_RAM_BASE ldmia r0!, {r2-r9} stmia r1!, {r2-r9} ldmia r0, {r2-r5} stmia r1, {r2-r5} - bx r10 + bx lr _vectorStubs_: .word MAKE_BRANCH(A9_RAM_BASE + 0x00, A9_RAM_BASE + 0x00) // IRQ .word 0 @@ -88,6 +73,18 @@ dataAbortHandlerPtr: .word dataAbortHandler +setupTcms: + ldr r0, =0xFFF0000A @ Base = 0xFFF00000, size = 16 KB + mcr p15, 0, r0, c9, c1, 0 @ Write DTCM region reg + mov r0, #0x00000024 @ Base = 0x00000000, size = 512 KB (32 KB mirrored) + mcr p15, 0, r0, c9, c1, 1 @ Write ITCM region reg + + mrc p15, 0, r0, c1, c0, 0 @ Read control register + orr r0, r0, #0x50000 @ Enable DTCM and ITCM + mcr p15, 0, r0, c1, c0, 0 @ Write control register + bx lr + + #define REGION_4KB (0b01011) #define REGION_8KB (0b01100) #define REGION_16KB (0b01101)