Allow running GodMode9 in any environment

This commit is contained in:
Wolfvak 2017-07-27 18:28:27 +02:00 committed by d0k3
parent d6490453ba
commit 15882e7111
7 changed files with 87 additions and 126 deletions

View File

@ -139,7 +139,8 @@ binary: common
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
firm: binary screeninit 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 gateway: binary
@cp resources/LauncherTemplate.dat $(OUTPUT_D)/Launcher.dat @cp resources/LauncherTemplate.dat $(OUTPUT_D)/Launcher.dat
@ -172,6 +173,7 @@ release:
#@[ -d $(RELEASE)/$(TARGET) ] || mkdir -p $(RELEASE)/$(TARGET) #@[ -d $(RELEASE)/$(TARGET) ] || mkdir -p $(RELEASE)/$(TARGET)
@cp $(OUTPUT).bin $(RELEASE) @cp $(OUTPUT).bin $(RELEASE)
@cp $(OUTPUT).firm $(RELEASE) @cp $(OUTPUT).firm $(RELEASE)
#@cp $(OUTPUT)_dev.firm $(RELEASE)
#@-cp $(OUTPUT).dat $(RELEASE) #@-cp $(OUTPUT).dat $(RELEASE)
#@-cp $(OUTPUT).nds $(RELEASE) #@-cp $(OUTPUT).nds $(RELEASE)
#@-cp $(OUTPUT).3dsx $(RELEASE)/$(TARGET) #@-cp $(OUTPUT).3dsx $(RELEASE)/$(TARGET)

View File

@ -5,6 +5,7 @@ ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x23F00000; . = 0x23F00000;
__start__ = ABSOLUTE(.);
.text.start : ALIGN(4) { *(.text.start) } .text.start : ALIGN(4) { *(.text.start) }
.text : ALIGN(4) { *(.text*) } .text : ALIGN(4) { *(.text*) }
@ -15,4 +16,7 @@ SECTIONS
. = ALIGN(4); . = ALIGN(4);
__end__ = ABSOLUTE(.); __end__ = ABSOLUTE(.);
__stack_top = __start__;
__code_size__ = __end__ - __start__;
} }

View File

@ -7,12 +7,13 @@
#define PDN_GPU_CNT (*(vu8 *)0x10141200) #define PDN_GPU_CNT (*(vu8 *)0x10141200)
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1) #define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
#define BRIGHTNESS 0x39 #define BRIGHTNESS (0xBF)
void main(void) void main(void)
{ {
char do_disco = !ARESCREENSINITIALIZED;
vu32 *arm11Entry = (vu32 *)0x1FFFFFFC; vu32 *arm11Entry = (vu32 *)0x1FFFFFFC;
if (ARESCREENSINITIALIZED) return; // nothing to do in that case u32 entry;
*(vu32 *)0x10141200 = 0x1007F; *(vu32 *)0x10141200 = 0x1007F;
*(vu32 *)0x10202014 = 0x00000001; *(vu32 *)0x10202014 = 0x00000001;
@ -53,10 +54,6 @@ void main(void)
*(vu32 *)0x10400490 = 0x000002D0; *(vu32 *)0x10400490 = 0x000002D0;
*(vu32 *)0x1040049C = 0x00000000; *(vu32 *)0x1040049C = 0x00000000;
//Disco register
for(u32 i = 0; i < 256; i++)
*(vu32 *)0x10400484 = 0x10101 * i;
//Bottom screen //Bottom screen
*(vu32 *)0x10400500 = 0x000001c2; *(vu32 *)0x10400500 = 0x000001c2;
*(vu32 *)0x10400504 = 0x000000d1; *(vu32 *)0x10400504 = 0x000000d1;
@ -80,16 +77,19 @@ void main(void)
*(vu32 *)0x1040055C = 0x00f00140; *(vu32 *)0x1040055C = 0x00f00140;
*(vu32 *)0x10400560 = 0x01c100d1; *(vu32 *)0x10400560 = 0x01c100d1;
*(vu32 *)0x10400564 = 0x01920052; *(vu32 *)0x10400564 = 0x01920052;
*(vu32 *)0x10400568 = 0x18300000 + 0x46500; *(vu32 *)0x10400568 = 0x18346500;
*(vu32 *)0x10400570 = 0x80301; *(vu32 *)0x10400570 = 0x80301;
*(vu32 *)0x10400574 = 0x00010501; *(vu32 *)0x10400574 = 0x00010501;
*(vu32 *)0x10400578 = 0; *(vu32 *)0x10400578 = 0;
*(vu32 *)0x10400590 = 0x000002D0; *(vu32 *)0x10400590 = 0x000002D0;
*(vu32 *)0x1040059C = 0x00000000; *(vu32 *)0x1040059C = 0x00000000;
//Disco register if (do_disco) {
for(u32 i = 0; i < 256; i++) for(u32 i = 0; i < 256; i++) {
*(vu32 *)0x10400584 = 0x10101 * i; *(vu32 *)0x10400484 = 0x10101 * i;
*(vu32 *)0x10400584 = 0x10101 * i;
}
}
//Set CakeBrah framebuffers //Set CakeBrah framebuffers
fb->top_left = (u8 *)0x18300000; fb->top_left = (u8 *)0x18300000;
@ -118,12 +118,10 @@ void main(void)
while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2)));
//Clear ARM11 entrypoint // Clear ARM11 entrypoint
*arm11Entry = 0; *arm11Entry = 0;
//Wait for the entrypoint to be set //Wait for the entrypoint to be set, then branch to it
while(!*arm11Entry); while((entry=*arm11Entry) == 0);
((void (*)())(entry))();
//Jump to it
((void (*)())*arm11Entry)();
} }

