Compare commits

..

19 Commits
v5.2 ... v5.4

Author SHA1 Message Date
Aurora
5b51574ebf We do not need all that space anymore 2016-04-30 03:34:28 +02:00
Aurora
df112b550b Move loadPayload to fs.c, and the path to the beginning of the chainloader 2016-04-29 17:22:13 +02:00
Aurora
85615d1916 Fix external FIRM loading 2016-04-29 15:21:49 +02:00
Aurora
c6d3158b56 Remade the chainloader to only try to load the right payload for the pressed button, got rid of the default payload (start now boots "start_NAME.bin"), sel_NAME is now select_NAME as there is no more SFN limitations anymore 2016-04-29 15:08:33 +02:00
Aurora
e651c3d9cc Small cleanup 2016-04-28 16:27:32 +02:00
Aurora
bfc2448662 Simplify makefiles 2016-04-28 00:43:25 +02:00
Aurora
5a9d0e2569 Fail 2016-04-27 16:16:25 +02:00
Aurora
041ca8451e Use the older cxi, should fix NANDs with incomplete background updates 2016-04-27 15:37:13 +02:00
Aurora
2382e6d82c Fixed oversight in the injector 2016-04-27 04:52:23 +02:00
Aurora
f9a1f1a79b Move the UNITINFO patch to the developer version 2016-04-26 21:51:57 +02:00
Aurora
a736e4602a Cleanup 2016-04-26 20:10:20 +02:00
Aurora
5202ba8826 Update ReadME 2016-04-26 14:33:01 +02:00
Aurora
0f1bc98bb7 Rename "Use SysNAND FIRM as default" to "SysNAND is updated" 2016-04-26 14:11:34 +02:00
Aurora
d40722af53 Apply the eShop update skipping patch only if the updated NAND was not booted (depends on the "Use SysNAND FIRM as default" option) 2016-04-26 14:05:48 +02:00
Aurora
c9781ab626 Added python implementation of the path changer from @TuxSH 2016-04-26 03:39:36 +02:00
Aurora
4cbf4e93e7 Minor stuff 2016-04-26 01:30:03 +02:00
Aurora
1f68c2da42 Update ReadME 2016-04-24 20:19:35 +02:00
Aurora
d786c292f3 Update submodules 2016-04-24 19:49:09 +02:00
Aurora
ada3e09784 Added L+A payload 2016-04-24 19:46:33 +02:00
29 changed files with 210 additions and 242 deletions

Submodule CakeHax updated: 6b8fca0b37...5245c7b9dc

View File

@@ -111,12 +111,4 @@ $(dir_build)/%.o: $(dir_source)/%.c $(bundled)
$(dir_build)/%.o: $(dir_source)/%.s $(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)" @mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $< $(COMPILE.s) $(OUTPUT_OPTION) $<
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
include $(call rwildcard, $(dir_build), *.d) include $(call rwildcard, $(dir_build), *.d)

View File

