From 15882e7111704cf6e767f5e1b087a26a0f1273d5 Mon Sep 17 00:00:00 2001 From: Wolfvak Date: Thu, 27 Jul 2017 18:28:27 +0200 Subject: [PATCH] Allow running GodMode9 in any environment --- Makefile | 4 +- link.ld | 4 ++ screeninit/source/main.c | 30 +++++----- source/common/ui.h | 6 +- source/main.c | 18 +----- source/nand/nand.c | 27 +++++---- source/start.s | 124 ++++++++++++++------------------------- 7 files changed, 87 insertions(+), 126 deletions(-) diff --git a/Makefile b/Makefile index 4572823..1a2630d 100644 --- a/Makefile +++ b/Makefile @@ -139,7 +139,8 @@ binary: common @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile firm: binary screeninit - firmtool build $(OUTPUT).firm -D $(OUTPUT).elf $(OUTPUT_D)/screeninit.elf -C NDMA XDMA + firmtool build $(OUTPUT).firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-retail + firmtool build $(OUTPUT)_dev.firm -n 0x08006000 -A 0x08006000 -D $(OUTPUT).bin $(OUTPUT_D)/screeninit.elf -C NDMA XDMA -S nand-dev gateway: binary @cp resources/LauncherTemplate.dat $(OUTPUT_D)/Launcher.dat @@ -172,6 +173,7 @@ release: #@[ -d $(RELEASE)/$(TARGET) ] || mkdir -p $(RELEASE)/$(TARGET) @cp $(OUTPUT).bin $(RELEASE) @cp $(OUTPUT).firm $(RELEASE) + #@cp $(OUTPUT)_dev.firm $(RELEASE) #@-cp $(OUTPUT).dat $(RELEASE) #@-cp $(OUTPUT).nds $(RELEASE) #@-cp $(OUTPUT).3dsx $(RELEASE)/$(TARGET) diff --git a/link.ld b/link.ld index 72a46fa..3b08ee3 100644 --- a/link.ld +++ b/link.ld @@ -5,6 +5,7 @@ ENTRY(_start) SECTIONS { . = 0x23F00000; + __start__ = ABSOLUTE(.); .text.start : ALIGN(4) { *(.text.start) } .text : ALIGN(4) { *(.text*) } @@ -15,4 +16,7 @@ SECTIONS . = ALIGN(4); __end__ = ABSOLUTE(.); + + __stack_top = __start__; + __code_size__ = __end__ - __start__; } diff --git a/screeninit/source/main.c b/screeninit/source/main.c index 0c907cb..9c11c14 100644 --- a/screeninit/source/main.c +++ b/screeninit/source/main.c @@ -7,12 +7,13 @@ #define PDN_GPU_CNT (*(vu8 *)0x10141200) #define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1) -#define BRIGHTNESS 0x39 +#define BRIGHTNESS (0xBF) void main(void) { + char do_disco = !ARESCREENSINITIALIZED; vu32 *arm11Entry = (vu32 *)0x1FFFFFFC; - if (ARESCREENSINITIALIZED) return; // nothing to do in that case + u32 entry; *(vu32 *)0x10141200 = 0x1007F; *(vu32 *)0x10202014 = 0x00000001; @@ -53,10 +54,6 @@ void main(void) *(vu32 *)0x10400490 = 0x000002D0; *(vu32 *)0x1040049C = 0x00000000; - //Disco register - for(u32 i = 0; i < 256; i++) - *(vu32 *)0x10400484 = 0x10101 * i; - //Bottom screen *(vu32 *)0x10400500 = 0x000001c2; *(vu32 *)0x10400504 = 0x000000d1; @@ -80,16 +77,19 @@ void main(void) *(vu32 *)0x1040055C = 0x00f00140; *(vu32 *)0x10400560 = 0x01c100d1; *(vu32 *)0x10400564 = 0x01920052; - *(vu32 *)0x10400568 = 0x18300000 + 0x46500; + *(vu32 *)0x10400568 = 0x18346500; *(vu32 *)0x10400570 = 0x80301; *(vu32 *)0x10400574 = 0x00010501; *(vu32 *)0x10400578 = 0; *(vu32 *)0x10400590 = 0x000002D0; *(vu32 *)0x1040059C = 0x00000000; - //Disco register - for(u32 i = 0; i < 256; i++) - *(vu32 *)0x10400584 = 0x10101 * i; + if (do_disco) { + for(u32 i = 0; i < 256; i++) { + *(vu32 *)0x10400484 = 0x10101 * i; + *(vu32 *)0x10400584 = 0x10101 * i; + } + } //Set CakeBrah framebuffers fb->top_left = (u8 *)0x18300000; @@ -118,12 +118,10 @@ void main(void) while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); - //Clear ARM11 entrypoint + // Clear ARM11 entrypoint *arm11Entry = 0; - //Wait for the entrypoint to be set - while(!*arm11Entry); - - //Jump to it - ((void (*)())*arm11Entry)(); + //Wait for the entrypoint to be set, then branch to it + while((entry=*arm11Entry) == 0); + ((void (*)())(entry))(); } diff --git a/source/common/ui.h b/source/common/ui.h index 6354eba..e7358f2 100644 --- a/source/common/ui.h +++ b/source/common/ui.h @@ -52,8 +52,8 @@ #define COLOR_STD_BG COLOR_BLACK #define COLOR_STD_FONT COLOR_WHITE -#define TOP_SCREEN top_screen -#define BOT_SCREEN bottom_screen +#define TOP_SCREEN ((u8*)(*(u32*)0x23FFFE00)) +#define BOT_SCREEN ((u8*)(*(u32*)0x23FFFE08)) #ifdef SWITCH_SCREENS #define MAIN_SCREEN TOP_SCREEN @@ -67,8 +67,6 @@ #define SCREEN_WIDTH_ALT SCREEN_WIDTH_TOP #endif -extern u8 *top_screen, *bottom_screen; - void ClearScreen(unsigned char *screen, int color); void ClearScreenF(bool clear_main, bool clear_alt, int color); void DrawRectangle(u8* screen, int x, int y, int width, int height, int color); diff --git a/source/main.c b/source/main.c index 72d795f..ba9757b 100644 --- a/source/main.c +++ b/source/main.c @@ -1,28 +1,16 @@ #include "common.h" #include "godmode.h" -#include "ui.h" #include "i2c.h" #include "power.h" -u8 *top_screen, *bottom_screen; - void main(int argc, char** argv) { + (void) argc; // unused for now + (void) argv; // unused for now + // Turn on backlight I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); - // Fetch the framebuffer addresses - if(argc >= 2) { - // newer entrypoints - u8 **fb = (u8 **)(void *)argv[1]; - top_screen = fb[0]; - bottom_screen = fb[2]; - } else { - // outdated entrypoints - top_screen = (u8*)(*(u32*)0x23FFFE00); - bottom_screen = (u8*)(*(u32*)0x23FFFE08); - } - // Run the main program (GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff(); } diff --git a/source/nand/nand.c b/source/nand/nand.c index 68da57a..508a643 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -145,9 +145,9 @@ bool InitNandCrypto(void) for(u32 i = 0; i < 16; i++) // little endian and reversed order TwlNandCtr[i] = shasum[15-i]; - // part #2: TWL KEY + // part #2: TWL KEY (if not already set up // see: https://www.3dbrew.org/wiki/Memory_layout#ARM9_ITCM - if (IS_A9LH && !IS_SIGHAX) { // only for a9lh + if (GetNandPartitionInfo(NULL, NP_TYPE_FAT, NP_SUBTYPE_TWL, 0, NAND_SYSNAND) != 0) { u8 TwlKeyY[16] __attribute__((aligned(32))); // k9l already did the part of the init that required the OTP registers @@ -181,22 +181,27 @@ bool InitNandCrypto(void) use_aeskey(0x03); } - // part #3: CTRNAND N3DS KEY / AGBSAVE CMAC KEY + // part #3: CTRNAND N3DS KEY (if not set up) // thanks AuroraWright and Gelex for advice on this // see: https://github.com/AuroraWright/Luma3DS/blob/master/source/crypto.c#L347 - if (IS_A9LH && !IS_SIGHAX) { // only on A9LH, not required on sighax - // keyY 0x05 is encrypted @0x0EB014 in the FIRM90 - // keyY 0x05 is encrypted @0x0EB24C in the FIRM81 - if ((LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB014, 0x05) != 0) && - (LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB24C, 0x05) != 0)) - LoadKeyFromFile(slot0x05KeyY, 0x05, 'Y', NULL); - + if (GetNandPartitionInfo(NULL, NP_TYPE_FAT, NP_SUBTYPE_CTR, 0, NAND_SYSNAND) != 0) { + if (IS_A9LH && !IS_SIGHAX) { // only on A9LH + // keyY 0x05 is encrypted @0x0EB014 in the FIRM90 + // keyY 0x05 is encrypted @0x0EB24C in the FIRM81 + if ((LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB014, 0x05) != 0) && + (LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB24C, 0x05) != 0)) + LoadKeyFromFile(slot0x05KeyY, 0x05, 'Y', NULL); + } else LoadKeyFromFile(slot0x05KeyY, 0x05, 'Y', NULL); + } + + // part #4: AGBSAVE CMAC KEY (source see above) + if (IS_A9LH && !IS_SIGHAX) { // only on A9LH // keyY 0x24 is encrypted @0x0E62DC in the FIRM90 // keyY 0x24 is encrypted @0x0E6514 in the FIRM81 if ((LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E62DC, 0x24) != 0) && (LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E6514, 0x24) != 0)) LoadKeyFromFile(NULL, 0x24, 'Y', NULL); - } + } else LoadKeyFromFile(NULL, 0x24, 'Y', NULL); return true; } diff --git a/source/start.s b/source/start.s index 8679a27..8a5beb3 100644 --- a/source/start.s +++ b/source/start.s @@ -1,86 +1,50 @@ .section .text.start -.global _start .align 4 .arm -@ if the binary is booted from Brahma/CakeHax/k9lh -@ the entrypoint is -@ framebuffers are already set +@ make sure not to clobber r0-r2 +.global _start _start: - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop - nop @ dummy - b _skip_gw + @ Switch to supervisor mode and disable interrupts + msr cpsr_c, #0xD3 -@ if the binary is booted from the GW exploit -@ the entrypoint is -_start_gw: + @ Short delay (not always necessary, just in case) + mov r3, #0x40000 + .Lwaitloop: + subs r3, #1 + bgt .Lwaitloop - @@wait for the arm11 kernel threads to be ready - mov r1, #0x10000 - waitLoop9: - sub r1, #1 - cmp r1, #0 - bgt waitLoop9 + @ Check the load address + adr r3, _start + ldr r4, =__start__ + cmp r3, r4 + beq _start_gm - mov r1, #0x10000 - waitLoop92: - sub r1, #1 - cmp r1, #0 - bgt waitLoop92 + @ Relocate the binary to the correct location and branch to it + ldr r5, =__code_size__ + .Lbincopyloop: + subs r5, #4 + ldrge r6, [r3, r5] + strge r6, [r4, r5] + bge .Lbincopyloop - - @ copy the payload to the standard entrypoint (0x23F00000) - adr r0, _start - add r1, r0, #0x100000 - ldr r2, .entry - .copy_binary_fcram: - cmp r0, r1 - ldrlt r3, [r0], #4 - strlt r3, [r2], #4 - blt .copy_binary_fcram - - @ setup framebuffers to look like Brahma/etc - - ldr r0, .gw_fba - ldr r1, [r0, #0x18] - and r1, #1 - ldr r1, [r0, r1, lsl #2] @ r1 := top framebuffer loc - mov r2, r1 @ r2 := top framebuffer loc - - ldr r0, .gw_fbb - ldr r3, [r0, #0xC] - and r3, #1 - ldr r3, [r0, r3, lsl #2] @ r3 := bottom framebuffer loc - - ldr r0, .cakehax - stmia r0, {r1,r2,r3} - @ framebuffers properly set - - ldr r3, =0xFFFF0830 @ flush (clean & invalidate) entire dcache b9 func + mov r5, r0 + mov r6, r1 + mov r7, r2 + ldr r3, =0xFFFF0830 @ Writeback & Invalidate DCache blx r3 + mov r0, r5 + mov r1, r6 + mov r2, r7 - mov r3, #0 - mcr p15, 0, r3, c7, c5, 0 @ invalidate I-cache + mov lr, #0 + mcr p15, 0, lr, c7, c5, 0 @ Invalidate ICache - mov r2, #0 - ldr r3, .entry - bx r3 + bx r4 -.gw_fba: .word 0x080FFFC0 -.gw_fbb: .word 0x080FFFD0 -.cakehax: .word 0x23FFFE00 -.entry: .word 0x23F00000 +_start_gm: + ldr sp, =__stack_top -_skip_gw: mov r9, r0 @ argc mov r10, r1 @ argv @@ -102,11 +66,10 @@ _skip_gw: ldr r0, =__bss_start ldr r1, =__bss_end mov r2, #0 - - .bss_clr: + .Lbss_clr: cmp r0, r1 strlt r2, [r0], #4 - blt .bss_clr + blt .Lbss_clr @ Invalidate caches mov r5, #0 @@ -121,14 +84,14 @@ _skip_gw: @ Sets MPU permissions and cache settings ldr r0, =0xFFFF001F @ ffff0000 64k | bootrom (unprotected / protected) - ldr r1, =0x3000801B @ 30000000 16k | dtcm + ldr r1, =0x3000801B @ 30008000 16k | dtcm ldr r2, =0x01FF801D @ 01ff8000 32k | itcm - ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) + ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS) ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB) ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) - mov r8, #0x2D + mov r8, #0b00101101 @ bootrom/itcm/arm9 mem and fcram are cacheable/bufferable mcr p15, 0, r0, c6, c0, 0 mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r2, c6, c2, 0 @@ -145,6 +108,13 @@ _skip_gw: ldr r1, =0x3000800A @ set dtcm mcr p15, 0, r1, c9, c1, 0 @ set the dtcm Region Register + @ Wait for screen init + mov r0, #0x20000000 + .Lwaitforsi: + ldr r1, [r0, #-4] + cmp r1, #0 + bne .Lwaitforsi + @ Enable caches mrc p15, 0, r4, c1, c0, 0 @ read control register orr r4, r4, #(1<<18) @ - itcm enable @@ -159,10 +129,6 @@ _skip_gw: mov r1, #0x340 str r1, [r0] - ldr sp, =0x23F00000 - mov r0, r9 mov r1, r10 b main - -.pool