Add safety checks, support booting from CTRNAND

This commit is contained in:
Aurora 2016-10-07 14:27:30 +02:00
parent bd6c7b7fdb
commit 0caf9f4214
20 changed files with 142 additions and 141 deletions

View File

@ -18,7 +18,7 @@ dir_build := build
dir_out := ../../$(dir_build) dir_out := ../../$(dir_build)
ASFLAGS := -mcpu=mpcore -mfpu=vfp ASFLAGS := -mcpu=mpcore -mfpu=vfp
CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -Os -flto -ffast-math CFLAGS := -Wall -Wextra -MMD -MP -mthumb -mthumb-interwork $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
LDFLAGS := -nostdlib LDFLAGS := -nostdlib
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \

View File

@ -47,7 +47,7 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
u32 registerDump[REG_DUMP_SIZE / 4]; u32 registerDump[REG_DUMP_SIZE / 4];
u8 codeDump[CODE_DUMP_SIZE]; u8 codeDump[CODE_DUMP_SIZE];
u8 *const finalBuffer = cannotAccessVA((const void *)0xE5000000) ? (u8 *)0xF5000000 : (u8 *)0xE5000000; //VA for 0x25000000 u8 *finalBuffer = cannotAccessVA((void *)0xE5000000) ? (u8 *)0xF5000000 : (u8 *)0xE5000000; //VA for 0x25000000
u8 *final = finalBuffer; u8 *final = finalBuffer;
while(*(vu32 *)final == 0xDEADC0DE && *((vu32 *)final + 1) == 0xDEADCAFE); while(*(vu32 *)final == 0xDEADC0DE && *((vu32 *)final + 1) == 0xDEADCAFE);
@ -88,7 +88,7 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1); dumpHeader.stackDumpSize = copyMemory(final, (const void *)registerDump[13], 0x1000 - (registerDump[13] & 0xFFF), 1);
final += dumpHeader.stackDumpSize; final += dumpHeader.stackDumpSize;
if(!cannotAccessVA((u8 *)0xFFFF9004)) if(!cannotAccessVA((void *)0xFFFF9004))
{ {
vu64 *additionalData = (vu64 *)final; vu64 *additionalData = (vu64 *)final;
dumpHeader.additionalDataSize = 16; dumpHeader.additionalDataSize = 16;
@ -106,4 +106,4 @@ void __attribute__((noreturn)) mainHandler(u32 *regs, u32 type, u32 cpuId)
cleanInvalidateDCacheAndDMB(); cleanInvalidateDCacheAndDMB();
mcuReboot(); //Also contains DCache-cleaning code mcuReboot(); //Also contains DCache-cleaning code
} }

View File

@ -33,9 +33,7 @@ DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */ BYTE pdrv /* Physical drive nmuber to identify the drive */
) )
{ {
sdmmc_sdcard_init(); return sdmmc_sdcard_init() ? RES_OK : RES_PARERR;
return RES_OK;
} }

View File

@ -274,17 +274,17 @@ static u32 calcSDSize(u8 *csd, int type)
switch(type) switch(type)
{ {
case 0: case 0:
{ {
u32 block_len = csd[9] & 0xF; u32 block_len = csd[9] & 0xF;
block_len = 1u << block_len; block_len = 1u << block_len;
u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1)); u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1));
mult = 1u << (mult + 2); mult = 1u << (mult + 2);
result = csd[8] & 3; result = csd[8] & 3;
result = (result << 8) | csd[7]; result = (result << 8) | csd[7];
result = (result << 2) | (csd[6] >> 6); result = (result << 2) | (csd[6] >> 6);
result = (result + 1) * mult * block_len / 512; result = (result + 1) * mult * block_len / 512;
}
break; break;
}
case 1: case 1:
result = csd[7] & 0x3F; result = csd[7] & 0x3F;
result = (result << 8) | csd[6]; result = (result << 8) | csd[6];
@ -482,9 +482,9 @@ void sdmmc_get_cid(bool isNand, u32 *info)
} }
*/ */
void sdmmc_sdcard_init() bool sdmmc_sdcard_init()
{ {
InitSD(); InitSD();
//Nand_Init(); //Nand_Init();
SD_Init(); return SD_Init() == 0;
} }

