Merge branch 'master' into developer
Conflicts: source/config.c
This commit is contained in:
commit
153bbd6242
2
CakeBrah
2
CakeBrah
@ -1 +1 @@
|
|||||||
Subproject commit 42ebe0d0bc075ba98fa631441590de9bd2733d2b
|
Subproject commit bead2ce337cc31da6b7ca1c1ce30672d78a7fe00
|
@ -135,31 +135,29 @@ static void progIdToStr(char *strEnd, u64 progId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
static void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
|
||||||
{
|
{
|
||||||
/* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin"
|
/* Here we look for "/luma/code_sections/[u64 titleID in hex, uppercase].bin"
|
||||||
If it exists it should be a decompressed binary code file */
|
If it exists it should be a decompressed binary code file */
|
||||||
|
|
||||||
char path[] = "/luma/code_sections/0000000000000000.bin";
|
char path[] = "/luma/code_sections/0000000000000000.bin";
|
||||||
progIdToStr(path + 35, progId);
|
progIdToStr(path + 35, progId);
|
||||||
|
|
||||||
IFile file;
|
IFile file;
|
||||||
Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
Result ret = fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ);
|
||||||
|
|
||||||
if(R_SUCCEEDED(ret))
|
if(R_SUCCEEDED(ret))
|
||||||
{
|
{
|
||||||
u64 fileSize, total;
|
u64 fileSize, total;
|
||||||
|
|
||||||
ret = IFile_GetSize(&file, &fileSize);
|
ret = IFile_GetSize(&file, &fileSize);
|
||||||
if(!R_SUCCEEDED(ret) || fileSize > size) return -1;
|
|
||||||
|
if(R_SUCCEEDED(ret) && fileSize <= size)
|
||||||
ret = IFile_Read(&file, &total, code, fileSize);
|
{
|
||||||
IFile_Close(&file);
|
ret = IFile_Read(&file, &total, code, fileSize);
|
||||||
if(!R_SUCCEEDED(ret)) return -1;
|
IFile_Close(&file);
|
||||||
else if(total < fileSize) return -2; //Shouldn't happen
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
|
static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
|
||||||
@ -366,7 +364,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
);
|
);
|
||||||
|
|
||||||
//Apply only if the updated NAND hasn't been booted
|
//Apply only if the updated NAND hasn't been booted
|
||||||
if((BOOTCONFIG(0, 3) != 0) == (BOOTCONFIG(3, 1) && CONFIG(1)))
|
if((BOOTCONFIG(0, 3) != 0) == (BOOTCONFIG(2, 1) && CONFIG(1)))
|
||||||
{
|
{
|
||||||
static const u8 skipEshopUpdateCheckPattern[] = {
|
static const u8 skipEshopUpdateCheckPattern[] = {
|
||||||
0x30, 0xB5, 0xF1, 0xB0
|
0x30, 0xB5, 0xF1, 0xB0
|
||||||
@ -586,8 +584,8 @@ void patchCode(u64 progId, u8 *code, u32 size)
|
|||||||
if(tidHigh == 0x0004000)
|
if(tidHigh == 0x0004000)
|
||||||
{
|
{
|
||||||
//External .code section loading
|
//External .code section loading
|
||||||
if(loadTitleCodeSection(progId, code, size) == -2) svcBreak(USERBREAK_ASSERT);
|
loadTitleCodeSection(progId, code, size);
|
||||||
|
|
||||||
//Language emulation
|
//Language emulation
|
||||||
u8 regionId = 0xFF,
|
u8 regionId = 0xFF,
|
||||||
languageId = 0xFF;
|
languageId = 0xFF;
|
||||||
|
5
loader/source/cache.h
Normal file
5
loader/source/cache.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
void flushCaches(void);
|
39
loader/source/cache.s
Normal file
39
loader/source/cache.s
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
@
|
||||||
|
@ cache.s
|
||||||
|
@ by TuxSH
|
||||||
|
@
|
||||||
|
@ This is part of Luma3DS, see LICENSE.txt for details
|
||||||
|
@
|
||||||
|
|
||||||
|
.arm
|
||||||
|
.global flushCaches
|
||||||
|
.type flushCaches STT_FUNC
|
||||||
|
|
||||||
|
flushCaches:
|
||||||
|
@ Clean and flush data cache
|
||||||
|
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
|
||||||
|
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||||
|
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||||
|
@ Implemented in bootROM at address 0xffff0830
|
||||||
|
|
||||||
|
mov r1, #0 @ segment counter
|
||||||
|
outer_loop:
|
||||||
|
mov r0, #0 @ line counter
|
||||||
|
|
||||||
|
inner_loop:
|
||||||
|
orr r2, r1, r0 @ generate segment and line address
|
||||||
|
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||||
|
add r0, #0x20 @ increment to next line
|
||||||
|
cmp r0, #0x400
|
||||||
|
bne inner_loop
|
||||||
|
|
||||||
|
add r1, #0x40000000
|
||||||
|
cmp r1, #0
|
||||||
|
bne outer_loop
|
||||||
|
|
||||||
|
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
||||||
|
|
||||||
|
@ Flush instruction cache
|
||||||
|
mcr p15, 0, r1, c7, c5, 0
|
||||||
|
|
||||||
|
bx lr
|
@ -1,4 +1,5 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
#include "cache.h"
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
{
|
{
|
||||||
@ -6,8 +7,7 @@ void main(void)
|
|||||||
|
|
||||||
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04);
|
memcpy(payloadAddress, (void*)0x24F00000, *(u32 *)0x24FFFF04);
|
||||||
|
|
||||||
((void (*)(void))0xFFFF0830)(); //Clean and flush the entire DCache, then drain the write buffer
|
flushCaches();
|
||||||
((void (*)(void))0xFFFF0AB4)(); //Flush the entire ICache
|
|
||||||
|
|
||||||
((void (*)())payloadAddress)();
|
((void (*)())payloadAddress)();
|
||||||
}
|
}
|
@ -2,15 +2,6 @@
|
|||||||
.align 4
|
.align 4
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
b start
|
b main
|
||||||
|
|
||||||
.word 0
|
.word 0
|
||||||
|
|
||||||
start:
|
|
||||||
@ Flush caches
|
|
||||||
mov r0, #0
|
|
||||||
mcr p15, 0, r0, c7, c5, 0 @ flush I-cache
|
|
||||||
mcr p15, 0, r0, c7, c6, 0 @ flush D-cache
|
|
||||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
|
||||||
|
|
||||||
b main
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
.arm.little
|
.arm.little
|
||||||
|
|
||||||
payload_addr equ 0x23F00000 ; Brahma payload address.
|
payload_addr equ 0x23F00000 ; Brahma payload address.
|
||||||
payload_maxsize equ 0x20000 ; Maximum size for the payload (200 KB will do).
|
payload_maxsize equ 0x10000 ; Maximum size for the payload (maximum that CakeBrah supports).
|
||||||
|
|
||||||
.create "build/reboot.bin", 0
|
.create "build/reboot.bin", 0
|
||||||
.arm
|
.arm
|
||||||
@ -88,60 +88,31 @@ dat_fname: .dcw "sdmc:/Luma3DS.dat"
|
|||||||
|
|
||||||
.align 4
|
.align 4
|
||||||
kernelcode_start:
|
kernelcode_start:
|
||||||
; Set MPU settings
|
|
||||||
mrc p15, 0, r0, c2, c0, 0 ; dcacheable
|
|
||||||
mrc p15, 0, r12, c2, c0, 1 ; icacheable
|
|
||||||
mrc p15, 0, r1, c3, c0, 0 ; write bufferable
|
|
||||||
mrc p15, 0, r2, c5, c0, 2 ; daccess
|
|
||||||
mrc p15, 0, r3, c5, c0, 3 ; iaccess
|
|
||||||
ldr r4, =0x18000035 ; 0x18000000 128M
|
|
||||||
bic r2, r2, #0xF0000 ; unprotect region 4
|
|
||||||
bic r3, r3, #0xF0000 ; unprotect region 4
|
|
||||||
orr r0, r0, #0x10 ; dcacheable region 4
|
|
||||||
orr r2, r2, #0x30000 ; region 4 r/w
|
|
||||||
orr r3, r3, #0x30000 ; region 4 r/w
|
|
||||||
orr r12, r12, #0x10 ; icacheable region 4
|
|
||||||
orr r1, r1, #0x10 ; write bufferable region 4
|
|
||||||
mcr p15, 0, r0, c2, c0, 0
|
|
||||||
mcr p15, 0, r12, c2, c0, 1
|
|
||||||
mcr p15, 0, r1, c3, c0, 0 ; write bufferable
|
|
||||||
mcr p15, 0, r2, c5, c0, 2 ; daccess
|
|
||||||
mcr p15, 0, r3, c5, c0, 3 ; iaccess
|
|
||||||
mcr p15, 0, r4, c6, c4, 0 ; region 4 (hmmm)
|
|
||||||
|
|
||||||
mrc p15, 0, r0, c2, c0, 0 ; dcacheable
|
; Disable MPU
|
||||||
mrc p15, 0, r1, c2, c0, 1 ; icacheable
|
|
||||||
mrc p15, 0, r2, c3, c0, 0 ; write bufferable
|
|
||||||
orr r0, r0, #0x20 ; dcacheable region 5
|
|
||||||
orr r1, r1, #0x20 ; icacheable region 5
|
|
||||||
orr r2, r2, #0x20 ; write bufferable region 5
|
|
||||||
mcr p15, 0, r0, c2, c0, 0 ; dcacheable
|
|
||||||
mcr p15, 0, r1, c2, c0, 1 ; icacheable
|
|
||||||
mcr p15, 0, r2, c3, c0, 0 ; write bufferable
|
|
||||||
|
|
||||||
; Flush cache
|
|
||||||
mov r2, #0
|
|
||||||
mov r1, r2
|
|
||||||
flush_cache:
|
|
||||||
mov r0, #0
|
|
||||||
mov r3, r2, lsl #30
|
|
||||||
flush_cache_inner_loop:
|
|
||||||
orr r12, r3, r0, lsl#5
|
|
||||||
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
|
||||||
mcr p15, 0, r12, c7, c14, 2 ; clean and flush dcache entry (index and segment)
|
|
||||||
add r0, #1
|
|
||||||
cmp r0, #0x20
|
|
||||||
bcc flush_cache_inner_loop
|
|
||||||
add r2, #1
|
|
||||||
cmp r2, #4
|
|
||||||
bcc flush_cache
|
|
||||||
|
|
||||||
; Enable MPU
|
|
||||||
ldr r0, =0x42078 ; alt vector select, enable itcm
|
ldr r0, =0x42078 ; alt vector select, enable itcm
|
||||||
mcr p15, 0, r0, c1, c0, 0
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
mcr p15, 0, r1, c7, c5, 0 ; flush dcache
|
|
||||||
mcr p15, 0, r1, c7, c6, 0 ; flush icache
|
; Clean and flush data cache
|
||||||
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
mov r1, #0 ; segment counter
|
||||||
|
outer_loop:
|
||||||
|
mov r0, #0 ; line counter
|
||||||
|
|
||||||
|
inner_loop:
|
||||||
|
orr r2, r1, r0 ; generate segment and line address
|
||||||
|
mcr p15, 0, r2, c7, c14, 2 ; clean and flush the line
|
||||||
|
add r0, #0x20 ; increment to next line
|
||||||
|
cmp r0, #0x400
|
||||||
|
bne inner_loop
|
||||||
|
|
||||||
|
add r1, #0x40000000
|
||||||
|
cmp r1, #0
|
||||||
|
bne outer_loop
|
||||||
|
|
||||||
|
mcr p15, 0, r1, c7, c10, 4 ; drain write buffer
|
||||||
|
|
||||||
|
; Flush instruction cache
|
||||||
|
mcr p15, 0, r1, c7, c5, 0
|
||||||
|
|
||||||
; Jump to payload
|
; Jump to payload
|
||||||
ldr r0, =payload_addr
|
ldr r0, =payload_addr
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
/***
|
/***
|
||||||
@ -17,6 +18,5 @@
|
|||||||
|
|
||||||
void flushEntireDCache(void); //actually: "clean and flush"
|
void flushEntireDCache(void); //actually: "clean and flush"
|
||||||
void flushDCacheRange(void *startAddress, u32 size);
|
void flushDCacheRange(void *startAddress, u32 size);
|
||||||
|
|
||||||
void flushEntireICache(void);
|
void flushEntireICache(void);
|
||||||
void flushICacheRange(void *startAddress, u32 size);
|
void flushICacheRange(void *startAddress, u32 size);
|
@ -12,69 +12,65 @@
|
|||||||
.global flushEntireDCache
|
.global flushEntireDCache
|
||||||
.type flushEntireDCache, %function
|
.type flushEntireDCache, %function
|
||||||
flushEntireDCache:
|
flushEntireDCache:
|
||||||
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
|
@ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
|
||||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||||
|
|
||||||
@ Implemented in bootROM at address 0xffff0830
|
@ Implemented in bootROM at address 0xffff0830
|
||||||
|
|
||||||
mov r1, #0 @ segment counter
|
mov r1, #0 @ segment counter
|
||||||
outer_loop:
|
outer_loop:
|
||||||
mov r0, #0 @ line counter
|
mov r0, #0 @ line counter
|
||||||
|
|
||||||
inner_loop:
|
inner_loop:
|
||||||
orr r2, r1, r0 @ generate segment and line address
|
orr r2, r1, r0 @ generate segment and line address
|
||||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||||
add r0, #0x20 @ increment to next line
|
add r0, #0x20 @ increment to next line
|
||||||
cmp r0, #0x400
|
cmp r0, #0x400
|
||||||
bne inner_loop
|
bne inner_loop
|
||||||
|
|
||||||
add r1, #0x40000000
|
add r1, #0x40000000
|
||||||
cmp r1, #0
|
cmp r1, #0
|
||||||
bne outer_loop
|
bne outer_loop
|
||||||
|
|
||||||
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
.global flushDCacheRange
|
.global flushDCacheRange
|
||||||
.type flushDCacheRange, %function
|
.type flushDCacheRange, %function
|
||||||
flushDCacheRange:
|
flushDCacheRange:
|
||||||
@ Implemented in bootROM at address 0xffff08a0
|
@ Implemented in bootROM at address 0xffff08a0
|
||||||
|
|
||||||
add r1, r0, r1 @ end address
|
add r1, r0, r1 @ end address
|
||||||
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
||||||
|
|
||||||
flush_dcache_range_loop:
|
flush_dcache_range_loop:
|
||||||
mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding
|
mcr p15, 0, r0, c7, c14, 1 @ clean and flush the line corresponding to the address r0 is holding
|
||||||
add r0, #0x20
|
add r0, #0x20
|
||||||
cmp r0, r1
|
cmp r0, r1
|
||||||
blt flush_dcache_range_loop
|
blo flush_dcache_range_loop
|
||||||
|
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
.global flushEntireICache
|
.global flushEntireICache
|
||||||
.type flushEntireICache, %function
|
.type flushEntireICache, %function
|
||||||
flushEntireICache:
|
flushEntireICache:
|
||||||
@ Implemented in bootROM at address 0xffff0ab4
|
@ Implemented in bootROM at address 0xffff0ab4
|
||||||
|
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
mcr p15, 0, r0, c7, c5, 0
|
mcr p15, 0, r0, c7, c5, 0
|
||||||
bx lr
|
bx lr
|
||||||
|
|
||||||
.global flushICacheRange
|
.global flushICacheRange
|
||||||
.type flushICacheRange, %function
|
.type flushICacheRange, %function
|
||||||
flushICacheRange:
|
flushICacheRange:
|
||||||
@ Implemented in bootROM at address 0xffff0ac0
|
@ Implemented in bootROM at address 0xffff0ac0
|
||||||
|
|
||||||
add r1, r0, r1 @ end address
|
add r1, r0, r1 @ end address
|
||||||
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
bic r0, #0x1f @ align source address to cache line size (32 bytes)
|
||||||
|
|
||||||
flush_icache_range_loop:
|
flush_icache_range_loop:
|
||||||
mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding
|
mcr p15, 0, r0, c7, c5, 1 @ flush the line corresponding to the address r0 is holding
|
||||||
add r0, #0x20
|
add r0, #0x20
|
||||||
cmp r0, r1
|
cmp r0, r1
|
||||||
blt flush_icache_range_loop
|
blo flush_icache_range_loop
|
||||||
|
|
||||||
bx lr
|
bx lr
|
||||||
|
|
@ -25,7 +25,7 @@ void configureCFW(const char *configPath)
|
|||||||
"( ) SysNAND is updated (A9LH-only)",
|
"( ) SysNAND is updated (A9LH-only)",
|
||||||
"( ) Force A9LH detection",
|
"( ) Force A9LH detection",
|
||||||
"( ) Use second EmuNAND as default",
|
"( ) Use second EmuNAND as default",
|
||||||
"( ) Enable region/language emu. and external .code loading",
|
"( ) Enable region/language emu. and ext. .code",
|
||||||
"( ) Show current NAND in System Settings",
|
"( ) Show current NAND in System Settings",
|
||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
"( ) Enable splash screen with no screen-init" };
|
"( ) Enable splash screen with no screen-init" };
|
||||||
@ -147,6 +147,9 @@ void configureCFW(const char *configPath)
|
|||||||
u32 oldEnabled = multiOptions[selectedOption].enabled;
|
u32 oldEnabled = multiOptions[selectedOption].enabled;
|
||||||
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[oldEnabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_BLACK);
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[oldEnabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_BLACK);
|
||||||
multiOptions[selectedOption].enabled = (oldEnabled == 3 || !multiOptions[selectedOption].posXs[oldEnabled + 1]) ? 0 : oldEnabled + 1;
|
multiOptions[selectedOption].enabled = (oldEnabled == 3 || !multiOptions[selectedOption].posXs[oldEnabled + 1]) ? 0 : oldEnabled + 1;
|
||||||
|
|
||||||
|
if(!selectedOption)
|
||||||
|
updateBrightness(multiOptions[selectedOption].enabled);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -158,12 +161,7 @@ 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'
|
//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 < multiOptionsAmount)
|
||||||
{
|
|
||||||
if(selectedOption == 0)
|
|
||||||
updateBrightness(multiOptions[selectedOption].enabled);
|
|
||||||
|
|
||||||
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
drawCharacter(selected, 10 + multiOptions[selectedOption].posXs[multiOptions[selectedOption].enabled] * SPACING_X, multiOptions[selectedOption].posY, COLOR_RED);
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
u32 singleSelected = selectedOption - multiOptionsAmount;
|
u32 singleSelected = selectedOption - multiOptionsAmount;
|
||||||
|
@ -19,6 +19,8 @@
|
|||||||
#define COLOR_RED 0x0000FF
|
#define COLOR_RED 0x0000FF
|
||||||
#define COLOR_BLACK 0x000000
|
#define COLOR_BLACK 0x000000
|
||||||
|
|
||||||
|
extern volatile struct fb *const fb;
|
||||||
|
|
||||||
u32 loadSplash(void);
|
u32 loadSplash(void);
|
||||||
void drawCharacter(char character, int posX, int posY, u32 color);
|
void drawCharacter(char character, int posX, int posY, u32 color);
|
||||||
int drawString(const char *string, int posX, int posY, u32 color);
|
int drawString(const char *string, int posX, int posY, u32 color);
|
@ -23,7 +23,7 @@ static const firmSectionHeader *section;
|
|||||||
u32 config,
|
u32 config,
|
||||||
isN3DS,
|
isN3DS,
|
||||||
emuOffset;
|
emuOffset;
|
||||||
|
|
||||||
FirmwareSource firmSource;
|
FirmwareSource firmSource;
|
||||||
|
|
||||||
void main(void)
|
void main(void)
|
||||||
@ -38,7 +38,7 @@ void main(void)
|
|||||||
FirmwareSource nandType;
|
FirmwareSource nandType;
|
||||||
ConfigurationStatus needConfig;
|
ConfigurationStatus needConfig;
|
||||||
A9LHMode a9lhMode;
|
A9LHMode a9lhMode;
|
||||||
|
|
||||||
//Detect the console being used
|
//Detect the console being used
|
||||||
isN3DS = PDN_MPCORE_CFG == 7;
|
isN3DS = PDN_MPCORE_CFG == 7;
|
||||||
|
|
||||||
@ -478,7 +478,7 @@ static inline void launchFirm(FirmwareType firmType, u32 isFirmlaunch)
|
|||||||
|
|
||||||
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
flushEntireICache();
|
flushEntireICache();
|
||||||
|
|
||||||
//Set ARM11 kernel entrypoint
|
//Set ARM11 kernel entrypoint
|
||||||
*arm11 = (u32)firm->arm11Entry;
|
*arm11 = (u32)firm->arm11Entry;
|
||||||
|
|
||||||
|
@ -12,18 +12,17 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "i2c.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;
|
vu32 *arm11Entry = (vu32 *)0x1FFFFFF8;
|
||||||
|
volatile struct fb *const fb = (volatile struct fb *)0x23FFFE00;
|
||||||
|
|
||||||
void __attribute__((naked)) arm11Stub(void)
|
void __attribute__((naked)) arm11Stub(void)
|
||||||
{
|
{
|
||||||
//Disable interrupts
|
//Disable interrupts
|
||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
//Wait for the entry to be set
|
//Wait for the entry to be set
|
||||||
while(*arm11Entry == ARM11_STUB_ADDRESS);
|
while(*arm11Entry == ARM11_STUB_ADDRESS);
|
||||||
|
|
||||||
//Jump to it
|
//Jump to it
|
||||||
((void (*)())*arm11Entry)();
|
((void (*)())*arm11Entry)();
|
||||||
}
|
}
|
||||||
@ -31,12 +30,14 @@ void __attribute__((naked)) arm11Stub(void)
|
|||||||
static inline void invokeArm11Function(void (*func)())
|
static inline void invokeArm11Function(void (*func)())
|
||||||
{
|
{
|
||||||
static u32 hasCopiedStub = 0;
|
static u32 hasCopiedStub = 0;
|
||||||
if(!hasCopiedStub++)
|
|
||||||
|
if(!hasCopiedStub)
|
||||||
{
|
{
|
||||||
memcpy((void *)ARM11_STUB_ADDRESS, arm11Stub, 0x40);
|
memcpy((void *)ARM11_STUB_ADDRESS, arm11Stub, 0x40);
|
||||||
flushDCacheRange((void *)ARM11_STUB_ADDRESS, 0x40);
|
flushDCacheRange((void *)ARM11_STUB_ADDRESS, 0x40);
|
||||||
|
hasCopiedStub = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*arm11Entry = (u32)func;
|
*arm11Entry = (u32)func;
|
||||||
while(*arm11Entry);
|
while(*arm11Entry);
|
||||||
*arm11Entry = ARM11_STUB_ADDRESS;
|
*arm11Entry = ARM11_STUB_ADDRESS;
|
||||||
@ -62,25 +63,23 @@ void deinitScreens(void)
|
|||||||
if(PDN_GPU_CNT != 1) invokeArm11Function(ARM11);
|
if(PDN_GPU_CNT != 1) invokeArm11Function(ARM11);
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateBrightness(u32 brightnessLevel)
|
void updateBrightness(u32 brightnessIndex)
|
||||||
{
|
{
|
||||||
static int brightnessValue;
|
u32 brightnessLevel = brightness[brightnessIndex];
|
||||||
|
|
||||||
brightnessValue = brightness[brightnessLevel];
|
|
||||||
|
|
||||||
void __attribute__((naked)) ARM11(void)
|
void __attribute__((naked)) ARM11(void)
|
||||||
{
|
{
|
||||||
//Disable interrupts
|
//Disable interrupts
|
||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
//Change brightness
|
//Change brightness
|
||||||
*(vu32 *)0x10202240 = brightnessValue;
|
*(vu32 *)0x10202240 = brightnessLevel;
|
||||||
*(vu32 *)0x10202A40 = brightnessValue;
|
*(vu32 *)0x10202A40 = brightnessLevel;
|
||||||
|
|
||||||
WAIT_FOR_ARM9();
|
WAIT_FOR_ARM9();
|
||||||
}
|
}
|
||||||
|
|
||||||
flushDCacheRange(&brightnessValue, 4);
|
flushDCacheRange(&brightnessLevel, 4);
|
||||||
invokeArm11Function(ARM11);
|
invokeArm11Function(ARM11);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,21 +89,20 @@ void clearScreens(void)
|
|||||||
{
|
{
|
||||||
//Disable interrupts
|
//Disable interrupts
|
||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
//Setting up two simultaneous memory fills using the GPU
|
//Setting up two simultaneous memory fills using the GPU
|
||||||
|
|
||||||
vu32 *REGs_PSC0 = (vu32 *)0x10400010;
|
vu32 *REGs_PSC0 = (vu32 *)0x10400010;
|
||||||
REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address
|
REGs_PSC0[0] = (u32)fb->top_left >> 3; //Start address
|
||||||
REGs_PSC0[1] = (u32)(fb->top_left + 0x46500) >> 3; //End address
|
REGs_PSC0[1] = (u32)(fb->top_left + 0x46500) >> 3; //End address
|
||||||
REGs_PSC0[2] = 0; //Fill value
|
REGs_PSC0[2] = 0; //Fill value
|
||||||
REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start
|
REGs_PSC0[3] = (2 << 8) | 1; //32-bit pattern; start
|
||||||
|
|
||||||
vu32 *REGs_PSC1 = (vu32 *)0x10400020;
|
vu32 *REGs_PSC1 = (vu32 *)0x10400020;
|
||||||
REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address
|
REGs_PSC1[0] = (u32)fb->bottom >> 3; //Start address
|
||||||
REGs_PSC1[1] = (u32)(fb->bottom + 0x38400) >> 3; //End address
|
REGs_PSC1[1] = (u32)(fb->bottom + 0x38400) >> 3; //End address
|
||||||
REGs_PSC1[2] = 0; //Fill value
|
REGs_PSC1[2] = 0; //Fill value
|
||||||
REGs_PSC1[3] = (2 << 8) | 1; //32-bit patter; start
|
REGs_PSC1[3] = (2 << 8) | 1; //32-bit pattern; start
|
||||||
|
|
||||||
while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2)));
|
while(!((REGs_PSC0[3] & 2) && (REGs_PSC1[3] & 2)));
|
||||||
|
|
||||||
if(fb->top_right != fb->top_left)
|
if(fb->top_right != fb->top_left)
|
||||||
@ -112,14 +110,14 @@ void clearScreens(void)
|
|||||||
REGs_PSC0[0] = (u32)fb->top_right >> 3; //Start address
|
REGs_PSC0[0] = (u32)fb->top_right >> 3; //Start address
|
||||||
REGs_PSC0[1] = (u32)(fb->top_right + 0x46500) >> 3; //End address
|
REGs_PSC0[1] = (u32)(fb->top_right + 0x46500) >> 3; //End address
|
||||||
REGs_PSC0[2] = 0; //Fill value
|
REGs_PSC0[2] = 0; //Fill value
|
||||||
REGs_PSC0[3] = (2 << 8) | 1; //32-bit patter; start
|
REGs_PSC0[3] = (2 << 8) | 1; //32-bit pattern; start
|
||||||
|
|
||||||
while(!(REGs_PSC0[3] & 2));
|
while(!(REGs_PSC0[3] & 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
WAIT_FOR_ARM9();
|
WAIT_FOR_ARM9();
|
||||||
}
|
}
|
||||||
|
|
||||||
flushDCacheRange((void *)fb, sizeof(struct fb));
|
flushDCacheRange((void *)fb, sizeof(struct fb));
|
||||||
invokeArm11Function(ARM11);
|
invokeArm11Function(ARM11);
|
||||||
}
|
}
|
||||||
@ -133,13 +131,13 @@ u32 initScreens(void)
|
|||||||
//Disable interrupts
|
//Disable interrupts
|
||||||
__asm(".word 0xF10C01C0");
|
__asm(".word 0xF10C01C0");
|
||||||
|
|
||||||
u32 brightnessLevel = MULTICONFIG(0);
|
u32 brightnessLevel = brightness[MULTICONFIG(0)];
|
||||||
|
|
||||||
*(vu32 *)0x10141200 = 0x1007F;
|
*(vu32 *)0x10141200 = 0x1007F;
|
||||||
*(vu32 *)0x10202014 = 0x00000001;
|
*(vu32 *)0x10202014 = 0x00000001;
|
||||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||||
*(vu32 *)0x10202240 = brightness[brightnessLevel];
|
*(vu32 *)0x10202240 = brightnessLevel;
|
||||||
*(vu32 *)0x10202A40 = brightness[brightnessLevel];
|
*(vu32 *)0x10202A40 = brightnessLevel;
|
||||||
*(vu32 *)0x10202244 = 0x1023E;
|
*(vu32 *)0x10202244 = 0x1023E;
|
||||||
*(vu32 *)0x10202A44 = 0x1023E;
|
*(vu32 *)0x10202A44 = 0x1023E;
|
||||||
|
|
||||||
@ -225,7 +223,7 @@ u32 initScreens(void)
|
|||||||
|
|
||||||
WAIT_FOR_ARM9();
|
WAIT_FOR_ARM9();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(needToInit)
|
if(needToInit)
|
||||||
{
|
{
|
||||||
flushDCacheRange(&config, 4);
|
flushDCacheRange(&config, 4);
|
||||||
@ -235,9 +233,8 @@ u32 initScreens(void)
|
|||||||
//Turn on backlight
|
//Turn on backlight
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
||||||
}
|
}
|
||||||
else
|
else updateBrightness(MULTICONFIG(0));
|
||||||
updateBrightness(MULTICONFIG(0));
|
|
||||||
|
|
||||||
clearScreens();
|
clearScreens();
|
||||||
|
|
||||||
return needToInit;
|
return needToInit;
|
||||||
|
@ -10,14 +10,16 @@
|
|||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||||
|
#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)();
|
||||||
|
|
||||||
static volatile struct fb {
|
struct fb {
|
||||||
u8 *top_left;
|
u8 *top_left;
|
||||||
u8 *top_right;
|
u8 *top_right;
|
||||||
u8 *bottom;
|
u8 *bottom;
|
||||||
} *const fb = (volatile struct fb *)0x23FFFE00;
|
};
|
||||||
|
|
||||||
void deinitScreens(void);
|
void deinitScreens(void);
|
||||||
void updateBrightness(u32 brightnessLevel);
|
void updateBrightness(u32 brightnessIndex);
|
||||||
void clearScreens(void);
|
void clearScreens(void);
|
||||||
u32 initScreens(void);
|
u32 initScreens(void);
|
@ -10,28 +10,32 @@ start:
|
|||||||
@ Change the stack pointer
|
@ Change the stack pointer
|
||||||
mov sp, #0x27000000
|
mov sp, #0x27000000
|
||||||
|
|
||||||
@ Disable caches / mpu
|
@ Disable caches / MPU
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||||
bic r0, #(1<<12) @ - instruction cache disable
|
bic r0, #(1<<12) @ - instruction cache disable
|
||||||
bic r0, #(1<<2) @ - data cache disable
|
bic r0, #(1<<2) @ - data cache disable
|
||||||
bic r0, #(1<<0) @ - mpu disable
|
bic r0, #(1<<0) @ - mpu disable
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||||
|
|
||||||
|
@ Flush caches
|
||||||
|
bl flushEntireDCache
|
||||||
|
bl flushEntireICache
|
||||||
|
|
||||||
@ Give read/write access to all the memory regions
|
@ Give read/write access to all the memory regions
|
||||||
ldr r0, =0x33333333
|
ldr r0, =0x3333333
|
||||||
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
mcr p15, 0, r0, c5, c0, 2 @ write data access
|
||||||
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
mcr p15, 0, r0, c5, c0, 3 @ write instruction access
|
||||||
|
|
||||||
@ Sets MPU permissions and cache settings
|
@ Set MPU permissions and cache settings
|
||||||
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
ldr r0, =0xFFFF001D @ ffff0000 32k | bootrom (unprotected part)
|
||||||
ldr r1, =0x3000801B @ fff00000 16k | dtcm
|
ldr r1, =0x01FF801D @ 01ff8000 32k | itcm
|
||||||
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
ldr r2, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
||||||
ldr r3, =0x08000029 @ 08000000 2M | arm9 mem (O3DS / N3DS)
|
ldr r3, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
||||||
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
ldr r4, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
||||||
ldr r5, =0x20000037 @ 20000000 256M | fcram (O3DS / N3DS)
|
ldr r5, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||||
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
ldr r6, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||||
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
mov r7, #0
|
||||||
mov r8, #0x29
|
mov r8, #0x15
|
||||||
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
|
||||||
@ -40,30 +44,18 @@ start:
|
|||||||
mcr p15, 0, r5, c6, c5, 0
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
mcr p15, 0, r6, c6, c6, 0
|
mcr p15, 0, r6, c6, c6, 0
|
||||||
mcr p15, 0, r7, c6, c7, 0
|
mcr p15, 0, r7, c6, c7, 0
|
||||||
mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 3, 5
|
mcr p15, 0, r8, c3, c0, 0 @ Write bufferable 0, 2, 4
|
||||||
mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 3, 5
|
mcr p15, 0, r8, c2, c0, 0 @ Data cacheable 0, 2, 4
|
||||||
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 3, 5
|
mcr p15, 0, r8, c2, c0, 1 @ Inst cacheable 0, 2, 4
|
||||||
|
|
||||||
@ Enable dctm
|
@ Enable caches / MPU
|
||||||
ldr r0, =0x3000800A @ set dtcm
|
|
||||||
mcr p15, 0, r0, c9, c1, 0 @ set the dtcm Region Register
|
|
||||||
|
|
||||||
@ Enable caches
|
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||||
orr r0, r0, #(1<<18) @ - itcm enable
|
|
||||||
orr r0, r0, #(1<<16) @ - dtcm enable
|
|
||||||
orr r0, r0, #(1<<12) @ - instruction cache enable
|
orr r0, r0, #(1<<12) @ - instruction cache enable
|
||||||
orr r0, r0, #(1<<2) @ - data cache enable
|
orr r0, r0, #(1<<2) @ - data cache enable
|
||||||
orr r0, r0, #(1<<0) @ - mpu enable
|
orr r0, r0, #(1<<0) @ - mpu enable
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||||
|
|
||||||
@ Flush caches
|
@ Fix mounting of SDMC
|
||||||
mov r0, #0
|
|
||||||
mcr p15, 0, r0, c7, c5, 0 @ flush I-cache
|
|
||||||
mcr p15, 0, r0, c7, c6, 0 @ flush D-cache
|
|
||||||
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
|
|
||||||
|
|
||||||
@ Fixes mounting of SDMC
|
|
||||||
ldr r0, =0x10000020
|
ldr r0, =0x10000020
|
||||||
mov r1, #0x340
|
mov r1, #0x340
|
||||||
str r1, [r0]
|
str r1, [r0]
|
||||||
|
@ -38,7 +38,7 @@ u32 waitInput(void)
|
|||||||
void mcuReboot(void)
|
void mcuReboot(void)
|
||||||
{
|
{
|
||||||
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
flushEntireDCache(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
|
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||||
while(1);
|
while(1);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user