@@ -3,8 +3,10 @@
**Compiling:** **Compiling:**
You'll need armips, [bin2c](https://sourceforge.net/projects/bin2c/), and a recent build of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. [HERE](http://www91.zippyshare.com/v/ePGpjk9r/file.html) is a pre-compiled version of armips for Windows. First you need to clone the repository recursively with: 'git clone --recursive https://github.com/AuroraWright/Luma3DS.git'
Then, just run "make" and everything should work! To compile, you'll need [armips](https://github.com/Kingcom/armips), [bin2c](https://sourceforge.net/projects/bin2c/), and a recent build of [makerom](https://github.com/profi200/Project_CTR) added to your PATH.
For your convenience, here are [Windows](http://www91.zippyshare.com/v/ePGpjk9r/file.html) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!).
Finally just run 'make' and everything should work!
You can find the compiled files in the 'out' folder. You can find the compiled files in the 'out' folder.
**Setup / Usage / Features:** **Setup / Usage / Features:**
@@ -14,3 +16,8 @@ See https://github.com/AuroraWright/Luma3DS/wiki
**Credits:** **Credits:**
See https://github.com/AuroraWright/Luma3DS/wiki/Credits See https://github.com/AuroraWright/Luma3DS/wiki/Credits
**Licensing:**
This software is licensed under the terms of the GPLv3.
You can find a copy of the license in the LICENSE.txt file.

View File

@@ -143,7 +143,7 @@ static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
u32 i = 29; u32 i = 29;
while(progId > 0) while(progId)
{ {
static const char hexDigits[] = "0123456789ABCDEF"; static const char hexDigits[] = "0123456789ABCDEF";
path[i--] = hexDigits[(u32)(progId & 0xF)]; path[i--] = hexDigits[(u32)(progId & 0xF)];
@@ -336,12 +336,6 @@ void patchCode(u64 progId, u8 *code, u32 size)
static const u8 blockAutoUpdatesPatch[] = { static const u8 blockAutoUpdatesPatch[] = {
0xE3, 0xA0 0xE3, 0xA0
}; };
static const u8 skipEshopUpdateCheckPattern[] = {
0x30, 0xB5, 0xF1, 0xB0
};
static const u8 skipEshopUpdateCheckPatch[] = {
0x00, 0x20, 0x08, 0x60, 0x70, 0x47
};
//Block silent auto-updates //Block silent auto-updates
patchMemory(code, size, patchMemory(code, size,
@@ -351,6 +345,16 @@ void patchCode(u64 progId, u8 *code, u32 size)
sizeof(blockAutoUpdatesPatch), 1 sizeof(blockAutoUpdatesPatch), 1
); );
//Apply only if the updated NAND hasn't been booted
if((BOOTCONFIG(0, 3) != 0) == (BOOTCONFIG(3, 1) && CONFIG(1)))
{
static const u8 skipEshopUpdateCheckPattern[] = {
0x30, 0xB5, 0xF1, 0xB0
};
static const u8 skipEshopUpdateCheckPatch[] = {
0x00, 0x20, 0x08, 0x60, 0x70, 0x47
};
//Skip update checks to access the EShop //Skip update checks to access the EShop
patchMemory(code, size, patchMemory(code, size,
skipEshopUpdateCheckPattern, skipEshopUpdateCheckPattern,
@@ -358,6 +362,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
skipEshopUpdateCheckPatch, skipEshopUpdateCheckPatch,
sizeof(skipEshopUpdateCheckPatch), 1 sizeof(skipEshopUpdateCheckPatch), 1
); );
}
break; break;
} }
@@ -388,7 +393,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
case 0x0004001000027000LL: // KOR MSET case 0x0004001000027000LL: // KOR MSET
case 0x0004001000028000LL: // TWN MSET case 0x0004001000028000LL: // TWN MSET
{ {
if(CONFIG(6)) if(CONFIG(5))
{ {
static const u16 verPattern[] = u"Ver."; static const u16 verPattern[] = u"Ver.";
const u32 currentNand = BOOTCONFIG(0, 3); const u32 currentNand = BOOTCONFIG(0, 3);
@@ -504,8 +509,8 @@ void patchCode(u64 progId, u8 *code, u32 size)
} }
} }
} }
}
break; break;
} }
} }
}

View File

@@ -44,12 +44,4 @@ $(dir_build)/%.o: $(dir_source)/%.c
$(dir_build)/%.o: $(dir_source)/%.s $(dir_build)/%.o: $(dir_source)/%.s
@mkdir -p "$(@D)" @mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $< $(COMPILE.s) $(OUTPUT_OPTION) $<
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.c
@mkdir -p "$(@D)"
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(dir_build)/fatfs/%.o: $(dir_source)/fatfs/%.s
@mkdir -p "$(@D)"
$(COMPILE.s) $(OUTPUT_OPTION) $<
include $(call rwildcard, $(dir_build), *.d) include $(call rwildcard, $(dir_build), *.d)

View File

@@ -1,13 +0,0 @@
#pragma once
#include "types.h"
#define HID_PAD (*(vu32 *)0x10146000 ^ 0xFFF)
#define BUTTON_RIGHT (1 << 4)
#define BUTTON_LEFT (1 << 5)
#define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7)
#define BUTTON_X (1 << 10)
#define BUTTON_Y (1 << 11)
#define BUTTON_R1 (1 << 8)
#define BUTTON_SELECT (1 << 2)

View File