View File

@ -52,8 +52,8 @@
#define COLOR_STD_BG COLOR_BLACK #define COLOR_STD_BG COLOR_BLACK
#define COLOR_STD_FONT COLOR_WHITE #define COLOR_STD_FONT COLOR_WHITE
#define TOP_SCREEN top_screen #define TOP_SCREEN ((u8*)(*(u32*)0x23FFFE00))
#define BOT_SCREEN bottom_screen #define BOT_SCREEN ((u8*)(*(u32*)0x23FFFE08))
#ifdef SWITCH_SCREENS #ifdef SWITCH_SCREENS
#define MAIN_SCREEN TOP_SCREEN #define MAIN_SCREEN TOP_SCREEN
@ -67,8 +67,6 @@
#define SCREEN_WIDTH_ALT SCREEN_WIDTH_TOP #define SCREEN_WIDTH_ALT SCREEN_WIDTH_TOP
#endif #endif
extern u8 *top_screen, *bottom_screen;
void ClearScreen(unsigned char *screen, int color); void ClearScreen(unsigned char *screen, int color);
void ClearScreenF(bool clear_main, bool clear_alt, 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); void DrawRectangle(u8* screen, int x, int y, int width, int height, int color);

View File

@ -1,28 +1,16 @@
#include "common.h" #include "common.h"
#include "godmode.h" #include "godmode.h"
#include "ui.h"
#include "i2c.h" #include "i2c.h"
#include "power.h" #include "power.h"
u8 *top_screen, *bottom_screen;
void main(int argc, char** argv) void main(int argc, char** argv)
{ {
(void) argc; // unused for now
(void) argv; // unused for now
// Turn on backlight // Turn on backlight
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A); 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 // Run the main program
(GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff(); (GodMode() == GODMODE_EXIT_REBOOT) ? Reboot() : PowerOff();
} }

View File

@ -145,9 +145,9 @@ bool InitNandCrypto(void)
for(u32 i = 0; i < 16; i++) // little endian and reversed order for(u32 i = 0; i < 16; i++) // little endian and reversed order
TwlNandCtr[i] = shasum[15-i]; 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 // 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))); u8 TwlKeyY[16] __attribute__((aligned(32)));
// k9l already did the part of the init that required the OTP registers // k9l already did the part of the init that required the OTP registers
@ -181,22 +181,27 @@ bool InitNandCrypto(void)
use_aeskey(0x03); 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 // thanks AuroraWright and Gelex for advice on this
// see: https://github.com/AuroraWright/Luma3DS/blob/master/source/crypto.c#L347 // see: https://github.com/AuroraWright/Luma3DS/blob/master/source/crypto.c#L347
if (IS_A9LH && !IS_SIGHAX) { // only on A9LH, not required on sighax if (GetNandPartitionInfo(NULL, NP_TYPE_FAT, NP_SUBTYPE_CTR, 0, NAND_SYSNAND) != 0) {
// keyY 0x05 is encrypted @0x0EB014 in the FIRM90 if (IS_A9LH && !IS_SIGHAX) { // only on A9LH
// keyY 0x05 is encrypted @0x0EB24C in the FIRM81 // keyY 0x05 is encrypted @0x0EB014 in the FIRM90
if ((LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB014, 0x05) != 0) && // keyY 0x05 is encrypted @0x0EB24C in the FIRM81
(LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB24C, 0x05) != 0)) if ((LoadKeyYFromP9(slot0x05KeyY, slot0x05KeyY_sha256, 0x0EB014, 0x05) != 0) &&
LoadKeyFromFile(slot0x05KeyY, 0x05, 'Y', NULL); (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 @0x0E62DC in the FIRM90
// keyY 0x24 is encrypted @0x0E6514 in the FIRM81 // keyY 0x24 is encrypted @0x0E6514 in the FIRM81
if ((LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E62DC, 0x24) != 0) && if ((LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E62DC, 0x24) != 0) &&
(LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E6514, 0x24) != 0)) (LoadKeyYFromP9(NULL, slot0x24KeyY_sha256, 0x0E6514, 0x24) != 0))
LoadKeyFromFile(NULL, 0x24, 'Y', NULL); LoadKeyFromFile(NULL, 0x24, 'Y', NULL);
} } else LoadKeyFromFile(NULL, 0x24, 'Y', NULL);
return true; return true;
} }

