Revamp CTRNAND support, add proper support for hiding options in config menu

This commit is contained in:
Aurora 2016-10-08 01:46:41 +02:00
parent f005da4d12
commit 37030621ac
19 changed files with 150 additions and 100 deletions

View File

@ -77,7 +77,7 @@ static void loadCustomVerString(u16 *out, u32 *verStringSize, u32 currentNand)
IFile file; IFile file;
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, paths[currentNand], FS_OPEN_READ))) if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, paths[currentNand], FS_OPEN_READ)) || R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, paths[currentNand], FS_OPEN_READ)))
{ {
u64 fileSize; u64 fileSize;
@ -135,7 +135,7 @@ static void loadTitleCodeSection(u64 progId, u8 *code, u32 size)
IFile file; IFile file;
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ))) if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ)) || R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)))
{ {
u64 fileSize; u64 fileSize;
@ -159,7 +159,7 @@ static void loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
IFile file; IFile file;
if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ))) if(R_SUCCEEDED(fileOpen(&file, ARCHIVE_SDMC, path, FS_OPEN_READ)) || R_SUCCEEDED(fileOpen(&file, ARCHIVE_NAND_RW, path, FS_OPEN_READ)))
{ {
u64 fileSize; u64 fileSize;

View File

@ -29,18 +29,17 @@
#include "buttons.h" #include "buttons.h"
#include "pin.h" #include "pin.h"
bool readConfig(bool isSdMounted) bool readConfig(void)
{ {
bool ret; bool ret;
if(!isSdMounted || if(fileRead(&configData, CONFIG_PATH, sizeof(CfgData)) != sizeof(CfgData) ||
fileRead(&configData, CONFIG_PATH, sizeof(CfgData)) != sizeof(CfgData) ||
memcmp(configData.magic, "CONF", 4) != 0 || memcmp(configData.magic, "CONF", 4) != 0 ||
configData.formatVersionMajor != CONFIG_VERSIONMAJOR || configData.formatVersionMajor != CONFIG_VERSIONMAJOR ||
configData.formatVersionMinor != CONFIG_VERSIONMINOR) configData.formatVersionMinor != CONFIG_VERSIONMINOR)
{ {
configData.config = 0; configData.config = 0;
ret = !isSdMounted; ret = false;
} }
else ret = true; else ret = true;
@ -68,7 +67,7 @@ void writeConfig(ConfigurationStatus needConfig, u32 configTemp)
} }
} }
void configMenu(bool oldPinStatus, u32 oldPinMode) void configMenu(Fs fsStatus, bool oldPinStatus, u32 oldPinMode)
{ {
const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )", const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )",
"Screen brightness: 4( ) 3( ) 2( ) 1( )", "Screen brightness: 4( ) 3( ) 2( ) 1( )",
@ -80,7 +79,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
const char *singleOptionsText[] = { "( ) Autoboot SysNAND", const char *singleOptionsText[] = { "( ) Autoboot SysNAND",
"( ) Use SysNAND FIRM if booting with R (A9LH)", "( ) Use SysNAND FIRM if booting with R (A9LH)",
"( ) Enable FIRMs and modules loading from SD", "( ) Enable loading external FIRMs and modules",
"( ) Use custom path", "( ) Use custom path",
"( ) Enable region/language emu. and ext. .code", "( ) Enable region/language emu. and ext. .code",
"( ) Show NAND or user string in System Settings", "( ) Show NAND or user string in System Settings",
@ -148,8 +147,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
"1/2/3/4), also add A if you have\n" "1/2/3/4), also add A if you have\n"
"a matching payload.", "a matching payload.",
"Enable loading FIRMs and\n" "Enable loading external FIRMs and\n"
"system modules from the SD card.\n\n" "system modules.\n\n"
"This isn't needed in most cases.\n\n" "This isn't needed in most cases.\n\n"
"Refer to the wiki for instructions.", "Refer to the wiki for instructions.",
@ -193,25 +192,37 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
u32 posXs[4]; u32 posXs[4];
u32 posY; u32 posY;
u32 enabled; u32 enabled;
bool visible;
} multiOptions[] = { } multiOptions[] = {
{ .posXs = {19, 24, 29, 34} }, { .posXs = {19, 24, 29, 34}, .visible = fsStatus == SD_CARD },
{ .posXs = {21, 26, 31, 36} }, { .posXs = {21, 26, 31, 36}, .visible = true },
{ .posXs = {12, 22, 31, 0} }, { .posXs = {12, 22, 31, 0}, .visible = true },
{ .posXs = {14, 19, 24, 29} }, { .posXs = {14, 19, 24, 29}, .visible = true },
{ .posXs = {17, 26, 32, 44} }, { .posXs = {17, 26, 32, 44}, .visible = isN3DS },
{ .posXs = {19, 30, 42, 0} } { .posXs = {19, 30, 42, 0}, .visible = true }
}; };
//Calculate the amount of the various kinds of options and pre-select the first single one
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
singleOptionsAmount = sizeof(singleOptionsText) / sizeof(char *),
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
selectedOption = multiOptionsAmount;
struct singleOption { struct singleOption {
u32 posY; u32 posY;
bool enabled; bool enabled;
} singleOptions[singleOptionsAmount]; bool visible;
} singleOptions[] = {
{ .visible = fsStatus == SD_CARD },
{ .visible = fsStatus == SD_CARD },
{ .visible = true },
{ .visible = fsStatus == SD_CARD },
{ .visible = true },
{ .visible = true },
{ .visible = true },
{ .visible = true }
};
//Calculate the amount of the various kinds of options and pre-select the first single one
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
singleOptionsAmount = sizeof(singleOptions) / sizeof(struct singleOption),
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
selectedOption = multiOptionsAmount;
while(!singleOptions[selectedOption - multiOptionsAmount].visible) selectedOption++;
//Parse the existing options //Parse the existing options
for(u32 i = 0; i < multiOptionsAmount; i++) for(u32 i = 0; i < multiOptionsAmount; i++)
@ -232,7 +243,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
//Display all the multiple choice options in white //Display all the multiple choice options in white
for(u32 i = 0; i < multiOptionsAmount; i++) for(u32 i = 0; i < multiOptionsAmount; i++)
{ {
if(!(i == NEWCPU && !isN3DS)) if(multiOptions[i].visible)
{ {
multiOptions[i].posY = endPos + SPACING_Y; multiOptions[i].posY = endPos + SPACING_Y;
endPos = drawString(multiOptionsText[i], true, 10, multiOptions[i].posY, COLOR_WHITE); endPos = drawString(multiOptionsText[i], true, 10, multiOptions[i].posY, COLOR_WHITE);
@ -246,10 +257,13 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
//Display all the normal options in white except for the first one //Display all the normal options in white except for the first one
for(u32 i = 0; i < singleOptionsAmount; i++) for(u32 i = 0; i < singleOptionsAmount; i++)
{ {
singleOptions[i].posY = endPos + SPACING_Y; if(singleOptions[i].visible)
endPos = drawString(singleOptionsText[i], true, 10, singleOptions[i].posY, color); {
if(singleOptions[i].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[i].posY, color); singleOptions[i].posY = endPos + SPACING_Y;
color = COLOR_WHITE; endPos = drawString(singleOptionsText[i], true, 10, singleOptions[i].posY, color);
if(singleOptions[i].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[i].posY, color);
color = COLOR_WHITE;
}
} }
drawString(optionsDescription[selectedOption], false, 10, 10, COLOR_WHITE); drawString(optionsDescription[selectedOption], false, 10, 10, COLOR_WHITE);
@ -270,24 +284,31 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
//Remember the previously selected option //Remember the previously selected option
u32 oldSelectedOption = selectedOption; u32 oldSelectedOption = selectedOption;
switch(pressed) while(true)
{ {
case BUTTON_UP: switch(pressed)
if(!selectedOption) selectedOption = totalIndexes; {
else selectedOption = (selectedOption == NEWCPU + 1 && !isN3DS) ? selectedOption - 2 : selectedOption - 1; case BUTTON_UP:
break; selectedOption = !selectedOption ? totalIndexes : selectedOption - 1;
case BUTTON_DOWN: break;
if(selectedOption == totalIndexes) selectedOption = 0; case BUTTON_DOWN:
else selectedOption = (selectedOption == NEWCPU - 1 && !isN3DS) ? selectedOption + 2 : selectedOption + 1; selectedOption = selectedOption == totalIndexes ? 0 : selectedOption + 1;
break; break;
case BUTTON_LEFT: case BUTTON_LEFT:
selectedOption = 0; pressed = BUTTON_DOWN;
break; selectedOption = 0;
case BUTTON_RIGHT: break;
selectedOption = totalIndexes; case BUTTON_RIGHT:
break; pressed = BUTTON_UP;
default: selectedOption = totalIndexes;
continue; break;
}
if(selectedOption < multiOptionsAmount)
{
if(multiOptions[selectedOption].visible) break;
}
else if(singleOptions[selectedOption - multiOptionsAmount].visible) break;
} }
if(selectedOption == oldSelectedOption) continue; if(selectedOption == oldSelectedOption) continue;

View File

@ -28,7 +28,7 @@
#define MULTICONFIG(a) ((configData.config >> (a * 2 + 9)) & 3) #define MULTICONFIG(a) ((configData.config >> (a * 2 + 9)) & 3)
#define BOOTCONFIG(a, b) ((configData.config >> a) & b) #define BOOTCONFIG(a, b) ((configData.config >> a) & b)
#define CONFIG_PATH "/luma/config.bin" #define CONFIG_PATH "luma/config.bin"
#define CONFIG_VERSIONMAJOR 1 #define CONFIG_VERSIONMAJOR 1
#define CONFIG_VERSIONMINOR 6 #define CONFIG_VERSIONMINOR 6
@ -78,6 +78,6 @@ typedef enum ConfigurationStatus
extern CfgData configData; extern CfgData configData;
extern bool isN3DS; extern bool isN3DS;
bool readConfig(bool isSdMounted); bool readConfig(void);
void writeConfig(ConfigurationStatus needConfig, u32 configTemp); void writeConfig(ConfigurationStatus needConfig, u32 configTemp);
void configMenu(bool oldPinStatus, u32 oldPinMode); void configMenu(Fs fsStatus, bool oldPinStatus, u32 oldPinMode);

View File

@ -347,6 +347,20 @@ int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
return result; return result;
} }
int ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf)
{
u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)];
memcpy(tmpCtr, nandCtr, sizeof(nandCtr));
aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
//Encrypt
aes_use_keyslot(nandSlot);
aes(inbuf, inbuf, sectorCount * 0x200 / AES_BLOCK_SIZE, tmpCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
//Write
return sdmmc_nand_writesectors(sector + fatStart, sectorCount, inbuf);
}
void set6x7xKeys(void) void set6x7xKeys(void)
{ {
const u8 __attribute__((aligned(4))) keyX0x25[AES_BLOCK_SIZE] = {0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3}; const u8 __attribute__((aligned(4))) keyX0x25[AES_BLOCK_SIZE] = {0xCE, 0xE7, 0xD8, 0xAB, 0x30, 0xC0, 0x0D, 0xAE, 0x85, 0x0E, 0xF5, 0xE3, 0x82, 0xAC, 0x5A, 0xF3};

View File

@ -107,6 +107,7 @@ extern FirmwareSource firmSource;
void ctrNandInit(void); void ctrNandInit(void);
int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
int ctrNandWrite(u32 sector, u32 sectorCount, u8 *inbuf);
void set6x7xKeys(void); void set6x7xKeys(void);
void decryptExeFs(u8 *inbuf); void decryptExeFs(u8 *inbuf);
void decryptNusFirm(const u8 *inbuf, u8 *outbuf, u32 ncchSize); void decryptNusFirm(const u8 *inbuf, u8 *outbuf, u32 ncchSize);

View File

@ -34,8 +34,8 @@
bool loadSplash(void) bool loadSplash(void)
{ {
const char topSplashPath[] = "/luma/splash.bin", const char topSplashPath[] = "luma/splash.bin",
bottomSplashPath[] = "/luma/splashbottom.bin"; bottomSplashPath[] = "luma/splashbottom.bin";
bool isTopSplashValid = getFileSize(topSplashPath) == SCREEN_TOP_FBSIZE, bool isTopSplashValid = getFileSize(topSplashPath) == SCREEN_TOP_FBSIZE,
isBottomSplashValid = getFileSize(bottomSplashPath) == SCREEN_BOTTOM_FBSIZE; isBottomSplashValid = getFileSize(bottomSplashPath) == SCREEN_BOTTOM_FBSIZE;

View File

@ -172,9 +172,9 @@ void detectAndProcessExceptionDumps(void)
} }
} }
char path[42]; char path[41];
char fileName[] = "crash_dump_00000000.dmp"; char fileName[] = "crash_dump_00000000.dmp";
const char *pathFolder = dumpHeader->processor == 9 ? "/luma/dumps/arm9" : "/luma/dumps/arm11"; const char *pathFolder = dumpHeader->processor == 9 ? "luma/dumps/arm9" : "luma/dumps/arm11";
findDumpFile(pathFolder, fileName); findDumpFile(pathFolder, fileName);
memcpy(path, pathFolder, strlen(pathFolder) + 1); memcpy(path, pathFolder, strlen(pathFolder) + 1);

View File

@ -87,7 +87,8 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
return (pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) ? RES_OK : RES_PARERR; return ((pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) ||
(pdrv == CTRNAND && !ctrNandWrite(sector, count, (BYTE *)buff))) ? RES_OK : RES_PARERR;
} }
#endif #endif