@@ -15,7 +15,7 @@
/ and optional writing functions as well. */ / and optional writing functions as well. */
#define _FS_MINIMIZE 1 #define _FS_MINIMIZE 3
/* This option defines minimization level to remove some basic API functions. /* This option defines minimization level to remove some basic API functions.
/ /
/ 0: All basic functions are enabled. / 0: All basic functions are enabled.
@@ -34,7 +34,7 @@
/ 2: Enable with LF-CRLF conversion. */ / 2: Enable with LF-CRLF conversion. */
#define _USE_FIND 1 #define _USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and /* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ / f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */

View File

@@ -1,4 +1,15 @@
#pragma once #pragma once
#include <stdbool.h> #include <stdbool.h>
#include "../../types.h" #include <stdint.h>
#include <stdlib.h>
//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;

View File

@@ -1,39 +1,6 @@
#include "types.h"
#include "buttons.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#define PAYLOAD_ADDRESS 0x23F00000 #define PAYLOAD_ADDRESS 0x23F00000
#define LOAD_PAYLOAD(a) loadPayload(a "_*.bin")
static u32 loadPayload(const char *pattern)
{
char path[30] = "/luma/payloads";
DIR dir;
FILINFO info;
FRESULT result = f_findfirst(&dir, &info, path, pattern);
f_closedir(&dir);
if(result != FR_OK || !info.fname[0])
return 0;
path[14] = '/';
u32 i;
for(i = 0; info.fname[i]; i++)
path[15 + i] = info.fname[i];
path[15 + i] = '\0';
FIL payload;
unsigned int br;
f_open(&payload, path, FA_READ);
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &br);
f_close(&payload);
return 1;
}
void main(void) void main(void)
{ {
@@ -41,17 +8,12 @@ void main(void)
f_mount(&fs, "0:", 1); f_mount(&fs, "0:", 1);
//Get pressed buttons FIL payload;
u32 pressed = HID_PAD; unsigned int read;
f_open(&payload, (char *)0x24F00004, FA_READ);
f_read(&payload, (void *)PAYLOAD_ADDRESS, f_size(&payload), &read);
f_close(&payload);
if(((pressed & BUTTON_RIGHT) && LOAD_PAYLOAD("right")) ||
((pressed & BUTTON_LEFT) && LOAD_PAYLOAD("left")) ||
((pressed & BUTTON_UP) && LOAD_PAYLOAD("up")) ||
((pressed & BUTTON_DOWN) && LOAD_PAYLOAD("down")) ||
((pressed & BUTTON_X) && LOAD_PAYLOAD("x")) ||
((pressed & BUTTON_Y) && LOAD_PAYLOAD("y")) ||
((pressed & BUTTON_R1) && LOAD_PAYLOAD("r")) ||
((pressed & BUTTON_SELECT) && LOAD_PAYLOAD("sel")) ||
LOAD_PAYLOAD("def"))
((void (*)())PAYLOAD_ADDRESS)(); ((void (*)())PAYLOAD_ADDRESS)();
} }

View File

@@ -2,6 +2,11 @@
.align 4 .align 4
.global _start .global _start
_start: _start:
b start
.word 0, 0, 0, 0, 0, 0, 0
start:
@ Flush caches @ Flush caches
mov r0, #0 mov r0, #0
mcr p15, 0, r0, c7, c5, 0 @ flush I-cache mcr p15, 0, r0, c7, c5, 0 @ flush I-cache

View File

@@ -1,14 +0,0 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
//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;

View File

@@ -0,0 +1,40 @@
#!/usr/bin/env python
# Requires Python >= 3.2 or >= 2.7
# This is part of Luma3DS
__author__ = "TuxSH"
__copyright__ = "Copyright (c) 2016 TuxSH"
__license__ = "GPLv3"
__version__ = "v1.0"
import argparse
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Changes the path to Luma3DS for reboot patches")
parser.add_argument("payload", help="Path to the Luma3DS payload")
parser.add_argument("new_path", help="New Luma3DS payload path")
args = parser.parse_args()
data = b""
if len(args.new_path) > 37:
raise SystemExit("The new payload path is too large (37 characters max.)")
with open(args.payload, "rb") as f: data = bytearray(f.read())
if len(data) == 0: raise SystemExit("Could not read {0}".format(args.payload))
if len(data) > 0x20000:
raise SystemExit("The input file is too large, are you sure you're using a Luma3DS payload?")
found_index = data.find("sdmc:/".encode("utf-16-le"))
if found_index == -1:
raise SystemExit("The pattern was not found, are you sure you're usinga a Luma3DS payload?")
namebuf = args.new_path.encode("utf-16-le")
namebuf += b'\x00' * (74 - len(namebuf))
data[found_index + 12 : found_index + 12 + 74] = namebuf
with open(args.payload, "wb+") as f: f.write(data)

