diff --git a/include/arm11/start.h b/include/arm11/start.h index dae0809..e4fe8f3 100644 --- a/include/arm11/start.h +++ b/include/arm11/start.h @@ -23,5 +23,4 @@ noreturn void _start(void); -void clearMem(u32 *adr, u32 size); void deinitCpu(void); diff --git a/include/arm9/hardware/crypto.h b/include/arm9/hardware/crypto.h index e8cae17..851a16b 100644 --- a/include/arm9/hardware/crypto.h +++ b/include/arm9/hardware/crypto.h @@ -307,7 +307,7 @@ * * @return Returns true on success, false otherwise. */ -bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp); +bool RSA_setKey2048(u8 keyslot, const u32 *const mod, u32 exp); /** * @brief Decrypts a RSA 2048 signature. @@ -317,7 +317,7 @@ * * @return Returns true on success, false otherwise. */ -bool RSA_decrypt2048(void *const decSig, const void *const encSig); +bool RSA_decrypt2048(u32 *const decSig, const u32 *const encSig); /** * @brief Verifies a RSA 2048 SHA 256 signature. diff --git a/include/arm9/start.h b/include/arm9/start.h index 53fab51..97900f1 100644 --- a/include/arm9/start.h +++ b/include/arm9/start.h @@ -22,5 +22,4 @@ -void clearMem(u32 *adr, u32 size); void deinitCpu(void); diff --git a/include/mmio.h b/include/mmio.h new file mode 100644 index 0000000..532b616 --- /dev/null +++ b/include/mmio.h @@ -0,0 +1,26 @@ +/* + * This file is part of fastboot 3DS + * Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s + +#include "types.h" + + + +void iomemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size); +void iomemset(vu32 *ptr, u32 value, u32 size); diff --git a/source/arm11/hardware/hash.c b/source/arm11/hardware/hash.c index afce122..b1137bb 100644 --- a/source/arm11/hardware/hash.c +++ b/source/arm11/hardware/hash.c @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -#include #include "types.h" #include "mem_map.h" #include "arm11/hardware/hash.h" +#include "mmio.h" @@ -27,11 +27,11 @@ // HASH // ////////////////////////////////// -#define HASH_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x1000) -#define REG_HASH_CNT *((vu32*)(HASH_REGS_BASE + 0x00)) -#define REG_HASH_BLKCNT *((vu32*)(HASH_REGS_BASE + 0x04)) -#define REG_HASH_HASH ((u32* )(HASH_REGS_BASE + 0x40)) -#define REG_HASH_INFIFO ( (IO_MEM_ARM11_ONLY + 0x101000)) // INFIFO is in the DMA region +#define HASH_REGS_BASE (IO_MEM_ARM9_ARM11 + 0x1000) +#define REG_HASH_CNT *((vu32*)(HASH_REGS_BASE + 0x00)) +#define REG_HASH_BLKCNT *((vu32*)(HASH_REGS_BASE + 0x04)) +#define REGs_HASH_HASH ((vu32*)(HASH_REGS_BASE + 0x40)) +#define REGs_HASH_INFIFO ((vu32*)(IO_MEM_ARM11_ONLY + 0x101000)) // INFIFO is in the DMA region void HASH_start(u8 params) @@ -43,14 +43,13 @@ { while(size >= 64) { - *((_u512*)REG_HASH_INFIFO) = *((const _u512*)data); - data += 16; - while(REG_HASH_CNT & HASH_ENABLE); - + *((volatile _u512*)REGs_HASH_INFIFO) = *((const _u512*)data); + data += 64 / 4; size -= 64; + while(REG_HASH_CNT & HASH_ENABLE); } - if(size) memcpy((void*)REG_HASH_INFIFO, data, size); + if(size) iomemcpy(REGs_HASH_INFIFO, data, size); } void HASH_finish(u32 *const hash, u8 endianess) @@ -63,23 +62,21 @@ void HASH_getState(u32 *const out) { - u32 stateSize; + u32 size; switch(REG_HASH_CNT & HASH_MODE_MASK) { case HASH_MODE_256: - stateSize = 32; + size = 32; break; case HASH_MODE_224: - stateSize = 28; + size = 28; break; case HASH_MODE_1: - stateSize = 20; - break; - default: - return; + default: // 2 and 3 are both SHA1 + size = 20; } - memcpy(out, REG_HASH_HASH, stateSize); + iomemcpy(out, REGs_HASH_HASH, size); } void hash(const u32 *data, u32 size, u32 *const hash, u8 params, u8 hashEndianess) diff --git a/source/arm11/hardware/mmu.c b/source/arm11/hardware/mmu.c index 57b0100..c8266f5 100644 --- a/source/arm11/hardware/mmu.c +++ b/source/arm11/hardware/mmu.c @@ -20,7 +20,7 @@ #include "mem_map.h" #include "fb_assert.h" #include "arm11/hardware/scu.h" -#include "arm11/start.h" +#include "mmio.h" #include "arm.h" @@ -153,7 +153,7 @@ if(!__getCpuId()) { // Clear L1 and L2 tables - clearMem((u32*)A11_MMU_TABLES_BASE, 0x4C00); + iomemset((u32*)A11_MMU_TABLES_BASE, 0, 0x4C00); // IO mem mapping mmuMapSections(IO_MEM_ARM9_ARM11, IO_MEM_ARM9_ARM11, 4, true, diff --git a/source/arm11/start.s b/source/arm11/start.s index 3a2b922..d4d1765 100644 --- a/source/arm11/start.s +++ b/source/arm11/start.s @@ -26,7 +26,6 @@ .fpu vfpv2 .global _start -.global clearMem .global _init .global deinitCpu .global __superhaxEnabled @@ -34,7 +33,6 @@ .type vectors %function .type _start %function .type stubExceptionVectors %function -.type clearMem %function .type checkSuperhax %function .type setupVfp %function .type _init %function @@ -47,6 +45,7 @@ .extern __bss_start__ .extern __bss_end__ .extern __end__ +.extern iomemset .extern fake_heap_start .extern fake_heap_end .extern setupMmu @@ -132,8 +131,9 @@ @ Clear bss section ldr r0, =__bss_start__ ldr r1, =__bss_end__ - sub r1, r1, r0 - bl clearMem + sub r2, r1, r0 + mov r1, #0 + bl iomemset @ Setup newlib heap ldr r0, =A11_HEAP_END ldr r1, =fake_heap_end @@ -182,38 +182,7 @@ .pool -@ void clearMem(u32 *adr, u32 size) .align 2 -clearMem: - bics r12, r1, #31 - mov r2, #0 - sub r1, r1, r12 - beq clearMem_check_zero - stmfd sp!, {r4-r9} - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov r8, #0 - mov r9, #0 - clearMem_block_lp: - stmia r0!, {r2-r9} - subs r12, r12, #32 - bne clearMem_block_lp - ldmfd sp!, {r4-r9} -clearMem_check_zero: - cmp r1, #0 - bxeq lr - clearMem_remaining_lp: - str r2, [r0], #4 - subs r1, r1, #4 - bne clearMem_remaining_lp - bx lr - -.pool - - checkSuperhax: ldr r0, =BOOT11_BASE + 0x8000 ldr r1, [r0] diff --git a/source/arm9/hardware/crypto.c b/source/arm9/hardware/crypto.c index 1b5823d..492f558 100644 --- a/source/arm9/hardware/crypto.c +++ b/source/arm9/hardware/crypto.c @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -#include +//#include #include "mem_map.h" #include "fb_assert.h" #include "types.h" @@ -25,6 +25,7 @@ #include "arm9/hardware/interrupt.h" #include "arm9/hardware/ndma.h" #include "arm.h" +#include "mmio.h" @@ -555,11 +556,11 @@ // SHA // ////////////////////////////////// -#define SHA_REGS_BASE (IO_MEM_ARM9_ONLY + 0xA000) -#define REG_SHA_CNT *((vu32*)(SHA_REGS_BASE + 0x00)) -#define REG_SHA_BLKCNT *((vu32*)(SHA_REGS_BASE + 0x04)) -#define REG_SHA_HASH ((u32* )(SHA_REGS_BASE + 0x40)) -#define REG_SHA_INFIFO ( (SHA_REGS_BASE + 0x80)) +#define SHA_REGS_BASE (IO_MEM_ARM9_ONLY + 0xA000) +#define REG_SHA_CNT *((vu32*)(SHA_REGS_BASE + 0x00)) +#define REG_SHA_BLKCNT *((vu32*)(SHA_REGS_BASE + 0x04)) +#define REGs_SHA_HASH ((vu32*)(SHA_REGS_BASE + 0x40)) +#define REGs_SHA_INFIFO ((vu32*)(SHA_REGS_BASE + 0x80)) void SHA_start(u8 params) @@ -571,14 +572,13 @@ { while(size >= 64) { - *((_u512*)REG_SHA_INFIFO) = *((const _u512*)data); - data += 16; - while(REG_SHA_CNT & SHA_ENABLE); - + *((volatile _u512*)REGs_SHA_INFIFO) = *((const _u512*)data); + data += 64 / 4; size -= 64; + while(REG_SHA_CNT & SHA_ENABLE); } - if(size) memcpy((void*)REG_SHA_INFIFO, data, size); + if(size) iomemcpy(REGs_SHA_INFIFO, data, size); } void SHA_finish(u32 *const hash, u8 endianess) @@ -591,23 +591,21 @@ void SHA_getState(u32 *const out) { - u32 stateSize; + u32 size; switch(REG_SHA_CNT & SHA_MODE_MASK) { case SHA_MODE_256: - stateSize = 32; + size = 32; break; case SHA_MODE_224: - stateSize = 28; + size = 28; break; case SHA_MODE_1: - stateSize = 20; - break; - default: - return; + default: // 2 and 3 are both SHA1 + size = 20; } - memcpy(out, REG_SHA_HASH, stateSize); + iomemcpy(out, REGs_SHA_HASH, size); } void sha(const u32 *data, u32 size, u32 *const hash, u8 params, u8 hashEndianess) @@ -631,9 +629,9 @@ #define REGs_RSA_SLOT2 ((vu32*)(RSA_REGS_BASE + 0x120)) #define REGs_RSA_SLOT3 ((vu32*)(RSA_REGS_BASE + 0x130)) #define rsaSlots ((RsaSlot*)(RSA_REGS_BASE + 0x100)) -#define REG_RSA_EXP ((vu32*)(RSA_REGS_BASE + 0x200)) -#define REG_RSA_MOD ( (RSA_REGS_BASE + 0x400)) -#define REG_RSA_TXT ( (RSA_REGS_BASE + 0x800)) +#define REGs_RSA_EXP ((vu32*)(RSA_REGS_BASE + 0x200)) +#define REGs_RSA_MOD ((vu32*)(RSA_REGS_BASE + 0x400)) +#define REGs_RSA_TXT ((vu32*)(RSA_REGS_BASE + 0x800)) typedef struct { @@ -662,7 +660,7 @@ REG_RSA_CNT = (REG_RSA_CNT & ~RSA_KEYSLOT(0xFu)) | RSA_KEYSLOT(keyslot); } -bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp) +bool RSA_setKey2048(u8 keyslot, const u32 *const mod, u32 exp) { fb_assert(keyslot < 4); fb_assert(mod != NULL); @@ -674,16 +672,16 @@ if(!(slot->REG_RSA_SLOTCNT & RSA_KEY_UNK_BIT31)) slot->REG_RSA_SLOTCNT &= ~RSA_KEY_STAT_SET; REG_RSA_CNT = RSA_INPUT_NORMAL | RSA_INPUT_BIG | RSA_KEYSLOT(keyslot); - memset((void*)REG_RSA_EXP, 0, 0x100 - 4); - REG_RSA_EXP[(0x100>>2) - 1] = exp; + iomemset(REGs_RSA_EXP, 0, 0x100 - 4); + REGs_RSA_EXP[(0x100>>2) - 1] = exp; if(slot->REG_RSA_SLOTSIZE != RSA_SLOTSIZE_2048) return false; - memcpy((void*)REG_RSA_MOD, mod, 0x100); + iomemcpy(REGs_RSA_MOD, mod, 0x100); return true; } -bool RSA_decrypt2048(void *const decSig, const void *const encSig) +bool RSA_decrypt2048(u32 *const decSig, const u32 *const encSig) { fb_assert(decSig != NULL); fb_assert(encSig != NULL); @@ -693,11 +691,11 @@ if(!(rsaSlots[keyslot].REG_RSA_SLOTCNT & RSA_KEY_STAT_SET)) return false; REG_RSA_CNT |= RSA_INPUT_NORMAL | RSA_INPUT_BIG; - memcpy((void*)REG_RSA_TXT, encSig, 0x100); + iomemcpy(REGs_RSA_TXT, encSig, 0x100); REG_RSA_CNT |= RSA_ENABLE; rsaWaitBusy(); - memcpy(decSig, (void*)REG_RSA_TXT, 0x100); + iomemcpy(decSig, REGs_RSA_TXT, 0x100); return true; } @@ -707,8 +705,8 @@ fb_assert(encSig != NULL); fb_assert(data != NULL); - u8 decSig[0x100]; - if(!RSA_decrypt2048(decSig, encSig)) return false; + alignas(4) u8 decSig[0x100]; + if(!RSA_decrypt2048((u32*)decSig, encSig)) return false; if(decSig[0] != 0x00 || decSig[1] != 0x01) return false; diff --git a/source/arm9/start.s b/source/arm9/start.s index bf96c06..de44f9e 100644 --- a/source/arm9/start.s +++ b/source/arm9/start.s @@ -26,14 +26,12 @@ .fpu softvfp .global _start -.global clearMem .global _init .global deinitCpu .type _start %function .type setupExceptionVectors %function .type setupTcms %function -.type clearMem %function .type checkSuperhax %function .type setupMpu %function .type _init %function @@ -42,6 +40,7 @@ .extern __bss_start__ .extern __bss_end__ .extern __end__ +.extern iomemset .extern fake_heap_start .extern fake_heap_end .extern __libc_init_array @@ -103,8 +102,9 @@ @ Clear bss section ldr r0, =__bss_start__ ldr r1, =__bss_end__ - sub r1, r1, r0 - bl clearMem + sub r2, r1, r0 + mov r1, #0 + bl iomemset @ Setup newlib heap ldr r0, =IO_MEM_ARM9_ONLY @ CFG9 regs ldr r1, [r0, #0xFFC] @ REG_CFG9_MPCORECFG @@ -174,38 +174,7 @@ .pool -@ void clearMem(u32 *adr, u32 size) .align 2 -clearMem: - bics r12, r1, #31 - mov r2, #0 - sub r1, r1, r12 - beq clearMem_check_zero - stmfd sp!, {r4-r9} - mov r3, #0 - mov r4, #0 - mov r5, #0 - mov r6, #0 - mov r7, #0 - mov r8, #0 - mov r9, #0 - clearMem_block_lp: - stmia r0!, {r2-r9} - subs r12, r12, #32 - bne clearMem_block_lp - ldmfd sp!, {r4-r9} -clearMem_check_zero: - cmp r1, #0 - bxeq lr - clearMem_remaining_lp: - str r2, [r0], #4 - subs r1, r1, #4 - bne clearMem_remaining_lp - bx lr - -.pool - - checkSuperhax: ldr r0, =IO_MEM_ARM9_ONLY @ CFG9 regs ldrb r1, [r0] diff --git a/source/mmio.s b/source/mmio.s new file mode 100644 index 0000000..fb0e5ab --- /dev/null +++ b/source/mmio.s @@ -0,0 +1,87 @@ +/* + * This file is part of fastboot 3DS + * Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + @ Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s + +#include "asmfunc.h" + +.arm +.cpu arm946e-s +.fpu softvfp + + + +@ void iomemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size) +ASM_FUNC iomemcpy + bics r12, r2, #31 + beq iomemcpy_test_words + stmfd sp!, {r4-r10} + iomemcpy_blocks_lp: + ldmia r1!, {r3-r10} + stmia r0!, {r3-r10} + subs r12, #32 + bne iomemcpy_blocks_lp + ldmfd sp!, {r4-r10} +iomemcpy_test_words: + ands r12, r2, #28 + beq iomemcpy_halfword_byte + iomemcpy_words_lp: + ldr r3, [r1], #4 + str r3, [r0], #4 + subs r12, #4 + bne iomemcpy_words_lp +iomemcpy_halfword_byte: + tst r2, #2 + ldrneh r3, [r1], #2 + strneh r3, [r0], #2 + tst r2, #1 + ldrneb r3, [r1] + strneb r3, [r0] + bx lr + + +@ void iomemset(vu32 *ptr, u32 value, u32 size) +ASM_FUNC iomemset + bics r12, r2, #31 + beq iomemset_test_words + stmfd sp!, {r4-r9} + mov r3, r1 + mov r4, r1 + mov r5, r1 + mov r6, r1 + mov r7, r1 + mov r8, r1 + mov r9, r1 + iomemset_blocks_lp: + stmia r0!, {r1, r3-r9} + subs r12, #32 + bne iomemset_blocks_lp + ldmfd sp!, {r4-r9} +iomemset_test_words: + ands r12, r2, #28 + beq iomemset_halfword_byte + iomemset_words_lp: + str r1, [r0], #4 + subs r12, #4 + bne iomemset_words_lp +iomemset_halfword_byte: + tst r2, #2 + strneh r1, [r0], #2 + tst r2, #1 + strneb r1, [r0] + bx lr