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