View File

@ -91,7 +91,7 @@ typedef struct mmcdevice {
u32 res; u32 res;
} mmcdevice; } mmcdevice;
void sdmmc_sdcard_init(); bool 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);

View File

@ -25,13 +25,18 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
cmp r0, r2 cmp r0, r2
bne pxi_wait_recv bne pxi_wait_recv
; Open file adr r1, sd_fname
add r0, r7, #8
adr r1, fname open_payload:
mov r2, #1 ; Open file
ldr r6, [fopen] add r0, r7, #8
orr r6, 1 mov r2, #1
blx r6 ldr r6, [fopen]
orr r6, 1
blx r6
cmp r0, #0
adrne r1, nand_fname
bne open_payload
; Read file ; Read file
mov r0, r7 mov r0, r7
@ -71,8 +76,11 @@ payload_maxsize equ 0x100000 ; Maximum size for the payload (maximum that CakeB
bytes_read: .word 0 bytes_read: .word 0
fopen: .ascii "OPEN" fopen: .ascii "OPEN"
.pool .pool
fname: .dcw "sdmc:/arm9loaderhax.bin" sd_fname: .dcw "sdmc:/arm9loaderhax.bin"
.word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
.pool
nand_fname: .dcw "nand:/arm9loaderhax.bin"
.word 0
.align 4 .align 4
kernelcode_start: kernelcode_start:

View File

@ -29,18 +29,22 @@
#include "buttons.h" #include "buttons.h"
#include "pin.h" #include "pin.h"
bool readConfig(void) bool readConfig(bool isSdMounted)
{ {
if(fileRead(&configData, CONFIG_PATH, sizeof(CfgData)) != sizeof(CfgData) || bool ret;
if(!isSdMounted ||
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;
return false; ret = !isSdMounted;
} }
else ret = true;
return true; return ret;
} }
void writeConfig(ConfigurationStatus needConfig, u32 configTemp) void writeConfig(ConfigurationStatus needConfig, u32 configTemp)

View File

@ -78,6 +78,6 @@ typedef enum ConfigurationStatus
extern CfgData configData; extern CfgData configData;
extern bool isN3DS; extern bool isN3DS;
bool readConfig(void); bool readConfig(bool isSdMounted);
void writeConfig(ConfigurationStatus needConfig, u32 configTemp); void writeConfig(ConfigurationStatus needConfig, u32 configTemp);
void configMenu(bool oldPinStatus, u32 oldPinMode); void configMenu(bool oldPinStatus, u32 oldPinMode);

View File

@ -82,7 +82,7 @@ __asm__\
static void aes_setkey(u8 keyslot, const void *key, u32 keyType, u32 mode) static void aes_setkey(u8 keyslot, const void *key, u32 keyType, u32 mode)
{ {
if(keyslot <= 0x03) return; // Ignore TWL keys for now if(keyslot <= 0x03) return; //Ignore TWL keys for now
u32 *key32 = (u32 *)key; u32 *key32 = (u32 *)key;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE; *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | AES_KEYCNT_WRITE;
@ -107,7 +107,7 @@ static void aes_setiv(const void *iv, u32 mode)
const u32 *iv32 = (const u32 *)iv; const u32 *iv32 = (const u32 *)iv;
*REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode; *REG_AESCNT = (*REG_AESCNT & ~(AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER)) | mode;
// Word order for IV can't be changed in REG_AESCNT and always default to reversed //Word order for IV can't be changed in REG_AESCNT and always default to reversed
if(mode & AES_INPUT_NORMAL) if(mode & AES_INPUT_NORMAL)
{ {
REG_AESCTR[0] = iv32[3]; REG_AESCTR[0] = iv32[3];
@ -131,7 +131,7 @@ static void aes_advctr(void *ctr, u32 val, u32 mode)
int i; int i;
if(mode & AES_INPUT_BE) if(mode & AES_INPUT_BE)
{ {
for(i = 0; i < 4; ++i) // Endian swap for(i = 0; i < 4; ++i) //Endian swap
BSWAP32(ctr32[i]); BSWAP32(ctr32[i]);
} }
@ -146,7 +146,7 @@ static void aes_advctr(void *ctr, u32 val, u32 mode)
if(mode & AES_INPUT_BE) if(mode & AES_INPUT_BE)
{ {
for(i = 0; i < 4; ++i) // Endian swap for(i = 0; i < 4; ++i) //Endian swap
BSWAP32(ctr32[i]); BSWAP32(ctr32[i]);
} }
} }
@ -186,7 +186,7 @@ static void aes_batch(void *dst, const void *src, u32 blockCount)
while(rbc) while(rbc)
{ {
if(wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) // There's space for at least 4 ints if(wbc && ((*REG_AESCNT & 0x1F) <= 0xC)) //There's space for at least 4 ints
{ {
*REG_AESWRFIFO = *src32++; *REG_AESWRFIFO = *src32++;
*REG_AESWRFIFO = *src32++; *REG_AESWRFIFO = *src32++;
@ -195,7 +195,7 @@ static void aes_batch(void *dst, const void *src, u32 blockCount)
wbc--; wbc--;
} }
if(rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) // At least 4 ints available for read if(rbc && ((*REG_AESCNT & (0x1F << 0x5)) >= (0x4 << 0x5))) //At least 4 ints available for read
{ {
*dst32++ = *REG_AESRDFIFO; *dst32++ = *REG_AESRDFIFO;
*dst32++ = *REG_AESRDFIFO; *dst32++ = *REG_AESRDFIFO;
@ -222,24 +222,24 @@ static void aes(void *dst, const void *src, u32 blockCount, void *iv, u32 mode,
blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount; blocks = (blockCount >= 0xFFFF) ? 0xFFFF : blockCount;
// Save the last block for the next decryption CBC batch's iv //Save the last block for the next decryption CBC batch's iv
if((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE) if((mode & AES_ALL_MODES) == AES_CBC_DECRYPT_MODE)
{ {
memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); memcpy(iv, src + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
} }
// Process the current batch //Process the current batch
aes_batch(dst, src, blocks); aes_batch(dst, src, blocks);
// Save the last block for the next encryption CBC batch's iv //Save the last block for the next encryption CBC batch's iv
if((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE) if((mode & AES_ALL_MODES) == AES_CBC_ENCRYPT_MODE)
{ {
memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE); memcpy(iv, dst + (blocks - 1) * AES_BLOCK_SIZE, AES_BLOCK_SIZE);
aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode); aes_change_ctrmode(iv, AES_INPUT_BE | AES_INPUT_NORMAL, ivMode);
} }
// Advance counter for CTR mode //Advance counter for CTR mode
else if((mode & AES_ALL_MODES) == AES_CTR_MODE) else if((mode & AES_ALL_MODES) == AES_CTR_MODE)
aes_advctr(iv, blocks, ivMode); aes_advctr(iv, blocks, ivMode);
@ -324,14 +324,14 @@ void ctrNandInit(void)
} }
} }
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf) int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf)
{ {
u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)]; u8 __attribute__((aligned(4))) tmpCtr[sizeof(nandCtr)];
memcpy(tmpCtr, nandCtr, sizeof(nandCtr)); memcpy(tmpCtr, nandCtr, sizeof(nandCtr));
aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL); aes_advctr(tmpCtr, ((sector + fatStart) * 0x200) / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
//Read //Read
u32 result; int result;
if(firmSource == FIRMWARE_SYSNAND) if(firmSource == FIRMWARE_SYSNAND)
result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf); result = sdmmc_nand_readsectors(sector + fatStart, sectorCount, outbuf);
else else

View File

@ -106,7 +106,7 @@ extern bool isN3DS, isDevUnit, isA9lh;
extern FirmwareSource firmSource; extern FirmwareSource firmSource;
void ctrNandInit(void); void ctrNandInit(void);
u32 ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf); int ctrNandRead(u32 sector, u32 sectorCount, u8 *outbuf);
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