View File

@ -1,86 +1,50 @@
.section .text.start .section .text.start
.global _start
.align 4 .align 4
.arm .arm
@ if the binary is booted from Brahma/CakeHax/k9lh @ make sure not to clobber r0-r2
@ the entrypoint is <start + 0x0> .global _start
@ framebuffers are already set
_start: _start:
nop @ Switch to supervisor mode and disable interrupts
nop msr cpsr_c, #0xD3
nop
nop
nop
nop
nop
nop
nop
nop
nop @ dummy
b _skip_gw
@ if the binary is booted from the GW exploit @ Short delay (not always necessary, just in case)
@ the entrypoint is <start + 0x30> mov r3, #0x40000
_start_gw: .Lwaitloop:
subs r3, #1
bgt .Lwaitloop
@@wait for the arm11 kernel threads to be ready @ Check the load address
mov r1, #0x10000 adr r3, _start
waitLoop9: ldr r4, =__start__
sub r1, #1 cmp r3, r4
cmp r1, #0 beq _start_gm
bgt waitLoop9
mov r1, #0x10000 @ Relocate the binary to the correct location and branch to it
waitLoop92: ldr r5, =__code_size__
sub r1, #1 .Lbincopyloop:
cmp r1, #0 subs r5, #4
bgt waitLoop92 ldrge r6, [r3, r5]
strge r6, [r4, r5]
bge .Lbincopyloop
mov r5, r0
@ copy the payload to the standard entrypoint (0x23F00000) mov r6, r1
adr r0, _start mov r7, r2
add r1, r0, #0x100000 ldr r3, =0xFFFF0830 @ Writeback & Invalidate DCache
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
blx r3 blx r3
mov r0, r5
mov r1, r6
mov r2, r7
mov r3, #0 mov lr, #0
mcr p15, 0, r3, c7, c5, 0 @ invalidate I-cache mcr p15, 0, lr, c7, c5, 0 @ Invalidate ICache
mov r2, #0 bx r4
ldr r3, .entry
bx r3
.gw_fba: .word 0x080FFFC0 _start_gm:
.gw_fbb: .word 0x080FFFD0 ldr sp, =__stack_top
.cakehax: .word 0x23FFFE00
.entry: .word 0x23F00000
_skip_gw:
mov r9, r0 @ argc mov r9, r0 @ argc
mov r10, r1 @ argv mov r10, r1 @ argv
@ -102,11 +66,10 @@ _skip_gw:
ldr r0, =__bss_start ldr r0, =__bss_start
ldr r1, =__bss_end ldr r1, =__bss_end
mov r2, #0 mov r2, #0
.Lbss_clr:
.bss_clr:
cmp r0, r1 cmp r0, r1
strlt r2, [r0], #4 strlt r2, [r0], #4
blt .bss_clr blt .Lbss_clr
@ Invalidate caches @ Invalidate caches
mov r5, #0 mov r5, #0
@ -121,14 +84,14 @@ _skip_gw:
@ Sets MPU permissions and cache settings @ Sets MPU permissions and cache settings
ldr r0, =0xFFFF001F @ ffff0000 64k | bootrom (unprotected / protected) 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 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 r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS) ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB) 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, r0, c6, c0, 0
mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r1, c6, c1, 0
mcr p15, 0, r2, c6, c2, 0 mcr p15, 0, r2, c6, c2, 0
@ -145,6 +108,13 @@ _skip_gw:
ldr r1, =0x3000800A @ set dtcm ldr r1, =0x3000800A @ set dtcm
mcr p15, 0, r1, c9, c1, 0 @ set the dtcm Region Register 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 @ Enable caches
mrc p15, 0, r4, c1, c0, 0 @ read control register mrc p15, 0, r4, c1, c0, 0 @ read control register
orr r4, r4, #(1<<18) @ - itcm enable orr r4, r4, #(1<<18) @ - itcm enable
@ -159,10 +129,6 @@ _skip_gw:
mov r1, #0x340 mov r1, #0x340
str r1, [r0] str r1, [r0]
ldr sp, =0x23F00000
mov r0, r9 mov r0, r9
mov r1, r10 mov r1, r10
b main b main
.pool