View File

@ -134,7 +134,7 @@
/ This option has no effect when _LFN_UNICODE == 0. */ / This option has no effect when _LFN_UNICODE == 0. */
#define _FS_RPATH 0 #define _FS_RPATH 1
/* This option configures support of relative path. /* This option configures support of relative path.
/ /
/ 0: Disable relative path and remove related functions. / 0: Disable relative path and remove related functions.

View File

@ -244,7 +244,6 @@ int __attribute__((noinline)) sdmmc_nand_readsectors(u32 sector_no, u32 numsecto
return geterror(&handleNAND); return geterror(&handleNAND);
} }
/*
int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in) //experimental
{ {
if(handleNAND.isSDHC == 0) sector_no <<= 9; if(handleNAND.isSDHC == 0) sector_no <<= 9;
@ -259,7 +258,6 @@ int __attribute__((noinline)) sdmmc_nand_writesectors(u32 sector_no, u32 numsect
inittarget(&handleSD); inittarget(&handleSD);
return geterror(&handleNAND); return geterror(&handleNAND);
} }
*/
static u32 calcSDSize(u8 *csd, int type) static u32 calcSDSize(u8 *csd, int type)
{ {

View File

@ -95,6 +95,6 @@ u32 sdmmc_sdcard_init();
int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out); int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, u8 *out);
int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in); int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out); int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, u8 *out);
//int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in); int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, const u8 *in);
void sdmmc_get_cid(bool isNand, u32 *info); void sdmmc_get_cid(bool isNand, u32 *info);
mmcdevice *getMMCDevice(int drive); mmcdevice *getMMCDevice(int drive);

