Add code to backup essential files
This commit is contained in:
parent
bc6e14ada7
commit
fcdb6a7ab5
111
arm9/source/fs.c
111
arm9/source/fs.c
@ -37,6 +37,8 @@
|
|||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
|
#include "alignedseqmemcpy.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
|
||||||
static FATFS sdFs,
|
static FATFS sdFs,
|
||||||
nandFs;
|
nandFs;
|
||||||
@ -121,6 +123,79 @@ bool fileDelete(const char *path)
|
|||||||
return f_unlink(path) == FR_OK;
|
return f_unlink(path) == FR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fileCopy(const char *pathSrc, const char *pathDst, bool replace, void *tmpBuffer, size_t bufferSize)
|
||||||
|
{
|
||||||
|
FIL fileSrc, fileDst;
|
||||||
|
FRESULT res;
|
||||||
|
|
||||||
|
res = f_open(&fileSrc, pathSrc, FA_READ);
|
||||||
|
if (res != FR_OK)
|
||||||
|
return true; // Succeed if the source file doesn't exist
|
||||||
|
|
||||||
|
size_t szSrc = f_size(&fileSrc), rem = szSrc;
|
||||||
|
|
||||||
|
res = f_open(&fileDst, pathDst, FA_WRITE | (replace ? FA_CREATE_ALWAYS : FA_CREATE_NEW));
|
||||||
|
|
||||||
|
if (res == FR_EXIST)
|
||||||
|
{
|
||||||
|
// We did not fail
|
||||||
|
f_close(&fileSrc);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (res == FR_NO_PATH)
|
||||||
|
{
|
||||||
|
const char *c;
|
||||||
|
for (c = pathDst + strlen(pathDst); *c != '/' && c >= pathDst; --c);
|
||||||
|
if (c >= pathDst && c - pathDst <= FF_MAX_LFN && *c != '\0')
|
||||||
|
{
|
||||||
|
char path[FF_MAX_LFN + 1];
|
||||||
|
strncpy(path, pathDst, c - pathDst);
|
||||||
|
path[FF_MAX_LFN] = '\0';
|
||||||
|
res = f_mkdir(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == FR_OK)
|
||||||
|
res = f_open(&fileDst, pathDst, FA_WRITE | (replace ? FA_CREATE_ALWAYS : FA_CREATE_NEW));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
f_close(&fileSrc);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (rem > 0)
|
||||||
|
{
|
||||||
|
size_t sz = rem >= bufferSize ? bufferSize : rem;
|
||||||
|
UINT n = 0;
|
||||||
|
|
||||||
|
res = f_read(&fileSrc, tmpBuffer, sz, &n);
|
||||||
|
if (n != sz)
|
||||||
|
res = FR_INT_ERR; // should not happen
|
||||||
|
|
||||||
|
if (res == FR_OK)
|
||||||
|
{
|
||||||
|
res = f_write(&fileDst, tmpBuffer, sz, &n);
|
||||||
|
if (n != sz)
|
||||||
|
res = FR_DENIED; // disk full
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res != FR_OK)
|
||||||
|
{
|
||||||
|
f_close(&fileSrc);
|
||||||
|
f_close(&fileDst);
|
||||||
|
f_unlink(pathDst); // oops, failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rem -= sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_close(&fileSrc);
|
||||||
|
f_close(&fileDst);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool findPayload(char *path, u32 pressed)
|
bool findPayload(char *path, u32 pressed)
|
||||||
{
|
{
|
||||||
const char *pattern;
|
const char *pattern;
|
||||||
@ -309,3 +384,39 @@ void findDumpFile(const char *folderPath, char *fileName)
|
|||||||
|
|
||||||
if(result == FR_OK) f_closedir(&dir);
|
if(result == FR_OK) f_closedir(&dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 fileCopyBuffer[0x1000];
|
||||||
|
bool backupEssentialFiles(void)
|
||||||
|
{
|
||||||
|
size_t sz = sizeof(fileCopyBuffer);
|
||||||
|
|
||||||
|
bool ok = !(isSdMode && !mountFs(false, false));
|
||||||
|
|
||||||
|
ok = ok && fileCopy("1:/ro/sys/HWCAL0.dat", "backups/HWCAL0.dat", false, fileCopyBuffer, sz);
|
||||||
|
ok = ok && fileCopy("1:/ro/sys/HWCAL1.dat", "backups/HWCAL1.dat", false, fileCopyBuffer, sz);
|
||||||
|
|
||||||
|
ok = ok && fileCopy("1:/rw/sys/LocalFriendCodeSeed_A", "backups/LocalFriendCodeSeed_A", false, fileCopyBuffer, sz); // often doesn't exist
|
||||||
|
ok = ok && fileCopy("1:/rw/sys/LocalFriendCodeSeed_B", "backups/LocalFriendCodeSeed_B", false, fileCopyBuffer, sz);
|
||||||
|
|
||||||
|
ok = ok && fileCopy("1:/rw/sys/SecureInfo_A", "backups/SecureInfo_A", false, fileCopyBuffer, sz);
|
||||||
|
ok = ok && fileCopy("1:/rw/sys/SecureInfo_B", "backups/SecureInfo_B", false, fileCopyBuffer, sz); // often doesn't exist
|
||||||
|
|
||||||
|
if (!ok) return false;
|
||||||
|
|
||||||
|
alignedseqmemcpy(fileCopyBuffer, (const void *)0x10012000, 0x100);
|
||||||
|
if (getFileSize("backups/otp.bin") != 0x100)
|
||||||
|
ok = ok && fileWrite(fileCopyBuffer, "backups/otp.bin", 0x100);
|
||||||
|
|
||||||
|
if (!ok) return false;
|
||||||
|
|
||||||
|
// On dev boards, but not O3DS IS_DEBUGGER, hwcal is on an EEPROM chip accessed via I2C
|
||||||
|
u8 c = mcuConsoleInfo[0];
|
||||||
|
if (c == 2 || c == 4 || (ISN3DS && c == 5) || c == 6)
|
||||||
|
{
|
||||||
|
I2C_readRegBuf(I2C_DEV_EEPROM, 0, fileCopyBuffer, 0x1000); // Up to two instances of hwcal, with the second one @0x800
|
||||||
|
if (getFileSize("backups/HWCAL_01_EEPROM.dat") != 0x1000)
|
||||||
|
ok = ok && fileWrite(fileCopyBuffer, "backups/HWCAL_01_EEPROM.dat", 0x1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
@ -35,7 +35,10 @@ 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);
|
||||||
bool fileDelete(const char *path);
|
bool fileDelete(const char *path);
|
||||||
|
bool fileCopy(const char *pathSrc, const char *pathDst, bool replace, void *tmpBuffer, size_t bufferSize);
|
||||||
bool findPayload(char *path, u32 pressed);
|
bool findPayload(char *path, u32 pressed);
|
||||||
bool payloadMenu(char *path, bool *hasDisplayedMenu);
|
bool payloadMenu(char *path, bool *hasDisplayedMenu);
|
||||||
u32 firmRead(void *dest, u32 firmType);
|
u32 firmRead(void *dest, u32 firmType);
|
||||||
void findDumpFile(const char *folderPath, char *fileName);
|
void findDumpFile(const char *folderPath, char *fileName);
|
||||||
|
|
||||||
|
bool backupEssentialFiles(void);
|
||||||
|
@ -49,6 +49,9 @@ bool isSdMode;
|
|||||||
u16 launchedPath[80+1];
|
u16 launchedPath[80+1];
|
||||||
BootType bootType;
|
BootType bootType;
|
||||||
|
|
||||||
|
u16 mcuFwVersion;
|
||||||
|
u8 mcuConsoleInfo[9];
|
||||||
|
|
||||||
void main(int argc, char **argv, u32 magicWord)
|
void main(int argc, char **argv, u32 magicWord)
|
||||||
{
|
{
|
||||||
bool isFirmProtEnabled,
|
bool isFirmProtEnabled,
|
||||||
@ -117,6 +120,11 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__);
|
memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__);
|
||||||
memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__);
|
memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__);
|
||||||
I2C_init();
|
I2C_init();
|
||||||
|
|
||||||
|
I2C_readRegBuf(I2C_DEV_MCU, 0x00, (u8 *)&mcuFwVersion, 2);
|
||||||
|
if ((mcuFwVersion & 0xFFF) < 0x0100) error("Unsupported MCU FW version.");
|
||||||
|
I2C_readRegBuf(I2C_DEV_MCU, 0x7F, mcuConsoleInfo, 9);
|
||||||
|
|
||||||
if(isInvalidLoader) error("Launched using an unsupported loader.");
|
if(isInvalidLoader) error("Launched using an unsupported loader.");
|
||||||
|
|
||||||
installArm9Handlers();
|
installArm9Handlers();
|
||||||
|
@ -130,3 +130,6 @@ extern BootType bootType;
|
|||||||
|
|
||||||
extern u16 launchedFirmTidLow[8];
|
extern u16 launchedFirmTidLow[8];
|
||||||
extern u16 launchedPath[80+1];
|
extern u16 launchedPath[80+1];
|
||||||
|
|
||||||
|
extern u16 mcuFwVersion;
|
||||||
|
extern u8 mcuConsoleInfo[9];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user