Revamp CTRNAND support, add proper support for hiding options in config menu
This commit is contained in:
parent
f005da4d12
commit
37030621ac
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
@ -245,12 +256,15 @@ 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++)
|
||||||
|
{
|
||||||
|
if(singleOptions[i].visible)
|
||||||
{
|
{
|
||||||
singleOptions[i].posY = endPos + SPACING_Y;
|
singleOptions[i].posY = endPos + SPACING_Y;
|
||||||
endPos = drawString(singleOptionsText[i], true, 10, singleOptions[i].posY, color);
|
endPos = drawString(singleOptionsText[i], true, 10, singleOptions[i].posY, color);
|
||||||
if(singleOptions[i].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[i].posY, color);
|
if(singleOptions[i].enabled) drawCharacter(selected, true, 10 + SPACING_X, singleOptions[i].posY, color);
|
||||||
color = COLOR_WHITE;
|
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;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
switch(pressed)
|
switch(pressed)
|
||||||
{
|
{
|
||||||
case BUTTON_UP:
|
case BUTTON_UP:
|
||||||
if(!selectedOption) selectedOption = totalIndexes;
|
selectedOption = !selectedOption ? totalIndexes : selectedOption - 1;
|
||||||
else selectedOption = (selectedOption == NEWCPU + 1 && !isN3DS) ? selectedOption - 2 : selectedOption - 1;
|
|
||||||
break;
|
break;
|
||||||
case BUTTON_DOWN:
|
case BUTTON_DOWN:
|
||||||
if(selectedOption == totalIndexes) selectedOption = 0;
|
selectedOption = selectedOption == totalIndexes ? 0 : selectedOption + 1;
|
||||||
else selectedOption = (selectedOption == NEWCPU - 1 && !isN3DS) ? selectedOption + 2 : selectedOption + 1;
|
|
||||||
break;
|
break;
|
||||||
case BUTTON_LEFT:
|
case BUTTON_LEFT:
|
||||||
|
pressed = BUTTON_DOWN;
|
||||||
selectedOption = 0;
|
selectedOption = 0;
|
||||||
break;
|
break;
|
||||||
case BUTTON_RIGHT:
|
case BUTTON_RIGHT:
|
||||||
|
pressed = BUTTON_UP;
|
||||||
selectedOption = totalIndexes;
|
selectedOption = totalIndexes;
|
||||||
break;
|
break;
|
||||||
default:
|
}
|
||||||
continue;
|
|
||||||
|
if(selectedOption < multiOptionsAmount)
|
||||||
|
{
|
||||||
|
if(multiOptions[selectedOption].visible) break;
|
||||||
|
}
|
||||||
|
else if(singleOptions[selectedOption - multiOptionsAmount].visible) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(selectedOption == oldSelectedOption) continue;
|
if(selectedOption == oldSelectedOption) continue;
|
||||||
|
@ -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);
|
@ -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};
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
{
|
{
|
||||||
|
@ -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);
|
@ -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();
|
||||||
|
|
||||||
|
if(fsStatus == CTRNAND) nandType = FIRMWARE_SYSNAND;
|
||||||
|
|
||||||
|
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
||||||
|
else if(pressed & BUTTON_R1)
|
||||||
|
{
|
||||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||||
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
|
bool useSysAsDefault = isA9lh ? CONFIG(USESYSFIRM) : false;
|
||||||
|
|
||||||
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
|
||||||
if(pressed & BUTTON_R1)
|
|
||||||
{
|
|
||||||
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
|
||||||
|
@ -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);
|
||||||
|
12
source/fs.c
12
source/fs.c
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -56,3 +56,10 @@ typedef enum FirmwareType
|
|||||||
SAFE_FIRM,
|
SAFE_FIRM,
|
||||||
NATIVE_FIRM1X2X
|
NATIVE_FIRM1X2X
|
||||||
} FirmwareType;
|
} FirmwareType;
|
||||||
|
|
||||||
|
typedef enum Fs
|
||||||
|
{
|
||||||
|
SD_CARD = 0,
|
||||||
|
CTRNAND,
|
||||||
|
NONE
|
||||||
|
} Fs;
|
Reference in New Issue
Block a user