View File

@ -64,11 +64,17 @@ void main(void)
//Detect dev units //Detect dev units
isDevUnit = CFG_UNITINFO != 0; isDevUnit = CFG_UNITINFO != 0;
//Mount SD //Mount SD or CTRNAND
bool isSdMounted = mountFs(true); Fs fsStatus;
if(mountFs(true)) fsStatus = SD_CARD;
else
{
firmSource = FIRMWARE_SYSNAND;
fsStatus = (mountFs(false) && switchToCtrNand()) ? CTRNAND : NONE;
}
//Attempt to read the configuration file //Attempt to read the configuration file
needConfig = readConfig(isSdMounted) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
u32 devMode = MULTICONFIG(DEVOPTIONS); u32 devMode = MULTICONFIG(DEVOPTIONS);
@ -94,6 +100,8 @@ void main(void)
//Determine if booting with A9LH //Determine if booting with A9LH
isA9lh = !PDN_SPI_CNT; isA9lh = !PDN_SPI_CNT;
if(fsStatus == NONE) error("Error mounting SD and CTRNAND.");
if(devMode != 0 && isA9lh) detectAndProcessExceptionDumps(); if(devMode != 0 && isA9lh) detectAndProcessExceptionDumps();
//Get pressed buttons //Get pressed buttons
@ -102,15 +110,8 @@ void main(void)
//Save old options and begin saving the new boot configuration //Save old options and begin saving the new boot configuration
configTemp = (configData.config & 0xFFFFFE00) | ((u32)isA9lh << 6); configTemp = (configData.config & 0xFFFFFE00) | ((u32)isA9lh << 6);
if(!isSdMounted)
{
nandType = FIRMWARE_SYSNAND;
firmSource = FIRMWARE_SYSNAND;
needConfig = DONT_CONFIGURE;
}
//If it's a MCU reboot, try to force boot options //If it's a MCU reboot, try to force boot options
else if(isA9lh && CFG_BOOTENV) if(isA9lh && CFG_BOOTENV)
{ {
//Always force a sysNAND boot when quitting AGB_FIRM //Always force a sysNAND boot when quitting AGB_FIRM
if(CFG_BOOTENV == 7) if(CFG_BOOTENV == 7)
@ -149,7 +150,7 @@ void main(void)
if(shouldLoadConfigMenu) if(shouldLoadConfigMenu)
{ {
configMenu(pinExists, pinMode); configMenu(fsStatus, pinExists, pinMode);
//Update pressed buttons //Update pressed buttons
pressed = HID_PAD; pressed = HID_PAD;
@ -189,12 +190,14 @@ void main(void)
if(splashMode == 2) loadSplash(); if(splashMode == 2) loadSplash();
//Determine if the user chose to use the SysNAND FIRM as default for a R boot if(fsStatus == CTRNAND) nandType = FIRMWARE_SYSNAND;
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one //If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
if(pressed & BUTTON_R1) else if(pressed & BUTTON_R1)
{ {
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
nandType = useSysAsDefault ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND; nandType = useSysAsDefault ? FIRMWARE_EMUNAND : FIRMWARE_SYSNAND;
firmSource = useSysAsDefault ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND; firmSource = useSysAsDefault ? FIRMWARE_SYSNAND : FIRMWARE_EMUNAND;
} }
@ -248,14 +251,14 @@ void main(void)
else if(firmSource != FIRMWARE_SYSNAND) else if(firmSource != FIRMWARE_SYSNAND)
locateEmuNand(&emuHeader, &firmSource); locateEmuNand(&emuHeader, &firmSource);
if(isSdMounted && !isFirmlaunch) if(!isFirmlaunch)
{ {
configTemp |= (u32)nandType | ((u32)firmSource << 3); configTemp |= (u32)nandType | ((u32)firmSource << 3);
writeConfig(needConfig, configTemp); writeConfig(needConfig, configTemp);
} }
bool loadFromSd = CONFIG(LOADSDFIRMSANDMODULES); bool loadFromSd = CONFIG(LOADSDFIRMSANDMODULES);
u32 firmVersion = loadFirm(&firmType, firmSource, loadFromSd, isSdMounted); u32 firmVersion = loadFirm(&firmType, firmSource, loadFromSd, fsStatus);
switch(firmType) switch(firmType)
{ {
@ -274,24 +277,24 @@ void main(void)
launchFirm(firmType, loadFromSd); launchFirm(firmType, loadFromSd);
} }
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd, bool isSdMounted) static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd, Fs fsStatus)
{ {
section = firm->section; section = firm->section;
const char *firmwareFiles[] = { const char *firmwareFiles[] = {
"/luma/firmware.bin", "luma/firmware.bin",
"/luma/firmware_twl.bin", "luma/firmware_twl.bin",
"/luma/firmware_agb.bin", "luma/firmware_agb.bin",
"/luma/firmware_safe.bin" "luma/firmware_safe.bin"
}, },
*cetkFiles[] = { *cetkFiles[] = {
"/luma/cetk", "luma/cetk",
"/luma/cetk_twl", "luma/cetk_twl",
"/luma/cetk_agb", "luma/cetk_agb",
"/luma/cetk_safe" "luma/cetk_safe"
}; };
if(!mountFs(false)) error("Error mounting CTRNAND."); if(fsStatus == SD_CARD && !mountFs(false)) error("Error mounting CTRNAND.");
//Load FIRM from CTRNAND //Load FIRM from CTRNAND
u32 firmVersion = firmRead(firm, (u32)*firmType); u32 firmVersion = firmRead(firm, (u32)*firmType);
@ -308,7 +311,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
if(firmSource != FIRMWARE_SYSNAND) if(firmSource != FIRMWARE_SYSNAND)
error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it."); error("An old unsupported EmuNAND has been detected.\nLuma3DS is unable to boot it.");
if(HID_PAD == SAFE_MODE) error("SAFE_MODE is not supported on 1.x/2.x FIRM."); if(BOOTCFG_SAFEMODE != 0) error("SAFE_MODE is not supported on 1.x/2.x FIRM.");
*firmType = NATIVE_FIRM1X2X; *firmType = NATIVE_FIRM1X2X;
} }
@ -317,7 +320,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
else if(firmVersion < 0x25) mustLoadFromSd = true; else if(firmVersion < 0x25) mustLoadFromSd = true;
} }
if(isSdMounted && (loadFromSd || mustLoadFromSd)) if(loadFromSd || mustLoadFromSd)
{ {
u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000); u32 firmSize = fileRead(firm, *firmType == NATIVE_FIRM1X2X ? firmwareFiles[0] : firmwareFiles[(u32)*firmType], 0x400000);
@ -329,12 +332,12 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk)) == sizeof(cetk)) if(fileRead(cetk, *firmType == NATIVE_FIRM1X2X ? cetkFiles[0] : cetkFiles[(u32)*firmType], sizeof(cetk)) == sizeof(cetk))
decryptNusFirm(cetk, (u8 *)firm, firmSize); decryptNusFirm(cetk, (u8 *)firm, firmSize);
else error("The firmware.bin in /luma is encrypted\nor corrupted."); else error("The firmware.bin in luma is encrypted\nor corrupted.");
} }
//Check that the SD FIRM is right for the console from the ARM9 section address //Check that the SD FIRM is right for the console from the ARM9 section address
if((section[3].offset ? section[3].address : section[2].address) != (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800)) if((section[3].offset ? section[3].address : section[2].address) != (isN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
error("The firmware.bin in /luma is not valid for this\nconsole."); error("The firmware.bin in luma is not valid for this\nconsole.");
firmVersion = 0xFFFFFFFF; firmVersion = 0xFFFFFFFF;
} }
@ -342,7 +345,7 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
if(firmVersion != 0xFFFFFFFF) if(firmVersion != 0xFFFFFFFF)
{ {
if(mustLoadFromSd) error("An old unsupported FIRM has been detected.\nCopy a firmware.bin in /luma to boot."); if(mustLoadFromSd) error("An old unsupported FIRM has been detected.\nCopy a firmware.bin in luma to boot.");
decryptExeFs((u8 *)firm); decryptExeFs((u8 *)firm);
} }
@ -485,7 +488,7 @@ static inline void copySection0AndInjectSystemModules(FirmwareType firmType, boo
if(loadFromSd) if(loadFromSd)
{ {
char fileName[30] = "/luma/sysmodules/"; char fileName[30] = "luma/sysmodules/";
const char *ext = ".cxi"; const char *ext = ".cxi";
//Read modules from files if they exist //Read modules from files if they exist

View File

@ -47,7 +47,7 @@ typedef struct firmHeader {
firmSectionHeader section[4]; firmSectionHeader section[4];
} firmHeader; } firmHeader;
static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd, bool isSdMounted); static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bool loadFromSd, Fs fsStatus);
static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, u32 devMode); static inline void patchNativeFirm(u32 firmVersion, FirmwareSource nandType, u32 emuHeader, u32 devMode);
static inline void patchLegacyFirm(FirmwareType firmType, u32 firmVersion, u32 devMode); static inline void patchLegacyFirm(FirmwareType firmType, u32 firmVersion, u32 devMode);
static inline void patch1x2xNativeAndSafeFirm(u32 devMode); static inline void patch1x2xNativeAndSafeFirm(u32 devMode);

