Implement a new config file format which allows invalidating the config with new releases, fix config-related bugs, cleanup
This commit is contained in:
parent
c711ed6253
commit
31458e9938
@ -21,12 +21,50 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "memory.h"
|
||||
#include "fs.h"
|
||||
#include "utils.h"
|
||||
#include "screen.h"
|
||||
#include "draw.h"
|
||||
#include "buttons.h"
|
||||
|
||||
void configureCFW(void)
|
||||
bool readConfig(const char *configPath)
|
||||
{
|
||||
if(fileRead(&configData, configPath) != sizeof(cfgData) ||
|
||||
memcmp(configData.magic, "CONF", 4) != 0 ||
|
||||
configData.formatVersionMajor != CONFIG_VERSIONMAJOR ||
|
||||
configData.formatVersionMinor != CONFIG_VERSIONMINOR)
|
||||
{
|
||||
configData.config = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void writeConfig(const char *configPath, u32 configTemp)
|
||||
{
|
||||
/* If the configuration is different from previously, overwrite it.
|
||||
Just the no-forcing flag being set is not enough */
|
||||
if((configTemp & 0xFFFFFFEF) != configData.config)
|
||||
{
|
||||
//Merge the new options and new boot configuration
|
||||
configData.config = (configData.config & 0xFFFFFFC0) | (configTemp & 0x3F);
|
||||
|
||||
memcpy(configData.magic, "CONF", 4);
|
||||
configData.formatVersionMajor = CONFIG_VERSIONMAJOR;
|
||||
configData.formatVersionMinor = CONFIG_VERSIONMINOR;
|
||||
|
||||
if(!fileWrite(&configData, configPath, sizeof(configData)))
|
||||
{
|
||||
createDirectory("luma");
|
||||
if(!fileWrite(&configData, configPath, sizeof(configData)))
|
||||
error("Error writing the configuration file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void configure(void)
|
||||
{
|
||||
initScreens();
|
||||
|
||||
@ -41,10 +79,10 @@ void configureCFW(void)
|
||||
"( ) Use second EmuNAND as default",
|
||||
"( ) Enable region/language emu. and ext. .code",
|
||||
"( ) Show current NAND in System Settings",
|
||||
"( ) Enable experimental TwlBg patches",
|
||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||
"( ) Display splash screen before payloads",
|
||||
"( ) Use a PIN",
|
||||
"( ) Enable experimental TwlBg patches" };
|
||||
"( ) Use a PIN" };
|
||||
|
||||
struct multiOption {
|
||||
int posXs[4];
|
||||
@ -185,13 +223,13 @@ void configureCFW(void)
|
||||
}
|
||||
|
||||
//Preserve the last-used boot options (last 12 bits)
|
||||
config &= 0x3F;
|
||||
configData.config &= 0x3F;
|
||||
|
||||
//Parse and write the new configuration
|
||||
for(u32 i = 0; i < multiOptionsAmount; i++)
|
||||
config |= multiOptions[i].enabled << (i * 2 + 6);
|
||||
configData.config |= multiOptions[i].enabled << (i * 2 + 6);
|
||||
for(u32 i = 0; i < singleOptionsAmount; i++)
|
||||
config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16);
|
||||
configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 16);
|
||||
|
||||
//Wait for the pressed buttons to change
|
||||
while(HID_PAD == BUTTON_START);
|
||||
|
@ -24,10 +24,23 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define CONFIG(a) (((config >> (a + 16)) & 1) != 0)
|
||||
#define MULTICONFIG(a) ((config >> (a * 2 + 6)) & 3)
|
||||
#define BOOTCONFIG(a, b) ((config >> a) & b)
|
||||
#define CONFIG(a) (((configData.config >> (a + 16)) & 1) != 0)
|
||||
#define MULTICONFIG(a) ((configData.config >> (a * 2 + 6)) & 3)
|
||||
#define BOOTCONFIG(a, b) ((configData.config >> a) & b)
|
||||
|
||||
extern u32 config;
|
||||
#define CONFIG_VERSIONMAJOR 1
|
||||
#define CONFIG_VERSIONMINOR 0
|
||||
|
||||
void configureCFW(void);
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
char magic[4];
|
||||
u16 formatVersionMajor, formatVersionMinor;
|
||||
|
||||
u32 config;
|
||||
} cfgData;
|
||||
|
||||
extern cfgData configData;
|
||||
|
||||
bool readConfig(const char *configPath);
|
||||
void writeConfig(const char *configPath, u32 configTemp);
|
||||
void configure(void);
|
@ -35,18 +35,18 @@
|
||||
#include "pin.h"
|
||||
#include "../build/injector.h"
|
||||
|
||||
extern u16 launchedFirmTIDLow[8]; //defined in start.s
|
||||
extern u16 launchedFirmTIDLow[8]; //Defined in start.s
|
||||
|
||||
static firmHeader *const firm = (firmHeader *)0x24000000;
|
||||
static const firmSectionHeader *section;
|
||||
|
||||
u32 config,
|
||||
emuOffset;
|
||||
u32 emuOffset;
|
||||
|
||||
bool isN3DS,
|
||||
isDevUnit,
|
||||
isFirmlaunch;
|
||||
|
||||
cfgData configData;
|
||||
FirmwareSource firmSource;
|
||||
|
||||
void main(void)
|
||||
@ -72,7 +72,7 @@ void main(void)
|
||||
const char configPath[] = "/luma/config.bin";
|
||||
|
||||
//Attempt to read the configuration file
|
||||
needConfig = fileRead(&config, configPath) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||
needConfig = readConfig(configPath) ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||
|
||||
//Determine if this is a firmlaunch boot
|
||||
if(launchedFirmTIDLow[5] != 0)
|
||||
@ -99,11 +99,8 @@ void main(void)
|
||||
//Determine if booting with A9LH
|
||||
isA9lh = !PDN_SPI_CNT;
|
||||
|
||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||
bool useSysAsDefault = isA9lh ? CONFIG(1) : false;
|
||||
|
||||
//Save old options and begin saving the new boot configuration
|
||||
configTemp = (config & 0xFFFFFFC0) | ((u32)isA9lh << 3);
|
||||
configTemp = (configData.config & 0xFFFFFFC0) | ((u32)isA9lh << 3);
|
||||
|
||||
//If it's a MCU reboot, try to force boot options
|
||||
if(isA9lh && CFG_BOOTENV)
|
||||
@ -112,7 +109,7 @@ void main(void)
|
||||
if(CFG_BOOTENV == 7)
|
||||
{
|
||||
nandType = FIRMWARE_SYSNAND;
|
||||
firmSource = useSysAsDefault ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCONFIG(2, 1);
|
||||
firmSource = CONFIG(1) ? FIRMWARE_SYSNAND : (FirmwareSource)BOOTCONFIG(2, 1);
|
||||
needConfig = DONT_CONFIGURE;
|
||||
|
||||
//Flag to prevent multiple boot options-forcing
|
||||
@ -121,7 +118,7 @@ void main(void)
|
||||
|
||||
/* Else, force the last used boot options unless a button is pressed
|
||||
or the no-forcing flag is set */
|
||||
else if(!pressed && !BOOTCONFIG(4, 1))
|
||||
else if(needConfig != CREATE_CONFIGURATION && !pressed && !BOOTCONFIG(4, 1))
|
||||
{
|
||||
nandType = (FirmwareSource)BOOTCONFIG(0, 3);
|
||||
firmSource = (FirmwareSource)BOOTCONFIG(2, 1);
|
||||
@ -134,7 +131,7 @@ void main(void)
|
||||
{
|
||||
PINData pin;
|
||||
|
||||
bool pinExists = CONFIG(7) && readPin(&pin);
|
||||
bool pinExists = CONFIG(8) && readPin(&pin);
|
||||
|
||||
//If we get here we should check the PIN (if it exists) in all cases
|
||||
if(pinExists) verifyPin(&pin);
|
||||
@ -144,9 +141,9 @@ void main(void)
|
||||
|
||||
if(shouldLoadConfigurationMenu)
|
||||
{
|
||||
configureCFW();
|
||||
configure();
|
||||
|
||||
if(!pinExists && CONFIG(7)) newPin();
|
||||
if(!pinExists && CONFIG(8)) newPin();
|
||||
|
||||
chrono(2);
|
||||
|
||||
@ -164,7 +161,7 @@ void main(void)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(CONFIG(6) && loadSplash()) pressed = HID_PAD;
|
||||
if(CONFIG(7) && loadSplash()) pressed = HID_PAD;
|
||||
|
||||
/* If L and R/A/Select or one of the single payload buttons are pressed,
|
||||
chainload an external payload (the PIN, if any, has been verified)*/
|
||||
@ -172,7 +169,10 @@ void main(void)
|
||||
|
||||
if(shouldLoadPayload) loadPayload(pressed);
|
||||
|
||||
if(!CONFIG(6)) loadSplash();
|
||||
if(!CONFIG(7)) loadSplash();
|
||||
|
||||
//Determine if the user chose to use the SysNAND FIRM as default for a R boot
|
||||
bool useSysAsDefault = isA9lh ? CONFIG(1) : false;
|
||||
|
||||
//If R is pressed, boot the non-updated NAND with the FIRM of the opposite one
|
||||
if(pressed & BUTTON_R1)
|
||||
@ -210,21 +210,7 @@ void main(void)
|
||||
if(!isFirmlaunch)
|
||||
{
|
||||
configTemp |= (u32)nandType | ((u32)firmSource << 2);
|
||||
|
||||
/* If the configuration is different from previously, overwrite it.
|
||||
Just the no-forcing flag being set is not enough */
|
||||
if((configTemp & 0xFFFFFFEF) != config)
|
||||
{
|
||||
//Merge the new options and new boot configuration
|
||||
config = (config & 0xFFFFFFC0) | (configTemp & 0x3F);
|
||||
|
||||
if(!fileWrite(&config, configPath, 4))
|
||||
{
|
||||
createDirectory("luma");
|
||||
if(!fileWrite(&config, configPath, 4))
|
||||
error("Error writing the configuration file");
|
||||
}
|
||||
}
|
||||
writeConfig(configPath, configTemp);
|
||||
}
|
||||
|
||||
u32 firmVersion = loadFirm(firmType);
|
||||
@ -331,7 +317,7 @@ static inline void patchLegacyFirm(FirmwareType firmType)
|
||||
|
||||
applyLegacyFirmPatches((u8 *)firm, firmType);
|
||||
|
||||
if(firmType == TWL_FIRM && CONFIG(8))
|
||||
if(firmType == TWL_FIRM && CONFIG(5))
|
||||
patchTwlBg((u8 *)firm + section[1].offset);
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,11 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
||||
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
||||
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
||||
|
||||
//FIRM Header layout
|
||||
typedef struct firmSectionHeader {
|
||||
u32 offset;
|
||||
|
@ -98,9 +98,9 @@ void patchSignatureChecks(u8 *pos, u32 size)
|
||||
void patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
||||
{
|
||||
//Look for firmlaunch code
|
||||
const u8 pattern[] = {0xDE, 0x1F, 0x8D, 0xE2};
|
||||
const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
|
||||
|
||||
u8 *off = memsearch(pos, pattern, size, 4) - 0x10;
|
||||
u8 *off = memsearch(pos, pattern, size, 4) - 0x13;
|
||||
|
||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
||||
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
||||
@ -180,7 +180,7 @@ void implementSvcGetCFWInfo(u8 *pos, u32 size)
|
||||
CFWInfo *info = (CFWInfo *)memsearch(freeK11Space, "LUMA", svcGetCFWInfo_size, 4);
|
||||
|
||||
info->commitHash = COMMIT_HASH;
|
||||
info->config = config;
|
||||
info->config = configData.config;
|
||||
info->versionMajor = (u8)(rev[1] - '0');
|
||||
info->versionMinor = (u8)(rev[3] - '0');
|
||||
if(rev[4] == '.')
|
||||
@ -227,7 +227,7 @@ void applyLegacyFirmPatches(u8 *pos, FirmwareType firmType)
|
||||
/* Calculate the amount of patches to apply. Only count the boot screen patch for AGB_FIRM
|
||||
if the matching option was enabled (keep it as last) */
|
||||
u32 numPatches = firmType == TWL_FIRM ? (sizeof(twlPatches) / sizeof(patchData)) :
|
||||
(sizeof(agbPatches) / sizeof(patchData) - !CONFIG(5));
|
||||
(sizeof(agbPatches) / sizeof(patchData) - !CONFIG(6));
|
||||
const patchData *patches = firmType == TWL_FIRM ? twlPatches : agbPatches;
|
||||
|
||||
//Patch
|
||||
|
@ -48,7 +48,6 @@ typedef struct __attribute__((packed))
|
||||
} CFWInfo;
|
||||
|
||||
extern bool isN3DS;
|
||||
extern u32 config;
|
||||
|
||||
u8 *getProcess9(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||
void patchSignatureChecks(u8 *pos, u32 size);
|
||||
|
30
source/pin.c
30
source/pin.c
@ -36,11 +36,14 @@
|
||||
|
||||
bool readPin(PINData *out)
|
||||
{
|
||||
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
||||
if(fileRead(out, "/luma/pin.bin") != sizeof(PINData) ||
|
||||
memcmp(out->magic, "PINF", 4) != 0 ||
|
||||
out->formatVersionMajor != PIN_VERSIONMAJOR ||
|
||||
out->formatVersionMinor != PIN_VERSIONMINOR)
|
||||
return false;
|
||||
|
||||
if(fileRead(out, "/luma/pin.bin") != sizeof(PINData)) return false;
|
||||
if(memcmp(out->magic, "PINF", 4) != 0) return false;
|
||||
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
||||
u8 __attribute__((aligned(4))) tmp[32];
|
||||
|
||||
computePINHash(tmp, zeroes, 1);
|
||||
|
||||
@ -89,13 +92,13 @@ void newPin(void)
|
||||
charDrawPos += 2 * SPACING_X;
|
||||
}
|
||||
|
||||
PINData pin = {0};
|
||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
||||
PINData pin;
|
||||
u8 __attribute__((aligned(4))) tmp[32];
|
||||
u8 __attribute__((aligned(4))) zeroes[16] = {0};
|
||||
|
||||
memcpy(pin.magic, "PINF", 4);
|
||||
pin.formatVersionMajor = 1;
|
||||
pin.formatVersionMinor = 0;
|
||||
pin.formatVersionMajor = PIN_VERSIONMAJOR;
|
||||
pin.formatVersionMinor = PIN_VERSIONMINOR;
|
||||
|
||||
computePINHash(tmp, zeroes, 1);
|
||||
memcpy(pin.testHash, tmp, 32);
|
||||
@ -103,8 +106,13 @@ void newPin(void)
|
||||
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
||||
memcpy(pin.hash, tmp, 32);
|
||||
|
||||
fileWrite(&pin, "/luma/pin.bin", sizeof(PINData));
|
||||
|
||||
if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData)))
|
||||
{
|
||||
createDirectory("luma");
|
||||
if(!fileWrite(&pin, "/luma/pin.bin", sizeof(PINData)))
|
||||
error("Error writing the PIN file");
|
||||
}
|
||||
|
||||
while(HID_PAD & PIN_BUTTONS);
|
||||
}
|
||||
|
||||
@ -145,7 +153,7 @@ void verifyPin(PINData *in)
|
||||
|
||||
if(cnt >= PIN_LENGTH)
|
||||
{
|
||||
u8 __attribute__((aligned(4))) tmp[32] = {0};
|
||||
u8 __attribute__((aligned(4))) tmp[32];
|
||||
|
||||
computePINHash(tmp, enteredPassword, (PIN_LENGTH + 15) / 16);
|
||||
unlock = memcmp(in->hash, tmp, 32) == 0;
|
||||
|
@ -31,6 +31,8 @@
|
||||
#include "types.h"
|
||||
|
||||
#define PIN_LENGTH 4
|
||||
#define PIN_VERSIONMAJOR 1
|
||||
#define PIN_VERSIONMINOR 0
|
||||
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
|
@ -242,7 +242,7 @@ void initScreens(void)
|
||||
|
||||
if(PDN_GPU_CNT == 1)
|
||||
{
|
||||
flushDCacheRange(&config, 4);
|
||||
flushDCacheRange(&configData, sizeof(cfgData));
|
||||
flushDCacheRange((void *)fb, sizeof(struct fb));
|
||||
invokeArm11Function(ARM11);
|
||||
|
||||
|
@ -29,6 +29,8 @@
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||
|
||||
#define ARM11_STUB_ADDRESS (0x25000000 - 0x30) //It's currently only 0x28 bytes large. We're putting 0x30 just to be sure here
|
||||
#define WAIT_FOR_ARM9() *arm11Entry = 0; while(!*arm11Entry); ((void (*)())*arm11Entry)();
|
||||
|
||||
|
@ -26,13 +26,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define CFG_BOOTENV (*(vu32 *)0x10010000)
|
||||
#define CFG_UNITINFO (*(vu8 *)0x10010010)
|
||||
|
||||
#define PDN_MPCORE_CFG (*(vu32 *)0x10140FFC)
|
||||
#define PDN_SPI_CNT (*(vu32 *)0x101401C0)
|
||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
||||
|
||||
//Common data types
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
@ -43,7 +36,7 @@ typedef volatile u16 vu16;
|
||||
typedef volatile u32 vu32;
|
||||
typedef volatile u64 vu64;
|
||||
|
||||
//Used by multiple files:
|
||||
//Used by multiple files
|
||||
typedef enum FirmwareSource
|
||||
{
|
||||
FIRMWARE_SYSNAND = 0,
|
||||
|
Reference in New Issue
Block a user