@ -47,8 +47,8 @@ bool loadSplash(void)
initScreens(); initScreens();
clearScreens(true, true, true); clearScreens(true, true, true);
if(isTopSplashValid) fileRead(fbs[1].top_left, topSplashPath, 0); if(isTopSplashValid) fileRead(fbs[1].top_left, topSplashPath, SCREEN_TOP_FBSIZE);
if(isBottomSplashValid) fileRead(fbs[1].bottom, bottomSplashPath, 0); if(isBottomSplashValid) fileRead(fbs[1].bottom, bottomSplashPath, SCREEN_BOTTOM_FBSIZE);
swapFramebuffers(true); swapFramebuffers(true);

View File

@ -37,17 +37,18 @@ DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */ BYTE pdrv /* Physical drive nmuber to identify the drive */
) )
{ {
switch(pdrv) DRESULT ret = RES_OK;
static bool sdmmcInited = false;
if(!sdmmcInited)
{ {
case SDCARD: if(!sdmmc_sdcard_init()) ret = RES_PARERR;
sdmmc_sdcard_init(); else sdmmcInited = true;
break;
case CTRNAND:
ctrNandInit();
break;
} }
return RES_OK; if(pdrv == CTRNAND) ctrNandInit();
return ret;
} }
@ -63,19 +64,8 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
switch(pdrv) return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff)) ||
{ (pdrv == CTRNAND && !ctrNandRead(sector, count, (BYTE *)buff))) ? RES_OK : RES_PARERR;
case SDCARD:
if(sdmmc_sdcard_readsectors(sector, count, (BYTE *)buff))
return RES_PARERR;
break;
case CTRNAND:
if(ctrNandRead(sector, count, (BYTE *)buff))
return RES_PARERR;
break;
}
return RES_OK;
} }
@ -92,10 +82,7 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
if(pdrv == SDCARD && sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) return (pdrv == SDCARD && !sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) ? RES_OK : RES_PARERR;
return RES_PARERR;
return RES_OK;
} }
#endif #endif