View File

@ -38,6 +38,11 @@ bool mountFs(bool isSd)
return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK : f_mount(&nandFs, "1:", 1) == FR_OK; return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK : f_mount(&nandFs, "1:", 1) == FR_OK;
} }
bool switchToCtrNand(void)
{
return f_chdrive("1:") == FR_OK && f_chdir("/rw") == FR_OK;
}
u32 fileRead(void *dest, const char *path, u32 maxSize) u32 fileRead(void *dest, const char *path, u32 maxSize)
{ {
FIL file; FIL file;
@ -84,11 +89,10 @@ bool fileWrite(const void *buffer, const char *path, u32 size)
char folder[i + 1]; char folder[i + 1];
memcpy(folder, path, i); memcpy(folder, path, i);
folder[i] = 0; folder[i] = 0;
ret = f_mkdir(folder) == FR_OK; f_mkdir(folder);
if(!ret) break;
} }
if(ret) ret = fileWrite(buffer, path, size); ret = fileWrite(buffer, path, size);
} }
else ret = false; else ret = false;
@ -118,7 +122,7 @@ void loadPayload(u32 pressed)
DIR dir; DIR dir;
FILINFO info; FILINFO info;
char path[28] = "/luma/payloads"; char path[27] = "luma/payloads";
FRESULT result = f_findfirst(&dir, &info, path, pattern); FRESULT result = f_findfirst(&dir, &info, path, pattern);

