From e593584a476d5ffd8ff0b10dc8b2afb29613713a Mon Sep 17 00:00:00 2001 From: TuxSH Date: Fri, 10 Jun 2016 21:48:22 +0200 Subject: [PATCH 1/2] Move screen management code to screen.c and fix cache-related issues - Screen brightness is now updated as soon as the user selects a brightness option, on all boot environments - Payloads can now be 1KB bigger - Some cache-related bugs may have been fixed --- Makefile | 8 +- loader/linker.ld | 2 +- loader/source/main.c | 3 +- loader/source/memory.c | 5 + loader/source/memory.h | 12 +- screeninit/Makefile | 47 -------- screeninit/linker.ld | 12 -- screeninit/source/main.c | 105 ----------------- screeninit/source/start.s | 10 -- screeninit/source/types.h | 13 --- source/config.c | 7 +- source/draw.c | 16 +-- source/draw.h | 1 - source/firm.c | 4 +- source/fs.c | 5 +- source/memory.c | 5 + source/memory.h | 12 +- source/screen.c | 237 ++++++++++++++++++++++++++++++++++++++ source/screen.h | 23 ++++ source/screeninit.c | 69 ----------- source/screeninit.h | 15 --- source/start.s | 24 ++-- source/utils.c | 3 + 23 files changed, 324 insertions(+), 314 deletions(-) delete mode 100755 screeninit/Makefile delete mode 100755 screeninit/linker.ld delete mode 100755 screeninit/source/main.c delete mode 100644 screeninit/source/start.s delete mode 100755 screeninit/source/types.h create mode 100644 source/screen.c create mode 100644 source/screen.h delete mode 100644 source/screeninit.c delete mode 100644 source/screeninit.h diff --git a/Makefile b/Makefile index d90e21e..676e94f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,6 @@ revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0- dir_source := source dir_patches := patches dir_loader := loader -dir_screeninit := screeninit dir_injector := injector dir_mset := CakeHax dir_ninjhax := CakeBrah @@ -33,7 +32,7 @@ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ $(call rwildcard, $(dir_source), *.s *.c))) -bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/injector.h $(dir_build)/loader.h $(dir_build)/screeninit.h +bundled = $(dir_build)/rebootpatch.h $(dir_build)/emunandpatch.h $(dir_build)/injector.h $(dir_build)/loader.h .PHONY: all all: launcher a9lh ninjhax @@ -55,7 +54,6 @@ clean: @$(MAKE) $(FLAGS) -C $(dir_mset) clean @$(MAKE) $(FLAGS) -C $(dir_ninjhax) clean @$(MAKE) -C $(dir_loader) clean - @$(MAKE) -C $(dir_screeninit) clean @$(MAKE) -C $(dir_injector) clean @rm -rf $(dir_out) $(dir_build) @@ -102,10 +100,6 @@ $(dir_build)/loader.h: $(dir_loader)/Makefile @$(MAKE) -C $(dir_loader) @bin2c -o $@ -n loader $(@D)/loader.bin -$(dir_build)/screeninit.h: $(dir_screeninit)/Makefile - @$(MAKE) -C $(dir_screeninit) - @bin2c -o $@ -n screeninit $(@D)/screeninit.bin - $(dir_build)/memory.o: CFLAGS += -O3 $(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\"" diff --git a/loader/linker.ld b/loader/linker.ld index 6fbf471..2ca0165 100644 --- a/loader/linker.ld +++ b/loader/linker.ld @@ -1,7 +1,7 @@ ENTRY(_start) SECTIONS { - . = 0x24FFFB00; + . = 0x24FFFF00; .text.start : { *(.text.start) } .text : { *(.text) } .data : { *(.data) } diff --git a/loader/source/main.c b/loader/source/main.c index ca42a16..18aea19 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -4,7 +4,8 @@ void main(void) { void *payloadAddress = (void *)0x23F00000; - memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFB04); + memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04); + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed ((void (*)())payloadAddress)(); } \ No newline at end of file diff --git a/loader/source/memory.c b/loader/source/memory.c index 4f4c96a..69dd2f2 100644 --- a/loader/source/memory.c +++ b/loader/source/memory.c @@ -7,4 +7,9 @@ void memcpy(void *dest, const void *src, u32 size) for(u32 i = 0; i < size; i++) destc[i] = srcc[i]; +} + +void cleanInvalidateDCacheAndDMB(void) +{ + ((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM? } \ No newline at end of file diff --git a/loader/source/memory.h b/loader/source/memory.h index 466220c..4c74b6d 100644 --- a/loader/source/memory.h +++ b/loader/source/memory.h @@ -2,4 +2,14 @@ #include "types.h" -void memcpy(void *dest, const void *src, u32 size); \ No newline at end of file +void memcpy(void *dest, const void *src, u32 size); + +/*** + Cleans and invalidates the data cache, then waits for all memory transfers to be finished. + This function MUST be called before doing the following: + - rebooting + - powering down + - setting the ARM11 entrypoint to execute a function + - jumping to a payload (?) +***/ +void cleanInvalidateDCacheAndDMB(void); \ No newline at end of file diff --git a/screeninit/Makefile b/screeninit/Makefile deleted file mode 100755 index 0096fd8..0000000 --- a/screeninit/Makefile +++ /dev/null @@ -1,47 +0,0 @@ -rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2)) - -ifeq ($(strip $(DEVKITARM)),) -$(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") -endif - -include $(DEVKITARM)/3ds_rules - -CC := arm-none-eabi-gcc -AS := arm-none-eabi-as -LD := arm-none-eabi-ld -OC := arm-none-eabi-objcopy - -name := $(shell basename $(CURDIR)) - -dir_source := source -dir_build := build - -ASFLAGS := -mcpu=mpcore -mfloat-abi=hard -CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math -LDFLAGS := -nostdlib - -objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ - $(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \ - $(call rwildcard, $(dir_source), *.s *.c))) - -.PHONY: all -all: ../$(dir_build)/$(name).bin - -.PHONY: clean -clean: - @rm -rf $(dir_build) - -../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf - $(OC) -S -O binary $< $@ - -$(dir_build)/$(name).elf: $(objects) - $(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^ - -$(dir_build)/%.o: $(dir_source)/%.c - @mkdir -p "$(@D)" - $(COMPILE.c) $(OUTPUT_OPTION) $< - -$(dir_build)/%.o: $(dir_source)/%.s - @mkdir -p "$(@D)" - $(COMPILE.s) $(OUTPUT_OPTION) $< -include $(call rwildcard, $(dir_build), *.d) diff --git a/screeninit/linker.ld b/screeninit/linker.ld deleted file mode 100755 index 9ae0eaa..0000000 --- a/screeninit/linker.ld +++ /dev/null @@ -1,12 +0,0 @@ -ENTRY(_start) -SECTIONS -{ - . = 0x24FFFC00; - .text.start : { *(.text.start) } - .text : { *(.text) } - .data : { *(.data) } - .bss : { *(.bss COMMON) } - .rodata : { *(.rodata) } - . = ALIGN(4); -} - diff --git a/screeninit/source/main.c b/screeninit/source/main.c deleted file mode 100755 index 78cba49..0000000 --- a/screeninit/source/main.c +++ /dev/null @@ -1,105 +0,0 @@ -#include "types.h" - -void main(void) -{ - const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; - u32 brightnessLevel = *(vu32 *)0x24FFFC08; - vu32 *const arm11 = (u32 *)0x1FFFFFF8; - - *(vu32 *)0x10141200 = 0x1007F; - *(vu32 *)0x10202014 = 0x00000001; - *(vu32 *)0x1020200C &= 0xFFFEFFFE; - *(vu32 *)0x10202240 = brightness[brightnessLevel]; - *(vu32 *)0x10202A40 = brightness[brightnessLevel]; - *(vu32 *)0x10202244 = 0x1023E; - *(vu32 *)0x10202A44 = 0x1023E; - - // Top screen - *(vu32 *)0x10400400 = 0x000001c2; - *(vu32 *)0x10400404 = 0x000000d1; - *(vu32 *)0x10400408 = 0x000001c1; - *(vu32 *)0x1040040c = 0x000001c1; - *(vu32 *)0x10400410 = 0x00000000; - *(vu32 *)0x10400414 = 0x000000cf; - *(vu32 *)0x10400418 = 0x000000d1; - *(vu32 *)0x1040041c = 0x01c501c1; - *(vu32 *)0x10400420 = 0x00010000; - *(vu32 *)0x10400424 = 0x0000019d; - *(vu32 *)0x10400428 = 0x00000002; - *(vu32 *)0x1040042c = 0x00000192; - *(vu32 *)0x10400430 = 0x00000192; - *(vu32 *)0x10400434 = 0x00000192; - *(vu32 *)0x10400438 = 0x00000001; - *(vu32 *)0x1040043c = 0x00000002; - *(vu32 *)0x10400440 = 0x01960192; - *(vu32 *)0x10400444 = 0x00000000; - *(vu32 *)0x10400448 = 0x00000000; - *(vu32 *)0x1040045C = 0x00f00190; - *(vu32 *)0x10400460 = 0x01c100d1; - *(vu32 *)0x10400464 = 0x01920002; - *(vu32 *)0x10400468 = 0x18300000; - *(vu32 *)0x10400470 = 0x80341; - *(vu32 *)0x10400474 = 0x00010501; - *(vu32 *)0x10400478 = 0; - *(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; - *(vu32 *)0x10400508 = 0x000001c1; - *(vu32 *)0x1040050c = 0x000001c1; - *(vu32 *)0x10400510 = 0x000000cd; - *(vu32 *)0x10400514 = 0x000000cf; - *(vu32 *)0x10400518 = 0x000000d1; - *(vu32 *)0x1040051c = 0x01c501c1; - *(vu32 *)0x10400520 = 0x00010000; - *(vu32 *)0x10400524 = 0x0000019d; - *(vu32 *)0x10400528 = 0x00000052; - *(vu32 *)0x1040052c = 0x00000192; - *(vu32 *)0x10400530 = 0x00000192; - *(vu32 *)0x10400534 = 0x0000004f; - *(vu32 *)0x10400538 = 0x00000050; - *(vu32 *)0x1040053c = 0x00000052; - *(vu32 *)0x10400540 = 0x01980194; - *(vu32 *)0x10400544 = 0x00000000; - *(vu32 *)0x10400548 = 0x00000011; - *(vu32 *)0x1040055C = 0x00f00140; - *(vu32 *)0x10400560 = 0x01c100d1; - *(vu32 *)0x10400564 = 0x01920052; - *(vu32 *)0x10400568 = 0x18300000 + 0x46500; - *(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; - - *(vu32 *)0x10400468 = 0x18300000; - *(vu32 *)0x1040046c = 0x18300000; - *(vu32 *)0x10400494 = 0x18300000; - *(vu32 *)0x10400498 = 0x18300000; - *(vu32 *)0x10400568 = 0x18346500; - *(vu32 *)0x1040056c = 0x18346500; - - //Set CakeBrah framebuffers - *((vu32 *)0x23FFFE00) = 0x18300000; - *((vu32 *)0x23FFFE04) = 0x18300000; - *((vu32 *)0x23FFFE08) = 0x18346500; - - //Clear ARM11 entry offset - *arm11 = 0; - - //Wait for the entry to be set - while(!*arm11); - - //Jump to it - ((void (*)())*arm11)(); -} \ No newline at end of file diff --git a/screeninit/source/start.s b/screeninit/source/start.s deleted file mode 100644 index 40392d1..0000000 --- a/screeninit/source/start.s +++ /dev/null @@ -1,10 +0,0 @@ -.section .text.start -.align 4 -.global _start -_start: - @ Disable interrupts - CPSID aif - - b main - - .word 0 diff --git a/screeninit/source/types.h b/screeninit/source/types.h deleted file mode 100755 index d27412b..0000000 --- a/screeninit/source/types.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once - -#include - -//Common data types -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef volatile u8 vu8; -typedef volatile u16 vu16; -typedef volatile u32 vu32; -typedef volatile u64 vu64; \ No newline at end of file diff --git a/source/config.c b/source/config.c index 07ce486..538b3d7 100644 --- a/source/config.c +++ b/source/config.c @@ -4,7 +4,7 @@ #include "config.h" #include "utils.h" -#include "screeninit.h" +#include "screen.h" #include "draw.h" #include "fs.h" #include "i2c.h" @@ -156,7 +156,12 @@ void configureCFW(const char *configPath) //In any case, if the current option is enabled (or a multiple choice option is selected) we must display a red 'x' if(selectedOption < multiOptionsAmount) + { + if(selectedOption == 0) + updateBrightness(multiOptions[selectedOption].enabled); + drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED); + } else { u32 singleSelected = selectedOption - multiOptionsAmount; diff --git a/source/draw.c b/source/draw.c index 1f13e9d..e818847 100644 --- a/source/draw.c +++ b/source/draw.c @@ -5,18 +5,11 @@ */ #include "draw.h" -#include "screeninit.h" +#include "screen.h" #include "utils.h" #include "fs.h" -#include "memory.h" #include "font.h" -static const struct fb { - u8 *top_left; - u8 *top_right; - u8 *bottom; -} *const fb = (struct fb *)0x23FFFE00; - static inline int strlen(const char *string) { char *stringEnd = (char *)string; @@ -26,13 +19,6 @@ static inline int strlen(const char *string) return stringEnd - string; } -void clearScreens(void) -{ - memset32(fb->top_left, 0, 0x46500); - memset32(fb->top_right, 0, 0x46500); - memset32(fb->bottom, 0, 0x38400); -} - u32 loadSplash(void) { initScreens(); diff --git a/source/draw.h b/source/draw.h index 18b46d0..e21b0d5 100644 --- a/source/draw.h +++ b/source/draw.h @@ -20,6 +20,5 @@ #define COLOR_BLACK 0x000000 u32 loadSplash(void); -void clearScreens(void); void drawCharacter(char character, int posX, int posY, u32 color); int drawString(const char *string, int posX, int posY, u32 color); \ No newline at end of file diff --git a/source/firm.c b/source/firm.c index b7e964c..45ed4ab 100755 --- a/source/firm.c +++ b/source/firm.c @@ -11,7 +11,7 @@ #include "emunand.h" #include "crypto.h" #include "draw.h" -#include "screeninit.h" +#include "screen.h" #include "buttons.h" #include "../build/injector.h" @@ -376,6 +376,8 @@ static inline void launchFirm(u32 firmType, u32 bootType) arm11 = (u32 *)0x1FFFFFF8; } + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed + //Set ARM11 kernel entrypoint *arm11 = (u32)firm->arm11Entry; diff --git a/source/fs.c b/source/fs.c index 7dfef8d..375dbed 100644 --- a/source/fs.c +++ b/source/fs.c @@ -4,7 +4,7 @@ #include "fs.h" #include "memory.h" -#include "screeninit.h" +#include "screen.h" #include "fatfs/ff.h" #include "buttons.h" #include "../build/loader.h" @@ -76,7 +76,7 @@ void loadPayload(u32 pressed) { initScreens(); - u32 *const loaderAddress = (u32 *)0x24FFFB00; + u32 *const loaderAddress = (u32 *)0x24FFFF00; memcpy(loaderAddress, loader, loader_size); @@ -85,6 +85,7 @@ void loadPayload(u32 pressed) loaderAddress[1] = fileRead((void *)0x24F00000, path); + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed ((void (*)())loaderAddress)(); } } diff --git a/source/memory.c b/source/memory.c index b5027bd..e6b2e56 100644 --- a/source/memory.c +++ b/source/memory.c @@ -60,4 +60,9 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize) } return NULL; +} + +void cleanInvalidateDCacheAndDMB(void) +{ + ((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM? } \ No newline at end of file diff --git a/source/memory.h b/source/memory.h index 2982a0f..d1877c6 100644 --- a/source/memory.h +++ b/source/memory.h @@ -11,4 +11,14 @@ void memcpy(void *dest, const void *src, u32 size); void memset32(void *dest, u32 filler, u32 size); int memcmp(const void *buf1, const void *buf2, u32 size); -u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); \ No newline at end of file +u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); + +/*** + Cleans and invalidates the data cache, then waits for all memory transfers to be finished. + This function MUST be called before doing the following: + - rebooting + - powering down + - setting the ARM11 entrypoint to execute a function + - jumping to a payload (?) +***/ +void cleanInvalidateDCacheAndDMB(void); \ No newline at end of file diff --git a/source/screen.c b/source/screen.c new file mode 100644 index 0000000..588d014 --- /dev/null +++ b/source/screen.c @@ -0,0 +1,237 @@ +/* +* screen.c +* +* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. +* Screen deinit code by tiniVi. +*/ + +#include "screen.h" +#include "config.h" +#include "memory.h" +#include "draw.h" +#include "i2c.h" + +#define ARM11_STUB_ADDRESS (0x25000000 - 0x40) //It's currently only 0x28 bytes large. We're putting 0x40 just to be sure here +#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)(); +vu32 *arm11Entry = (vu32 *)0x1FFFFFF8; + +void __attribute__((naked)) arm11Stub(void) +{ + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Wait for the entry to be set + while(*arm11Entry == ARM11_STUB_ADDRESS); + + //Jump to it + ((void (*)())*arm11Entry)(); +} + +static inline void invokeArm11Function(void (*func)()) +{ + static u32 hasCopiedStub = 0; + if(!hasCopiedStub++) memcpy((void *)ARM11_STUB_ADDRESS, arm11Stub, 0x40); + + cleanInvalidateDCacheAndDMB(); + + *arm11Entry = (u32)func; + while(*arm11Entry); + *arm11Entry = (u32)arm11Stub; +} + +static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; + +void deinitScreens(void) +{ + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Shutdown LCDs + *(vu32 *)0x10202A44 = 0; + *(vu32 *)0x10202244 = 0; + *(vu32 *)0x10202014 = 0; + + WAIT_FOR_ARM9(); + } + + if(PDN_GPU_CNT != 1) invokeArm11Function(ARM11); +} + +void updateBrightness(u32 brightnessLevel) +{ + static int brightnessValue; + + brightnessValue = brightness[brightnessLevel]; + + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Change brightness + *(vu32 *)0x10202240 = brightnessValue; + *(vu32 *)0x10202A40 = brightnessValue; + + WAIT_FOR_ARM9(); + } + + invokeArm11Function(ARM11); +} + +void clearScreens(void) +{ + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + //Setting up two simultaneous memory fills using the GPU + + vu32 *REGs_PSC0 = (vu32 *)0x10400010; + REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address + REGs_PSC0[1] = (u32)(fb->top_left + 0x46500) >> 3; //End address + REGs_PSC0[2] = 0; //Fill value + REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start + + vu32 *REGs_PSC1 = (vu32 *)0x10400020; + REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address + REGs_PSC1[1] = (u32)(fb->bottom + 0x38400) >> 3; //End address + REGs_PSC1[2] = 0; //Fill value + REGs_PSC1[3] = (2 << 8) | 1; //32-bit patter; start + + while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2))); + + if(fb->top_right != fb->top_left) + { + REGs_PSC0[0] = (u32)fb->top_right >> 3; //Start address + REGs_PSC0[1] = (u32)(fb->top_right + 0x46500) >> 3; //End address + REGs_PSC0[2] = 0; //Fill value + REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start + + while(!(REGs_PSC0[3] & 2)); + } + + WAIT_FOR_ARM9(); + } + + invokeArm11Function(ARM11); +} + +u32 initScreens(void) +{ + u32 needToInit = PDN_GPU_CNT == 1; + + void __attribute__((naked)) ARM11(void) + { + //Disable interrupts + __asm(".word 0xF10C01C0"); + + u32 brightnessLevel = MULTICONFIG(0); + + *(vu32 *)0x10141200 = 0x1007F; + *(vu32 *)0x10202014 = 0x00000001; + *(vu32 *)0x1020200C &= 0xFFFEFFFE; + *(vu32 *)0x10202240 = brightness[brightnessLevel]; + *(vu32 *)0x10202A40 = brightness[brightnessLevel]; + *(vu32 *)0x10202244 = 0x1023E; + *(vu32 *)0x10202A44 = 0x1023E; + + // Top screen + *(vu32 *)0x10400400 = 0x000001c2; + *(vu32 *)0x10400404 = 0x000000d1; + *(vu32 *)0x10400408 = 0x000001c1; + *(vu32 *)0x1040040c = 0x000001c1; + *(vu32 *)0x10400410 = 0x00000000; + *(vu32 *)0x10400414 = 0x000000cf; + *(vu32 *)0x10400418 = 0x000000d1; + *(vu32 *)0x1040041c = 0x01c501c1; + *(vu32 *)0x10400420 = 0x00010000; + *(vu32 *)0x10400424 = 0x0000019d; + *(vu32 *)0x10400428 = 0x00000002; + *(vu32 *)0x1040042c = 0x00000192; + *(vu32 *)0x10400430 = 0x00000192; + *(vu32 *)0x10400434 = 0x00000192; + *(vu32 *)0x10400438 = 0x00000001; + *(vu32 *)0x1040043c = 0x00000002; + *(vu32 *)0x10400440 = 0x01960192; + *(vu32 *)0x10400444 = 0x00000000; + *(vu32 *)0x10400448 = 0x00000000; + *(vu32 *)0x1040045C = 0x00f00190; + *(vu32 *)0x10400460 = 0x01c100d1; + *(vu32 *)0x10400464 = 0x01920002; + *(vu32 *)0x10400468 = 0x18300000; + *(vu32 *)0x10400470 = 0x80341; + *(vu32 *)0x10400474 = 0x00010501; + *(vu32 *)0x10400478 = 0; + *(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; + *(vu32 *)0x10400508 = 0x000001c1; + *(vu32 *)0x1040050c = 0x000001c1; + *(vu32 *)0x10400510 = 0x000000cd; + *(vu32 *)0x10400514 = 0x000000cf; + *(vu32 *)0x10400518 = 0x000000d1; + *(vu32 *)0x1040051c = 0x01c501c1; + *(vu32 *)0x10400520 = 0x00010000; + *(vu32 *)0x10400524 = 0x0000019d; + *(vu32 *)0x10400528 = 0x00000052; + *(vu32 *)0x1040052c = 0x00000192; + *(vu32 *)0x10400530 = 0x00000192; + *(vu32 *)0x10400534 = 0x0000004f; + *(vu32 *)0x10400538 = 0x00000050; + *(vu32 *)0x1040053c = 0x00000052; + *(vu32 *)0x10400540 = 0x01980194; + *(vu32 *)0x10400544 = 0x00000000; + *(vu32 *)0x10400548 = 0x00000011; + *(vu32 *)0x1040055C = 0x00f00140; + *(vu32 *)0x10400560 = 0x01c100d1; + *(vu32 *)0x10400564 = 0x01920052; + *(vu32 *)0x10400568 = 0x18300000 + 0x46500; + *(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; + + *(vu32 *)0x10400468 = 0x18300000; + *(vu32 *)0x1040046c = 0x18300000; + *(vu32 *)0x10400494 = 0x18300000; + *(vu32 *)0x10400498 = 0x18300000; + *(vu32 *)0x10400568 = 0x18346500; + *(vu32 *)0x1040056c = 0x18346500; + + //Set CakeBrah framebuffers + fb->top_left = (u8 *)0x18300000; + fb->top_right = (u8 *)0x18300000; + fb->bottom = (u8 *)0x18346500; + + WAIT_FOR_ARM9(); + } + + if(needToInit) + { + invokeArm11Function(ARM11); + + //Turn on backlight + i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); + } + else + updateBrightness(MULTICONFIG(0)); + + clearScreens(); + + return needToInit; +} \ No newline at end of file diff --git a/source/screen.h b/source/screen.h new file mode 100644 index 0000000..5f2bf1d --- /dev/null +++ b/source/screen.h @@ -0,0 +1,23 @@ +/* +* screen.h +* +* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. +* Screen deinit code by tiniVi. +*/ + +#pragma once + +#include "types.h" + +#define PDN_GPU_CNT (*(vu8 *)0x10141200) + +static volatile struct fb { + u8 *top_left; + u8 *top_right; + u8 *bottom; +} *const fb = (volatile struct fb *)0x23FFFE00; + +void deinitScreens(void); +void updateBrightness(u32 brightnessLevel); +void clearScreens(void); +u32 initScreens(void); \ No newline at end of file diff --git a/source/screeninit.c b/source/screeninit.c deleted file mode 100644 index 86f1390..0000000 --- a/source/screeninit.c +++ /dev/null @@ -1,69 +0,0 @@ -/* -* screeninit.c -* -* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. -* Screen deinit code by tiniVi. -*/ - -#include "screeninit.h" -#include "config.h" -#include "memory.h" -#include "draw.h" -#include "i2c.h" -#include "../build/screeninit.h" - -vu32 *arm11Entry = (u32 *)0x1FFFFFF8; - -void deinitScreens(void) -{ - void __attribute__((naked)) ARM11(void) - { - //Disable interrupts - __asm(".word 0xF10C01C0"); - - //Clear ARM11 entry offset - *arm11Entry = 0; - - //Shutdown LCDs - *(vu32 *)0x10202A44 = 0; - *(vu32 *)0x10202244 = 0; - *(vu32 *)0x10202014 = 0; - - //Wait for the entry to be set - while(!*arm11Entry); - - //Jump to it - ((void (*)())*arm11Entry)(); - } - - if(PDN_GPU_CNT != 1) - { - *arm11Entry = (u32)ARM11; - while(*arm11Entry); - } -} - -u32 initScreens(void) -{ - u32 needToInit = PDN_GPU_CNT == 1; - - if(needToInit) - { - u32 *const screenInitAddress = (u32 *)0x24FFFC00; - - memcpy(screenInitAddress, screeninit, screeninit_size); - - //Write brightness level for the stub to pick up - screenInitAddress[2] = MULTICONFIG(0); - - *arm11Entry = (u32)screenInitAddress; - while(*arm11Entry); - - //Turn on backlight - i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A); - } - - clearScreens(); - - return needToInit; -} \ No newline at end of file diff --git a/source/screeninit.h b/source/screeninit.h deleted file mode 100644 index 2c778ce..0000000 --- a/source/screeninit.h +++ /dev/null @@ -1,15 +0,0 @@ -/* -* screeninit.h -* -* Screen init code by dark_samus, bil1s, Normmatt, delebile and others. -* Screen deinit code by tiniVi. -*/ - -#pragma once - -#include "types.h" - -#define PDN_GPU_CNT (*(vu8 *)0x10141200) - -void deinitScreens(void); -u32 initScreens(void); \ No newline at end of file diff --git a/source/start.s b/source/start.s index d446a4f..1171c49 100644 --- a/source/start.s +++ b/source/start.s @@ -23,15 +23,15 @@ start: mcr p15, 0, r0, c5, c0, 3 @ write instruction access @ Sets MPU permissions and cache settings - ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) - ldr r1, =0x3000801B @ fff00000 16k | dtcm - ldr r2, =0x01FF801D @ 01ff8000 32k | itcm - 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, #0x25 + ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part) + ldr r1, =0x3000801B @ fff00000 16k | dtcm + ldr r2, =0x01FF801D @ 01ff8000 32k | itcm + 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, #0x29 mcr p15, 0, r0, c6, c0, 0 mcr p15, 0, r1, c6, c1, 0 mcr p15, 0, r2, c6, c2, 0 @@ -40,9 +40,9 @@ start: mcr p15, 0, r5, c6, c5, 0 mcr p15, 0, r6, c6, c6, 0 mcr p15, 0, r7, c6, c7, 0 - mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 5 - mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 5 - mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 5 + mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 3, 5 + mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 3, 5 + mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 3, 5 @ Enable dctm ldr r0, =0x3000800A @ set dtcm diff --git a/source/utils.c b/source/utils.c index 5497437..b1cd2fe 100644 --- a/source/utils.c +++ b/source/utils.c @@ -5,6 +5,7 @@ #include "utils.h" #include "i2c.h" #include "buttons.h" +#include "memory.h" u32 waitInput(void) { @@ -35,6 +36,8 @@ u32 waitInput(void) void mcuReboot(void) { + cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed + i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); while(1); } From edfd63e1f71d22838c60219e4f333c6f6ef37c4e Mon Sep 17 00:00:00 2001 From: TuxSH Date: Fri, 10 Jun 2016 23:33:03 +0200 Subject: [PATCH 2/2] We don't need to flush DCache when launching payloads. Fixes a derp as well. --- loader/source/main.c | 1 - loader/source/memory.c | 5 ----- loader/source/memory.h | 12 +----------- source/fs.c | 1 - source/memory.h | 1 - source/screen.c | 2 +- 6 files changed, 2 insertions(+), 20 deletions(-) diff --git a/loader/source/main.c b/loader/source/main.c index 18aea19..b611bfe 100644 --- a/loader/source/main.c +++ b/loader/source/main.c @@ -5,7 +5,6 @@ void main(void) void *payloadAddress = (void *)0x23F00000; memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04); - cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed ((void (*)())payloadAddress)(); } \ No newline at end of file diff --git a/loader/source/memory.c b/loader/source/memory.c index 69dd2f2..4f4c96a 100644 --- a/loader/source/memory.c +++ b/loader/source/memory.c @@ -7,9 +7,4 @@ void memcpy(void *dest, const void *src, u32 size) for(u32 i = 0; i < size; i++) destc[i] = srcc[i]; -} - -void cleanInvalidateDCacheAndDMB(void) -{ - ((void (*)())0xFFFF0830)(); //Why write our own code when it's well implemented in the unprotected bootROM? } \ No newline at end of file diff --git a/loader/source/memory.h b/loader/source/memory.h index 4c74b6d..466220c 100644 --- a/loader/source/memory.h +++ b/loader/source/memory.h @@ -2,14 +2,4 @@ #include "types.h" -void memcpy(void *dest, const void *src, u32 size); - -/*** - Cleans and invalidates the data cache, then waits for all memory transfers to be finished. - This function MUST be called before doing the following: - - rebooting - - powering down - - setting the ARM11 entrypoint to execute a function - - jumping to a payload (?) -***/ -void cleanInvalidateDCacheAndDMB(void); \ No newline at end of file +void memcpy(void *dest, const void *src, u32 size); \ No newline at end of file diff --git a/source/fs.c b/source/fs.c index 375dbed..61b2c04 100644 --- a/source/fs.c +++ b/source/fs.c @@ -85,7 +85,6 @@ void loadPayload(u32 pressed) loaderAddress[1] = fileRead((void *)0x24F00000, path); - cleanInvalidateDCacheAndDMB(); //Ensure that all memory transfers have completed and that the data cache has been flushed ((void (*)())loaderAddress)(); } } diff --git a/source/memory.h b/source/memory.h index d1877c6..c120581 100644 --- a/source/memory.h +++ b/source/memory.h @@ -19,6 +19,5 @@ u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize); - rebooting - powering down - setting the ARM11 entrypoint to execute a function - - jumping to a payload (?) ***/ void cleanInvalidateDCacheAndDMB(void); \ No newline at end of file diff --git a/source/screen.c b/source/screen.c index 588d014..e55c4bb 100644 --- a/source/screen.c +++ b/source/screen.c @@ -36,7 +36,7 @@ static inline void invokeArm11Function(void (*func)()) *arm11Entry = (u32)func; while(*arm11Entry); - *arm11Entry = (u32)arm11Stub; + *arm11Entry = ARM11_STUB_ADDRESS; } static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};