View File

@ -268,17 +268,17 @@ static u32 calcSDSize(u8 *csd, int type)
switch(type) switch(type)
{ {
case 0: case 0:
{ {
u32 block_len = csd[9] & 0xF; u32 block_len = csd[9] & 0xF;
block_len = 1u << block_len; block_len = 1u << block_len;
u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1)); u32 mult = (u32)((csd[4] >> 7) | ((csd[5] & 3) << 1));
mult = 1u << (mult + 2); mult = 1u << (mult + 2);
result = csd[8] & 3; result = csd[8] & 3;
result = (result << 8) | csd[7]; result = (result << 8) | csd[7];
result = (result << 2) | (csd[6] >> 6); result = (result << 2) | (csd[6] >> 6);
result = (result + 1) * mult * block_len / 512; result = (result + 1) * mult * block_len / 512;
}
break; break;
}
case 1: case 1:
result = csd[7] & 0x3F; result = csd[7] & 0x3F;
result = (result << 8) | csd[6]; result = (result << 8) | csd[6];
@ -472,9 +472,8 @@ void sdmmc_get_cid(bool isNand, u32 *info)
sdmmc_send_command(device, 0x10507, device->initarg << 0x10); sdmmc_send_command(device, 0x10507, device->initarg << 0x10);
} }
void sdmmc_sdcard_init() bool sdmmc_sdcard_init()
{ {
InitSD(); InitSD();
Nand_Init(); return (Nand_Init() | SD_Init()) == 0;
SD_Init();
} }

View File

@ -91,7 +91,7 @@ typedef struct mmcdevice {
u32 res; u32 res;
} mmcdevice; } mmcdevice;
void sdmmc_sdcard_init(); bool 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);

View File

