mirror of
https://github.com/modmii/YAWM-ModMii-Edition.git
synced 2025-02-25 08:53:41 +01:00
work in progress
This commit is contained in:
parent
62205f9ab5
commit
c86808e911
6
Makefile
6
Makefile
@ -28,7 +28,7 @@ INCLUDES :=
|
||||
# options for code generation
|
||||
#---------------------------------------------------------------------------------
|
||||
|
||||
CFLAGS = -Os -Wall $(MACHDEP) $(INCLUDE)
|
||||
CFLAGS = -g -Os -Wall $(MACHDEP) $(INCLUDE)
|
||||
CXXFLAGS = $(CFLAGS)
|
||||
|
||||
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map
|
||||
@ -128,9 +128,9 @@ $(OUTPUT).dol: $(OUTPUT).elf
|
||||
$(OUTPUT).elf: $(OFILES)
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# This rule links in binary data with the .jpg extension
|
||||
# This rule links in binary data with the .png extension
|
||||
#---------------------------------------------------------------------------------
|
||||
%.jpg.o : %.jpg
|
||||
%.png.o : %.png
|
||||
#---------------------------------------------------------------------------------
|
||||
@echo $(notdir $<)
|
||||
$(bin2o)
|
||||
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
@ -1,3 +1,6 @@
|
||||
#define WII_LIGHT_OFF 0
|
||||
#define WII_LIGHT_ON 1
|
||||
|
||||
void WIILIGHT_Init();
|
||||
void WIILIGHT_TurnOn();
|
||||
int WIILIGHT_GetLevel();
|
||||
|
@ -1,23 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "fileops.h"
|
||||
#include "malloc.h"
|
||||
|
||||
static struct stat st;
|
||||
#include "utils.h"
|
||||
|
||||
bool FSOPFileExists(const char* file)
|
||||
{
|
||||
struct stat st;
|
||||
return !stat(file, &st) && !S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
bool FSOPFolderExists(const char* path)
|
||||
{
|
||||
struct stat st;
|
||||
return !stat(path, &st) && S_ISDIR(st.st_mode);
|
||||
}
|
||||
|
||||
size_t FSOPGetFileSizeBytes(const char* path)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat(path, &st) < 0) return 0;
|
||||
|
||||
return st.st_size;
|
||||
@ -56,17 +58,20 @@ void FSOPMakeFolder(const char* path)
|
||||
s32 FSOPReadOpenFile(FILE* fp, void* buffer, u32 offset, u32 length)
|
||||
{
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
return fread(buffer, length, 1, fp);
|
||||
if (!fread(buffer, length, 1, fp))
|
||||
return -errno ?: -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 FSOPReadOpenFileA(FILE* fp, void** buffer, u32 offset, u32 length)
|
||||
{
|
||||
*buffer = memalign32(length);
|
||||
if (!*buffer)
|
||||
return -1;
|
||||
return -ENOMEM;
|
||||
|
||||
s32 ret = FSOPReadOpenFile(fp, *buffer, offset, length);
|
||||
if (ret <= 0)
|
||||
if (ret < 0)
|
||||
{
|
||||
free(*buffer);
|
||||
*buffer = NULL;
|
||||
|
@ -3,12 +3,10 @@
|
||||
|
||||
// Constants
|
||||
#define CIOS_VERSION 249
|
||||
#define ENTRIES_PER_PAGE 12
|
||||
#define MAX_FILE_PATH_LEN 1024
|
||||
#define WAD_DIRECTORY "/"
|
||||
#define WAD_ROOT_DIRECTORY "/wad/"
|
||||
#define DEFAULT_WAD_DIRECTORY "/wad/"
|
||||
|
||||
#define MAX_PASSWORD_LENGTH 10
|
||||
#define MAX_PASSWORD_LENGTH 16
|
||||
#define MAX_FAT_DEVICE_LENGTH 10
|
||||
#define MAX_NAND_DEVICE_LENGTH 10
|
||||
|
||||
@ -19,27 +17,23 @@
|
||||
#define NAND_DEVICE_INDEX_INVALID -1
|
||||
#define CIOS_VERSION_INVALID -1
|
||||
|
||||
// For the WiiLight
|
||||
#define WII_LIGHT_OFF 0
|
||||
#define WII_LIGHT_ON 1
|
||||
|
||||
typedef struct
|
||||
typedef struct wm_config
|
||||
{
|
||||
char password[MAX_PASSWORD_LENGTH];
|
||||
char startupPath[256];
|
||||
int cIOSVersion;
|
||||
int fatDeviceIndex;
|
||||
int nandDeviceIndex;
|
||||
/*
|
||||
const char *smbuser;
|
||||
const char *smbpassword;
|
||||
const char *share;
|
||||
const char *ip;
|
||||
} CONFIG;
|
||||
*/
|
||||
} CONFIG, wm_config_t;
|
||||
|
||||
|
||||
extern CONFIG gConfig;
|
||||
extern nandDevice ndevList[];
|
||||
//extern fatDevice fdevList[];
|
||||
extern wm_config_t gConfig;
|
||||
|
||||
|
||||
#endif
|
||||
|
83
source/gui.c
83
source/gui.c
@ -2,80 +2,61 @@
|
||||
#include <stdlib.h>
|
||||
#include <ogcsys.h>
|
||||
|
||||
#include "gui.h"
|
||||
#include "video.h"
|
||||
#include "fat.h"
|
||||
#include "menu.h"
|
||||
#include "nand.h"
|
||||
#include "pngu.h"
|
||||
#include "globals.h"
|
||||
#include "fileops.h"
|
||||
|
||||
#include "background_png.h"
|
||||
|
||||
/* Constants */
|
||||
#define CONSOLE_XCOORD 70
|
||||
#define CONSOLE_YCOORD 114
|
||||
#define CONSOLE_WIDTH 502
|
||||
#define CONSOLE_HEIGHT 300
|
||||
static const GuiWindow s_defaultBackgroundData = {
|
||||
.pngData = background_png,
|
||||
.pngTarget = { 0, 0 },
|
||||
|
||||
s32 __Gui_DrawPng(void *img, u32 x, u32 y)
|
||||
.consoleTarget = { 70, 114 },
|
||||
.consoleWidth = 502,
|
||||
.consoleHeight = 300,
|
||||
|
||||
// .consoleTarget = { 32, 32 },
|
||||
// .consoleWidth = 640 - 64,
|
||||
// .consoleHeight = 480 - 64,
|
||||
};
|
||||
|
||||
s32 Gui_InitConsole(const GuiWindow *window)
|
||||
{
|
||||
s32 ret = 0;
|
||||
IMGCTX ctx = NULL;
|
||||
PNGUPROP imgProp;
|
||||
char path[1024];
|
||||
s32 ret = -1;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < FatGetDeviceCount(); i++)
|
||||
{
|
||||
snprintf(path, sizeof(path), "%s:%s", FatGetDevicePrefix(i), WM_BACKGROUND_PATH);
|
||||
if (FSOPFileExists(path))
|
||||
{
|
||||
ctx = PNGU_SelectImageFromDevice(path);
|
||||
break;
|
||||
}
|
||||
if (!window)
|
||||
window = &s_defaultBackgroundData;
|
||||
|
||||
}
|
||||
|
||||
if(!ctx)
|
||||
if (window->pngData)
|
||||
{
|
||||
/* Select PNG data */
|
||||
ctx = PNGU_SelectImageFromBuffer(img);
|
||||
if (!ctx) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ctx = PNGU_SelectImageFromBuffer(window->pngData);
|
||||
if (!ctx)
|
||||
return -12;
|
||||
|
||||
/* Get image properties */
|
||||
ret = PNGU_GetImageProperties(ctx, &imgProp);
|
||||
if (ret != PNGU_OK) {
|
||||
ret = -1;
|
||||
if (ret != PNGU_OK)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Draw image */
|
||||
Video_DrawPng(ctx, imgProp, x, y);
|
||||
Video_DrawPng(ctx, imgProp, window->pngTarget.x, window->pngTarget.y);
|
||||
}
|
||||
|
||||
/* Success */
|
||||
ret = 0;
|
||||
|
||||
/* Initialize console */
|
||||
Con_Init(window->consoleTarget.x, window->consoleTarget.y, window->consoleWidth, window->consoleHeight);
|
||||
// Con_Init(32, 32, 640 - 64, 480 - 64);
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
if (ctx)
|
||||
PNGU_ReleaseImageContext(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Gui_InitConsole(void)
|
||||
{
|
||||
/* Initialize console */
|
||||
Con_Init(CONSOLE_XCOORD, CONSOLE_YCOORD, CONSOLE_WIDTH, CONSOLE_HEIGHT);
|
||||
}
|
||||
|
||||
void Gui_DrawBackground(void)
|
||||
{
|
||||
extern char bgData[];
|
||||
|
||||
/* Draw background */
|
||||
__Gui_DrawPng(bgData, 0, 0);
|
||||
return -ret;
|
||||
}
|
||||
|
11
source/gui.h
11
source/gui.h
@ -1,8 +1,15 @@
|
||||
#ifndef _GUI_H_
|
||||
#define _GUI_H_
|
||||
|
||||
typedef struct { u16 x, y; } point;
|
||||
typedef struct GuiWindow {
|
||||
const void *pngData;
|
||||
point pngTarget;
|
||||
point consoleTarget; // top left
|
||||
u16 consoleWidth, consoleHeight;
|
||||
} GuiWindow;
|
||||
|
||||
/* Prototypes */
|
||||
void Gui_InitConsole(void);
|
||||
void Gui_DrawBackground(void);
|
||||
s32 Gui_InitConsole(const GuiWindow *);
|
||||
|
||||
#endif
|
||||
|
@ -10,70 +10,88 @@
|
||||
// Copyright 2010 Joseph Jordan <joe.ftpii@psychlaw.com.au>
|
||||
// Wii U vWii patches Copyright 2012/2013 damysteryman
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gccore.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
/* memmem says hi */
|
||||
#define _GNU_SOURCE
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <ogc/ipc.h>
|
||||
|
||||
#include "iospatch.h"
|
||||
#include "sys.h"
|
||||
|
||||
#define MEM_REG_BASE 0xd8b4000
|
||||
#define MEM_PROT (MEM_REG_BASE + 0x20a)
|
||||
|
||||
static void disable_memory_protection() {
|
||||
write32(MEM_PROT, read32(MEM_PROT) & 0x0000FFFF);
|
||||
// I don't like hardcoding binary blobs like this either. We'll get serious later okay
|
||||
static const u32 armCode[] = {
|
||||
0xE3A00536, /* mov r0, #0x0D800000 */
|
||||
0xE5901060, /* ldr r1, [r0, #0x60] */
|
||||
0xE3811008, /* orr r1, #0x08 */
|
||||
0xE5801060, /* str r1, [r0, #0x60] */
|
||||
0xE5901064, /* ldr r1, [r0, #0x64] */
|
||||
0xE381113A, /* orr r1, #0x8000000E */
|
||||
0xE3811EDF, /* orr r1, #0x00000DF0 */
|
||||
0xE5801064, /* str r1, [r0, #0x64] */
|
||||
0xE12FFF1E, /* bx lr */
|
||||
};
|
||||
|
||||
/*
|
||||
* https://github.com/WiiLink24/wfc-patcher-wii/blob/main/launcher/source/IOS.cpp#L168-L171
|
||||
*/
|
||||
int do_sha_exploit(u32 addr) {
|
||||
int ret;
|
||||
int fd = 0x10001;
|
||||
ioctlv vecs[3] ATTRIBUTE_ALIGN(0x20) = {};
|
||||
|
||||
vecs[0].data = NULL;
|
||||
vecs[0].len = 0;
|
||||
vecs[1].data = (void *)0xFFFE0028;
|
||||
vecs[1].len = 0;
|
||||
|
||||
u32 *mem1 = (u32 *)0x80000000;
|
||||
*mem1++ = 0x4903468D;
|
||||
*mem1++ = 0x49034788;
|
||||
*mem1++ = 0x49036209;
|
||||
*mem1++ = 0x47080000;
|
||||
*mem1++ = 0x10100000;
|
||||
*mem1++ = MEM_VIRTUAL_TO_PHYSICAL(addr);
|
||||
*mem1++ = 0xFFFF0014;
|
||||
|
||||
vecs[2].data = mem1;
|
||||
vecs[2].len = 0x20;
|
||||
|
||||
ret = IOS_Ioctlv(fd, 0, 1, 2, vecs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u32 apply_patch(char *name, const u8 *old, u32 old_size, const u8 *patch, u32 patch_size, u32 patch_offset) {
|
||||
u8 *ptr_start = (u8*)*((u32*)0x80003134), *ptr_end = (u8*)0x94000000;
|
||||
u32 found = 0;
|
||||
// printf(" Patching %-30s", name);
|
||||
u8 *location = NULL;
|
||||
while (ptr_start < (ptr_end - patch_size)) {
|
||||
if (!memcmp(ptr_start, old, old_size)) {
|
||||
found++;
|
||||
location = ptr_start + patch_offset;
|
||||
u8 *start = location;
|
||||
u32 i;
|
||||
for (i = 0; i < patch_size; i++) {
|
||||
*location++ = patch[i];
|
||||
static u32 apply_patch(const void *old, u32 old_size, const void *patch, u32 patch_size, u32 patch_offset) {
|
||||
void *ptr_start = (void *)0x933E0000;
|
||||
void *ptr_end = (void *)0x94000000;
|
||||
u32 found;
|
||||
|
||||
for (found = 0; ptr_start < ptr_end; found++) {
|
||||
ptr_start = memmem(ptr_start, ptr_end - ptr_start, old, old_size);
|
||||
if (!ptr_start)
|
||||
break;
|
||||
|
||||
memcpy(ptr_start + patch_offset, patch, patch_size);
|
||||
DCFlushRange(ptr_start + patch_offset, patch_size);
|
||||
ptr_start += patch_offset + patch_size;
|
||||
}
|
||||
DCFlushRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
|
||||
ICInvalidateRange((u8 *)(((u32)start) >> 5 << 5), (patch_size >> 5 << 5) + 64);
|
||||
}
|
||||
ptr_start++;
|
||||
}
|
||||
// if (found)
|
||||
// printf(" patched\n");
|
||||
// else
|
||||
// printf(" not patched\n");
|
||||
|
||||
return found;
|
||||
}
|
||||
/*
|
||||
static const u8 di_readlimit_old[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x01, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x0A, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7E, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08
|
||||
};
|
||||
static const u8 di_readlimit_patch[] = { 0x7e, 0xd4 };
|
||||
|
||||
const u8 isfs_permissions_old[] = { 0x42, 0x8B, 0xD0, 0x01, 0x25, 0x66 };
|
||||
const u8 isfs_permissions_patch[] = { 0x42, 0x8B, 0xE0, 0x01, 0x25, 0x66 };
|
||||
static const u8 setuid_old[] = { 0xD1, 0x2A, 0x1C, 0x39 };
|
||||
static const u8 setuid_patch[] = { 0x46, 0xC0 };
|
||||
const u8 es_identify_old[] = { 0x28, 0x03, 0xD1, 0x23 };
|
||||
const u8 es_identify_patch[] = { 0x00, 0x00 };*/
|
||||
const u8 hash_old[] = { 0x20, 0x07, 0x23, 0xA2 };
|
||||
const u8 hash_patch[] = { 0x00 };
|
||||
const u8 new_hash_old[] = { 0x20, 0x07, 0x4B, 0x0B };
|
||||
const u8 es_set_ahbprot_old[] = { 0x68, 0x5B, 0x22, 0xEC, 0x00, 0x52, 0x18, 0x9B, 0x68, 0x1B, 0x46, 0x98, 0x07, 0xDB };
|
||||
const u8 es_set_ahbprot_patch[] = { 0x01 };
|
||||
const u8 ES_TitleVersionCheck_old[] = { 0xD2, 0x01, 0x4E, 0x56 };
|
||||
const u8 ES_TitleVersionCheck_patch[] = { 0xE0, 0x01, 0x4E, 0x56 };
|
||||
|
||||
const u8 ES_TitleDeleteCheck_old[] = { 0xD8, 0x00, 0x4A, 0x04 };
|
||||
const u8 ES_TitleDeleteCheck_patch[] = { 0xE0, 0x00, 0x4A, 0x04 };
|
||||
|
||||
const u16 ES_KeyslotPermissionCheck_old[] = { 0x2d06, 0xd000, 0x4803 };
|
||||
const u16 ES_KeyslotPermissionCheck_patch[] = { 0x2d06, 0xe000, 0x4803 };
|
||||
|
||||
const u8 isfs_permissions_old[] = { 0x9B, 0x05, 0x40, 0x03, 0x99, 0x05, 0x42, 0x8B, };
|
||||
const u8 isfs_permissions_patch[] = { 0x9B, 0x05, 0x40, 0x03, 0x1C, 0x0B, 0x42, 0x8B, };
|
||||
|
||||
@ -85,34 +103,102 @@ const u8 Kill_AntiSysTitleInstallv3_pt2_patch[] = { 0x46, 0xC0, 0x33, 0x06, 0x42
|
||||
const u8 Kill_AntiSysTitleInstallv3_pt3_old[] = { 0x68, 0xFB, 0x2B, 0x00, 0xDB, 0x01 };
|
||||
const u8 Kill_AntiSysTitleInstallv3_pt3_patch[] = { 0x68, 0xFB, 0x2B, 0x00, 0xDB, 0x10 };
|
||||
|
||||
u32 IOSPATCH_AHBPROT() {
|
||||
if (AHBPROT_DISABLED) {
|
||||
write32(MEM_PROT, read32(MEM_PROT) & 0x0000FFFF);
|
||||
//return apply_patch("set_ahbprot", check_tmd_old, sizeof(check_tmd_old), check_tmd_patch, sizeof(check_tmd_patch), 6);
|
||||
return apply_patch("es_set_ahbprot", es_set_ahbprot_old, sizeof(es_set_ahbprot_old), es_set_ahbprot_patch, sizeof(es_set_ahbprot_patch), 25);
|
||||
static inline bool validJumptablePtr(uint32_t x) {
|
||||
return (x >= 0xFFFF0040) && (x < 0xFFFFF000) && ((x & 3) == 0);
|
||||
}
|
||||
|
||||
#define SRAMNOMIRR(x) (x - 0xF2B00000)
|
||||
static u32 findTheSyscallTable(void) {
|
||||
u32 undfInstruction = read32(0xD4F0004);
|
||||
if ((undfInstruction & 0xFFFFF000) != 0xE59FF000 /* ldr pc, [pc, something] */)
|
||||
// SRNPROT is probably on
|
||||
return 0;
|
||||
|
||||
u32 undfHandler = read32(0xD4F0004 + 8 /* pc is 2 steps ahead */ + (undfInstruction & 0xFFF));
|
||||
if (!validJumptablePtr(undfHandler))
|
||||
// Eh?
|
||||
return 0;
|
||||
|
||||
undfHandler = SRAMNOMIRR(undfHandler);
|
||||
|
||||
// arbitrary number. don't plan to go far
|
||||
for (int i = 0; i < 0x80; i += 4) {
|
||||
undfInstruction = read32(undfHandler + i);
|
||||
if ((undfInstruction & 0xFFFF0000) == 0xE59F0000) { // find the first thing loaded relative to PC
|
||||
u32 addr = undfHandler + i + 8 + (undfInstruction & 0xFFF);
|
||||
// syscall instr mask stack args cnt map the actual syscall table (they are right next to each other)
|
||||
if (read32(addr) == 0xE6000010 && (read32(addr + 4) - read32(addr + 8)) < 0x400) { // this 0x400 (1024) is from the & 0xFF applied to the syscall # after it gets unmasked
|
||||
return SRAMNOMIRR(read32(addr + 8)); // the actual syscall table wooooooooo yeahh babyy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 IOSPATCH_Apply() {
|
||||
u32 count = 0;
|
||||
if (AHBPROT_DISABLED) {
|
||||
disable_memory_protection();
|
||||
//count += apply_patch("di_readlimit", di_readlimit_old, sizeof(di_readlimit_old), di_readlimit_patch, sizeof(di_readlimit_patch), 12);
|
||||
count += apply_patch("isfs_permissions", isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0);
|
||||
//count += apply_patch("es_setuid", setuid_old, sizeof(setuid_old), setuid_patch, sizeof(setuid_patch), 0);
|
||||
//count += apply_patch("es_identify", es_identify_old, sizeof(es_identify_old), es_identify_patch, sizeof(es_identify_patch), 2);
|
||||
count += apply_patch("hash_check", hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||
count += apply_patch("new_hash_check", new_hash_old, sizeof(new_hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||
count += apply_patch("ES_TitleVersionCheck", ES_TitleVersionCheck_old, sizeof(ES_TitleVersionCheck_old), ES_TitleVersionCheck_patch, sizeof(ES_TitleVersionCheck_patch), 0);
|
||||
count += apply_patch("ES_TitleDeleteCheck", ES_TitleDeleteCheck_old, sizeof(ES_TitleDeleteCheck_old), ES_TitleDeleteCheck_patch, sizeof(ES_TitleDeleteCheck_patch), 0);
|
||||
u32 *ptr_syscallTable = NULL;
|
||||
u32 ptr_IOSC_VerifyPublicKeySign = 0;
|
||||
static const u16 return0[] = {
|
||||
0x2000, // mov r0, #0
|
||||
0x4770, // bx lr
|
||||
};
|
||||
|
||||
if((*(vu16*)0xCD8005A0 == 0xCAFE))
|
||||
int IOSPATCH_Apply(void) {
|
||||
int fd = IOS_Open("/dev/dolphin", 0);
|
||||
IOS_Close(fd);
|
||||
if (fd >= 0)
|
||||
return 0;
|
||||
|
||||
int ret = fd = IOS_Open("/dev/sha", 0);
|
||||
IOS_Close(fd);
|
||||
if (ret < 0)
|
||||
return (ret == IPC_ENOENT) ? 0 : ret;
|
||||
|
||||
|
||||
ret = do_sha_exploit((u32)armCode);
|
||||
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
int clock = 1000;
|
||||
while (!AHBPROT_DISABLED) {
|
||||
if (clock-- == 0)
|
||||
return -0x123;
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
ptr_syscallTable = (u32 *)findTheSyscallTable();
|
||||
if (!ptr_syscallTable)
|
||||
return -0x105C;
|
||||
|
||||
ptr_IOSC_VerifyPublicKeySign = read32((u32)&ptr_syscallTable[0x6C]);
|
||||
|
||||
write16(MEM_PROT, 0);
|
||||
|
||||
IOSPATCH_SetSignatureChecks(false);
|
||||
// apply_patch(hash_old, sizeof(hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||
// apply_patch(new_hash_old, sizeof(new_hash_old), hash_patch, sizeof(hash_patch), 1);
|
||||
apply_patch(isfs_permissions_old, sizeof(isfs_permissions_old), isfs_permissions_patch, sizeof(isfs_permissions_patch), 0);
|
||||
apply_patch(ES_TitleVersionCheck_old, sizeof(ES_TitleVersionCheck_old), ES_TitleVersionCheck_patch, sizeof(ES_TitleVersionCheck_patch), 0);
|
||||
apply_patch(ES_TitleDeleteCheck_old, sizeof(ES_TitleDeleteCheck_old), ES_TitleDeleteCheck_patch, sizeof(ES_TitleDeleteCheck_patch), 0);
|
||||
apply_patch(ES_KeyslotPermissionCheck_old, sizeof(ES_KeyslotPermissionCheck_old), ES_KeyslotPermissionCheck_patch, sizeof(ES_KeyslotPermissionCheck_patch), 0);
|
||||
|
||||
if (IS_WIIU)
|
||||
{
|
||||
count += apply_patch("Kill_AntiSysTitleInstallv3_pt1", Kill_AntiSysTitleInstallv3_pt1_old, sizeof(Kill_AntiSysTitleInstallv3_pt1_old), Kill_AntiSysTitleInstallv3_pt1_patch, sizeof(Kill_AntiSysTitleInstallv3_pt1_patch), 0);
|
||||
count += apply_patch("Kill_AntiSysTitleInstallv3_pt2", Kill_AntiSysTitleInstallv3_pt2_old, sizeof(Kill_AntiSysTitleInstallv3_pt2_old), Kill_AntiSysTitleInstallv3_pt2_patch, sizeof(Kill_AntiSysTitleInstallv3_pt2_patch), 0);
|
||||
count += apply_patch("Kill_AntiSysTitleInstallv3_pt3", Kill_AntiSysTitleInstallv3_pt3_old, sizeof(Kill_AntiSysTitleInstallv3_pt3_old), Kill_AntiSysTitleInstallv3_pt3_patch, sizeof(Kill_AntiSysTitleInstallv3_pt3_patch), 0);
|
||||
apply_patch(Kill_AntiSysTitleInstallv3_pt1_old, sizeof(Kill_AntiSysTitleInstallv3_pt1_old), Kill_AntiSysTitleInstallv3_pt1_patch, sizeof(Kill_AntiSysTitleInstallv3_pt1_patch), 0);
|
||||
apply_patch(Kill_AntiSysTitleInstallv3_pt2_old, sizeof(Kill_AntiSysTitleInstallv3_pt2_old), Kill_AntiSysTitleInstallv3_pt2_patch, sizeof(Kill_AntiSysTitleInstallv3_pt2_patch), 0);
|
||||
apply_patch(Kill_AntiSysTitleInstallv3_pt3_old, sizeof(Kill_AntiSysTitleInstallv3_pt3_old), Kill_AntiSysTitleInstallv3_pt3_patch, sizeof(Kill_AntiSysTitleInstallv3_pt3_patch), 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
return count;
|
||||
|
||||
void IOSPATCH_SetSignatureChecks(bool enable)
|
||||
{
|
||||
if (!ptr_syscallTable)
|
||||
return;
|
||||
|
||||
u32 new = enable ? ptr_IOSC_VerifyPublicKeySign : (MEM_VIRTUAL_TO_PHYSICAL(return0) | 0x1);
|
||||
write32((u32)&ptr_syscallTable[0x6C], new);
|
||||
}
|
||||
|
@ -13,20 +13,12 @@
|
||||
#ifndef _IOSPATCH_H
|
||||
#define _IOSPATCH_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/* __cplusplus */
|
||||
|
||||
#include <gccore.h>
|
||||
#include <ogc/machine/processor.h>
|
||||
|
||||
#define AHBPROT_DISABLED ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||||
#define AHBPROT_DISABLED (read32(0xcd800064) != 0)
|
||||
|
||||
u32 IOSPATCH_AHBPROT();
|
||||
u32 IOSPATCH_Apply();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
int IOSPATCH_Apply();
|
||||
void IOSPATCH_SetSignatureChecks(bool);
|
||||
|
||||
#endif /* _IOSPATCH_H */
|
||||
|
@ -1,11 +0,0 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
static inline void *memalign32(size_t size)
|
||||
{
|
||||
return aligned_alloc(0x20, (size + 0x1F) & ~0x1F);
|
||||
}
|
||||
|
||||
static inline void *memalign64(size_t size)
|
||||
{
|
||||
return aligned_alloc(0x40, (size + 0x3F) & ~0x3F);
|
||||
}
|
378
source/menu.c
378
source/menu.c
@ -25,28 +25,13 @@
|
||||
#include "fileops.h"
|
||||
#include "menu.h"
|
||||
|
||||
/* NAND device list */
|
||||
nandDevice ndevList[] =
|
||||
{
|
||||
{ "Disable", 0, 0x00, 0x00 },
|
||||
{ "SD/SDHC Card", 1, 0xF0, 0xF1 },
|
||||
{ "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 },
|
||||
};
|
||||
|
||||
static nandDevice *ndev = NULL;
|
||||
|
||||
static int gSelected;
|
||||
|
||||
static bool gNeedPriiloaderOption = false;
|
||||
|
||||
/* Macros */
|
||||
#define NB_NAND_DEVICES (sizeof(ndevList) / sizeof(nandDevice))
|
||||
|
||||
// Local prototypes: wiiNinja
|
||||
void WaitPrompt (char *prompt);
|
||||
u32 WaitButtons(void);
|
||||
u32 Pad_GetButtons(void);
|
||||
void WiiLightControl (int state);
|
||||
#define ENTRIES_PER_PAGE (g_consoleHeight - 5)
|
||||
|
||||
void PriiloaderRetainedPrompt(void);
|
||||
|
||||
@ -68,10 +53,8 @@ static int __Menu_EntryCmp(const void *p1, const void *p2)
|
||||
fatFile *f2 = (fatFile *)p2;
|
||||
|
||||
/* Compare entries */ // wiiNinja: Include directory
|
||||
if ((f1->isdir) && !(f2->isdir))
|
||||
return (-1);
|
||||
else if (!(f1->isdir) && (f2->isdir))
|
||||
return (1);
|
||||
if (f1->isdir ^ f2->isdir)
|
||||
return f2->isdir - f1->isdir;
|
||||
else
|
||||
return strcasecmp(f1->filename, f2->filename);
|
||||
}
|
||||
@ -104,7 +87,7 @@ static s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen)
|
||||
bool iswad = false;
|
||||
size_t fsize = 0;
|
||||
|
||||
/* Hide entries that start with "._". I hate macOS */
|
||||
/* Hide entries that start with "._". I hate macOS. */
|
||||
if (!strncmp(ent->d_name, "._", 2))
|
||||
continue;
|
||||
|
||||
@ -187,7 +170,7 @@ static s32 __Menu_RetrieveList(char *inPath, fatFile **outbuf, u32 *outlen)
|
||||
|
||||
void Menu_SelectIOS(void)
|
||||
{
|
||||
u8 *iosVersion = NULL;
|
||||
u8 iosVersions[255] = {};
|
||||
u32 iosCnt;
|
||||
u8 tmpVersion;
|
||||
|
||||
@ -196,12 +179,12 @@ void Menu_SelectIOS(void)
|
||||
bool found = false;
|
||||
|
||||
/* Get IOS versions */
|
||||
ret = Title_GetIOSVersions(&iosVersion, &iosCnt);
|
||||
ret = Title_GetIOSVersions(iosVersions, &iosCnt);
|
||||
if (ret < 0)
|
||||
return;
|
||||
|
||||
/* Sort list */
|
||||
qsort(iosVersion, iosCnt, sizeof(u8), __Menu_IsGreater);
|
||||
qsort(iosVersions, iosCnt, sizeof(u8), __Menu_IsGreater);
|
||||
|
||||
if (gConfig.cIOSVersion < 0)
|
||||
{
|
||||
@ -218,7 +201,7 @@ void Menu_SelectIOS(void)
|
||||
/* Set default version */
|
||||
for (cnt = 0; cnt < iosCnt; cnt++)
|
||||
{
|
||||
u8 version = iosVersion[cnt];
|
||||
u8 version = iosVersions[cnt];
|
||||
|
||||
/* Custom IOS available */
|
||||
//if (version == CIOS_VERSION)
|
||||
@ -242,7 +225,7 @@ void Menu_SelectIOS(void)
|
||||
/* Clear console */
|
||||
Con_Clear();
|
||||
|
||||
printf("\t>> Select IOS version to use: < IOS%d >\n\n", iosVersion[selected]);
|
||||
printf("\t>> Select IOS version to use: < IOS%d >\n\n", iosVersions[selected]);
|
||||
|
||||
printf("\t Press LEFT/RIGHT to change IOS version.\n\n");
|
||||
|
||||
@ -271,7 +254,7 @@ void Menu_SelectIOS(void)
|
||||
}
|
||||
}
|
||||
|
||||
u8 version = iosVersion[selected];
|
||||
u8 version = iosVersions[selected];
|
||||
|
||||
if (IOS_GetVersion() != version) {
|
||||
/* Shutdown subsystems */
|
||||
@ -280,7 +263,7 @@ void Menu_SelectIOS(void)
|
||||
|
||||
|
||||
/* Load IOS */
|
||||
if (!loadIOS(version))
|
||||
if (Sys_LoadIOS(version) != 0)
|
||||
{
|
||||
Wpad_Init();
|
||||
Menu_SelectIOS();
|
||||
@ -337,14 +320,18 @@ void Menu_FatDevice(void)
|
||||
* 0xcc - vertical conjuction to right
|
||||
*/
|
||||
|
||||
char horizontal[60];
|
||||
char horizontal[80];
|
||||
memset(horizontal, 0xcd, sizeof(horizontal));
|
||||
|
||||
printf(" \xc9%.59s\xbb", horizontal);
|
||||
printf(" \xcc%.14sWelcome to YAWM ModMii Edition!%.14s\xb9", horizontal, horizontal);
|
||||
printf(" \xc8%.59s\xbc", horizontal);
|
||||
/*
|
||||
printf("\xc9%.*s\xbb", g_consoleWidth - 2, horizontal);
|
||||
//31
|
||||
printf("\xcc%.*sWelcome to YAWM ModMii Edition!%.*s\xb9", (g_consoleWidth - 33) / 2, horizontal, (g_consoleWidth - 32) / 2, horizontal);
|
||||
printf("\xc8%.*s\xbc", g_consoleWidth - 2, horizontal);
|
||||
*/
|
||||
|
||||
printf(" Running on IOS%u v%u (AHB access %s)\n\n", iosVersion, iosRevision, AHBPROT_DISABLED ? "enabled" : "disabled");
|
||||
printf(" -== Welcome to YAWM ModMii Edition! ==-\n");
|
||||
printf(" Running on IOS%u v%u (%u.%u)\n\n", iosVersion, iosRevision, iosRevision >> 8, iosRevision & 0xFF);
|
||||
|
||||
if (VersionIsOriginal(version))
|
||||
printf(" System menu: %s%c %s\n", GetSysMenuVersionString(version), region ?: '?', GetSysMenuRegionString(region)); // The ? should not appear any more, but, in any case.
|
||||
@ -476,10 +463,10 @@ void Menu_NandDevice(void)
|
||||
/* LEFT/RIGHT buttons */
|
||||
if (buttons & WPAD_BUTTON_LEFT) {
|
||||
if ((--selected) <= -1)
|
||||
selected = (NB_NAND_DEVICES - 1);
|
||||
selected = (ndevCount - 1);
|
||||
}
|
||||
if (buttons & WPAD_BUTTON_RIGHT) {
|
||||
if ((++selected) >= NB_NAND_DEVICES)
|
||||
if ((++selected) >= ndevCount)
|
||||
selected = 0;
|
||||
}
|
||||
|
||||
@ -533,20 +520,30 @@ err:
|
||||
|
||||
char gTmpFilePath[MAX_FILE_PATH_LEN];
|
||||
/* Install and/or Uninstall multiple WADs - Leathl */
|
||||
int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath)
|
||||
int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath, bool delete)
|
||||
{
|
||||
int installCnt = 0;
|
||||
int uninstallCnt = 0;
|
||||
int count;
|
||||
int wadcnt = 0;
|
||||
int ret = 0;
|
||||
fatFile* wads[fileCount];
|
||||
|
||||
for (fatFile* f = files; f < files + fileCount; f++) {
|
||||
if (f->install == 1) installCnt++; else
|
||||
if (f->install == 2) uninstallCnt++;
|
||||
switch (f->install) {
|
||||
case 1:
|
||||
wads[wadcnt++] = f;
|
||||
installCnt++;
|
||||
break;
|
||||
case 2:
|
||||
wads[wadcnt++] = f;
|
||||
uninstallCnt++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(installCnt || uninstallCnt))
|
||||
return 0;
|
||||
|
||||
/*
|
||||
for (;;)
|
||||
{
|
||||
Con_Clear();
|
||||
@ -678,6 +675,139 @@ int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
char *ptr_fname = gTmpFilePath + sprintf(gTmpFilePath, "%s/", inFilePath);
|
||||
|
||||
int start = 0; // No cursor here so we just need start
|
||||
while (true)
|
||||
{
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] List of WADs to %sinstall%s:\n\n", uninstallCnt ? "(un)" : "", delete ? " and delete" : "");
|
||||
for (int i = 0; i < ENTRIES_PER_PAGE; i++)
|
||||
{
|
||||
int index = start + i;
|
||||
if (index >= wadcnt) // Data store interrupt safety!!
|
||||
putchar('\n');
|
||||
else
|
||||
printf(" %c %.50s\n", " +-"[wads[index]->install], wads[index]->filename);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
puts("[+] A: Continue UP/DOWN: Move list");
|
||||
puts(" B: Cancel -/R: Toggle deletion");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (buttons & WPAD_BUTTON_UP)
|
||||
{
|
||||
if (start) start--;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_DOWN)
|
||||
{
|
||||
if (wadcnt - start > ENTRIES_PER_PAGE) start++;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_A)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_B)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_MINUS)
|
||||
{
|
||||
delete ^= true;
|
||||
}
|
||||
}
|
||||
|
||||
WiiLightControl(WII_LIGHT_ON);
|
||||
|
||||
for (int i = 0; i < wadcnt; i++)
|
||||
{
|
||||
fatFile *f = wads[i];
|
||||
FILE *fp = NULL;
|
||||
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] Processing WAD %i/%i...\n\n", i + 1, wadcnt);
|
||||
|
||||
printf("[+] Opening \"%s\", please wait... ", f->filename);
|
||||
strcpy(ptr_fname, f->filename);
|
||||
fp = fopen(gTmpFilePath, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
printf("ERROR!\n");
|
||||
perror(" ");
|
||||
f->installstate = ret = -996;
|
||||
}
|
||||
else
|
||||
{
|
||||
puts("OK!");
|
||||
printf(" >> %s WAD...\n", f->install == 1 ? "Installing" : "Uninstalling");
|
||||
f->installstate = ret = (f->install == 1 ? Wad_Install : Wad_Uninstall)(fp);
|
||||
fclose(fp);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (delete)
|
||||
{
|
||||
printf(" >> Deleting WAD... ");
|
||||
// ret = FSOPDeleteFile(gTmpFilePath);
|
||||
ret = remove(gTmpFilePath);
|
||||
if (!ret)
|
||||
puts("OK!");
|
||||
else
|
||||
printf("ERROR! (errno=%i)\n", errno);
|
||||
}
|
||||
} else
|
||||
|
||||
if (ret == -1010)
|
||||
{
|
||||
do { wads[i++]->installstate = -1010; } while (i < wadcnt);
|
||||
WaitPrompt("Wii System Memory is full. Installation terminated...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
usleep((!ret) ? 500000 : 4000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
start = 0;
|
||||
while (true)
|
||||
{
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] End results:\n\n");
|
||||
|
||||
for (int i = 0; i < ENTRIES_PER_PAGE; i++)
|
||||
{
|
||||
int index = start + i;
|
||||
if (index >= wadcnt) // Data store interrupt safety!!
|
||||
putchar('\n');
|
||||
else
|
||||
printf(" %-.32s: %s\n", wads[index]->filename, wad_strerror(wads[index]->installstate));
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
puts("[+] A: Continue UP/DOWN: Move list");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (buttons & WPAD_BUTTON_UP)
|
||||
{
|
||||
if (start) start--;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_DOWN)
|
||||
{
|
||||
if (wadcnt - start > ENTRIES_PER_PAGE) start++;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_A)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gNeedPriiloaderOption)
|
||||
{
|
||||
@ -685,11 +815,6 @@ int Menu_BatchProcessWads(fatFile *files, int fileCount, char *inFilePath)
|
||||
|
||||
gNeedPriiloaderOption = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("\n Press any button to continue...\n");
|
||||
WaitButtons();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -761,15 +886,11 @@ int Menu_FolderOperations(fatFile* file, char* path)
|
||||
{
|
||||
int ret;
|
||||
|
||||
char workpath[MAX_FILE_PATH_LEN];
|
||||
|
||||
fatFile *flist = NULL;
|
||||
unsigned int fcnt = 0;
|
||||
unsigned int wadcnt = 0;
|
||||
|
||||
char* ptr_fname = workpath + sprintf(workpath, "%s%s/", path, file->filename);
|
||||
|
||||
ret = __Menu_RetrieveList(workpath, &flist, &fcnt);
|
||||
ret = __Menu_RetrieveList(path, &flist, &fcnt);
|
||||
if (ret != 0)
|
||||
{
|
||||
WaitPrompt("__Menu_RetrieveList failed");
|
||||
@ -802,6 +923,7 @@ int Menu_FolderOperations(fatFile* file, char* path)
|
||||
if (buttons & (WPAD_BUTTON_LEFT | WPAD_BUTTON_RIGHT))
|
||||
mode ^= 1;
|
||||
|
||||
|
||||
if (buttons & WPAD_BUTTON_A)
|
||||
break;
|
||||
|
||||
@ -815,128 +937,10 @@ int Menu_FolderOperations(fatFile* file, char* path)
|
||||
goto finish;
|
||||
}
|
||||
|
||||
int start = 0; // No cursor here so we just need start
|
||||
while (true)
|
||||
{
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] List of WADs to %s:\n\n", mode ? "install and delete" : "install");
|
||||
for (int i = 0; i < ENTRIES_PER_PAGE; i++)
|
||||
{
|
||||
int index = start + i;
|
||||
if (index >= wadcnt) // Data store interrupt safety!!
|
||||
putchar('\n');
|
||||
else
|
||||
printf(" %.50s\n", wads[index]->filename);
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
printf("[+] Press UP/DOWN to move list.\n");
|
||||
printf(" Press A to continue.\n");
|
||||
printf(" Press B to cancel.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (buttons & WPAD_BUTTON_UP)
|
||||
{
|
||||
if (start) start--;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_DOWN)
|
||||
{
|
||||
if (wadcnt - start > ENTRIES_PER_PAGE) start++;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_A)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_B)
|
||||
{
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < wadcnt; i++)
|
||||
{
|
||||
fatFile *f = wads[i];
|
||||
FILE *fp = NULL;
|
||||
wads[i]->install = 1;
|
||||
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] Processing WAD %i/%i...\n\n", i + 1, wadcnt);
|
||||
|
||||
printf("[+] Opening \"%s\", please wait...\n", f->filename);
|
||||
strcpy(ptr_fname, f->filename);
|
||||
fp = fopen(workpath, "rb");
|
||||
if (!fp)
|
||||
{
|
||||
printf(" ERROR! (errno=%i)\n", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
// puts(">> Installing WAD...");
|
||||
f->installstate = ret = Wad_Install(fp);
|
||||
fclose(fp);
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
if (mode == 1)
|
||||
{
|
||||
printf(">> Deleting WAD... ");
|
||||
// ret = FSOPDeleteFile(workpath);
|
||||
ret = remove(workpath);
|
||||
if (!ret)
|
||||
puts("OK!");
|
||||
else
|
||||
printf("ERROR! (errno=%i)\n", errno);
|
||||
}
|
||||
}
|
||||
else if (ret == -1010)
|
||||
{
|
||||
do { wads[i++]->installstate = -1010; } while (i < wadcnt);
|
||||
WaitPrompt("Wii System Memory is full to the brim. Installation terminated...\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
usleep((!ret) ? 500000 : 4000000);
|
||||
continue;
|
||||
}
|
||||
|
||||
start = 0;
|
||||
while (true)
|
||||
{
|
||||
Con_Clear();
|
||||
|
||||
printf("[+] End results:\n\n");
|
||||
|
||||
for (int i = 0; i < ENTRIES_PER_PAGE; i++)
|
||||
{
|
||||
int index = start + i;
|
||||
if (index >= wadcnt) // Data store interrupt safety!!
|
||||
putchar('\n');
|
||||
else
|
||||
printf(" %-.32s: %s\n", wads[index]->filename, wad_strerror(wads[index]->installstate));
|
||||
}
|
||||
|
||||
putchar('\n');
|
||||
printf("[+] Press UP/DOWN to move list.\n");
|
||||
printf(" Press A to continue.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (buttons & WPAD_BUTTON_UP)
|
||||
{
|
||||
if (start) start--;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_DOWN)
|
||||
{
|
||||
if (wadcnt - start > ENTRIES_PER_PAGE) start++;
|
||||
}
|
||||
else if (buttons & WPAD_BUTTON_A)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
Menu_BatchProcessWads(flist, fcnt, path, mode == 1);
|
||||
|
||||
finish:
|
||||
free(flist);
|
||||
@ -1085,7 +1089,7 @@ void Menu_WadList(void)
|
||||
fflush(stdout);
|
||||
|
||||
// if user provides startup directory, try it out first
|
||||
if (strcmp(gConfig.startupPath, WAD_DIRECTORY) != 0)
|
||||
if (*gConfig.startupPath != '\0')
|
||||
{
|
||||
// replace root dir with provided startup directory
|
||||
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), gConfig.startupPath);
|
||||
@ -1098,7 +1102,7 @@ void Menu_WadList(void)
|
||||
goto getList;
|
||||
}
|
||||
|
||||
sprintf(tmpPath, "%s:%s", FatGetDevicePrefix(gSelected), WAD_DIRECTORY);
|
||||
sprintf(tmpPath, "%s:/", FatGetDevicePrefix(gSelected));
|
||||
|
||||
/* Retrieve filelist */
|
||||
getList:
|
||||
@ -1155,23 +1159,25 @@ getList:
|
||||
if ((cnt - start) >= ENTRIES_PER_PAGE)
|
||||
break;
|
||||
|
||||
|
||||
/* Print filename */
|
||||
//printf("\t%2s %s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize);
|
||||
if (file->isdir) // wiiNinja
|
||||
{
|
||||
printf("\t%2s [%.40s]\n", (cnt == selected) ? ">>" : " ", file->filename);
|
||||
printf("\t%2s [%.*s]\n", (cnt == selected) ? ">>" : " ", g_consoleWidth - 7, file->filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(file->iswad)
|
||||
printf("\t%2s%c%.40s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", " +-"[file->install], file->filename, filesize);
|
||||
printf("\t%2s%c%.*s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", " +-"[file->install], g_consoleWidth - 7, file->filename, filesize);
|
||||
else
|
||||
printf("\t%2s %.40s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", file->filename, filesize);
|
||||
printf("\t%2s %.*s (%.2f MB)\n", (cnt == selected) ? ">>" : " ", g_consoleWidth - 7, file->filename, filesize);
|
||||
}
|
||||
}
|
||||
|
||||
while ((cnt++ - start) < ENTRIES_PER_PAGE)
|
||||
putchar('\n');
|
||||
|
||||
putchar('\n'); // One more newline!
|
||||
fatFile *file = &fileList[selected];
|
||||
// There is only one occurence of /, likely because we are at the root!
|
||||
bool atRoot = (strchr(tmpPath, '/') == strrchr(tmpPath, '/'));
|
||||
@ -1197,8 +1203,9 @@ getList:
|
||||
operationA = "Enter directory";
|
||||
|
||||
// "[+] A: Install/Uninstall WAD"
|
||||
printf("[+] A: %-23s" "B: %s\n", operationA, operationB);
|
||||
printf(" 1/R: %-23s" "2/L: Enable batch mode", operationR);
|
||||
unsigned somewidth = g_consoleWidth / 2;
|
||||
printf("[+] A: %-*s" "B: %-*s\n", somewidth - 9, operationA, somewidth - 6, operationB);
|
||||
printf(" 1/R: %-*s" "2/L: Enable batch mode", somewidth - 9, operationR);
|
||||
}
|
||||
|
||||
|
||||
@ -1299,7 +1306,7 @@ getList:
|
||||
{
|
||||
if (batchMode)
|
||||
{
|
||||
int res = Menu_BatchProcessWads(fileList, fileCnt, tmpPath);
|
||||
int res = Menu_BatchProcessWads(fileList, fileCnt, tmpPath, false);
|
||||
|
||||
if (res == 1)
|
||||
{
|
||||
@ -1374,15 +1381,6 @@ err:
|
||||
void Menu_Loop(void)
|
||||
{
|
||||
u8 iosVersion;
|
||||
if (AHBPROT_DISABLED)
|
||||
{
|
||||
IOSPATCH_Apply();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Select IOS menu */
|
||||
Menu_SelectIOS();
|
||||
}
|
||||
|
||||
/* Retrieve IOS version */
|
||||
iosVersion = IOS_GetVersion();
|
||||
@ -1463,9 +1461,11 @@ char *PeekCurrentDir (void)
|
||||
}
|
||||
#endif
|
||||
|
||||
void WaitPrompt (char *prompt)
|
||||
void WaitPrompt (const char *prompt)
|
||||
{
|
||||
if (prompt)
|
||||
printf("\n%s", prompt);
|
||||
|
||||
printf(" Press any button to continue...\n");
|
||||
|
||||
/* Wait for button */
|
||||
|
@ -2,6 +2,9 @@
|
||||
#define _MENU_H_
|
||||
|
||||
/* Prototypes */
|
||||
void WaitPrompt(const char *prompt);
|
||||
u32 WaitButtons(void);
|
||||
void WiiLightControl (int state);
|
||||
void Menu_Loop(void);
|
||||
void SetPriiloaderOption(bool enabled);
|
||||
bool MenuTestDevice();
|
||||
|
@ -1,267 +0,0 @@
|
||||
/*
|
||||
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||
SEEPROM support
|
||||
|
||||
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
|
||||
Copyright (C) 2008, 2009 Haxx Enterprises <bushing@gmail.com>
|
||||
Copyright (C) 2008, 2009 Hector Martin "marcan" <marcan@marcansoft.com>
|
||||
Copyright (C) 2008, 2009 John Kelley <wiidev@kelley.ca>
|
||||
Copyright (C) 2020 Pablo Curiel "DarkMatterCore" <pabloacurielz@gmail.com>
|
||||
|
||||
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||
# see http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
*/
|
||||
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "mini_seeprom.h"
|
||||
|
||||
#define HW_REG_BASE 0xd800000
|
||||
#define HW_GPIO1OUT (HW_REG_BASE + 0x0e0)
|
||||
#define HW_GPIO1IN (HW_REG_BASE + 0x0e8)
|
||||
|
||||
#define HW_SEEPROM_BLK_SIZE 2
|
||||
#define HW_SEEPROM_BLK_CNT (SEEPROM_SIZE / HW_SEEPROM_BLK_SIZE)
|
||||
|
||||
#define eeprom_delay() usleep(5)
|
||||
|
||||
enum {
|
||||
GP_EEP_CS = 0x000400,
|
||||
GP_EEP_CLK = 0x000800,
|
||||
GP_EEP_MOSI = 0x001000,
|
||||
GP_EEP_MISO = 0x002000
|
||||
};
|
||||
|
||||
static void seeprom_send_bits(u16 value, u8 bits)
|
||||
{
|
||||
if (!bits || bits > 16) return;
|
||||
|
||||
while(bits--)
|
||||
{
|
||||
if (value & (1 << bits))
|
||||
{
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_MOSI);
|
||||
} else {
|
||||
mask32(HW_GPIO1OUT, GP_EEP_MOSI, 0);
|
||||
}
|
||||
|
||||
eeprom_delay();
|
||||
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CLK);
|
||||
eeprom_delay();
|
||||
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CLK, 0);
|
||||
eeprom_delay();
|
||||
}
|
||||
}
|
||||
|
||||
static u16 seeprom_recv_bits(u8 bits)
|
||||
{
|
||||
if (!bits || bits > 16) return 0;
|
||||
|
||||
int res = 0;
|
||||
|
||||
while(bits--)
|
||||
{
|
||||
res <<= 1;
|
||||
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CLK);
|
||||
eeprom_delay();
|
||||
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CLK, 0);
|
||||
eeprom_delay();
|
||||
|
||||
res |= !!(read32(HW_GPIO1IN) & GP_EEP_MISO);
|
||||
}
|
||||
|
||||
return (u16)res;
|
||||
}
|
||||
|
||||
u16 seeprom_read(void *dst, u16 offset, u16 size)
|
||||
{
|
||||
/*
|
||||
* WiiUBrew told me that you interact with the SEEPROM the exact same way you do on Wii.
|
||||
* However the contents are way different. Like there's absolutely no vWii stuff here.
|
||||
*/
|
||||
if (read16(0xCD8005A0) == 0xCAFE) return 0;
|
||||
|
||||
if (!dst || offset >= SEEPROM_SIZE || !size || (offset + size) > SEEPROM_SIZE) return 0;
|
||||
|
||||
u16 cur_offset = 0;
|
||||
|
||||
u8 *ptr = (u8*)dst;
|
||||
u8 val[HW_SEEPROM_BLK_SIZE] = {0};
|
||||
|
||||
// Calculate block offsets and sizes
|
||||
u8 start_addr = (u8)(offset / HW_SEEPROM_BLK_SIZE);
|
||||
u8 start_addr_offset = (u8)(offset % HW_SEEPROM_BLK_SIZE);
|
||||
|
||||
u8 end_addr = (u8)((offset + size) / HW_SEEPROM_BLK_SIZE);
|
||||
u8 end_addr_size = (u8)((offset + size) % HW_SEEPROM_BLK_SIZE);
|
||||
|
||||
if (!end_addr_size)
|
||||
{
|
||||
end_addr--;
|
||||
end_addr_size = HW_SEEPROM_BLK_SIZE;
|
||||
}
|
||||
|
||||
if (end_addr == start_addr) end_addr_size -= start_addr_offset;
|
||||
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CLK, 0);
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
for(u16 i = start_addr; i <= end_addr; i++)
|
||||
{
|
||||
if (cur_offset >= size) break;
|
||||
|
||||
// Start command cycle
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
|
||||
// Send read command + address
|
||||
seeprom_send_bits(0x600 | i, 11);
|
||||
|
||||
// Receive data
|
||||
*((u16*)val) = seeprom_recv_bits(16);
|
||||
|
||||
// End of command cycle
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
// Copy read data to destination buffer
|
||||
if (i == start_addr && start_addr_offset != 0)
|
||||
{
|
||||
// Handle unaligned read at start address
|
||||
memcpy(ptr + cur_offset, val + start_addr_offset, HW_SEEPROM_BLK_SIZE - start_addr_offset);
|
||||
cur_offset += (HW_SEEPROM_BLK_SIZE - start_addr_offset);
|
||||
} else
|
||||
if (i == end_addr && end_addr_size != HW_SEEPROM_BLK_SIZE)
|
||||
{
|
||||
// Handle unaligned read at end address
|
||||
memcpy(ptr + cur_offset, val, end_addr_size);
|
||||
cur_offset += end_addr_size;
|
||||
} else {
|
||||
// Normal read
|
||||
memcpy(ptr + cur_offset, val, HW_SEEPROM_BLK_SIZE);
|
||||
cur_offset += HW_SEEPROM_BLK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return cur_offset;
|
||||
}
|
||||
|
||||
#if 0
|
||||
u16 seeprom_write(const void *src, u16 offset, u16 size)
|
||||
{
|
||||
if (!src || offset >= SEEPROM_SIZE || !size || (offset + size) > SEEPROM_SIZE) return 0;
|
||||
|
||||
u32 level = 0;
|
||||
u16 cur_offset = 0;
|
||||
|
||||
const u8 *ptr = (const u8*)src;
|
||||
u8 val[HW_SEEPROM_BLK_SIZE] = {0};
|
||||
|
||||
// Calculate block offsets and sizes
|
||||
u8 start_addr = (u8)(offset / HW_SEEPROM_BLK_SIZE);
|
||||
u8 start_addr_offset = (u8)(offset % HW_SEEPROM_BLK_SIZE);
|
||||
|
||||
u8 end_addr = (u8)((offset + size) / HW_SEEPROM_BLK_SIZE);
|
||||
u8 end_addr_size = (u8)((offset + size) % HW_SEEPROM_BLK_SIZE);
|
||||
|
||||
if (!end_addr_size)
|
||||
{
|
||||
end_addr--;
|
||||
end_addr_size = HW_SEEPROM_BLK_SIZE;
|
||||
}
|
||||
|
||||
if (end_addr == start_addr) end_addr_size -= start_addr_offset;
|
||||
|
||||
// Disable CPU interruptions
|
||||
_CPU_ISR_Disable(level);
|
||||
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CLK, 0);
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
// EWEN - Enable programming commands
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
seeprom_send_bits(0x4FF, 11);
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
for(u16 i = start_addr; i <= end_addr; i++)
|
||||
{
|
||||
if (cur_offset >= size) break;
|
||||
|
||||
// Copy data to write from source buffer
|
||||
if ((i == start_addr && start_addr_offset != 0) || (i == end_addr && end_addr_size != HW_SEEPROM_BLK_SIZE))
|
||||
{
|
||||
// Read data from SEEPROM to handle unaligned writes
|
||||
|
||||
// Start command cycle
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
|
||||
// Send read command + address
|
||||
seeprom_send_bits(0x600 | i, 11);
|
||||
|
||||
// Receive data
|
||||
*((u16*)val) = seeprom_recv_bits(16);
|
||||
|
||||
// End of command cycle
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
if (i == start_addr && start_addr_offset != 0)
|
||||
{
|
||||
// Handle unaligned write at start address
|
||||
memcpy(val + start_addr_offset, ptr + cur_offset, HW_SEEPROM_BLK_SIZE - start_addr_offset);
|
||||
cur_offset += (HW_SEEPROM_BLK_SIZE - start_addr_offset);
|
||||
} else {
|
||||
// Handle unaligned write at end address
|
||||
memcpy(val, ptr + cur_offset, end_addr_size);
|
||||
cur_offset += end_addr_size;
|
||||
}
|
||||
} else {
|
||||
// Normal write
|
||||
memcpy(val, ptr + cur_offset, HW_SEEPROM_BLK_SIZE);
|
||||
cur_offset += HW_SEEPROM_BLK_SIZE;
|
||||
}
|
||||
|
||||
// Start command cycle
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
|
||||
// Send write command + address
|
||||
seeprom_send_bits(0x500 | i, 11);
|
||||
|
||||
// Send data
|
||||
seeprom_send_bits(*((u16*)val), 16);
|
||||
|
||||
// End of command cycle
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
// Wait until SEEPROM is ready (write cycle is self-timed so no clocking needed)
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
|
||||
do {
|
||||
eeprom_delay();
|
||||
} while(!(read32(HW_GPIO1IN) & GP_EEP_MISO));
|
||||
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
}
|
||||
|
||||
// EWDS - Disable programming commands
|
||||
mask32(HW_GPIO1OUT, 0, GP_EEP_CS);
|
||||
seeprom_send_bits(0x400, 11);
|
||||
mask32(HW_GPIO1OUT, GP_EEP_CS, 0);
|
||||
eeprom_delay();
|
||||
|
||||
// Enable CPU interruptions
|
||||
_CPU_ISR_Restore(level);
|
||||
|
||||
return cur_offset;
|
||||
}
|
||||
#endif
|
@ -1,59 +0,0 @@
|
||||
/*
|
||||
mini - a Free Software replacement for the Nintendo/BroadOn IOS.
|
||||
SEEPROM support
|
||||
|
||||
Copyright (C) 2008, 2009 Sven Peter <svenpeter@gmail.com>
|
||||
|
||||
# This code is licensed to you under the terms of the GNU GPL, version 2;
|
||||
# see http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
*/
|
||||
|
||||
#ifndef __MINI_SEEPROM_H__
|
||||
#define __MINI_SEEPROM_H__
|
||||
|
||||
#define SEEPROM_SIZE 0x100
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
u8 boot2version;
|
||||
u8 unknown1;
|
||||
u8 unknown2;
|
||||
u8 pad;
|
||||
u32 update_tag;
|
||||
};
|
||||
u8 data[8];
|
||||
};
|
||||
u16 checksum; // sum of data[] elements?
|
||||
} __attribute__((packed)) eep_boot2_ctr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union {
|
||||
u32 nand_gen; // matches offset 0x8 in nand SFFS blocks
|
||||
u8 data[4];
|
||||
};
|
||||
u16 checksum; // sum of data[] elements?
|
||||
} __attribute__((packed)) eep_nand_ctr_t;
|
||||
|
||||
struct SEEPROM
|
||||
{
|
||||
u32 ms_id; // 0x00000002
|
||||
u32 ca_id; // 0x00000001
|
||||
u32 ng_key_id;
|
||||
u8 ng_sig[60];
|
||||
eep_boot2_ctr_t boot2_counters[2];
|
||||
eep_nand_ctr_t nand_counters[3]; // current slot rotates on each write
|
||||
u8 pad0[6];
|
||||
u8 korean_key[16];
|
||||
u8 pad1[116];
|
||||
u16 prng_seed[2]; // u32 with lo word stored first, incremented every time IOS starts. Used with the PRNG key to setup IOS's PRNG (syscalls 73/74 etc.)
|
||||
u8 pad2[4];
|
||||
};
|
||||
_Static_assert(sizeof(struct SEEPROM) == SEEPROM_SIZE, "SEEPROM struct size incorrect!");
|
||||
|
||||
u16 seeprom_read(void *dst, u16 offset, u16 size);
|
||||
// u16 seeprom_write(const void *src, u16 offset, u16 size);
|
||||
|
||||
#endif /* __MINI_SEEPROM_H__ */
|
@ -4,13 +4,21 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "nand.h"
|
||||
#include "malloc.h"
|
||||
#include "utils.h"
|
||||
#include "fileops.h"
|
||||
|
||||
/* Buffer */
|
||||
static u32 inbuf[8] ATTRIBUTE_ALIGN(32);
|
||||
static bool gNandInitialized = false;
|
||||
|
||||
/* NAND device list */
|
||||
nandDevice ndevList[] =
|
||||
{
|
||||
{ "Disable", 0, 0x00, 0x00 },
|
||||
{ "SD/SDHC Card", 1, 0xF0, 0xF1 },
|
||||
{ "USB 2.0 Mass Storage Device", 2, 0xF2, 0xF3 },
|
||||
};
|
||||
const int ndevCount = (sizeof(ndevList) / sizeof(nandDevice));
|
||||
|
||||
s32 Nand_Mount(nandDevice *dev)
|
||||
{
|
||||
|
@ -20,6 +20,8 @@ typedef struct
|
||||
int type;
|
||||
} NameList;
|
||||
|
||||
extern nandDevice ndevList[];
|
||||
extern const int ndevCount;
|
||||
|
||||
/* Prototypes */
|
||||
s32 Nand_Mount(nandDevice *);
|
||||
|
67
source/otp.c
67
source/otp.c
@ -1,67 +0,0 @@
|
||||
#include <ogc/machine/processor.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "otp.h"
|
||||
|
||||
#define HW_OTP_COMMAND (*(vu32*)0xCD8001EC)
|
||||
#define HW_OTP_DATA (*(vu32*)0xCD8001F0)
|
||||
|
||||
#define HW_OTP_BLK_SIZE 4
|
||||
#define HW_OTP_BLK_CNT (OTP_SIZE / HW_OTP_BLK_SIZE)
|
||||
|
||||
u8 otp_read(void *dst, u8 offset, u8 size)
|
||||
{
|
||||
if (!dst || offset >= OTP_SIZE || !size || (offset + size) > OTP_SIZE) return 0;
|
||||
|
||||
u8 cur_offset = 0;
|
||||
|
||||
u8 *ptr = (u8*)dst;
|
||||
u8 val[HW_OTP_BLK_SIZE] = {0};
|
||||
|
||||
// Calculate block offsets and sizes
|
||||
u8 start_addr = (offset / HW_OTP_BLK_SIZE);
|
||||
u8 start_addr_offset = (offset % HW_OTP_BLK_SIZE);
|
||||
|
||||
u8 end_addr = ((offset + size) / HW_OTP_BLK_SIZE);
|
||||
u8 end_addr_size = ((offset + size) % HW_OTP_BLK_SIZE);
|
||||
|
||||
if (!end_addr_size)
|
||||
{
|
||||
end_addr--;
|
||||
end_addr_size = HW_OTP_BLK_SIZE;
|
||||
}
|
||||
|
||||
if (end_addr == start_addr) end_addr_size -= start_addr_offset;
|
||||
|
||||
for(u8 i = start_addr; i <= end_addr; i++)
|
||||
{
|
||||
if (cur_offset >= size) break;
|
||||
|
||||
// Send command + address
|
||||
HW_OTP_COMMAND = (0x80000000 | i);
|
||||
|
||||
// Receive data
|
||||
*((u32*)val) = HW_OTP_DATA;
|
||||
|
||||
// Copy read data to destination buffer
|
||||
if (i == start_addr && start_addr_offset != 0)
|
||||
{
|
||||
// Handle unaligned read at start address
|
||||
memcpy(ptr + cur_offset, val + start_addr_offset, HW_OTP_BLK_SIZE - start_addr_offset);
|
||||
cur_offset += (HW_OTP_BLK_SIZE - start_addr_offset);
|
||||
} else
|
||||
if (i == end_addr && end_addr_size != HW_OTP_BLK_SIZE)
|
||||
{
|
||||
// Handle unaligned read at end address
|
||||
memcpy(ptr + cur_offset, val, end_addr_size);
|
||||
cur_offset += end_addr_size;
|
||||
} else {
|
||||
// Normal read
|
||||
memcpy(ptr + cur_offset, val, HW_OTP_BLK_SIZE);
|
||||
cur_offset += HW_OTP_BLK_SIZE;
|
||||
}
|
||||
}
|
||||
|
||||
return cur_offset;
|
||||
}
|
29
source/otp.h
29
source/otp.h
@ -1,29 +0,0 @@
|
||||
#ifndef __OTP_H__
|
||||
#define __OTP_H__
|
||||
|
||||
#define OTP_SIZE 0x80
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 boot1_hash[20];
|
||||
u8 common_key[16];
|
||||
u8 ng_id[4];
|
||||
union { // first two bytes of nand_hmac overlap last two bytes of ng_priv
|
||||
struct {
|
||||
u8 ng_priv[30];
|
||||
u8 _wtf1[18];
|
||||
};
|
||||
struct {
|
||||
u8 _wtf2[28];
|
||||
u8 nand_hmac[20];
|
||||
};
|
||||
};
|
||||
u8 nand_key[16];
|
||||
u8 rng_key[16];
|
||||
u32 unk1;
|
||||
u32 unk2; // 0x00000007
|
||||
} otp_t;
|
||||
|
||||
u8 otp_read(void *dst, u8 offset, u8 size);
|
||||
|
||||
#endif /* __OTP_H__ */
|
@ -1,6 +0,0 @@
|
||||
.rodata
|
||||
|
||||
.globl bgData
|
||||
.balign 32
|
||||
bgData:
|
||||
.incbin "../data/background"
|
121
source/sys.c
121
source/sys.c
@ -6,17 +6,11 @@
|
||||
|
||||
#include "sys.h"
|
||||
#include "nand.h"
|
||||
#include "mini_seeprom.h"
|
||||
#include "malloc.h"
|
||||
#include "utils.h"
|
||||
#include "mload.h"
|
||||
#include "ehcmodule_elf.h"
|
||||
|
||||
/* Constants */
|
||||
#define CERTS_LEN 0x280
|
||||
|
||||
/* Variables */
|
||||
static const char certs_fs[] ATTRIBUTE_ALIGN(32) = "/sys/cert.sys";
|
||||
u32 boot2version;
|
||||
static bool gDisablePRButtons = false;
|
||||
|
||||
void __Sys_ResetCallback(__attribute__((unused)) u32 irq, __attribute__((unused)) void *ctx)
|
||||
@ -33,57 +27,46 @@ void __Sys_PowerCallback(void)
|
||||
Sys_Shutdown();
|
||||
}
|
||||
|
||||
bool tmdIsStubIOS(tmd* p_tmd)
|
||||
{
|
||||
return
|
||||
p_tmd->sys_version >> 32 == 0
|
||||
&& p_tmd->num_contents == 3
|
||||
&& p_tmd->contents[0].type == 0x0001
|
||||
&& p_tmd->contents[1].type == 0x8001
|
||||
&& p_tmd->contents[2].type == 0x8001;
|
||||
}
|
||||
|
||||
// we should be gangster and call the real ioctlv 69
|
||||
// (in all honesty I really don't like the blind copies of otp.c and mini_seeprom.c I added)
|
||||
bool ES_CheckHasKoreanKey(void)
|
||||
{
|
||||
aeskey korean_key;
|
||||
unsigned char iv[16] = {};
|
||||
|
||||
__attribute__ ((__aligned__(0x10)))
|
||||
ATTRIBUTE_ALIGN(0x20)
|
||||
unsigned char data[16] = { 0x56, 0x52, 0x6f, 0x63, 0xa1, 0x2c, 0xd1, 0x32, 0x07, 0x99, 0x82, 0x3b, 0x1b, 0x08, 0x17, 0xd0 };
|
||||
u32 iv[4] = {};
|
||||
|
||||
if (seeprom_read(korean_key, offsetof(struct SEEPROM, korean_key), sizeof(korean_key)) != sizeof(korean_key))
|
||||
return false;
|
||||
|
||||
AES_Decrypt(korean_key, 0x10, iv, 0x10, data, data, sizeof(data));
|
||||
int ret = ES_Decrypt(11, iv, data, sizeof(data), data);
|
||||
|
||||
// return (!strcmp((char*) data, "thepikachugamer")) Just remembered that this is how the Trucha bug came to be
|
||||
return (!memcmp(data, "thepikachugamer", sizeof(data)));
|
||||
return (ret == 0) && (!memcmp(data, "thepikachugamer", sizeof(data)));
|
||||
}
|
||||
|
||||
bool isIOSstub(u8 ios_number)
|
||||
bool Sys_CanLoadIOS(int ios)
|
||||
{
|
||||
int ret;
|
||||
u32 tmd_size = 0;
|
||||
tmd_view *ios_tmd;
|
||||
u32 boot2version = 0;
|
||||
tmd_view *view;
|
||||
|
||||
if ((boot2version >= 5) && (ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224))
|
||||
ES_GetBoot2Version(&boot2version);
|
||||
if ((boot2version >= 5) && (ios == 202 || ios == 222 || ios == 223 || ios == 224))
|
||||
return true;
|
||||
|
||||
ES_GetTMDViewSize(0x0000000100000000ULL | ios_number, &tmd_size);
|
||||
if (!tmd_size)
|
||||
ret = ES_GetTMDViewSize(0x0000000100000000ULL | ios, &tmd_size);
|
||||
if (ret < 0)
|
||||
return true;
|
||||
|
||||
view = memalign32(tmd_size);
|
||||
if (!view)
|
||||
return true;
|
||||
|
||||
ret = ES_GetTMDView(0x0000000100000000ULL | ios, (u8 *)view, tmd_size);
|
||||
if (ret < 0)
|
||||
{
|
||||
// getting size failed. invalid or fake tmd for sure!
|
||||
// gprintf("failed to get tmd for ios %d\n",ios_number);
|
||||
free(view);
|
||||
return true;
|
||||
}
|
||||
ios_tmd = memalign32(tmd_size);
|
||||
if (!ios_tmd)
|
||||
{
|
||||
// gprintf("failed to mem align the TMD struct!\n");
|
||||
return true;
|
||||
}
|
||||
memset(ios_tmd, 0, tmd_size);
|
||||
ES_GetTMDView(0x0000000100000000ULL | ios_number, (u8 *)ios_tmd, tmd_size);
|
||||
// gprintf("IOS %d is rev %d(0x%x) with tmd size of %u and %u contents\n",ios_number,ios_tmd->title_version,ios_tmd->title_version,tmd_size,ios_tmd->num_contents);
|
||||
/*Stubs have a few things in common:
|
||||
- title version : it is mostly 65280 , or even better : in hex the last 2 digits are 0.
|
||||
example : IOS 60 rev 6400 = 0x1900 = 00 = stub
|
||||
@ -91,40 +74,34 @@ bool isIOSstub(u8 ios_number)
|
||||
- the stub ios' have 1 app of their own (type 0x1) and 2 shared apps (type 0x8001).
|
||||
eventho the 00 check seems to work fine , we'll only use other knowledge as well cause some
|
||||
people/applications install an ios with a stub rev >_> ...*/
|
||||
u8 Version = ios_tmd->title_version;
|
||||
|
||||
if ((boot2version >= 5) && (ios_number == 249 || ios_number == 250) && (Version < 18))
|
||||
u16 title_version = view->title_version;
|
||||
free(view);
|
||||
|
||||
if ((boot2version >= 5) && (ios == 249 || ios == 250) && (title_version < 18))
|
||||
return true;
|
||||
if ((ios_number == 202 || ios_number == 222 || ios_number == 223 || ios_number == 224) && (Version < 4))
|
||||
|
||||
if ((ios == 202 || ios == 222 || ios == 223 || ios == 224) && (title_version < 4))
|
||||
return true;
|
||||
// version now contains the last 2 bytes. as said above, if this is 00, its a stub
|
||||
if (Version == 0)
|
||||
{
|
||||
if ((ios_tmd->num_contents == 3) && (ios_tmd->contents[0].type == 1 && ios_tmd->contents[1].type == 0x8001 && ios_tmd->contents[2].type == 0x8001))
|
||||
{
|
||||
// gprintf("IOS %d is a stub\n",ios_number);
|
||||
free(ios_tmd);
|
||||
|
||||
if ((title_version & 0xFF) == 0 && (ios < 200 || title_version == 0xFF00))
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// gprintf("IOS %d is active\n",ios_number);
|
||||
free(ios_tmd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// gprintf("IOS %d is active\n",ios_number);
|
||||
free(ios_tmd);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool loadIOS(int ios)
|
||||
int Sys_LoadIOS(int ios)
|
||||
{
|
||||
if (isIOSstub(ios))
|
||||
return false;
|
||||
if (Sys_CanLoadIOS(ios))
|
||||
return -1;
|
||||
|
||||
mload_close();
|
||||
if (IOS_ReloadIOS(ios) >= 0)
|
||||
{
|
||||
int ret = IOS_ReloadIOS(ios);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
usleep(100000); // there should be a more professional way to do this
|
||||
|
||||
if (IOS_GetVersion() != 249 && IOS_GetVersion() != 250)
|
||||
{
|
||||
if (mload_init() >= 0)
|
||||
@ -134,16 +111,12 @@ bool loadIOS(int ios)
|
||||
mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, 0x47);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Sys_Init(void)
|
||||
{
|
||||
/* Initialize video subsytem */
|
||||
VIDEO_Init();
|
||||
|
||||
/* Set RESET/POWER button callback */
|
||||
SYS_SetResetCallback(__Sys_ResetCallback);
|
||||
SYS_SetPowerCallback(__Sys_PowerCallback);
|
||||
@ -186,6 +159,9 @@ void Sys_Shutdown(void)
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
// this is a title.c thing
|
||||
// also we're a wad manager we don't need to be reading the system certificate store
|
||||
s32 Sys_GetCerts(signed_blob **certs, u32 *len)
|
||||
{
|
||||
static signed_blob certificates[CERTS_LEN] ATTRIBUTE_ALIGN(32);
|
||||
@ -212,6 +188,7 @@ s32 Sys_GetCerts(signed_blob **certs, u32 *len)
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetPRButtons(bool enabled)
|
||||
{
|
||||
|
10
source/sys.h
10
source/sys.h
@ -3,17 +3,13 @@
|
||||
|
||||
#define IS_WIIU (*(vu16*)0xCD8005A0 == 0xCAFE)
|
||||
|
||||
extern u32 boot2version;
|
||||
|
||||
/* Prototypes */
|
||||
bool isIOSstub(u8 ios_number);
|
||||
bool tmdIsStubIOS(tmd*);
|
||||
bool loadIOS(int ios);
|
||||
bool ES_CheckHasKoreanKey(void);
|
||||
void Sys_Init(void);
|
||||
void Sys_Reboot(void);
|
||||
void Sys_Shutdown(void);
|
||||
s32 Sys_GetCerts(signed_blob **, u32 *);
|
||||
bool Sys_CanLoadIOS(int ios);
|
||||
int Sys_LoadIOS(int ios);
|
||||
bool ES_CheckHasKoreanKey(void);
|
||||
void SetPRButtons(bool enabled);
|
||||
|
||||
#endif
|
||||
|
183
source/title.c
183
source/title.c
@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <ogcsys.h>
|
||||
@ -10,7 +11,6 @@
|
||||
#include "nand.h"
|
||||
#include "sha1.h"
|
||||
#include "utils.h"
|
||||
#include "otp.h"
|
||||
#include "malloc.h"
|
||||
|
||||
s32 Title_ZeroSignature(signed_blob *p_sig)
|
||||
@ -185,14 +185,33 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetTMDContents(signed_blob *s_tmd, u32 **contents, u32 *num_contents)
|
||||
{
|
||||
s32 ret;
|
||||
|
||||
ret = ES_GetNumStoredTMDContents(s_tmd, SIGNED_TMD_SIZE(s_tmd), num_contents);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
*contents = memalign32(*num_contents * sizeof(u32));
|
||||
if (!*contents)
|
||||
return -1;
|
||||
|
||||
ret = ES_GetStoredTMDContents(s_tmd, SIGNED_TMD_SIZE(s_tmd), *contents, *num_contents);
|
||||
if (ret >= 0)
|
||||
return ret;
|
||||
|
||||
free(*contents);
|
||||
*contents = NULL;
|
||||
*num_contents = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetTMDView(u64 tid, tmd_view** outbuf, u32* outlen)
|
||||
{
|
||||
s32 ret;
|
||||
u32 view_sz = 0;
|
||||
|
||||
*outbuf = NULL;
|
||||
*outlen = 0;
|
||||
|
||||
ret = ES_GetTMDViewSize(tid, &view_sz);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
@ -210,79 +229,66 @@ s32 Title_GetTMDView(u64 tid, tmd_view** outbuf, u32* outlen)
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
*outbuf = NULL;
|
||||
*outlen = 0;
|
||||
free(view);
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetVersion(u64 tid, u16 *outbuf)
|
||||
{
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 len;
|
||||
s32 ret;
|
||||
tmd_view *view = NULL;
|
||||
u32 len;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
ret = Title_GetTMDView(tid, &view, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Set values */
|
||||
*outbuf = tmd_data->title_version;
|
||||
*outbuf = view->title_version;
|
||||
|
||||
/* Free memory */
|
||||
free(p_tmd);
|
||||
free(view);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_GetSysVersion(u64 tid, u64 *outbuf)
|
||||
{
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 len;
|
||||
s32 ret;
|
||||
tmd_view *view = NULL;
|
||||
u32 len;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
ret = Title_GetTMDView(tid, &view, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Set values */
|
||||
*outbuf = tmd_data->sys_version;
|
||||
*outbuf = view->sys_version;
|
||||
|
||||
/* Free memory */
|
||||
free(p_tmd);
|
||||
free(view);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_GetSize(u64 tid, u32 *outbuf)
|
||||
{
|
||||
signed_blob *p_tmd = NULL;
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 cnt, len, size = 0;
|
||||
s32 ret;
|
||||
tmd_view *view = NULL;
|
||||
u32 len, size = 0;
|
||||
|
||||
/* Get title TMD */
|
||||
ret = Title_GetTMD(tid, &p_tmd, &len);
|
||||
ret = Title_GetTMDView(tid, &view, &len);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Retrieve TMD info */
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
/* Calculate title size */
|
||||
for (cnt = 0; cnt < tmd_data->num_contents; cnt++) {
|
||||
tmd_content *content = &tmd_data->contents[cnt];
|
||||
for (int cnt = 0; cnt < view->num_contents; cnt++) {
|
||||
tmd_view_content *content = &view->contents[cnt];
|
||||
|
||||
/* Add content size */
|
||||
size += content->size;
|
||||
@ -297,7 +303,7 @@ s32 Title_GetSize(u64 tid, u32 *outbuf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen)
|
||||
s32 Title_GetIOSVersions(u8 *outbuf, u32 *outlen)
|
||||
{
|
||||
u8 *buffer = NULL;
|
||||
u64 *list = NULL;
|
||||
@ -310,23 +316,6 @@ s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* Count IOS */
|
||||
for (cnt = idx = 0; idx < count; idx++) {
|
||||
u32 tidh = (list[idx] >> 32);
|
||||
u32 tidl = (list[idx] & 0xFFFFFFFF);
|
||||
|
||||
/* Title is IOS */
|
||||
if ((tidh == 0x1) && (tidl >= 3) && (tidl <= 255))
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/* Allocate memory */
|
||||
buffer = memalign32(cnt);
|
||||
if (!buffer) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Copy IOS */
|
||||
for (cnt = idx = 0; idx < count; idx++) {
|
||||
u32 tidh = (list[idx] >> 32);
|
||||
@ -338,63 +327,24 @@ s32 Title_GetIOSVersions(u8 **outbuf, u32 *outlen)
|
||||
}
|
||||
|
||||
/* Set values */
|
||||
*outbuf = buffer;
|
||||
*outlen = cnt;
|
||||
|
||||
goto out;
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
free(list);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 Title_GetSharedContents(SharedContent** out, u32* count)
|
||||
s32 Title_GetcIOSInfo(int ios, cIOSInfo* out)
|
||||
{
|
||||
if (!out || !count) return false;
|
||||
|
||||
u32 size;
|
||||
SharedContent* buf = (SharedContent*)NANDLoadFile("/shared1/content.map", &size);
|
||||
|
||||
if (!buf)
|
||||
return (s32)size;
|
||||
|
||||
else if (size % sizeof(SharedContent) != 0) {
|
||||
free(buf);
|
||||
return -996;
|
||||
}
|
||||
|
||||
*out = buf;
|
||||
*count = size / sizeof(SharedContent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Title_SharedContentPresent(tmd_content* content, SharedContent shared[], u32 count)
|
||||
{
|
||||
if (!shared || !content || !count)
|
||||
return false;
|
||||
|
||||
if (!(content->type & 0x8000))
|
||||
return false;
|
||||
|
||||
for (SharedContent* s_content = shared; s_content < shared + count; s_content++)
|
||||
{
|
||||
if (memcmp(s_content->hash, content->hash, sizeof(sha1)) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Title_GetcIOSInfo(int IOS, cIOSInfo* out)
|
||||
{
|
||||
u64 titleID = 0x0000000100000000ULL | IOS;
|
||||
u64 titleID = 0x100000000ULL | ios;
|
||||
tmd_view* view = NULL;
|
||||
u32 view_size = 0;
|
||||
int i;
|
||||
|
||||
char path[ISFS_MAXPATH];
|
||||
u32 size;
|
||||
u32 size = 0;
|
||||
|
||||
cIOSInfo* buf = NULL;
|
||||
|
||||
s32 ret = Title_GetTMDView(titleID, &view, &view_size);
|
||||
@ -402,7 +352,7 @@ bool Title_GetcIOSInfo(int IOS, cIOSInfo* out)
|
||||
return ret;
|
||||
|
||||
u32 content0 = 0;
|
||||
for (int i = 0; i < view->num_contents; i++)
|
||||
for (i = 0; i < view->num_contents; i++)
|
||||
{
|
||||
if (view->contents[i].index == 0) {
|
||||
content0 = view->contents[i].cid;
|
||||
@ -411,19 +361,20 @@ bool Title_GetcIOSInfo(int IOS, cIOSInfo* out)
|
||||
}
|
||||
free(view);
|
||||
|
||||
sprintf(path, "/title/00000001/%08x/content/%08x.app", IOS, content0);
|
||||
// insert ES_OpenTitleContent here
|
||||
sprintf(path, "/title/00000001/%08x/content/%08x.app", ios, content0);
|
||||
buf = (cIOSInfo*)NANDLoadFile(path, &size);
|
||||
|
||||
if (!buf || size != 0x40 || buf->hdr_magic != CIOS_INFO_MAGIC || buf->hdr_version != CIOS_INFO_VERSION)
|
||||
goto fail;
|
||||
|
||||
if (buf && size == 0x40 && buf->hdr_magic == CIOS_INFO_MAGIC && buf->hdr_version == CIOS_INFO_VERSION) {
|
||||
*out = *buf;
|
||||
free(buf);
|
||||
return true;
|
||||
ret = 0;
|
||||
}
|
||||
else {
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
fail:
|
||||
free(buf);
|
||||
return false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -461,8 +412,7 @@ void Title_GetFreeSpace(u32* free, s32* user_free)
|
||||
*user_free = user_clusters_free * cluster_size;
|
||||
}
|
||||
#endif
|
||||
__attribute__((aligned(0x10)))
|
||||
aeskey WiiCommonKey, vWiiCommonKey;
|
||||
u32 vWiiCommonKey[4] ATTRIBUTE_ALIGN(0x20);
|
||||
|
||||
void Title_SetupCommonKeys(void)
|
||||
{
|
||||
@ -470,16 +420,17 @@ void Title_SetupCommonKeys(void)
|
||||
if (keys_ok)
|
||||
return;
|
||||
|
||||
// Grab the Wii common key...
|
||||
otp_read(WiiCommonKey, offsetof(otp_t, common_key), sizeof(aeskey));
|
||||
ATTRIBUTE_ALIGN(0x20)
|
||||
static const u32 vWiiCommonKey_enc[4] = { 0x6E18DB23, 0x847CBA6C, 0x1931A417, 0x9BAF8E09 };
|
||||
u32 iv[4] = {};
|
||||
|
||||
// ...and decrypt the vWii common key with it.
|
||||
static const unsigned char vwii_key_enc_bin[0x10] = { 0x6e, 0x18, 0xdb, 0x23, 0x84, 0x7c, 0xba, 0x6c, 0x19, 0x31, 0xa4, 0x17, 0x9b, 0xaf, 0x8e, 0x09 };
|
||||
unsigned char iv[0x10] = {};
|
||||
s32 ret = ES_Decrypt(ES_KEY_COMMON, iv, vWiiCommonKey_enc, sizeof(vWiiCommonKey_enc), vWiiCommonKey);
|
||||
|
||||
memcpy(vWiiCommonKey, vwii_key_enc_bin, sizeof(vwii_key_enc_bin));
|
||||
AES_Decrypt(WiiCommonKey, sizeof(aeskey), iv, sizeof(iv), vWiiCommonKey, vWiiCommonKey, sizeof(aeskey));
|
||||
if (ret != 0) {
|
||||
printf("ES_Encrypt -> %i\n", ret);
|
||||
sleep(10);
|
||||
}
|
||||
|
||||
keys_ok = true;
|
||||
keys_ok = (ret == 0);
|
||||
return;
|
||||
};
|
||||
|
@ -3,16 +3,6 @@
|
||||
|
||||
#include <ogc/es.h>
|
||||
|
||||
/* Constants */
|
||||
#define BLOCK_SIZE 0x4000
|
||||
|
||||
/* /shared1/content.map entry */
|
||||
typedef struct
|
||||
{
|
||||
char filename[8];
|
||||
sha1 hash;
|
||||
} ATTRIBUTE_PACKED SharedContent;
|
||||
|
||||
/* "cIOS build tag" */
|
||||
enum
|
||||
{
|
||||
@ -35,7 +25,7 @@ typedef struct
|
||||
_Static_assert(sizeof(cIOSInfo) == 0x40, "cIOSInfo struct size wrong");
|
||||
|
||||
/* Variables */
|
||||
extern aeskey WiiCommonKey, vWiiCommonKey;
|
||||
extern u32 vWiiCommonKey[4];
|
||||
|
||||
/* Prototypes */
|
||||
s32 Title_ZeroSignature(signed_blob *);
|
||||
@ -45,13 +35,12 @@ s32 Title_GetList(u64 **, u32 *);
|
||||
s32 Title_GetTicketViews(u64, tikview **, u32 *);
|
||||
s32 Title_GetTMDView(u64, tmd_view **, u32 *);
|
||||
s32 Title_GetTMD(u64, signed_blob **, u32 *);
|
||||
s32 Title_GetTMDContents(signed_blob *, u32**, u32*);
|
||||
s32 Title_GetVersion(u64, u16 *);
|
||||
s32 Title_GetSysVersion(u64, u64 *);
|
||||
s32 Title_GetSize(u64, u32 *);
|
||||
s32 Title_GetIOSVersions(u8 **, u32 *);
|
||||
s32 Title_GetSharedContents(SharedContent** out, u32* count);
|
||||
bool Title_SharedContentPresent(tmd_content* content, SharedContent shared[], u32 count);
|
||||
bool Title_GetcIOSInfo(int IOS, cIOSInfo*);
|
||||
s32 Title_GetIOSVersions(u8 *, u32 *);
|
||||
s32 Title_GetcIOSInfo(int IOS, cIOSInfo*);
|
||||
|
||||
void Title_SetupCommonKeys(void);
|
||||
|
||||
|
@ -1,15 +1,30 @@
|
||||
#ifndef _UTILS_H_
|
||||
#define _UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
/* Constants */
|
||||
#define KB_SIZE 1024.0
|
||||
#define MB_SIZE 1048576.0
|
||||
#define GB_SIZE 1073741824.0
|
||||
|
||||
/* Macros */
|
||||
#define round_up(x,n) (-(-(x) & -(n)))
|
||||
#ifdef __builtin_align_up
|
||||
# define round_up(x,n) __builtin_align_up(x, n)
|
||||
#else
|
||||
# define round_up(x,n) ((x + n - 1) & ~(n - 1))
|
||||
#endif
|
||||
|
||||
/* Prototypes */
|
||||
u32 swap32(u32);
|
||||
|
||||
static inline void *memalign32(size_t size)
|
||||
{
|
||||
return aligned_alloc(0x20, (size + 0x1F) & ~0x1F);
|
||||
}
|
||||
|
||||
static inline void *memalign64(size_t size)
|
||||
{
|
||||
return aligned_alloc(0x40, (size + 0x3F) & ~0x3F);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -8,11 +8,15 @@
|
||||
static void *framebuffer = NULL;
|
||||
static GXRModeObj *vmode = NULL;
|
||||
|
||||
/* Console Variables */
|
||||
int g_consoleWidth, g_consoleHeight;
|
||||
|
||||
void Con_Init(u32 x, u32 y, u32 w, u32 h)
|
||||
{
|
||||
/* Create console in the framebuffer */
|
||||
CON_InitEx(vmode, x, y, w, h);
|
||||
|
||||
CON_GetMetrics(&g_consoleWidth, &g_consoleHeight);
|
||||
}
|
||||
|
||||
void Con_Clear(void)
|
||||
@ -24,17 +28,13 @@ void Con_Clear(void)
|
||||
|
||||
void Con_ClearLine(void)
|
||||
{
|
||||
int cols, rows;
|
||||
u32 cnt;
|
||||
|
||||
printf("\r");
|
||||
fflush(stdout);
|
||||
|
||||
/* Get console metrics */
|
||||
CON_GetMetrics(&cols, &rows);
|
||||
|
||||
/* Erase line */
|
||||
for (cnt = 1; cnt < cols; cnt++) {
|
||||
for (cnt = 1; cnt < g_consoleWidth; cnt++) {
|
||||
printf(" ");
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -59,16 +59,12 @@ void Con_BgColor(u32 color, u8 bold)
|
||||
|
||||
void Con_FillRow(u32 row, u32 color, u8 bold)
|
||||
{
|
||||
int cols, rows;
|
||||
u32 cnt;
|
||||
|
||||
/* Set color */
|
||||
printf("\x1b[%u;%um", color + 40, bold);
|
||||
fflush(stdout);
|
||||
|
||||
/* Get console metrics */
|
||||
CON_GetMetrics(&cols, &rows);
|
||||
|
||||
/* Save current row and col */
|
||||
printf("\x1b[s");
|
||||
fflush(stdout);
|
||||
@ -78,7 +74,7 @@ void Con_FillRow(u32 row, u32 color, u8 bold)
|
||||
fflush(stdout);
|
||||
|
||||
/* Fill row */
|
||||
for (cnt = 0; cnt < cols; cnt++) {
|
||||
for (cnt = 0; cnt < g_consoleWidth; cnt++) {
|
||||
printf(" ");
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -92,22 +88,10 @@ void Con_FillRow(u32 row, u32 color, u8 bold)
|
||||
Con_FgColor(7, 1);
|
||||
}
|
||||
|
||||
void Video_Configure(GXRModeObj *rmode)
|
||||
void Video_Init(void)
|
||||
{
|
||||
/* Configure the video subsystem */
|
||||
VIDEO_Configure(rmode);
|
||||
VIDEO_Init();
|
||||
|
||||
/* Setup video */
|
||||
VIDEO_SetBlack(FALSE);
|
||||
VIDEO_Flush();
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
if (rmode->viTVMode & VI_NON_INTERLACE)
|
||||
VIDEO_WaitVSync();
|
||||
}
|
||||
|
||||
void Video_SetMode(void)
|
||||
{
|
||||
/* Select preferred video mode */
|
||||
vmode = VIDEO_GetPreferredMode(NULL);
|
||||
|
||||
@ -127,7 +111,7 @@ void Video_SetMode(void)
|
||||
VIDEO_WaitVSync();
|
||||
|
||||
/* Clear the screen */
|
||||
Video_Clear(COLOR_BLACK);
|
||||
Video_Clear(COLOR_RED);
|
||||
}
|
||||
|
||||
void Video_Clear(s32 color)
|
||||
|
@ -3,7 +3,14 @@
|
||||
|
||||
#include "libpng/pngu/pngu.h"
|
||||
|
||||
/* Variables */
|
||||
extern int g_consoleWidth, g_consoleHeight;
|
||||
|
||||
/* Prototypes */
|
||||
void Video_Init(void);
|
||||
void Video_Clear(s32);
|
||||
void Video_DrawPng(IMGCTX, PNGUPROP, u16, u16);
|
||||
|
||||
void Con_Init(u32, u32, u32, u32);
|
||||
void Con_Clear(void);
|
||||
void Con_ClearLine(void);
|
||||
@ -11,9 +18,4 @@ void Con_FgColor(u32, u8);
|
||||
void Con_BgColor(u32, u8);
|
||||
void Con_FillRow(u32, u32, u8);
|
||||
|
||||
void Video_Configure(GXRModeObj *);
|
||||
void Video_SetMode(void);
|
||||
void Video_Clear(s32);
|
||||
void Video_DrawPng(IMGCTX, PNGUPROP, u16, u16);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <ctype.h>
|
||||
@ -23,19 +24,17 @@
|
||||
#include "iospatch.h"
|
||||
#include "fileops.h"
|
||||
|
||||
// Globals
|
||||
CONFIG gConfig;
|
||||
|
||||
// Prototypes
|
||||
extern void __exception_setreload(int t);
|
||||
extern u32 WaitButtons (void);
|
||||
extern void __exception_setreload(unsigned sec);
|
||||
|
||||
void CheckPassword (void);
|
||||
void SetDefaultConfig (void);
|
||||
int ReadConfigFile (void);
|
||||
int GetIntParam (char *inputStr);
|
||||
int GetStartupPath (char *startupPath, char *inputStr);
|
||||
int GetStringParam (char *outParam, char *inputStr, int maxChars);
|
||||
int LaunchApp(const char* path, bool external);
|
||||
|
||||
wm_config_t gConfig;
|
||||
|
||||
// Default password Up-Down-Left-Right-Up-Down
|
||||
//#define PASSWORD "UDLRUD"
|
||||
@ -151,38 +150,27 @@ void Disclaimer(void)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
__exception_setreload(10);
|
||||
__exception_setreload(15);
|
||||
Sys_LoadIOS(IOS_GetVersion());
|
||||
|
||||
ES_GetBoot2Version(&boot2version);
|
||||
if (!AHBPROT_DISABLED)
|
||||
/*
|
||||
We should just enable it tbh.
|
||||
Like, look at https://github.com/WiiLink24/wfc-patcher-wii/blob/main/launcher/source/IOS.cpp
|
||||
Awesome stuff.
|
||||
*/
|
||||
{
|
||||
if (boot2version < 5)
|
||||
{
|
||||
if (!loadIOS(202)) if (!loadIOS(222)) if (!loadIOS(223)) if (!loadIOS(224)) if (!loadIOS(249)) loadIOS(36);
|
||||
} else {
|
||||
if (!loadIOS(249)) loadIOS(36);
|
||||
}
|
||||
/* Initialize display */
|
||||
Video_Init();
|
||||
|
||||
/* Initialize console */
|
||||
Gui_InitConsole(NULL); // todo: custom background & console config ?
|
||||
|
||||
printf("hello\n");
|
||||
|
||||
s32 ret = IOSPATCH_Apply();
|
||||
if (ret != 0) {
|
||||
printf("We goofed up.... (%#X)\n", ret);
|
||||
sleep(15);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize subsystems */
|
||||
Sys_Init();
|
||||
|
||||
/* Set video mode */
|
||||
Video_SetMode();
|
||||
|
||||
FatMount();
|
||||
|
||||
/* Initialize console */
|
||||
Gui_InitConsole();
|
||||
|
||||
/* Draw background */
|
||||
Gui_DrawBackground();
|
||||
|
||||
/* Initialize Wiimote and GC Controller */
|
||||
Wpad_Init();
|
||||
PAD_Init();
|
||||
@ -190,7 +178,8 @@ int main(int argc, char **argv)
|
||||
WKB_Initialize();
|
||||
WIILIGHT_Init();
|
||||
|
||||
AES_Init();
|
||||
FatMount();
|
||||
|
||||
Title_SetupCommonKeys();
|
||||
|
||||
/* Print disclaimer */
|
||||
@ -219,98 +208,146 @@ int main(int argc, char **argv)
|
||||
int ReadConfigFile()
|
||||
{
|
||||
FILE* fptr;
|
||||
char tmpStr[MAX_FILE_PATH_LEN];
|
||||
char tmpOutStr[40], path[128];
|
||||
s32 i;
|
||||
bool found = false;
|
||||
char tmpStr[256];
|
||||
char path[128];
|
||||
|
||||
for (i = 0; i < FatGetDeviceCount(); i++)
|
||||
if (__system_argv->argvMagic == ARGV_MAGIC) {
|
||||
strncpy(path, __system_argv->argv[0], sizeof(path));
|
||||
char *fpath = strrchr(path, '/');
|
||||
if (fpath)
|
||||
{
|
||||
strcpy(fpath, "/config.txt");
|
||||
if (FSOPFileExists(path))
|
||||
goto found_the_file;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < FatGetDeviceCount(); i++)
|
||||
{
|
||||
snprintf(path, sizeof(path), "%s:%s", FatGetDevicePrefix(i), WM_CONFIG_FILE_PATH);
|
||||
if (FSOPFileExists(path))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
goto found_the_file;
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return -1;
|
||||
|
||||
found_the_file:
|
||||
// Read the file
|
||||
// fptr = fopen(path, "rb"); // umm, why are we opening with mode rb and then using fgets?
|
||||
fptr = fopen(path, "r");
|
||||
if (!fptr) {
|
||||
// perror(path);
|
||||
perror(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Read the options
|
||||
while (true)
|
||||
{
|
||||
if (!fgets(tmpStr, MAX_FILE_PATH_LEN, fptr))
|
||||
char *option, *value;
|
||||
unsigned valueLen;
|
||||
|
||||
if (!fgets(tmpStr, sizeof(tmpStr), fptr))
|
||||
break;
|
||||
|
||||
else if (isalpha((int)tmpStr[0]))
|
||||
{
|
||||
// Get the password
|
||||
if (strncmp (tmpStr, "Password", 8) == 0)
|
||||
{
|
||||
// Get password
|
||||
// GetPassword (gConfig.password, tmpStr);
|
||||
GetStringParam (gConfig.password, tmpStr, MAX_PASSWORD_LENGTH);
|
||||
option = tmpStr;
|
||||
while (isspace((int)*option))
|
||||
option++;
|
||||
|
||||
// If password is too long, ignore it
|
||||
if (strlen (gConfig.password) > 10)
|
||||
if (*option == ';' || *option == '#' || *option == '\0')
|
||||
continue;
|
||||
|
||||
value = strchr(tmpStr, '=');
|
||||
if (!value)
|
||||
continue;
|
||||
|
||||
while (isspace((int)*++value))
|
||||
;
|
||||
|
||||
if (!*value)
|
||||
continue;
|
||||
|
||||
valueLen = (strpbrk(value, "#;\r\n") ?: strchr(value, 0)) - value;
|
||||
while (isspace((int)value[valueLen]))
|
||||
valueLen--;
|
||||
|
||||
// Get the password
|
||||
if (strncasecmp(option, "password", 8) == 0)
|
||||
{
|
||||
gConfig.password [0] = 0;
|
||||
puts("Password longer than 10 characters; will be ignored. Press a button...");
|
||||
WaitButtons ();
|
||||
int i;
|
||||
|
||||
// Validate the length
|
||||
if (valueLen >= MAX_PASSWORD_LENGTH)
|
||||
{
|
||||
WaitPrompt("Password is too long....\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Validate the characters
|
||||
const char* const validPasswordChars = "UDLR12";
|
||||
for (i = 0; i < valueLen; i++) {
|
||||
if (!strchr(validPasswordChars, value[i]))
|
||||
break;
|
||||
}
|
||||
|
||||
if (i != valueLen)
|
||||
{
|
||||
printf("Password has invalid characters! (?)\n");
|
||||
printf(" Valid characters: %s\n", validPasswordChars);
|
||||
printf(" Provided password: %s\n", value);
|
||||
printf(" %.*s^\n\n", i, "");
|
||||
|
||||
WaitPrompt(NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
strncpy(gConfig.password, value, i);
|
||||
}
|
||||
|
||||
// Get startup path
|
||||
else if (strncmp (tmpStr, "StartupPath", 11) == 0)
|
||||
else if (strncasecmp(option, "startupPath", 11) == 0)
|
||||
{
|
||||
// Get startup Path
|
||||
GetStartupPath (gConfig.startupPath, tmpStr);
|
||||
value[valueLen] = '\0';
|
||||
|
||||
if (FSOPFolderExists(value))
|
||||
strncpy(gConfig.startupPath, value, sizeof(gConfig.startupPath));
|
||||
}
|
||||
|
||||
// cIOS
|
||||
else if (strncmp (tmpStr, "cIOSVersion", 11) == 0)
|
||||
else if (strncasecmp(option, "cIOSVersion", 11) == 0)
|
||||
{
|
||||
char *endPtr;
|
||||
long num = strtol(value, &endPtr, 10);
|
||||
|
||||
if (num < 3 || num >= 256)
|
||||
{
|
||||
printf("Invalid cIOSVersion %lu (%s)\n", num, value);
|
||||
WaitPrompt(NULL);
|
||||
}
|
||||
|
||||
// Get cIOSVersion
|
||||
gConfig.cIOSVersion = GetIntParam(tmpStr);
|
||||
gConfig.cIOSVersion = num;
|
||||
}
|
||||
|
||||
// FatDevice
|
||||
else if (strncmp (tmpStr, "FatDevice", 9) == 0)
|
||||
else if (strncasecmp(option, "fatDevice", 9) == 0)
|
||||
{
|
||||
// Get fatDevice
|
||||
GetStringParam (tmpOutStr, tmpStr, MAX_FAT_DEVICE_LENGTH);
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (strncmp(FatGetDevicePrefix(i), tmpOutStr, 4) == 0)
|
||||
for (int i = 0; i < FatGetDeviceCount(); i++)
|
||||
{
|
||||
if (strcmp(FatGetDevicePrefix(i), value) == 0)
|
||||
gConfig.fatDeviceIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NandDevice
|
||||
else if (strncmp (tmpStr, "NANDDevice", 10) == 0)
|
||||
else if (strncasecmp(tmpStr, "NANDDevice", 10) == 0)
|
||||
{
|
||||
// Get fatDevice
|
||||
GetStringParam (tmpOutStr, tmpStr, MAX_NAND_DEVICE_LENGTH);
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
if (strncmp (ndevList[i].name, tmpOutStr, 2) == 0)
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
if (strcmp(ndevList[i].name, value) == 0)
|
||||
gConfig.nandDeviceIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // EndWhile
|
||||
|
||||
// Close the config file
|
||||
@ -322,107 +359,13 @@ int ReadConfigFile()
|
||||
|
||||
void SetDefaultConfig (void)
|
||||
{
|
||||
// Default password is NULL or no password
|
||||
gConfig.password [0] = 0;
|
||||
memset(&gConfig, 0, sizeof(gConfig));
|
||||
|
||||
// Default startup folder
|
||||
strcpy (gConfig.startupPath, WAD_ROOT_DIRECTORY);
|
||||
strcpy (gConfig.startupPath, DEFAULT_WAD_DIRECTORY);
|
||||
|
||||
gConfig.cIOSVersion = CIOS_VERSION_INVALID; // Means that user has to select later
|
||||
gConfig.fatDeviceIndex = FAT_DEVICE_INDEX_INVALID; // Means that user has to select
|
||||
gConfig.nandDeviceIndex = NAND_DEVICE_INDEX_INVALID; // Means that user has to select
|
||||
|
||||
} // SetDefaultConfig
|
||||
|
||||
|
||||
int GetStartupPath (char *startupPath, char *inputStr)
|
||||
{
|
||||
int i = 0;
|
||||
int len = strlen (inputStr);
|
||||
|
||||
// Find the "="
|
||||
while ((inputStr [i] != '=') && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
|
||||
// Get to the "/"
|
||||
while ((inputStr [i] != '/') && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Get the startup Path
|
||||
int count = 0;
|
||||
while (isascii(inputStr [i]) && (i < len) && (inputStr [i] != '\n') &&
|
||||
(inputStr [i] != '\r') && (inputStr [i] != ' '))
|
||||
{
|
||||
startupPath [count++] = inputStr [i++];
|
||||
}
|
||||
startupPath [count] = 0; // NULL terminate
|
||||
|
||||
return (0);
|
||||
} // GetStartupPath
|
||||
|
||||
int GetIntParam (char *inputStr)
|
||||
{
|
||||
int retval = 0;
|
||||
int i = 0;
|
||||
int len = strlen (inputStr);
|
||||
char outParam [40];
|
||||
|
||||
// Find the "="
|
||||
while ((inputStr [i] != '=') && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
|
||||
// Get to the first alpha numeric character
|
||||
while ((isdigit((int)inputStr[i]) == 0) && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Get the string param
|
||||
int outCount = 0;
|
||||
while ((isdigit((int)inputStr[i])) && (i < len) && (outCount < 40))
|
||||
{
|
||||
outParam [outCount++] = inputStr [i++];
|
||||
}
|
||||
outParam [outCount] = 0; // NULL terminate
|
||||
retval = atoi (outParam);
|
||||
|
||||
return (retval);
|
||||
} // GetIntParam
|
||||
|
||||
|
||||
int GetStringParam (char *outParam, char *inputStr, int maxChars)
|
||||
{
|
||||
int i = 0;
|
||||
int len = strlen (inputStr);
|
||||
|
||||
// Find the "="
|
||||
while ((inputStr [i] != '=') && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
i++;
|
||||
|
||||
// Get to the first alpha character
|
||||
while ((isalpha((int)inputStr[i]) == 0) && (i < len))
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
// Get the string param
|
||||
int outCount = 0;
|
||||
while ((isalnum((int)inputStr[i])) && (i < len) && (outCount < maxChars))
|
||||
{
|
||||
outParam [outCount++] = inputStr [i++];
|
||||
}
|
||||
outParam [outCount] = 0; // NULL terminate
|
||||
|
||||
return (0);
|
||||
} // GetStringParam
|
||||
|
524
source/wad.c
524
source/wad.c
@ -9,8 +9,6 @@
|
||||
#include "sys.h"
|
||||
#include "title.h"
|
||||
#include "utils.h"
|
||||
#include "mini_seeprom.h"
|
||||
#include "otp.h"
|
||||
#include "video.h"
|
||||
#include "wad.h"
|
||||
#include "wpad.h"
|
||||
@ -95,76 +93,6 @@ static void DecEncTxtBuffer(char* buffer)
|
||||
}
|
||||
}
|
||||
|
||||
u64 get_title_ios(u64 title) {
|
||||
s32 ret, fd;
|
||||
static char filepath[256] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
// Check to see if title exists
|
||||
if (ES_GetDataDir(title, filepath) >= 0 ) {
|
||||
u32 tmd_size = 0;
|
||||
static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
ret = ES_GetStoredTMDSize(title, &tmd_size);
|
||||
if (ret < 0){
|
||||
// If we fail to use the ES function, try reading manually
|
||||
// This is a workaround added since some IOS (like 21) don't like our
|
||||
// call to ES_GetStoredTMDSize
|
||||
|
||||
//printf("Error! ES_GetStoredTMDSize: %d\n", ret);
|
||||
|
||||
sprintf(filepath, "/title/%08x/%08x/content/title.tmd", TITLE_UPPER(title), TITLE_LOWER(title));
|
||||
|
||||
ret = ISFS_Open(filepath, ISFS_OPEN_READ);
|
||||
if (ret <= 0)
|
||||
{
|
||||
//printf("Error! ISFS_Open (ret = %d)\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = ret;
|
||||
|
||||
ret = ISFS_Seek(fd, 0x184, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
//printf("Error! ISFS_Seek (ret = %d)\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ISFS_Read(fd,tmd_buf,8);
|
||||
if (ret < 0)
|
||||
{
|
||||
//printf("Error! ISFS_Read (ret = %d)\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = ISFS_Close(fd);
|
||||
if (ret < 0)
|
||||
{
|
||||
//printf("Error! ISFS_Close (ret = %d)\n", ret);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return be64(tmd_buf);
|
||||
|
||||
} else {
|
||||
// Normal versions of IOS won't have a problem, so we do things the "right" way.
|
||||
|
||||
// Some of this code adapted from bushing's title_lister.c
|
||||
signed_blob *s_tmd = (signed_blob *)tmd_buf;
|
||||
ret = ES_GetStoredTMD(title, s_tmd, tmd_size);
|
||||
if (ret < 0){
|
||||
//printf("Error! ES_GetStoredTMD: %d\n", ret);
|
||||
return -1;
|
||||
}
|
||||
tmd *t = SIGNATURE_PAYLOAD(s_tmd);
|
||||
return t->sys_version;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool GetRegionFromTXT(char* region)
|
||||
{
|
||||
u32 size = 0;
|
||||
@ -324,7 +252,9 @@ bool GetSysMenuExecPath(char path[ISFS_MAXPATH], bool mainDOL)
|
||||
u32 cid = GetSysMenuBootContent();
|
||||
if (!cid) return false;
|
||||
|
||||
if (mainDOL) cid |= 0x10000000;
|
||||
if (mainDOL)
|
||||
cid = (cid & ~0xF00000000) | 0x10000000;
|
||||
|
||||
sprintf(path, "/title/00000001/00000002/content/%08x.app", cid);
|
||||
|
||||
return true;
|
||||
@ -506,56 +436,20 @@ static bool CompareHashes(bool priiloader)
|
||||
|
||||
/* 'WAD Header' structure */
|
||||
typedef struct {
|
||||
/* Header length */
|
||||
u32 header_len;
|
||||
|
||||
/* WAD type */
|
||||
u16 type;
|
||||
|
||||
u16 padding;
|
||||
|
||||
/* Data length */
|
||||
u16 version;
|
||||
u32 certs_len;
|
||||
u32 crl_len;
|
||||
u32 tik_len;
|
||||
u32 tmd_len;
|
||||
u32 data_len;
|
||||
u32 footer_len;
|
||||
} ATTRIBUTE_PACKED wadHeader;
|
||||
} wadHeader;
|
||||
|
||||
/* Variables */
|
||||
static u8 wadBuffer[BLOCK_SIZE] ATTRIBUTE_ALIGN(32);
|
||||
|
||||
s32 __Wad_GetTitleID(FILE *fp, wadHeader *header, u64 *tid)
|
||||
{
|
||||
signed_blob *p_tik = NULL;
|
||||
tik *tik_data = NULL;
|
||||
|
||||
u32 offset = 0;
|
||||
s32 ret;
|
||||
|
||||
/* Ticket offset */
|
||||
offset += round_up(header->header_len, 64);
|
||||
offset += round_up(header->certs_len, 64);
|
||||
offset += round_up(header->crl_len, 64);
|
||||
|
||||
/* Read ticket */
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len);
|
||||
if (ret != 1)
|
||||
goto out;
|
||||
|
||||
/* Ticket data */
|
||||
tik_data = (tik *)SIGNATURE_PAYLOAD(p_tik);
|
||||
|
||||
/* Copy title ID */
|
||||
*tid = tik_data->titleid;
|
||||
|
||||
out:
|
||||
/* Free memory */
|
||||
free(p_tik);
|
||||
|
||||
return ret;
|
||||
}
|
||||
ATTRIBUTE_ALIGN(0x40)
|
||||
static u8 wadBuffer[16 << 10];
|
||||
|
||||
bool __Wad_FixTicket(signed_blob *s_tik)
|
||||
{
|
||||
@ -583,7 +477,7 @@ bool __Wad_FixTicket(signed_blob *s_tik)
|
||||
iv[0] = p_tik->titleid;
|
||||
iv[1] = 0;
|
||||
|
||||
AES_Encrypt(WiiCommonKey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf));
|
||||
ES_Encrypt(ES_KEY_COMMON, (u32 *)iv, tkeybuf, sizeof(tkeybuf), tkeybuf);
|
||||
|
||||
memcpy(p_tik->cipher_title_key, tkeybuf, sizeof(tkeybuf));
|
||||
}
|
||||
@ -597,10 +491,7 @@ bool __Wad_FixTicket(signed_blob *s_tik)
|
||||
|
||||
bool __Wad_VerifyHeader(wadHeader* header)
|
||||
{
|
||||
return
|
||||
header->header_len == 0x20
|
||||
&& header->type == ('I' << 8 | 's')
|
||||
&& header->padding == 0x00;
|
||||
return (header->header_len == 0x20 && header->type == 0x4973 && header->version == 0x0000);
|
||||
}
|
||||
|
||||
const char* wad_strerror(int ec)
|
||||
@ -614,10 +505,14 @@ const char* wad_strerror(int ec)
|
||||
case -999: return "BRICK BLOCKED";
|
||||
case -1010: return "Wii System memory full!";
|
||||
case -1017: return "Invalid argument";
|
||||
case -1020: return "Device ID mismatch";
|
||||
case -1022: return "Content hash mismatch";
|
||||
case -1027: return "Issuer not found in the certificate chain";
|
||||
case -1028: return "Ticket not found";
|
||||
case -1029: return "Invalid Ticket";
|
||||
case -1035: return "Newer version already installed";
|
||||
case -1036: return "Needed IOS missing!";
|
||||
case -2011: return "No trucha bug?";
|
||||
case -2011: return "No signature check patch?";
|
||||
/*
|
||||
* from libogc.
|
||||
* This rarely happens unless the WAD had an invalid ticket/tmd size
|
||||
@ -629,6 +524,12 @@ const char* wad_strerror(int ec)
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience purposes
|
||||
u32 hbcList[] = { 0x48415858, 0x4A4F4449, 0xAF1BF516, 0x4C554C5A, 0x4F484243 };
|
||||
u32 eulaList[] = { 0x48414B45, 0x48414B50, 0x48414B4A, 0x48414B4B };
|
||||
u32 rgnselList[] = { 0x48414C45, 0x48414C50, 0x48414C4A, 0x48414C4B };
|
||||
|
||||
|
||||
// Some of the safety checks can block region changing
|
||||
// Entering the Konami code turns this true, so it will
|
||||
// skip the problematic checks for region changing.
|
||||
@ -636,26 +537,26 @@ bool skipRegionSafetyCheck = false;
|
||||
|
||||
s32 Wad_Install(FILE *fp)
|
||||
{
|
||||
SetPRButtons(false);
|
||||
wadHeader *header = NULL;
|
||||
s32 ret;
|
||||
wadHeader *header = {};
|
||||
signed_blob *p_certs = NULL, *p_crl = NULL, *p_tik = NULL, *p_tmd = NULL;
|
||||
|
||||
SharedContent* sharedContents = NULL;
|
||||
|
||||
tmd *tmd_data = NULL;
|
||||
|
||||
u32 cnt, offset = 0;
|
||||
u32 sharedContentsCount = 0;
|
||||
int ret;
|
||||
u64 tid;
|
||||
tmd_view *view = NULL;
|
||||
u32 view_size = 0;
|
||||
u32 boot2version;
|
||||
u32 cnt, offset = 0;
|
||||
u32 *installedContents = NULL;
|
||||
u32 installedContentsCount = 0;
|
||||
|
||||
bool retainPriiloader = false;
|
||||
bool cleanupPriiloader = false;
|
||||
|
||||
printf("\t\t>> Reading WAD data...");
|
||||
fflush(stdout);
|
||||
SetPRButtons(false);
|
||||
printf("\t\t>> Reading WAD data...\n\n");
|
||||
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&header, offset, sizeof(wadHeader));
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
if (!__Wad_VerifyHeader(header))
|
||||
@ -666,6 +567,8 @@ s32 Wad_Install(FILE *fp)
|
||||
|
||||
offset += round_up(header->header_len, 64);
|
||||
|
||||
/*
|
||||
* IOS won't let you do this unless you actually call ES_ImportBoot
|
||||
//Don't try to install boot2
|
||||
__Wad_GetTitleID(fp, header, &tid);
|
||||
|
||||
@ -675,10 +578,10 @@ s32 Wad_Install(FILE *fp)
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
|
||||
*/
|
||||
/* WAD certificates */
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&p_certs, offset, header->certs_len);
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
offset += round_up(header->certs_len, 64);
|
||||
@ -686,7 +589,7 @@ s32 Wad_Install(FILE *fp)
|
||||
/* WAD crl */
|
||||
if (header->crl_len) {
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&p_crl, offset, header->crl_len);
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
offset += round_up(header->crl_len, 64);
|
||||
@ -694,84 +597,100 @@ s32 Wad_Install(FILE *fp)
|
||||
|
||||
/* WAD ticket */
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&p_tik, offset, header->tik_len);
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
bool isvWiiTitle = __Wad_FixTicket(p_tik);
|
||||
|
||||
offset += round_up(header->tik_len, 64);
|
||||
|
||||
/* WAD TMD */
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&p_tmd, offset, header->tmd_len);
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
offset += round_up(header->tmd_len, 64);
|
||||
|
||||
Con_ClearLine();
|
||||
bool isvWiiTitle = __Wad_FixTicket(p_tik);
|
||||
|
||||
/* Get TMD info */
|
||||
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
tid = tmd_data->title_id;
|
||||
|
||||
if (TITLE_UPPER(tmd_data->sys_version) == 0) // IOS
|
||||
{
|
||||
if ((isvWiiTitle || tmd_data->vwii_title) ^ IS_WIIU) // xor is one of my favourite binary operators of all time
|
||||
bool stubbed = (tmd_data->title_version & 0xFF) == 0 || tmd_data->title_version == 404;
|
||||
bool isCrossPlatformIOS = (isvWiiTitle || tmd_data->vwii_title) ^ IS_WIIU; // xor is one of my favourite binary operators of all time
|
||||
|
||||
if (isCrossPlatformIOS && !skipRegionSafetyCheck)
|
||||
{
|
||||
printf("\n Cannot install vWii IOS on Wii\n or Wii IOS on vWii.\n");
|
||||
printf(" Cannot install vWii IOS on Wii\n");
|
||||
printf(" or Wii IOS on vWii.\n");
|
||||
printf(" I mean maybe you can. I'm not going to find out though\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(1, 2)))
|
||||
ret = Title_GetTMDView(0x100000002LL, &view, &view_size);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
printf(" Hey, where's Perry?\n\n");
|
||||
|
||||
printf(" (No really, where is your Wii System Menu?)\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (view->sys_version == tmd_data->title_id)
|
||||
{
|
||||
printf("\n I won't install a stub System Menu IOS\n");
|
||||
if (isCrossPlatformIOS)
|
||||
{
|
||||
printf(" Anything but the System menu's IOS...!!!!\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
// this code feels like a MESS
|
||||
else if (!IS_WIIU && (tid == TITLE_ID(1, 70) || tid == TITLE_ID(1, 80)))
|
||||
if (stubbed) {
|
||||
printf(" I won't install a stub System Menu IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!IS_WIIU && (view->title_version >> 5) >= 15) // 4.2 or later. Again.
|
||||
{
|
||||
tik* ticket = (tik*)SIGNATURE_PAYLOAD(p_tik);
|
||||
|
||||
__aligned(0x10)
|
||||
__aligned(0x20)
|
||||
aeskey titlekey;
|
||||
u64 iv[2] = { tid };
|
||||
|
||||
|
||||
memcpy(titlekey, ticket->cipher_title_key, sizeof(aeskey));
|
||||
AES_Decrypt(WiiCommonKey, sizeof(aeskey), iv, sizeof(iv), titlekey, titlekey, sizeof(aeskey));
|
||||
ES_Decrypt(ES_KEY_COMMON, (u32 *)iv, titlekey, sizeof(aeskey), titlekey);
|
||||
|
||||
u32 content0_offset = offset;
|
||||
for (tmd_content* con = tmd_data->contents; con < tmd_data->contents + tmd_data->num_contents; con++)
|
||||
for (int i = 0; i < tmd_data->num_contents; i++)
|
||||
{
|
||||
if (con->index == 0) break;
|
||||
content0_offset += round_up(con->size, 0x40);
|
||||
if (tmd_data->contents[i].index == 0) break;
|
||||
content0_offset += round_up(tmd_data->contents[i].size, 0x40);
|
||||
}
|
||||
|
||||
__aligned(0x20)
|
||||
cIOSInfo build_tag = {};
|
||||
|
||||
ret = FSOPReadOpenFile(fp, (void*)&build_tag, content0_offset, sizeof(cIOSInfo));
|
||||
if (ret != 1)
|
||||
ret = FSOPReadOpenFile(fp, (void*)&build_tag, content0_offset, sizeof(build_tag));
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
iv[0] = 0;
|
||||
iv[1] = 0;
|
||||
AES_Decrypt(titlekey, sizeof(aeskey), iv, sizeof(iv), &build_tag, &build_tag, sizeof(cIOSInfo));
|
||||
AES_Decrypt(titlekey, sizeof(aeskey), iv, sizeof(iv), &build_tag, &build_tag, sizeof(build_tag));
|
||||
|
||||
if ((build_tag.hdr_magic != CIOS_INFO_MAGIC ||
|
||||
build_tag.hdr_version != CIOS_INFO_VERSION ||
|
||||
build_tag.ios_base != 60) && ES_CheckHasKoreanKey())
|
||||
{
|
||||
printf("\n"
|
||||
" Installing this System menu IOS will brick your Wii.\n"
|
||||
" Please remove the Korean key via KoreanKii,\n"
|
||||
" then try again.\n\n"
|
||||
);
|
||||
printf(" Installing this System menu IOS will brick your Wii.\n\n");
|
||||
|
||||
printf(" Please remove the Korean key via KoreanKii,\n");
|
||||
printf(" then try again.\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
@ -779,55 +698,58 @@ s32 Wad_Install(FILE *fp)
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K')))
|
||||
if (stubbed)
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
u64 sysvers = 0;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
printf("\n I won't install a stub EULA IOS\n");
|
||||
if ((Title_GetSysVersion(TITLE_ID(0x00010008, eulaList[i]), &sysvers) == 0) && tid == sysvers)
|
||||
{
|
||||
printf(" I won't install a stub EULA IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((Title_GetSysVersion(TITLE_ID(0x00010008, rgnselList[i]), &sysvers) == 0) && tid == sysvers)
|
||||
{
|
||||
printf(" I won't install a stub Region select IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K')))
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
if ((Title_GetSysVersion(TITLE_ID(0x00010001, hbcList[i]), &sysvers) == 0) && tid == sysvers)
|
||||
{
|
||||
printf("\n I won't install a stub rgnsel IOS\n");
|
||||
printf(" I won't stub The Homebrew Channel's IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if(tid == get_title_ios(TITLE_ID(0x10001, 0x48415858))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0xAF1BF516))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4C554C5A))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4F484243)))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n I won't stub Homebrew Channel's IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // not IOS
|
||||
{
|
||||
if (isIOSstub(TITLE_LOWER(tmd_data->sys_version)))
|
||||
ret = Title_GetTMDView(tmd_data->sys_version, &view, &view_size);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("\n This Title wants IOS%i but the installed version\n is a stub.\n", TITLE_LOWER(tmd_data->sys_version));
|
||||
printf(" This title wants IOS%i, but the installed ver-...\n", TITLE_LOWER(tmd_data->sys_version));
|
||||
printf(" ...is it even installed?\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((view->title_version & 0xFF) == 0 || view->title_version == 404)
|
||||
{
|
||||
printf(" This title wants IOS%i, but the installed version\n", TITLE_LOWER(tmd_data->sys_version));
|
||||
printf(" is a stub.\n");
|
||||
ret = -1036;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (tid == TITLE_ID(1, 2))
|
||||
if (tid == 0x100000002LL)
|
||||
{
|
||||
if (skipRegionSafetyCheck || gForcedInstall)
|
||||
goto skipChecks;
|
||||
@ -839,17 +761,18 @@ s32 Wad_Install(FILE *fp)
|
||||
|
||||
if (isvWiiTitle || tmd_data->vwii_title) // && !IS_WIIU ? :thinking:
|
||||
{
|
||||
printf("\n I won't install a vWii SM by default.\n\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
printf(" I won't install a vWii SM by default.\n\n");
|
||||
|
||||
printf(" If you're really sure about what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(region == 0)
|
||||
if (region == '\0')
|
||||
{
|
||||
printf("\n Unknown System menu region\n Please check the site for updates\n");
|
||||
printf(" Unknown System menu region. What's up with setting.txt?\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
@ -857,10 +780,11 @@ s32 Wad_Install(FILE *fp)
|
||||
|
||||
if (!VersionIsOriginal(tmd_data->title_version))
|
||||
{
|
||||
printf("\n I won't install an unknown SM versions by default.\n\n");
|
||||
printf("\n Are you installing a tweaked system menu?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
printf(" I won't install an unknown SM versions by default.\n\n");
|
||||
|
||||
printf(" Are you installing a tweaked system menu?\n");
|
||||
printf(" If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
@ -869,9 +793,10 @@ s32 Wad_Install(FILE *fp)
|
||||
if(region != RegionLookupTable[(tmd_data->title_version & 0x0F)])
|
||||
{
|
||||
printf("\n I won't install the wrong regions SM by default.\n\n");
|
||||
|
||||
printf("\n Are you region changing?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
printf(" select your device using Konami...\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
@ -882,15 +807,12 @@ s32 Wad_Install(FILE *fp)
|
||||
{
|
||||
cIOSInfo ios_info;
|
||||
|
||||
if (ES_CheckHasKoreanKey() &&
|
||||
(!Title_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) ||
|
||||
ios_info.ios_base != 60))
|
||||
if ((Title_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) != 0 ||
|
||||
ios_info.ios_base != 60) && ES_CheckHasKoreanKey())
|
||||
{
|
||||
printf("\n"
|
||||
" Installing this System menu will brick your Wii.\n"
|
||||
" Please remove the Korean key via KoreanKii,\n"
|
||||
" then try again.\n\n"
|
||||
);
|
||||
printf(" Installing this System menu will brick your Wii.\n");
|
||||
printf(" Please remove the Korean key via KoreanKii,\n");
|
||||
printf(" then try again.\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
@ -900,20 +822,24 @@ s32 Wad_Install(FILE *fp)
|
||||
skipChecks:
|
||||
if (tmd_data->title_version < 416)
|
||||
{
|
||||
ES_GetBoot2Version(&boot2version);
|
||||
if(boot2version == 4)
|
||||
{
|
||||
printf("\n This version of the System Menu\n is not compatible with your Wii\n");
|
||||
printf(" This version of the System Menu\n");
|
||||
printf(" is not compatible with your Wii\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gForcedInstall && AHBPROT_DISABLED && IsPriiloaderInstalled())
|
||||
if (!gForcedInstall && IsPriiloaderInstalled())
|
||||
{
|
||||
cleanupPriiloader = true;
|
||||
printf("\n Priiloader is installed next to the system menu.\n\n");
|
||||
printf(" Priiloader is installed next to the system menu.\n\n");
|
||||
|
||||
printf(" It is recommended to retain Priiloader as it can\n");
|
||||
printf(" protect your console from being bricked.\n\n");
|
||||
|
||||
printf(" Press A to retain Priiloader or B to remove.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
@ -989,26 +915,22 @@ skipChecks:
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("\t\t>> Installing ticket...");
|
||||
fflush(stdout);
|
||||
printf("\t\t>> Installing ticket...\n");
|
||||
|
||||
/* Install ticket */
|
||||
ret = ES_AddTicket(p_tik, header->tik_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
Con_ClearLine();
|
||||
|
||||
printf("\r\t\t>> Installing title...");
|
||||
fflush(stdout);
|
||||
printf("\t\t>> Installing title...\n");
|
||||
|
||||
/* Install title */
|
||||
ret = ES_AddTitleStart(p_tmd, header->tmd_len, p_certs, header->certs_len, p_crl, header->crl_len);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
/* Get list of currently installed shared contents */
|
||||
Title_GetSharedContents(&sharedContents, &sharedContentsCount);
|
||||
/* Get list of currently installed contents */
|
||||
Title_GetTMDContents(p_tmd, &installedContents, &installedContentsCount);
|
||||
|
||||
/* Install contents */
|
||||
for (cnt = 0; cnt < tmd_data->num_contents; cnt++)
|
||||
@ -1021,23 +943,21 @@ skipChecks:
|
||||
/* Encrypted content size */
|
||||
len = round_up(content->size, 64);
|
||||
|
||||
if (Title_SharedContentPresent(content, sharedContents, sharedContentsCount))
|
||||
if (content->type & 0x8000) // We're only doing shared. Unless we're going to genuinely read the non-shared contents and check the hash against what we're installing
|
||||
for (int i = 0; i < installedContentsCount; i++)
|
||||
if (installedContents[i] == content->cid)
|
||||
{
|
||||
offset += len;
|
||||
continue;
|
||||
}
|
||||
|
||||
Con_ClearLine();
|
||||
printf("\r\t\t>> Installing content #%02d...", content->cid);
|
||||
fflush(stdout);
|
||||
printf("\r\t\t>> Installing content #%02d...", content->index);
|
||||
|
||||
/* Install content */
|
||||
cfd = ES_AddContentStart(tmd_data->title_id, content->cid);
|
||||
if (cfd < 0)
|
||||
{
|
||||
ret = cfd;
|
||||
ret = cfd = ES_AddContentStart(tmd_data->title_id, content->cid);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Install content data */
|
||||
while (idx < len)
|
||||
@ -1046,12 +966,12 @@ skipChecks:
|
||||
|
||||
/* Data length */
|
||||
size = (len - idx);
|
||||
if (size > BLOCK_SIZE)
|
||||
size = BLOCK_SIZE;
|
||||
if (size > sizeof(wadBuffer))
|
||||
size = sizeof(wadBuffer);
|
||||
|
||||
/* Read data */
|
||||
ret = FSOPReadOpenFile(fp, &wadBuffer, offset, size);
|
||||
if (ret != 1)
|
||||
ret = FSOPReadOpenFile(fp, wadBuffer, offset, size);
|
||||
if (ret < 0)
|
||||
{
|
||||
ES_AddContentFinish(cfd);
|
||||
goto err;
|
||||
@ -1200,7 +1120,8 @@ out:
|
||||
free(p_crl);
|
||||
free(p_tik);
|
||||
free(p_tmd);
|
||||
free(sharedContents);
|
||||
free(installedContents);
|
||||
free(view);
|
||||
|
||||
if (gForcedInstall)
|
||||
return Wad_Install(fp);
|
||||
@ -1211,22 +1132,22 @@ out:
|
||||
|
||||
s32 Wad_Uninstall(FILE *fp)
|
||||
{
|
||||
SetPRButtons(false);
|
||||
wadHeader *header = NULL;
|
||||
tikview *viewData = NULL;
|
||||
wadHeader *header = {};
|
||||
|
||||
tikview *tikviews = NULL;
|
||||
signed_blob *s_tik = NULL;
|
||||
signed_blob *s_tmd = NULL;
|
||||
|
||||
u64 tid;
|
||||
u64 tid, sysvers;
|
||||
u32 viewCnt;
|
||||
int ret;
|
||||
|
||||
printf("\t\t>> Reading WAD data...");
|
||||
fflush(stdout);
|
||||
SetPRButtons(false);
|
||||
printf("\t\t>> Reading WAD data...\n");
|
||||
|
||||
/* WAD header */
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&header, 0, sizeof(wadHeader));
|
||||
if (ret != 1)
|
||||
if (ret < 0)
|
||||
{
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
goto out;
|
||||
@ -1234,7 +1155,7 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
|
||||
if (!__Wad_VerifyHeader(header))
|
||||
{
|
||||
puts("\t\tInvalid WAD file?");
|
||||
puts(" Invalid WAD file?");
|
||||
ret = ES_EINVAL;
|
||||
goto out;
|
||||
}
|
||||
@ -1246,7 +1167,7 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
offset += round_up(header->crl_len, 0x40);
|
||||
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&s_tik, offset, header->tik_len);
|
||||
if (ret != 1) {
|
||||
if (ret < 0) {
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
@ -1257,7 +1178,7 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
|
||||
offset += round_up(header->tik_len, 0x40);
|
||||
ret = FSOPReadOpenFileA(fp, (void*)&s_tmd, offset, header->tmd_len);
|
||||
if (ret != 1) {
|
||||
if (ret < 0) {
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
goto out;
|
||||
}
|
||||
@ -1267,15 +1188,15 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
//Assorted Checks
|
||||
if (TITLE_UPPER(tid) == 0x1)
|
||||
{
|
||||
if (!get_title_ios(TITLE_ID(1, 2)))
|
||||
if ((ret = Title_GetSysVersion(0x100000002LL, &sysvers)) != 0)
|
||||
{
|
||||
printf("\n I can't determine the System Menus IOS\nDeleting system titles is disabled\n");
|
||||
ret = -999;
|
||||
printf(" I can't determine the System Menus IOS\n");
|
||||
printf(" Deleting system titles is disabled\n");
|
||||
goto out;
|
||||
}
|
||||
if (((isvWiiTitle || tmd_data->vwii_title) ^ IS_WIIU) && !skipRegionSafetyCheck) // Only this way around this time // Ehh nvm
|
||||
{
|
||||
printf("\n"
|
||||
printf(
|
||||
" Attempting to uninstall a Wii IOS WAD on vWii.\n"
|
||||
" or a vWii IOS WAD on Wii.\n\n"
|
||||
|
||||
@ -1287,114 +1208,71 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == TITLE_ID(1, 1))
|
||||
if (tid == 0x100000001LL)
|
||||
{
|
||||
printf("\n I won't try to uninstall boot2\n");
|
||||
printf(" I won't try to uninstall boot2\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == TITLE_ID(1, 2))
|
||||
if (tid == 0x100000002LL)
|
||||
{
|
||||
printf("\n I won't uninstall the System Menu\n");
|
||||
printf(" I won't uninstall the System Menu\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == get_title_ios(TITLE_ID(1, 2)))
|
||||
if (tid == sysvers)
|
||||
{
|
||||
printf("\n I won't uninstall the System Menus IOS\n");
|
||||
printf(" I won't uninstall the System Menu's IOS\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0xAF1BF516))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4C554C5A))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10001, 0x4F484243)))
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
printf("\n I won't uninstall the Homebrew Channel's IOS!\n");
|
||||
if ((Title_GetSysVersion(TITLE_ID(0x00010001, hbcList[5 - i]), &sysvers) == 0) && tid == sysvers)
|
||||
{
|
||||
printf(" I won't uninstall the Homebrew Channel's IOS!\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char region = 0;
|
||||
GetSysMenuRegion(NULL, ®ion);
|
||||
|
||||
if((tid == TITLE_ID(0x10008, 0x48414B00 | 'E') || tid == TITLE_ID(0x10008, 0x48414B00 | 'P') || tid == TITLE_ID(0x10008, 0x48414B00 | 'J') || tid == TITLE_ID(0x10008, 0x48414B00 | 'K')
|
||||
|| (tid == TITLE_ID(0x10008, 0x48414C00 | 'E') || tid == TITLE_ID(0x10008, 0x48414C00 | 'P') || tid == TITLE_ID(0x10008, 0x48414C00 | 'J') || tid == TITLE_ID(0x10008, 0x48414C00 | 'K')))
|
||||
&& region == 0)
|
||||
if (((tid | 0xFF) == 0x0001000848414CFFLL || (tid | 0xFF) == 0x0001000848414BFFLL) && strchr("JEPK", (char)tid) && region == 0)
|
||||
{
|
||||
printf("\n Unknown SM region\n Please check the site for updates\n");
|
||||
printf(" Unknown System Menu region\n Please check the site for updates\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == TITLE_ID(0x10008, 0x48414B00 | region))
|
||||
{
|
||||
printf("\n I won't uninstall the EULA\n");
|
||||
printf(" I won't uninstall the EULA\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if (tid == TITLE_ID(0x10008, 0x48414C00 | region))
|
||||
{
|
||||
printf("\n I won't uninstall rgnsel\n");
|
||||
printf(" I won't uninstall rgnsel\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | region)))
|
||||
if (Title_GetSysVersion(0x0001000848414B00LL | region, &sysvers) == 0 && tid == sysvers)
|
||||
{
|
||||
printf("\n I won't uninstall the EULAs IOS\n");
|
||||
printf(" I won't uninstall the EULAs IOS\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | region)))
|
||||
if (Title_GetSysVersion(0x0001000848414C00LL | region, &sysvers) == 0 && tid == sysvers)
|
||||
{
|
||||
printf("\n I won't uninstall the rgnsel IOS\n");
|
||||
printf(" I won't uninstall rgnsel's IOS\n");
|
||||
ret = -999;
|
||||
goto out;
|
||||
}
|
||||
|
||||
Con_ClearLine();
|
||||
|
||||
/* Why don't we do this the other way around? Delete title contents, delete TMD, delete ticket. Seems more natural. */
|
||||
|
||||
printf("\t\t>> Deleting tickets...");
|
||||
fflush(stdout);
|
||||
|
||||
/* Get ticket views */
|
||||
ret = Title_GetTicketViews(tid, &viewData, &viewCnt);
|
||||
if (ret < 0)
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
|
||||
/* Delete tickets */
|
||||
else {
|
||||
u32 cnt;
|
||||
static tikview view ATTRIBUTE_ALIGN(0x20);
|
||||
|
||||
/* Delete all tickets */
|
||||
for (cnt = 0; cnt < viewCnt; cnt++) {
|
||||
memcpy(&view, viewData + cnt, sizeof(tikview));
|
||||
|
||||
if (view.devicetype)
|
||||
{
|
||||
u32 deviceID = 0;
|
||||
/* If we failed to get the ID or it actually matches, skip this */
|
||||
if (ES_GetDeviceID(&deviceID) || view.devicetype == deviceID) continue;
|
||||
}
|
||||
|
||||
ret = ES_DeleteTicket(&view);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
else
|
||||
printf(" OK!\n");
|
||||
}
|
||||
free(viewData);
|
||||
|
||||
printf("\t\t>> Deleting title contents... ");
|
||||
fflush(stdout);
|
||||
|
||||
/* Delete title contents */
|
||||
ret = ES_DeleteTitleContent(tid);
|
||||
@ -1405,7 +1283,6 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
|
||||
|
||||
printf("\t\t>> Deleting title...");
|
||||
fflush(stdout);
|
||||
|
||||
/* Delete title */
|
||||
ret = ES_DeleteTitle(tid);
|
||||
@ -1414,6 +1291,39 @@ s32 Wad_Uninstall(FILE *fp)
|
||||
else
|
||||
printf(" OK!\n");
|
||||
|
||||
printf("\t\t>> Deleting tickets...");
|
||||
|
||||
/* Get ticket views */
|
||||
ret = Title_GetTicketViews(tid, &tikviews, &viewCnt);
|
||||
if (ret < 0)
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
|
||||
/* Delete tickets */
|
||||
else
|
||||
{
|
||||
u32 cnt;
|
||||
|
||||
/* Delete all tickets */
|
||||
for (cnt = 0; cnt < viewCnt; cnt++) {
|
||||
#if 0
|
||||
if (view.devicetype)
|
||||
{
|
||||
u32 deviceID = 0;
|
||||
/* If we failed to get the ID or it actually matches, skip this */
|
||||
if (ES_GetDeviceID(&deviceID) || view.devicetype == deviceID) continue;
|
||||
}
|
||||
#endif
|
||||
ret = ES_DeleteTicket(&tikviews[cnt]);
|
||||
if (ret < 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
printf(" ERROR! (ret = %d)\n", ret);
|
||||
else
|
||||
printf(" OK!\n");
|
||||
}
|
||||
free(tikviews);
|
||||
out:
|
||||
/* Free memory */
|
||||
free(header);
|
||||
|
@ -86,6 +86,8 @@ static void WKBEventHandler(USBKeyboard_event evt)
|
||||
|
||||
static void* WKBThread(__attribute__((unused)) void* arg)
|
||||
{
|
||||
sleep(10); // HACK: IOS totally bricks up if I initialize this too early(??)
|
||||
|
||||
while (WKBThreadActive)
|
||||
{
|
||||
/*
|
||||
|
@ -1,10 +1,6 @@
|
||||
#ifndef _WKB_H_
|
||||
#define _WKB_H_
|
||||
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
//#include <malloc.h>
|
||||
#include <gctypes.h> // u8, u16, etc...
|
||||
|
||||
#include <wiikeyboard/keyboard.h>
|
||||
|
Loading…
x
Reference in New Issue
Block a user