diff --git a/arm9/Makefile b/arm9/Makefile index ccf663b..272765a 100644 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -159,8 +159,8 @@ $(OUTPUT).elf : $(OFILES) $(OFILES_SRC) : $(HFILES_BIN) memory.o strings.o: CFLAGS += -O3 -config.o: CFLAGS += -DCONFIG_TITLE="\"$(APP_TITLE) $(REVISION) configuration\"" -patches.o: CFLAGS += -DVERSION_MAJOR="$(VERSION_MAJOR)" -DVERSION_MINOR="$(VERSION_MINOR)"\ +patches.o config.o: CFLAGS += -DCONFIG_TITLE="\"$(APP_TITLE) $(REVISION) configuration\""\ + -DVERSION_MAJOR="$(VERSION_MAJOR)" -DVERSION_MINOR="$(VERSION_MINOR)"\ -DVERSION_BUILD="$(VERSION_BUILD)" -DISRELEASE="$(IS_RELEASE)" -DCOMMIT_HASH="0x$(COMMIT)" #--------------------------------------------------------------------------------- # you need a rule like this for each extension you use as binary data diff --git a/arm9/source/config.c b/arm9/source/config.c index fcac6c5..d5c8ea9 100644 --- a/arm9/source/config.c +++ b/arm9/source/config.c @@ -24,6 +24,7 @@ * reasonable ways as different from the original version. */ +#include #include "config.h" #include "memory.h" #include "fs.h" @@ -33,26 +34,97 @@ #include "emunand.h" #include "buttons.h" #include "pin.h" +#include "i2c.h" + +#define MAKE_LUMA_VERSION_MCU(major, minor, build) (u16)(((major) & 0xFF) << 8 | ((minor) & 0x1F) << 5 | ((build) & 7)) CfgData configData; ConfigurationStatus needConfig; static CfgData oldConfig; +static CfgDataMcu configDataMcu; +static_assert(sizeof(CfgDataMcu) > 0, "wrong data size"); + +static void writeConfigMcu(void) +{ + u8 data[sizeof(CfgDataMcu)]; + + // Set Luma version + configDataMcu.lumaVersion = MAKE_LUMA_VERSION_MCU(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); + + // Set bootconfig from CfgData + configDataMcu.bootCfg = configData.bootConfig; + + memcpy(data, &configDataMcu, sizeof(CfgDataMcu)); + + // Fix checksum + u8 checksum = 0; + for (u32 i = 0; i < sizeof(CfgDataMcu) - 1; i++) + checksum += data[i]; + checksum = ~checksum; + data[sizeof(CfgDataMcu) - 1] = checksum; + configDataMcu.checksum = checksum; + + I2C_writeReg(I2C_DEV_MCU, 0x60, 200 - sizeof(CfgDataMcu)); + I2C_writeRegBuf(I2C_DEV_MCU, 0x61, data, sizeof(CfgDataMcu)); +} + +static bool readConfigMcu(void) +{ + u8 data[sizeof(CfgDataMcu)]; + u16 curVer = MAKE_LUMA_VERSION_MCU(VERSION_MAJOR, VERSION_MINOR, VERSION_BUILD); + + // Select free reg id, then access the data regs + I2C_writeReg(I2C_DEV_MCU, 0x60, 200 - sizeof(CfgDataMcu)); + I2C_readRegBuf(I2C_DEV_MCU, 0x61, data, sizeof(CfgDataMcu)); + memcpy(&configDataMcu, data, sizeof(CfgDataMcu)); + + u8 checksum = 0; + for (u32 i = 0; i < sizeof(CfgDataMcu) - 1; i++) + checksum += data[i]; + checksum = ~checksum; + + if (checksum != configDataMcu.checksum || configDataMcu.lumaVersion < MAKE_LUMA_VERSION_MCU(10, 3, 0)) + { + // Invalid data stored in MCU... + configData.bootConfig = 0; + // Perform upgrade process (ignoring failures) + doLumaUpgradeProcess(); + writeConfigMcu(); + + return false; + } + + if (configDataMcu.lumaVersion < curVer) + { + // Perform upgrade process (ignoring failures) + doLumaUpgradeProcess(); + writeConfigMcu(); + } + + return true; +} + bool readConfig(void) { bool ret; + ret = readConfigMcu(); + if (!ret) + return false; + if(fileRead(&configData, CONFIG_FILE, sizeof(CfgData)) != sizeof(CfgData) || memcmp(configData.magic, "CONF", 4) != 0 || configData.formatVersionMajor != CONFIG_VERSIONMAJOR || configData.formatVersionMinor != CONFIG_VERSIONMINOR) { memset(&configData, 0, sizeof(CfgData)); - ret = false; } - else ret = true; + else + ret = true; + configData.bootConfig = configDataMcu.bootCfg; oldConfig = configData; return ret; @@ -73,7 +145,9 @@ void writeConfig(bool isConfigOptions) needConfig = MODIFY_CONFIGURATION; } - if(!fileWrite(&configData, CONFIG_FILE, sizeof(CfgData))) + if (!isConfigOptions) + writeConfigMcu(); + else if(!fileWrite(&configData, CONFIG_FILE, sizeof(CfgData))) error("Error writing the configuration file"); } diff --git a/arm9/source/config.h b/arm9/source/config.h index de81062..6b00bc1 100644 --- a/arm9/source/config.h +++ b/arm9/source/config.h @@ -34,7 +34,7 @@ #define CONFIG_FILE "config.bin" #define CONFIG_VERSIONMAJOR 2 -#define CONFIG_VERSIONMINOR 4 +#define CONFIG_VERSIONMINOR 5 #define BOOTCFG_NAND BOOTCONFIG(0, 7) #define BOOTCFG_FIRM BOOTCONFIG(3, 7) diff --git a/arm9/source/fs.c b/arm9/source/fs.c index 300a59f..30c4422 100644 --- a/arm9/source/fs.c +++ b/arm9/source/fs.c @@ -60,8 +60,19 @@ static bool switchToMainDir(bool isSd) bool mountFs(bool isSd, bool switchToCtrNand) { - return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK && switchToMainDir(true) : - f_mount(&nandFs, "1:", 1) == FR_OK && (!switchToCtrNand || (f_chdrive("1:") == FR_OK && switchToMainDir(false))); + static bool sdInitialized = false, nandInitialized = false; + if (isSd) + { + if (!sdInitialized) + sdInitialized = f_mount(&sdFs, "0:", 1) == FR_OK; + return sdInitialized && switchToMainDir(true); + } + else + { + if (!nandInitialized) + nandInitialized = f_mount(&nandFs, "1:", 1) == FR_OK; + return nandInitialized && (!switchToCtrNand || (f_chdrive("1:") == FR_OK && switchToMainDir(false))); + } } u32 fileRead(void *dest, const char *path, u32 maxSize) @@ -385,8 +396,9 @@ void findDumpFile(const char *folderPath, char *fileName) if(result == FR_OK) f_closedir(&dir); } -static u8 fileCopyBuffer[0x1000]; -bool backupEssentialFiles(void) +static u8 fileCopyBuffer[0x10000]; + +static bool backupEssentialFiles(void) { size_t sz = sizeof(fileCopyBuffer); @@ -420,3 +432,20 @@ bool backupEssentialFiles(void) return ok; } + +bool doLumaUpgradeProcess(void) +{ + // Ensure CTRNAND is mounted + bool ok = mountFs(false, false), ok2 = true; + if (!ok) + return false; + + // Try to boot.firm to CTRNAND, when applicable + if (isSdMode) + ok = fileCopy("0:/boot.firm", "1:/boot.firm", true, fileCopyBuffer, sizeof(fileCopyBuffer)); + + // Try to backup essential files + ok2 = backupEssentialFiles(); + + return ok && ok2; +} diff --git a/arm9/source/fs.h b/arm9/source/fs.h index 99c5a9c..477432c 100644 --- a/arm9/source/fs.h +++ b/arm9/source/fs.h @@ -41,4 +41,4 @@ bool payloadMenu(char *path, bool *hasDisplayedMenu); u32 firmRead(void *dest, u32 firmType); void findDumpFile(const char *folderPath, char *fileName); -bool backupEssentialFiles(void); +bool doLumaUpgradeProcess(void); diff --git a/arm9/source/types.h b/arm9/source/types.h index 871bb45..cba2d10 100644 --- a/arm9/source/types.h +++ b/arm9/source/types.h @@ -71,6 +71,14 @@ typedef struct __attribute__((packed, aligned(4))) u32 rosalinaMenuCombo; } CfgData; +typedef struct +{ + u16 lumaVersion; + u8 bootCfg; + u8 reserved[2]; + u8 checksum; +} CfgDataMcu; + typedef struct { char magic[4];