diff --git a/source/common/common.h b/source/common/common.h index 3661fd6..150fae7 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -88,7 +88,8 @@ // -> codelzss.c for decompressing .code // meaning: careful when using this! #define TEMP_BUFFER ((u8*)0x20800000) -#define TEMP_BUFFER_SIZE (0x1800000) // 24MB(!) +#define TEMP_BUFFER_SIZE (0x400000) // 4MB +#define TEMP_BUFFER_EXTSIZE (0x1800000) // 24MB(!) (only used by codelzss.c right now) // buffer area defines (in use by image.c, for RAMdrive) #define RAMDRV_BUFFER ((u8*)0x22800000) // top of STACK diff --git a/source/game/firm.c b/source/game/firm.c index da61447..8b18bc4 100644 --- a/source/game/firm.c +++ b/source/game/firm.c @@ -25,11 +25,11 @@ #define FIRM_VALID_ADDRESS_BOOT \ FIRM_VALID_ADDRESS, \ 0x20000000, 0x27FFFA00 - -u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) { + +u32 GetFirmSize(FirmHeader* header) { u8 magic[] = { FIRM_MAGIC }; if (memcmp(header->magic, magic, sizeof(magic)) != 0) - return 1; + return 0; u32 firm_size = sizeof(FirmHeader); int section_arm11 = -1; @@ -37,8 +37,8 @@ u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) { for (u32 i = 0; i < 4; i++) { FirmSectionHeader* section = header->sections + i; if (!section->size) continue; - if (section->offset < firm_size) return 1; - if ((section->offset % 512) || (section->address % 16) || (section->size % 512)) return 1; + if (section->offset < firm_size) return 0; + if ((section->offset % 512) || (section->address % 16) || (section->size % 512)) return 0; if ((header->entry_arm11 >= section->address) && (header->entry_arm11 < section->address + section->size)) section_arm11 = i; @@ -48,12 +48,16 @@ u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) { firm_size = section->offset + section->size; } - if ((firm_size > FIRM_MAX_SIZE) || (data_size && (firm_size > data_size))) - return 1; + if (firm_size > FIRM_MAX_SIZE) return 0; if ((header->entry_arm11 && (section_arm11 < 0)) || (header->entry_arm9 && (section_arm9 < 0))) - return 1; + return 0; - return 0; + return firm_size; +} + +u32 ValidateFirmHeader(FirmHeader* header, u32 data_size) { + u32 firm_size = GetFirmSize(header); + return (!firm_size || (data_size && (firm_size > data_size))) ? 1 : 0; } u32 ValidateFirmA9LHeader(FirmA9LHeader* header) { diff --git a/source/game/firm.h b/source/game/firm.h index 5ceb3e3..d11ddd0 100644 --- a/source/game/firm.h +++ b/source/game/firm.h @@ -48,6 +48,7 @@ typedef struct { u32 ValidateFirmHeader(FirmHeader* header, u32 data_size); u32 ValidateFirmA9LHeader(FirmA9LHeader* header); u32 ValidateFirm(void* firm, u32 firm_size, bool installable); +u32 GetFirmSize(FirmHeader* header); FirmSectionHeader* FindFirmArm9Section(FirmHeader* firm); u32 GetArm9BinarySize(FirmA9LHeader* a9l); diff --git a/source/godmode.c b/source/godmode.c index 16b7dc9..96e6fa9 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -1641,13 +1641,14 @@ u32 GodMode(bool is_b9s) { bool bootloader = !is_b9s && IS_SIGHAX && (boot_origin & BOOT_NAND); bool bootmenu = bootloader && CheckButton(BOOTMENU_KEY); bool godmode9 = !bootloader; - FirmHeader* firm_in_mem = (FirmHeader*) DIR_BUFFER; + FirmHeader* firm_in_mem = (FirmHeader*) (void*) (TEMP_BUFFER + TEMP_BUFFER_SIZE); // should be safe here memcpy(firm_in_mem, "NOPE", 4); // to prevent bootloops if (bootloader) { // check for FIRM in FCRAM, but prevent bootloops for (u8* addr = (u8*) 0x20000200; addr < (u8*) 0x24000000; addr += 0x400000) { if (memcmp(addr - 0x200, "A9NC", 4) != 0) continue; - if (ValidateFirmHeader((FirmHeader*) (void*) addr, 0x100000) != 0) continue; - if (memcmp(firm_in_mem, "FIRM", 4) != 0) memmove(firm_in_mem, addr, 0x100000); + u32 firm_size = GetFirmSize((FirmHeader*) (void*) addr); + if (!firm_size || (firm_size > (0x400000 - 0x200))) continue; + if (memcmp(firm_in_mem, "FIRM", 4) != 0) memmove(firm_in_mem, addr, firm_size); if (memcmp(addr, "FIRM", 4) == 0) memcpy(addr, "NOPE", 4); // prevent bootloops } } @@ -1735,7 +1736,7 @@ u32 GodMode(bool is_b9s) { } if (bootloader) { const char* bootfirm_paths[] = { BOOTFIRM_PATHS }; - if (ValidateFirm(firm_in_mem, 0x100000, false) == 0) BootFirm(firm_in_mem, "0:/bootonce.firm"); + if (ValidateFirm(firm_in_mem, FIRM_MAX_SIZE, false) == 0) BootFirm(firm_in_mem, "0:/bootonce.firm"); for (u32 i = 0; i < sizeof(bootfirm_paths) / sizeof(char*); i++) { BootFirmHandler(bootfirm_paths[i], false, (BOOTFIRM_TEMPS >> i) & 0x1); } diff --git a/source/utils/gameutil.c b/source/utils/gameutil.c index a845a5d..eb0d811 100644 --- a/source/utils/gameutil.c +++ b/source/utils/gameutil.c @@ -1413,7 +1413,7 @@ u32 DumpCxiSrlFromTmdFile(const char* path) { u32 ExtractCodeFromCxiFile(const char* path, const char* path_out) { u8* code = (u8*) TEMP_BUFFER; - u32 code_max_size = TEMP_BUFFER_SIZE; + u32 code_max_size = TEMP_BUFFER_EXTSIZE; // uses the extended temp buffer size NcchHeader ncch; NcchExtHeader exthdr;