@ -64,11 +64,11 @@ void main(void)
//Detect dev units //Detect dev units
isDevUnit = CFG_UNITINFO != 0; isDevUnit = CFG_UNITINFO != 0;
//Mount filesystems. CTRNAND will be mounted only if/when needed //Mount SD
mountFs(); bool isSdMounted = mountFs(true);
//Attempt to read the configuration file //Attempt to read the configuration file
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; needConfig = readConfig(isSdMounted) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
u32 devMode = MULTICONFIG(DEVOPTIONS); u32 devMode = MULTICONFIG(DEVOPTIONS);
@ -102,8 +102,15 @@ 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
if(isA9lh && CFG_BOOTENV) else 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)
@ -241,7 +248,7 @@ void main(void)
else if(firmSource != FIRMWARE_SYSNAND) else if(firmSource != FIRMWARE_SYSNAND)
locateEmuNand(&emuHeader, &firmSource); locateEmuNand(&emuHeader, &firmSource);
if(!isFirmlaunch) if(isSdMounted && !isFirmlaunch)
{ {
configTemp |= (u32)nandType | ((u32)firmSource << 3); configTemp |= (u32)nandType | ((u32)firmSource << 3);
writeConfig(needConfig, configTemp); writeConfig(needConfig, configTemp);
@ -284,9 +291,13 @@ static inline u32 loadFirm(FirmwareType *firmType, FirmwareSource firmSource, bo
"/luma/cetk_safe" "/luma/cetk_safe"
}; };
if(!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);
if(firmVersion == 0xFFFFFFFF) error("Error getting the CTRNAND FIRM.");
bool mustLoadFromSd = false; bool mustLoadFromSd = false;
if(!isN3DS && *firmType == NATIVE_FIRM) if(!isN3DS && *firmType == NATIVE_FIRM)

View File

@ -33,10 +33,9 @@
static FATFS sdFs, static FATFS sdFs,
nandFs; nandFs;
void mountFs(void) bool mountFs(bool isSd)
{ {
f_mount(&sdFs, "0:", 1); return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK : f_mount(&nandFs, "1:", 1) == FR_OK;
f_mount(&nandFs, "1:", 0);
} }
u32 fileRead(void *dest, const char *path, u32 maxSize) u32 fileRead(void *dest, const char *path, u32 maxSize)
@ -48,7 +47,7 @@ u32 fileRead(void *dest, const char *path, u32 maxSize)
{ {
u32 size = f_size(&file); u32 size = f_size(&file);
if(dest == NULL) ret = size; if(dest == NULL) ret = size;
else if(!(maxSize > 0 && size > maxSize)) else if(size <= maxSize)
f_read(&file, dest, size, (unsigned int *)&ret); f_read(&file, dest, size, (unsigned int *)&ret);
f_close(&file); f_close(&file);
} }
@ -64,6 +63,7 @@ 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)
{ {
FIL file; FIL file;
bool ret;
FRESULT result = f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS); FRESULT result = f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS);
@ -74,10 +74,9 @@ bool fileWrite(const void *buffer, const char *path, u32 size)
f_truncate(&file); f_truncate(&file);
f_close(&file); f_close(&file);
return true; ret = (u32)written == size;
} }
else if(result == FR_NO_PATH)
if(result == FR_NO_PATH)
{ {
for(u32 i = 1; path[i] != 0; i++) for(u32 i = 1; path[i] != 0; i++)
if(path[i] == '/') if(path[i] == '/')
@ -85,13 +84,15 @@ 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;
f_mkdir(folder); ret = f_mkdir(folder) == FR_OK;
if(!ret) break;
} }
return fileWrite(buffer, path, size); if(ret) ret = fileWrite(buffer, path, size);
} }
else ret = false;
return false; return ret;
} }
void fileDelete(const char *path) void fileDelete(const char *path)
@ -163,39 +164,42 @@ u32 firmRead(void *dest, u32 firmType)
DIR dir; DIR dir;
FILINFO info; FILINFO info;
f_opendir(&dir, path);
u32 firmVersion = 0xFFFFFFFF; u32 firmVersion = 0xFFFFFFFF;
//Parse the target directory if(f_opendir(&dir, path) == FR_OK)
while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0)
{ {
//Not a cxi //Parse the target directory
if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue; while(f_readdir(&dir, &info) == FR_OK && info.fname[0] != 0)
//Convert the .app name to an integer
u32 tempVersion = 0;
for(char *tmp = info.altname; *tmp != '.'; tmp++)
{ {
tempVersion <<= 4; //Not a cxi
tempVersion += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0'; if(info.fname[9] != 'a' || strlen(info.fname) != 12) continue;
//Convert the .app name to an integer
u32 tempVersion = 0;
for(char *tmp = info.altname; *tmp != '.'; tmp++)
{
tempVersion <<= 4;
tempVersion += *tmp > '9' ? *tmp - 'A' + 10 : *tmp - '0';
}
//Found an older cxi
if(tempVersion < firmVersion) firmVersion = tempVersion;
} }
//Found an older cxi f_closedir(&dir);
if(tempVersion < firmVersion) firmVersion = tempVersion;
if(firmVersion != 0xFFFFFFFF)
{
//Complete the string with the .app name
concatenateStrings(path, "/00000000.app");
//Convert back the .app name from integer to array
hexItoa(firmVersion, &path[35], 8);
if(!fileRead(dest, path, 0x400200)) firmVersion = 0xFFFFFFFF;
}
} }
f_closedir(&dir);
//Complete the string with the .app name
concatenateStrings(path, "/00000000.app");
//Convert back the .app name from integer to array
hexItoa(firmVersion, &path[35], 8);
fileRead(dest, path, 0);
return firmVersion; return firmVersion;
} }