View File

@@ -1,7 +1,7 @@
ENTRY(_start) ENTRY(_start)
SECTIONS SECTIONS
{ {
. = 0x24F03000; . = 0x24F02000;
.text.start : { *(.text.start) } .text.start : { *(.text.start) }
.text : { *(.text) } .text : { *(.text) }
.data : { *(.data) } .data : { *(.data) }

View File

@@ -3,7 +3,7 @@
void main(void) void main(void)
{ {
const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
u32 brightnessLevel = *(vu32 *)0x24F03008; u32 brightnessLevel = *(vu32 *)0x24F02008;
vu32 *const arm11 = (u32 *)0x1FFFFFF8; vu32 *const arm11 = (u32 *)0x1FFFFFF8;
*(vu32 *)0x10141200 = 0x1007F; *(vu32 *)0x10141200 = 0x1007F;

View File

@@ -19,9 +19,8 @@
#define BUTTON_LEFT (1 << 5) #define BUTTON_LEFT (1 << 5)
#define BUTTON_UP (1 << 6) #define BUTTON_UP (1 << 6)
#define BUTTON_DOWN (1 << 7) #define BUTTON_DOWN (1 << 7)
#define BUTTON_L1R1 (BUTTON_R1 | BUTTON_L1) #define SAFE_MODE (BUTTON_R1 | BUTTON_L1 | BUTTON_A | BUTTON_UP)
#define SAFE_MODE (BUTTON_L1R1 | BUTTON_A | BUTTON_UP)
#define OVERRIDE_BUTTONS (BUTTON_B ^ 0xFFF) #define OVERRIDE_BUTTONS (BUTTON_B ^ 0xFFF)
#define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START | BUTTON_X | BUTTON_Y) #define SINGLE_PAYLOAD_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_START | BUTTON_X | BUTTON_Y)
#define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_SELECT) #define L_PAYLOAD_BUTTONS (BUTTON_R1 | BUTTON_A | BUTTON_SELECT)
#define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START) #define MENU_BUTTONS (BUTTON_LEFT | BUTTON_RIGHT | BUTTON_UP | BUTTON_DOWN | BUTTON_A | BUTTON_START)

View File

@@ -20,11 +20,10 @@ void configureCFW(const char *configPath)
"New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )" }; "New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )" };
const char *singleOptionsText[] = { "( ) Autoboot SysNAND", const char *singleOptionsText[] = { "( ) Autoboot SysNAND",
"( ) Use SysNAND FIRM as default (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 emulation", "( ) Enable region/language emulation",
"( ) Use developer UNITINFO",
"( ) 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" };

View File

@@ -9,7 +9,7 @@
#include "fatfs/sdmmc/sdmmc.h" #include "fatfs/sdmmc/sdmmc.h"
/**************************************************************** /****************************************************************
* Crypto Libs * Crypto libs
****************************************************************/ ****************************************************************/
/* original version by megazig */ /* original version by megazig */
@@ -271,7 +271,7 @@ static void sha(void *res, const void *src, u32 size, u32 mode)
} }
/**************************************************************** /****************************************************************
* Nand/FIRM Crypto stuff * NAND/FIRM crypto
****************************************************************/ ****************************************************************/
static u8 nandCTR[0x10], static u8 nandCTR[0x10],
@@ -348,9 +348,9 @@ void decryptExeFs(u8 *inbuf)
void arm9Loader(u8 *arm9Section, u32 mode) void arm9Loader(u8 *arm9Section, u32 mode)
{ {
//Firm keys //Firm keys
u8 keyY[0x10]; u8 keyY[0x10],
u8 arm9BinCTR[0x10]; arm9BinCTR[0x10],
u8 arm9BinSlot = mode ? 0x16 : 0x15; arm9BinSlot = mode ? 0x16 : 0x15;
//Setup keys needed for arm9bin decryption //Setup keys needed for arm9bin decryption
memcpy(keyY, arm9Section + 0x10, 0x10); memcpy(keyY, arm9Section + 0x10, 0x10);
@@ -384,8 +384,8 @@ void arm9Loader(u8 *arm9Section, u32 mode)
//Set >=9.6 KeyXs //Set >=9.6 KeyXs
if(mode) if(mode)
{ {
u8 keyData[0x10] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}; u8 keyData[0x10] = {0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98},
u8 decKey[0x10]; decKey[0x10];
//Set keys 0x19..0x1F keyXs //Set keys 0x19..0x1F keyXs
aes_use_keyslot(0x11); aes_use_keyslot(0x11);

View File

@@ -22,6 +22,7 @@ static const struct fb {
static inline int strlen(const char *string) static inline int strlen(const char *string)
{ {
char *stringEnd = (char *)string; char *stringEnd = (char *)string;
while(*stringEnd) stringEnd++; while(*stringEnd) stringEnd++;
return stringEnd - string; return stringEnd - string;
@@ -39,11 +40,11 @@ void loadSplash(void)
initScreens(); initScreens();
//Don't delay boot if no splash image is on the SD //Don't delay boot if no splash image is on the SD
if(fileRead(fb->top_left, "/luma/splash.bin", 0x46500) + if(!(fileRead(fb->top_left, "/luma/splash.bin", 0x46500) +
fileRead(fb->bottom, "/luma/splashbottom.bin", 0x38400)) fileRead(fb->bottom, "/luma/splashbottom.bin", 0x38400)))
{ {
u64 i = 0x1400000; u64 i = 0x1400000;
while(--i) __asm("mov r0, r0"); //Less Ghetto sleep func while(i--) __asm("mov r0, r0"); //Less Ghetto sleep func
} }
} }

View File

@@ -6,7 +6,7 @@
#include "types.h" #include "types.h"
#define NCSD_MAGIC (0x4453434E) #define NCSD_MAGIC 0x4453434E
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND); void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND);
u32 getSDMMC(u8 *pos, u32 size); u32 getSDMMC(u8 *pos, u32 size);

View File

@@ -12,7 +12,6 @@
#include "crypto.h" #include "crypto.h"
#include "draw.h" #include "draw.h"
#include "screeninit.h" #include "screeninit.h"
#include "loader.h"
#include "buttons.h" #include "buttons.h"
#include "../build/patches.h" #include "../build/patches.h"
@@ -43,7 +42,7 @@ void main(void)
//Attempt to read the configuration file //Attempt to read the configuration file
const char configPath[] = "/luma/config.bin"; const char configPath[] = "/luma/config.bin";
if(fileRead(&config, configPath, 4)) needConfig = 1; if(!fileRead(&config, configPath, 4)) needConfig = 1;
else else
{ {
config = 0; config = 0;
@@ -129,16 +128,15 @@ void main(void)
the Safe Mode combo is not pressed, chainload an external payload */ the Safe Mode combo is not pressed, chainload an external payload */
if(((pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS))) if(((pressed & SINGLE_PAYLOAD_BUTTONS) || ((pressed & BUTTON_L1) && (pressed & L_PAYLOAD_BUTTONS)))
&& pressed != SAFE_MODE) && pressed != SAFE_MODE)
loadPayload(); loadPayload(pressed);
//If no configuration file exists or SELECT is held, load configuration menu //If no configuration file exists or SELECT is held, load configuration menu
if(needConfig == 2 || (pressed & BUTTON_SELECT)) if(needConfig == 2 || (pressed & BUTTON_SELECT))
configureCFW(configPath); configureCFW(configPath);
//If screens are inited or the corresponding option is set, load splash screen //If screens are inited or the corresponding option is set, load splash screen
if(PDN_GPU_CNT != 1 || CONFIG(8)) loadSplash(); if(PDN_GPU_CNT != 1 || CONFIG(7)) loadSplash();
//Determine if we need to autoboot sysNAND
u32 autoBootSys = CONFIG(0); u32 autoBootSys = CONFIG(0);
//Determine if we need to boot an emuNAND or sysNAND //Determine if we need to boot an emuNAND or sysNAND
@@ -187,15 +185,17 @@ void main(void)
launchFirm(bootType); launchFirm(bootType);
} }
//Load FIRM into FCRAM
static inline void loadFirm(u32 firmType, u32 externalFirm) static inline void loadFirm(u32 firmType, u32 externalFirm)
{ {
section = firm->section; section = firm->section;
u32 externalFirmLoaded = externalFirm &&
!fileRead(firm, "/luma/firmware.bin", 0) &&
(((u32)section[2].address >> 8) & 0xFF) == (console ? 0x60 : 0x68);
/* If the conditions to load the external FIRM aren't met, or reading fails, or the FIRM /* If the conditions to load the external FIRM aren't met, or reading fails, or the FIRM
doesn't match the console, load it from CTRNAND */ doesn't match the console, load FIRM from CTRNAND */
if(!externalFirm || !fileRead(firm, "/luma/firmware.bin", 0) || if(!externalFirmLoaded)
(((u32)section[2].address >> 8) & 0xFF) != (console ? 0x60 : 0x68))
{ {
const char *firmFolders[3][2] = {{ "00000002", "20000002" }, const char *firmFolders[3][2] = {{ "00000002", "20000002" },
{ "00000102", "20000102" }, { "00000102", "20000102" },
@@ -257,13 +257,6 @@ static inline void patchNativeFirm(u32 nandType, u32 emuHeader, u32 a9lhInstalle
*(u16 *)sigOffset2 = sigPatch[0]; *(u16 *)sigOffset2 = sigPatch[0];
*((u16 *)sigOffset2 + 1) = sigPatch[1]; *((u16 *)sigOffset2 + 1) = sigPatch[1];
if(CONFIG(5))
{
//Apply UNITINFO patch
u8 *unitInfoOffset = getUnitInfoValueSet(arm9Section, section[2].size);
*unitInfoOffset = unitInfoPatch;
}
//Replace the FIRM loader with the injector //Replace the FIRM loader with the injector
injectLoader(); injectLoader();
} }
@@ -368,7 +361,7 @@ static inline void patchTwlAgbFirm(u32 firmType)
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM /* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
if the matching option was enabled (keep it as last) */ if the matching option was enabled (keep it as last) */
u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) : u32 numPatches = firmType == 1 ? (sizeof(twlPatches) / sizeof(patchData)) :
(sizeof(agbPatches) / sizeof(patchData) - !CONFIG(7)); (sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6));
const patchData *patches = firmType == 1 ? twlPatches : agbPatches; const patchData *patches = firmType == 1 ? twlPatches : agbPatches;
//Patch //Patch
@@ -390,7 +383,7 @@ static inline void patchTwlAgbFirm(u32 firmType)
static inline void launchFirm(u32 bootType) static inline void launchFirm(u32 bootType)
{ {
//Copy firm partitions to respective memory locations //Copy FIRM sections to respective memory locations
for(u32 i = 0; i < 4 && section[i].size; i++) for(u32 i = 0; i < 4 && section[i].size; i++)
memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size); memcpy(section[i].address, (u8 *)firm + section[i].offset, section[i].size);
@@ -406,6 +399,6 @@ static inline void launchFirm(u32 bootType)
//Set ARM11 kernel entrypoint //Set ARM11 kernel entrypoint
*arm11 = (u32)firm->arm11Entry; *arm11 = (u32)firm->arm11Entry;
//Final jump to arm9 kernel //Final jump to ARM9 kernel
((void (*)())firm->arm9Entry)(); ((void (*)())firm->arm9Entry)();
} }

View File

@@ -4,7 +4,13 @@
#include "fs.h" #include "fs.h"
#include "memory.h" #include "memory.h"
#include "screeninit.h"
#include "fatfs/ff.h" #include "fatfs/ff.h"
#include "buttons.h"
#include "../build/loader.h"
#define PAYLOAD_ADDRESS 0x24F00000
#define PATTERN(a) a "_*.bin"
static FATFS sdFs, static FATFS sdFs,
nandFs; nandFs;
@@ -19,46 +25,73 @@ u32 mountFs(void)
u32 fileRead(void *dest, const char *path, u32 size) u32 fileRead(void *dest, const char *path, u32 size)
{ {
FRESULT fr; FRESULT result;
FIL fp; FIL file;
unsigned int br = 0;
fr = f_open(&fp, path, FA_READ); result = f_open(&file, path, FA_READ);
if(fr == FR_OK) if(result == FR_OK)
{ {
if(!size) size = f_size(&fp); unsigned int read;
fr = f_read(&fp, dest, size, &br); if(!size) size = f_size(&file);
result = f_read(&file, dest, size, &read);
} }
f_close(&fp); f_close(&file);
return fr ? 0 : 1; return result;
} }
u32 fileWrite(const void *buffer, const char *path, u32 size) u32 fileWrite(const void *buffer, const char *path, u32 size)
{ {
FRESULT fr; FRESULT result;
FIL fp; FIL file;
unsigned int br = 0;
fr = f_open(&fp, path, FA_WRITE | FA_OPEN_ALWAYS); result = f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS);
if(fr == FR_OK) fr = f_write(&fp, buffer, size, &br); if(result == FR_OK)
{
f_close(&fp); unsigned int read;
result = f_write(&file, buffer, size, &read);
return fr ? 0 : 1;
} }
u32 defPayloadExists(void) f_close(&file);
return result;
}
void loadPayload(u32 pressed)
{ {
const char *pattern;
if(pressed & BUTTON_RIGHT) pattern = PATTERN("right");
else if(pressed & BUTTON_LEFT) pattern = PATTERN("left");
else if(pressed & BUTTON_UP) pattern = PATTERN("up");
else if(pressed & BUTTON_DOWN) pattern = PATTERN("down");
else if(pressed & BUTTON_X) pattern = PATTERN("x");
else if(pressed & BUTTON_Y) pattern = PATTERN("y");
else if(pressed & BUTTON_R1) pattern = PATTERN("r");
else if(pressed & BUTTON_A) pattern = PATTERN("a");
else if(pressed & BUTTON_START) pattern = PATTERN("start");
else pattern = PATTERN("select");
DIR dir; DIR dir;
FILINFO info; FILINFO info;
char path[] = "/luma/payloads";
FRESULT result = f_findfirst(&dir, &info, "/luma/payloads", "def_*.bin"); FRESULT result = f_findfirst(&dir, &info, path, pattern);
f_closedir(&dir); f_closedir(&dir);
return (result == FR_OK && info.fname[0]); if(result == FR_OK && info.fname[0])
{
initScreens();
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
path[sizeof(path) - 1] = '/';
memcpy((void *)(PAYLOAD_ADDRESS + 4), path, sizeof(path));
memcpy((void *)(PAYLOAD_ADDRESS + 4 + sizeof(path)), info.altname, 13);
((void (*)())PAYLOAD_ADDRESS)();
}
} }
void firmRead(void *dest, const char *firmFolder) void firmRead(void *dest, const char *firmFolder)
@@ -71,7 +104,7 @@ void firmRead(void *dest, const char *firmFolder)
f_opendir(&dir, path); f_opendir(&dir, path);
u32 id = 0; u32 id = 0xFFFFFFFF;
//Parse the target directory //Parse the target directory
while(f_readdir(&dir, &info) == FR_OK && info.fname[0]) while(f_readdir(&dir, &info) == FR_OK && info.fname[0])
@@ -87,8 +120,8 @@ void firmRead(void *dest, const char *firmFolder)
tempId += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0'; tempId += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0';
} }
//Found a newer cxi //Found an older cxi
if(tempId > id) id = tempId; if(tempId < id) id = tempId;
} }
f_closedir(&dir); f_closedir(&dir);
@@ -96,12 +129,12 @@ void firmRead(void *dest, const char *firmFolder)
//Complete the string with the .app name //Complete the string with the .app name
memcpy(&path[34], "/00000000.app", 14); memcpy(&path[34], "/00000000.app", 14);
//Last digit of the .app
u32 i = 42; u32 i = 42;
//Convert back the .app name from integer to array //Convert back the .app name from integer to array
while(id > 0) while(id)
{ {
//Last digit of the .app
static const char hexDigits[] = "0123456789ABCDEF"; static const char hexDigits[] = "0123456789ABCDEF";
path[i--] = hexDigits[id & 0xF]; path[i--] = hexDigits[id & 0xF];
id >>= 4; id >>= 4;

View File

@@ -9,5 +9,5 @@
u32 mountFs(void); u32 mountFs(void);
u32 fileRead(void *dest, const char *path, u32 size); u32 fileRead(void *dest, const char *path, u32 size);
u32 fileWrite(const void *buffer, const char *path, u32 size); u32 fileWrite(const void *buffer, const char *path, u32 size);
u32 defPayloadExists(void); void loadPayload(u32 pressed);
void firmRead(void *dest, const char *firmFolder); void firmRead(void *dest, const char *firmFolder);

View File

@@ -1,21 +0,0 @@
/*
* loader.c
*/
#include "loader.h"
#include "fs.h"
#include "memory.h"
#include "screeninit.h"
#include "../build/loader.h"
#define PAYLOAD_ADDRESS 0x24F00000
void loadPayload(void)
{
if(defPayloadExists())
{
initScreens();
memcpy((void *)PAYLOAD_ADDRESS, loader, loader_size);
((void (*)())PAYLOAD_ADDRESS)();
}
}

View File

@@ -1,9 +0,0 @@
/*
* loader.h
*/
#pragma once
#include "types.h"
void loadPayload(void);

View File

@@ -11,13 +11,9 @@
const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603}; const u32 mpuPatch[3] = {0x00360003, 0x00200603, 0x001C0603};
const u16 nandRedir[2] = {0x4C00, 0x47A0}; const u16 nandRedir[2] = {0x4C00, 0x47A0},
sigPatch[2] = {0x2000, 0x4770},
const u16 sigPatch[2] = {0x2000, 0x4770}; writeBlock[2] = {0x2000, 0x46C0};
const u16 writeBlock[2] = {0x2000, 0x46C0};
const u8 unitInfoPatch = 0xE3;
/************************************************** /**************************************************
* Functions * Functions
@@ -67,14 +63,6 @@ u16 *getFirmWrite(u8 *pos, u32 size)
return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4); return (u16 *)memsearch(off - 0x100, pattern, 0x100, 4);
} }
u8 *getUnitInfoValueSet(u8 *pos, u32 size)
{
//Look for UNITINFO value being set
const u8 pattern[] = {0x01, 0x10, 0xA0, 0x13};
return memsearch(pos, pattern, size, 4) + 3;
}
void *getLoader(u8 *pos, u32 size, u32 *loaderSize) void *getLoader(u8 *pos, u32 size, u32 *loaderSize)
{ {
u8 *const off = memsearch(pos, "loade", size, 5); u8 *const off = memsearch(pos, "loade", size, 5);

View File

@@ -10,10 +10,9 @@
* Patches * Patches
**************************************************/ **************************************************/
const u32 mpuPatch[3]; const u32 mpuPatch[3];
const u16 nandRedir[2]; const u16 nandRedir[2],
const u16 sigPatch[2]; sigPatch[2],
const u16 writeBlock[2]; writeBlock[2];
const u8 unitInfoPatch;
/************************************************** /**************************************************
* Functions * Functions
@@ -23,5 +22,4 @@ void getSigChecks(u8 *pos, u32 size, u32 *off, u32 *off2);
void *getReboot(u8 *pos, u32 size); void *getReboot(u8 *pos, u32 size);
u32 getfOpen(u8 *proc9Offset, void *rebootOffset); u32 getfOpen(u8 *proc9Offset, void *rebootOffset);
u16 *getFirmWrite(u8 *pos, u32 size); u16 *getFirmWrite(u8 *pos, u32 size);
u8 *getUnitInfoValueSet(u8 *pos, u32 size);
void *getLoader(u8 *pos, u32 size, u32 *loaderSize); void *getLoader(u8 *pos, u32 size, u32 *loaderSize);

View File

@@ -12,7 +12,7 @@
#include "i2c.h" #include "i2c.h"
#include "../build/screeninit.h" #include "../build/screeninit.h"
#define SCREENINIT_ADDRESS 0x24F03000 #define SCREENINIT_ADDRESS 0x24F02000
vu32 *arm11Entry = (u32 *)0x1FFFFFF8; vu32 *arm11Entry = (u32 *)0x1FFFFFF8;