View File

@ -29,6 +29,7 @@
extern bool isN3DS, isA9lh; extern bool isN3DS, isA9lh;
bool mountFs(bool isSd); bool mountFs(bool isSd);
bool switchToCtrNand(void);
u32 fileRead(void *dest, const char *path, u32 maxSize); u32 fileRead(void *dest, const char *path, u32 maxSize);
u32 getFileSize(const char *path); u32 getFileSize(const char *path);
bool fileWrite(const void *buffer, const char *path, u32 size); bool fileWrite(const void *buffer, const char *path, u32 size);

View File

@ -93,7 +93,7 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
if(CONFIG(USECUSTOMPATH)) if(CONFIG(USECUSTOMPATH))
{ {
const char pathPath[] = "/luma/path.txt"; const char pathPath[] = "luma/path.txt";
u32 pathSize = getFileSize(pathPath); u32 pathSize = getFileSize(pathPath);

View File

@ -132,7 +132,7 @@ bool verifyPin(u32 pinMode)
u8 cnt = 0; u8 cnt = 0;
u32 charDrawPos = 16 * SPACING_X; u32 charDrawPos = 16 * SPACING_X;
const char messagePath[] = "/luma/pinmessage.txt"; const char messagePath[] = "luma/pinmessage.txt";
u32 messageSize = getFileSize(messagePath); u32 messageSize = getFileSize(messagePath);

View File

@ -28,7 +28,7 @@
#include "types.h" #include "types.h"
#define PIN_PATH "/luma/pin.bin" #define PIN_PATH "luma/pin.bin"
#define PIN_VERSIONMAJOR 1 #define PIN_VERSIONMAJOR 1
#define PIN_VERSIONMINOR 3 #define PIN_VERSIONMINOR 3

View File

@ -55,4 +55,11 @@ typedef enum FirmwareType
AGB_FIRM, AGB_FIRM,
SAFE_FIRM, SAFE_FIRM,
NATIVE_FIRM1X2X NATIVE_FIRM1X2X
} FirmwareType; } FirmwareType;
typedef enum Fs
{
SD_CARD = 0,
CTRNAND,
NONE
} Fs;