View File

@ -28,7 +28,7 @@
extern bool isN3DS, isA9lh; extern bool isN3DS, isA9lh;
void mountFs(void); bool mountFs(bool isSd);
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

@ -100,7 +100,7 @@ void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
if(pathSize > 5 && pathSize < 58) if(pathSize > 5 && pathSize < 58)
{ {
u8 path[pathSize]; u8 path[pathSize];
fileRead(path, pathPath, 0); fileRead(path, pathPath, pathSize);
if(path[pathSize - 1] == 0xA) pathSize--; if(path[pathSize - 1] == 0xA) pathSize--;
if(path[pathSize - 1] == 0xD) pathSize--; if(path[pathSize - 1] == 0xD) pathSize--;

View File

@ -139,7 +139,7 @@ bool verifyPin(u32 pinMode)
if(messageSize > 0 && messageSize <= 800) if(messageSize > 0 && messageSize <= 800)
{ {
char message[messageSize + 1]; char message[messageSize + 1];
fileRead(message, messagePath, 0); fileRead(message, messagePath, messageSize);
message[messageSize] = 0; message[messageSize] = 0;
drawString(message, false, 10, 10, COLOR_WHITE); drawString(message, false, 10, 10, COLOR_WHITE);
} }

View File

@ -41,7 +41,7 @@
#include "cache.h" #include "cache.h"
#include "i2c.h" #include "i2c.h"
vu32 *const arm11Entry = (vu32 *)BRAHMA_ARM11_ENTRY; vu32 *arm11Entry = (vu32 *)BRAHMA_ARM11_ENTRY;
static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26}; static const u32 brightness[4] = {0x5F, 0x4C, 0x39, 0x26};
void __attribute__((naked)) arm11Stub(void) void __attribute__((naked)) arm11Stub(void)
@ -167,16 +167,6 @@ void clearScreens(bool clearTop, bool clearBottom, bool clearAlternate)
while(!((!clearTopTmp || (REGs_PSC0[3] & 2)) && (!clearBottomTmp || (REGs_PSC1[3] & 2)))); while(!((!clearTopTmp || (REGs_PSC0[3] & 2)) && (!clearBottomTmp || (REGs_PSC1[3] & 2))));
if(fbTmp->top_right != fbTmp->top_left && clearTopTmp)
{
REGs_PSC0[0] = (u32)fbTmp->top_right >> 3; //Start address
REGs_PSC0[1] = (u32)(fbTmp->top_right + SCREEN_TOP_FBSIZE) >> 3; //End address
REGs_PSC0[2] = 0; //Fill value
REGs_PSC0[3] = (2 << 8) | 1; //32-bit pattern; start
while(!(REGs_PSC0[3] & 2));
}
WAIT_FOR_ARM9(); WAIT_FOR_ARM9();
} }