├── clean.bat ├── run.bat ├── .gitignore ├── HBC ├── boot.dol ├── icon.png └── meta.xml ├── data └── cert.sys ├── custom_font ├── libogc.a ├── libogc_v1.8.20_font_mod.rar └── README.TXT ├── portlibs ├── lib │ ├── libwupc.a │ └── libruntimeiospatch.a └── include │ ├── wupc │ └── wupc.h │ └── runtimeiospatch.h ├── source ├── mload │ ├── ehcmodule_5.h │ ├── mload_init.h │ ├── odip_frag.h │ ├── usb2storage.h │ ├── mload.h │ ├── mload_init.c │ ├── mload.c │ └── usb2storage.c ├── net.h ├── otp.h ├── aes.h ├── ssl.h ├── yabdm.h ├── tools.h ├── sha1.h ├── main.c ├── otp.c ├── ssl.c ├── sha1.c ├── net.c └── tools.c ├── Makefile ├── README.md └── LICENSE.md /clean.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | make clean -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | make run 3 | pause -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | boot.dol 3 | boot.elf 4 | .vscode 5 | -------------------------------------------------------------------------------- /HBC/boot.dol: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/HBC/boot.dol -------------------------------------------------------------------------------- /HBC/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/HBC/icon.png -------------------------------------------------------------------------------- /data/cert.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/data/cert.sys -------------------------------------------------------------------------------- /custom_font/libogc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/custom_font/libogc.a -------------------------------------------------------------------------------- /portlibs/lib/libwupc.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/portlibs/lib/libwupc.a -------------------------------------------------------------------------------- /source/mload/ehcmodule_5.h: -------------------------------------------------------------------------------- 1 | #define size_ehcmodule_5 27134 2 | 3 | extern unsigned char ehcmodule_5[27134]; 4 | -------------------------------------------------------------------------------- /portlibs/lib/libruntimeiospatch.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/portlibs/lib/libruntimeiospatch.a -------------------------------------------------------------------------------- /source/net.h: -------------------------------------------------------------------------------- 1 | #ifndef __NET_H__ 2 | #define __NET_H__ 3 | 4 | void UpdateYABDM(char *lpath); 5 | 6 | #endif /* __NET_H__ */ 7 | -------------------------------------------------------------------------------- /custom_font/libogc_v1.8.20_font_mod.rar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DarkMatterCore/bluedump-mod/HEAD/custom_font/libogc_v1.8.20_font_mod.rar -------------------------------------------------------------------------------- /source/mload/mload_init.h: -------------------------------------------------------------------------------- 1 | #ifndef __MLOAD_INIT_H__ 2 | #define __MLOAD_INIT_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int mload_Init(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /source/mload/odip_frag.h: -------------------------------------------------------------------------------- 1 | #ifndef ODIP_FRAG_H_ 2 | #define ODIP_FRAG_H_ 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern unsigned char odip_frag[9120]; 9 | 10 | #define odip_frag_size sizeof(odip_frag) 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /custom_font/README.TXT: -------------------------------------------------------------------------------- 1 | The custom font used in the application (confont512.c) is not part of the code; the font included in libogc NEEDS to be replaced, and then you have to recompile the whole library. 2 | 3 | To avoid problems, I have included a copy of the modified libogc.a file. Just replace the one you already have in $(LIBOGC)/lib/wii with the file included in this dir. If you want to compile the modified libOGC on your own, just extract the contents from the libogc_font_mod.rar archive to the root directory of your working copy, and replace files when prompted to. -------------------------------------------------------------------------------- /source/otp.h: -------------------------------------------------------------------------------- 1 | #ifndef __OTP_H__ 2 | #define __OTP_H__ 3 | 4 | extern bool use_bootmii_data; 5 | 6 | extern u8 prng_key[16]; // otp_ptr @ 0x68 7 | extern u32 console_id; // otp_ptr @ 0x24 8 | 9 | extern u8 bootmii_prng[16]; 10 | extern u32 bootmii_cid; 11 | 12 | typedef struct 13 | { 14 | u8 boot1_hash[20]; 15 | u8 common_key[16]; 16 | u8 ng_id[4]; 17 | union { // first two bytes of nand_hmac overlap last two bytes of ng_priv 18 | struct { 19 | u8 ng_priv[30]; 20 | u8 _wtf1[18]; 21 | }; 22 | struct { 23 | u8 _wtf2[28]; 24 | u8 nand_hmac[20]; 25 | }; 26 | }; 27 | u8 nand_key[16]; 28 | u8 rng_key[16]; 29 | u32 unk1; 30 | u32 unk2; // 0x00000007 31 | } __attribute__((packed)) otp_t; 32 | 33 | s32 Get_OTP_data(); 34 | s32 Get_BootMii_data(u32 cntbin_cid); 35 | 36 | #endif /* __OTP_H__ */ 37 | -------------------------------------------------------------------------------- /source/mload/usb2storage.h: -------------------------------------------------------------------------------- 1 | #ifndef _USBSTORAGE2_H_ 2 | #define _USBSTORAGE2_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define USB_REG_BASE 0x0D040000 8 | #define USB_REG_OP_BASE (USB_REG_BASE + (read32(USB_REG_BASE) & 0xff)) 9 | #define USB_PORT_CONNECTED (read32(USB_REG_OP_BASE + 0x44) & 0x0F) 10 | 11 | #ifdef __cplusplus 12 | extern "C" 13 | { 14 | #endif 15 | 16 | /* Prototypes */ 17 | s32 USBStorage2_Init(); 18 | void USBStorage2_Deinit(); 19 | s32 USBStorage2_GetCapacity(u32 *size); 20 | 21 | s32 USBStorage2_ReadSectors(u32 sector, u32 numSectors, void *buffer); 22 | s32 USBStorage2_WriteSectors(u32 sector, u32 numSectors, const void *buffer); 23 | 24 | #define DEVICE_TYPE_WII_UMS (('W'<<24)|('U'<<16)|('M'<<8)|'S') 25 | 26 | extern const DISC_INTERFACE __io_usbstorage2; 27 | 28 | #ifdef __cplusplus 29 | } 30 | #endif 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /source/aes.h: -------------------------------------------------------------------------------- 1 | /* 2 | * AES (Rijndael) cipher - encrypt 3 | * 4 | * Modifications to public domain implementation: 5 | * - support only 128-bit keys 6 | * - cleanup 7 | * - use C pre-processor to make it easier to change S table access 8 | * 9 | * Copyright (c) 2003-2005, Jouni Malinen 10 | * 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License version 2 as 13 | * published by the Free Software Foundation. 14 | * 15 | * Alternatively, this software may be distributed under the terms of BSD 16 | * license. 17 | * 18 | * See README and COPYING for more details. 19 | */ 20 | 21 | #ifndef __AES_H__ 22 | #define __AES_H__ 23 | 24 | int aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); 25 | int aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len); 26 | 27 | #endif /* __AES_H__ */ 28 | -------------------------------------------------------------------------------- /source/ssl.h: -------------------------------------------------------------------------------- 1 | /* Code taken from http://www.wiibrew.org/wiki//dev/net/ssl/code */ 2 | /* Made by Aruskano */ 3 | 4 | #ifndef __SSL_H__ 5 | #define __SSL_H__ 6 | 7 | #define IOCTLV_SSL_NEW 1 8 | #define IOCTLV_SSL_CONNECT 2 9 | #define IOCTLV_SSL_HANDSHAKE 3 10 | #define IOCTLV_SSL_READ 4 11 | #define IOCTLV_SSL_WRITE 5 12 | #define IOCTLV_SSL_SHUTDOWN 6 13 | #define IOCTLV_SSL_SETROOTCA 10 14 | #define IOCTLV_SSL_SETBUILTINCLIENTCERT 14 15 | 16 | #define SSL_HEAP_SIZE 0xB000 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif /* __cplusplus */ 21 | 22 | s32 ssl_init(void); 23 | s32 ssl_open(void); 24 | s32 ssl_close(void); 25 | s32 ssl_new(u8 * CN, u32 verify_options); 26 | s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index); 27 | s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length); 28 | s32 ssl_connect(s32 ssl_context, s32 socket); 29 | s32 ssl_handshake(s32 ssl_context); 30 | s32 ssl_read(s32 ssl_context, void* buffer, u32 length); 31 | s32 ssl_write(s32 ssl_context, const void * buffer, u32 length); 32 | s32 ssl_shutdown(s32 ssl_context); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif /* __cplusplus */ 37 | #endif /* __SSL_H__ */ 38 | -------------------------------------------------------------------------------- /portlibs/include/wupc/wupc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************** 2 | * Copyright (C) 2014 FIX94 3 | * 4 | * This program is free software: you can redistribute it and/or modify 5 | * it under the terms of the GNU General Public License as published by 6 | * the Free Software Foundation, either version 3 of the License, or 7 | * (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | * GNU General Public License for more details. 13 | * 14 | * You should have received a copy of the GNU General Public License 15 | * along with this program. If not, see . 16 | ****************************************************************************/ 17 | #ifndef _WUPC_H_ 18 | #define _WUPC_H_ 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | struct WUPCData { 25 | s16 xAxisL; 26 | s16 xAxisR; 27 | s16 yAxisL; 28 | s16 yAxisR; 29 | u32 button; 30 | u8 battery; 31 | u8 extra; 32 | }; 33 | 34 | #define WUPC_EXTRA_BUTTON_RSTICK 0x01 35 | #define WUPC_EXTRA_BUTTON_LSTICK 0x02 36 | 37 | #define WUPC_EXTRA_CHARGING 0x04 38 | #define WUPC_EXTRA_USBCONNECTED 0x08 39 | 40 | void WUPC_Init(); 41 | void WUPC_Disconnect(u8 chan); 42 | void WUPC_Shutdown(); 43 | struct WUPCData *WUPC_Data(u8 chan); 44 | void WUPC_Rumble(u8 chan, bool rumble); 45 | u32 WUPC_UpdateButtonStats(); 46 | u32 WUPC_ButtonsUp(u8 chan); 47 | u32 WUPC_ButtonsDown(u8 chan); 48 | u32 WUPC_ButtonsHeld(u8 chan); 49 | s16 WUPC_lStickX(u8 chan); 50 | s16 WUPC_lStickY(u8 chan); 51 | s16 WUPC_rStickX(u8 chan); 52 | s16 WUPC_rStickY(u8 chan); 53 | u8 WUPC_extra(u8 chan); 54 | 55 | #ifdef __cplusplus 56 | } 57 | #endif 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /source/yabdm.h: -------------------------------------------------------------------------------- 1 | #ifndef __YABDM_H__ 2 | #define __YABDM_H__ 3 | 4 | #define BLOCKSIZE 0x4000 // 16 KB 5 | #define SD_BLOCKSIZE 0x8000 // 32 KB 6 | 7 | #define DIRENT_T_FILE 0 8 | #define DIRENT_T_DIR 1 9 | 10 | #define ROOT_DIR "/title" 11 | #define SD_ROOT_DIR "sd:/private/wii/title" 12 | 13 | #define TYPE_SAVEDATA 0 14 | #define TYPE_TITLE 1 15 | #define TYPE_IOS 2 16 | #define TYPE_SYSTITLE 3 17 | #define TYPE_GAMECHAN 4 18 | #define TYPE_DLC 5 19 | #define TYPE_HIDDEN 6 20 | #define TYPE_OTHER 7 21 | 22 | #define round_up(x,n) (-(-(x) & -(n))) 23 | #define round64(x) round_up((x),0x40) 24 | #define round16(x) round_up((x),0x10) 25 | 26 | typedef struct _dirent 27 | { 28 | char name[ISFS_MAXPATH + 1]; 29 | u16 version; 30 | int type; 31 | int function; 32 | char titlename[ISFS_MAXPATH + 1]; 33 | } dirent_t; 34 | 35 | /* 'WAD Header' structure */ 36 | typedef struct 37 | { 38 | /* Header length */ 39 | u32 header_len; 40 | 41 | /* WAD type */ 42 | u16 type; 43 | 44 | u16 padding; 45 | 46 | /* Data length */ 47 | u32 certs_len; 48 | u32 crl_len; 49 | u32 tik_len; 50 | u32 tmd_len; 51 | u32 data_len; 52 | u32 footer_len; 53 | } ATTRIBUTE_PACKED wadHeader; 54 | 55 | /* Taken from Wiibrew */ 56 | typedef struct 57 | { 58 | u8 header[64]; // Header 59 | u8 zeroes[64]; // Padding 60 | u32 imet; // "IMET" magic word 61 | u32 hashsize; // Hash length 62 | u32 unk; // 3 fixed, unknown purpose. Possibly file count? 63 | u32 sizes[3]; // icon.bin, banner.bin, sound.bin 64 | u32 flag1; // unknown 65 | u8 names[20][42]; // Japanese, English, German, French, Spanish, Italian, Dutch, Simp. Chinese, Trad. Chinese, Korean 66 | u8 lol[0xC]; 67 | } IMET; 68 | 69 | typedef struct 70 | { 71 | u32 wibn; // "WIBN" magic word 72 | u32 flags; // Title flags 73 | u16 speed; // Animation speed 74 | u8 zeroes[22]; // Padding 75 | u8 name[64]; // Title name 76 | u8 desc[64]; // Title description 77 | } WIBN; 78 | 79 | void yabdm_loop(); 80 | 81 | #endif /* __YABDM_H__ */ 82 | -------------------------------------------------------------------------------- /source/tools.h: -------------------------------------------------------------------------------- 1 | #ifndef __TOOLS_H__ 2 | #define __TOOLS_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #define VERSION "1.86" 11 | 12 | #define MAXPATHLEN 256 13 | 14 | // Values for DetectInput 15 | #define DI_BUTTONS_DOWN 0 16 | #define DI_BUTTONS_HELD 1 17 | 18 | #define resetscreen() printf("\x1b[2J") 19 | //#define IsWiiU() ((*(vu32*)(0xCD8005A0) >> 16 ) == 0xCAFE) 20 | 21 | #define ARROW " \x10" 22 | #define DEVICE(x) (((x) == 0) ? (isSD ? "sd" : "usb") : (isSD ? "SD" : "USB")) 23 | #define MAX_CHARACTERS(x) ((sizeof((x))) / (sizeof((x)[0]))) // Returns the number of elements in an array 24 | 25 | #define TITLE_UPPER(x) ((u32)((x) >> 32)) 26 | #define TITLE_LOWER(x) ((u32)(x)) 27 | #define TITLE_ID(x,y) (((u64)(x) << 32) | (y)) 28 | 29 | #define IsHermesIOS(ios) ((ios) == 202 || (ios) == 222 || (ios) == 223 || (ios) == 224 || (ios) == 225) 30 | 31 | #define TITLEID_200 0x0000000100000200ll // IOS512 32 | 33 | typedef struct map_entry 34 | { 35 | char filename[8]; 36 | u8 sha1[20]; 37 | } __attribute__((packed)) map_entry_t; 38 | 39 | extern map_entry_t *cm; 40 | extern size_t content_map_size; 41 | extern size_t content_map_items; 42 | 43 | extern int lang; 44 | extern bool SDmnt, USBmnt, isSD, isUSB2, __debug, __wiilight, vwii, netw_init; 45 | 46 | extern char launch_path[MAXPATHLEN]; 47 | 48 | bool IsWiiU(void); 49 | u32 __fread(void *out, u32 size, u32 cnt, FILE *src); 50 | u32 __fwrite(const void *src, u32 size, u32 cnt, FILE *out); 51 | bool is_empty(void *buf, u32 size); 52 | void Reboot(); 53 | u32 DetectInput(u8 DownOrHeld); 54 | void waitforbuttonpress(); 55 | void Init_Console(); 56 | void printheadline(); 57 | void set_highlight(bool highlight); 58 | void Con_ClearLine(); 59 | bool PriiloaderCheck(u64 id); 60 | bool IsPriiloaderCnt(u16 cid); 61 | void Unmount_Devices(); 62 | int Mount_Devices(); 63 | int Device_Menu(bool swap); 64 | s32 Settings_Menu(); 65 | s32 ahbprot_menu(); 66 | void logfile(const char *format, ...); 67 | void logfile_header(); 68 | void hexdump_log(void *d, int len); 69 | void hex_key_dump(void *d, int len); 70 | 71 | #endif /* __TOOLS_H__ */ 72 | -------------------------------------------------------------------------------- /source/sha1.h: -------------------------------------------------------------------------------- 1 | /* 2 | * sha1.h 3 | * 4 | * Description: 5 | * This is the header file for code which implements the Secure 6 | * Hashing Algorithm 1 as defined in FIPS PUB 180-1 published 7 | * April 17, 1995. 8 | * 9 | * Many of the variable names in this code, especially the 10 | * single character names, were used because those were the names 11 | * used in the publication. 12 | * 13 | * Please read the file sha1.c for more information. 14 | * 15 | */ 16 | 17 | #ifndef _SHA1_H_ 18 | #define _SHA1_H_ 19 | 20 | #include 21 | 22 | /* 23 | * If you do not have the ISO standard stdint.h header file, then you 24 | * must typdef the following: 25 | * name meaning 26 | * uint32_t unsigned 32 bit integer 27 | * uint8_t unsigned 8 bit integer (i.e., unsigned char) 28 | * int_least16_t integer of >= 16 bits 29 | * 30 | */ 31 | 32 | #ifndef _SHA_enum_ 33 | #define _SHA_enum_ 34 | enum 35 | { 36 | shaSuccess = 0, 37 | shaNull, /* Null pointer parameter */ 38 | shaInputTooLong, /* input data too long */ 39 | shaStateError /* called Input after Result */ 40 | }; 41 | #endif 42 | 43 | #define SHA1HashSize 20 44 | 45 | /* 46 | * This structure will hold context information for the SHA-1 47 | * hashing operation 48 | */ 49 | typedef struct SHA1Context 50 | { 51 | uint32_t Intermediate_Hash[SHA1HashSize/4]; /* Message Digest */ 52 | 53 | uint32_t Length_Low; /* Message length in bits */ 54 | uint32_t Length_High; /* Message length in bits */ 55 | 56 | int_least16_t Message_Block_Index; /* Index into message block array */ 57 | uint8_t Message_Block[64]; /* 512-bit message blocks */ 58 | 59 | int Computed; /* Is the digest computed? */ 60 | int Corrupted; /* Is the message digest corrupted? */ 61 | } SHA1Context; 62 | 63 | /* 64 | * Function Prototypes 65 | */ 66 | int SHA1Reset(SHA1Context *context); 67 | int SHA1Input(SHA1Context *context, uint8_t *message_array, unsigned int length); 68 | int SHA1Result(SHA1Context *context, uint8_t Message_Digest[SHA1HashSize]); 69 | int SHA1(uint8_t *message_array, unsigned int length, uint8_t Message_Digest[SHA1HashSize]); 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "yabdm.h" 8 | #include "tools.h" 9 | 10 | // Check if string X is in current argument 11 | #define CHECK_ARG(X) (!strncmp((X), argv[i], sizeof((X))-1)) 12 | #define CHECK_ARG_VAL(X) (argv[i] + sizeof((X))-1) 13 | 14 | extern void __exception_setreload(int); 15 | 16 | int main(int argc, char* argv[]) 17 | { 18 | __exception_setreload(10); 19 | 20 | int i; 21 | s32 ret; 22 | 23 | Init_Console(); 24 | printf("\x1b[%u;%um", 37, false); 25 | 26 | PAD_Init(); 27 | WUPC_Init(); 28 | WPAD_Init(); 29 | WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR); 30 | 31 | printheadline(); 32 | 33 | vwii = IsWiiU(); 34 | __debug = false; 35 | __wiilight = false; 36 | 37 | /* Also check argv[0], since it appears arguments get initially passed here if Wiiload is launched from a batch script */ 38 | for (i = 0; i < argc; ++i) 39 | { 40 | /* Check "debug" argument */ 41 | if (CHECK_ARG("debug=")) 42 | { 43 | if (atoi(CHECK_ARG_VAL("debug=")) == 1) 44 | { 45 | __debug = true; 46 | 47 | printf("Debug mode activated!\n\n"); 48 | printf("Overall application performance may be slower than before.\n"); 49 | printf("This is completely normal, and is because debug info will be constantly\n"); 50 | printf("written to the \"YABDM.log\" file in the selected storage device.\n\n"); 51 | printf("Press any button to continue..."); 52 | fflush(stdout); 53 | 54 | while(true) 55 | { 56 | if (DetectInput(DI_BUTTONS_DOWN) != 0) 57 | { 58 | resetscreen(); 59 | printheadline(); 60 | break; 61 | } 62 | } 63 | } 64 | } 65 | 66 | /* Check "wiilight" argument */ 67 | if (CHECK_ARG("wiilight=")) 68 | { 69 | if (atoi(CHECK_ARG_VAL("wiilight=")) == 1) __wiilight = true; 70 | } 71 | } 72 | 73 | ret = ahbprot_menu(); 74 | if (ret >= 0) 75 | { 76 | /* Initialize NAND FS */ 77 | ISFS_Initialize(); 78 | 79 | /* Mount available storage devices */ 80 | ret = Mount_Devices(); 81 | if (ret >= 0) 82 | { 83 | /* Copy launch path */ 84 | if (argv[0] != NULL) snprintf(launch_path, MAX_CHARACTERS(launch_path), argv[0]); 85 | 86 | /* Main app loop */ 87 | yabdm_loop(); 88 | } 89 | } 90 | 91 | printf("Exiting..."); 92 | fflush(stdout); 93 | 94 | /* Free content.map buffer */ 95 | if (cm) free(cm); 96 | 97 | /* Deinitialize network */ 98 | if (netw_init) net_deinit(); 99 | 100 | /* Unmount storage devices (including NAND FS) and exit */ 101 | ISFS_Deinitialize(); 102 | Unmount_Devices(); 103 | Reboot(); 104 | 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /source/mload/mload.h: -------------------------------------------------------------------------------- 1 | /* mload.c (for PPC) (c) 2009, Hermes 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 | */ 17 | 18 | #ifndef __MLOAD_H__ 19 | #define __MLOAD_H__ 20 | 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #define MLOAD_MLOAD_THREAD_ID 0x4D4C4400 29 | #define MLOAD_GET_IOS_BASE 0x4D4C4401 30 | #define MLOAD_GET_MLOAD_VERSION 0x4D4C4402 31 | 32 | #define MLOAD_LOAD_MODULE 0x4D4C4480 33 | #define MLOAD_RUN_MODULE 0x4D4C4481 34 | #define MLOAD_RUN_THREAD 0x4D4C4482 35 | 36 | #define MLOAD_STOP_THREAD 0x4D4C4484 37 | #define MLOAD_CONTINUE_THREAD 0x4D4C4485 38 | 39 | #define MLOAD_GET_LOAD_BASE 0x4D4C4490 40 | #define MLOAD_MEMSET 0x4D4C4491 41 | 42 | #define MLOAD_GET_EHCI_DATA 0x4D4C44A0 43 | #define MLOAD_GET_LOG 0x4D4C44A1 44 | 45 | #define MLOAD_SET_ES_IOCTLV 0x4D4C44B0 46 | 47 | #define MLOAD_GETW 0x4D4C44C0 48 | #define MLOAD_GETH 0x4D4C44C1 49 | #define MLOAD_GETB 0x4D4C44C2 50 | #define MLOAD_SETW 0x4D4C44C3 51 | #define MLOAD_SETH 0x4D4C44C4 52 | #define MLOAD_SETB 0x4D4C44C5 53 | 54 | #define MLOAD_SET_LOG_MODE 0x4D4C44D0 55 | #define MLOAD_GET_LOG_BUFFER 0x4D4C44D1 56 | 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | 61 | // from IOS ELF stripper of neimod 62 | 63 | #define getbe32(x) ((adr[x]<<24) | (adr[x+1]<<16) | (adr[x+2]<<8) | (adr[x+3])) 64 | 65 | typedef struct 66 | { 67 | u32 ident0; 68 | u32 ident1; 69 | u32 ident2; 70 | u32 ident3; 71 | u32 machinetype; 72 | u32 version; 73 | u32 entry; 74 | u32 phoff; 75 | u32 shoff; 76 | u32 flags; 77 | u16 ehsize; 78 | u16 phentsize; 79 | u16 phnum; 80 | u16 shentsize; 81 | u16 shnum; 82 | u16 shtrndx; 83 | } elfheader; 84 | 85 | typedef struct 86 | { 87 | u32 type; 88 | u32 offset; 89 | u32 vaddr; 90 | u32 paddr; 91 | u32 filesz; 92 | u32 memsz; 93 | u32 flags; 94 | u32 align; 95 | } elfphentry; 96 | 97 | typedef struct 98 | { 99 | void *start; 100 | int prio; 101 | void *stack; 102 | int size_stack; 103 | } data_elf; 104 | 105 | /*--------------------------------------------------------------------------------------------------------------*/ 106 | 107 | // to init/test if the device is running 108 | 109 | int mload_init(); 110 | 111 | /*--------------------------------------------------------------------------------------------------------------*/ 112 | 113 | // to close the device (remember call it when rebooting the IOS!) 114 | 115 | int mload_close(); 116 | 117 | /*--------------------------------------------------------------------------------------------------------------*/ 118 | 119 | // load a module from the PPC 120 | // the module must be a elf made with stripios 121 | 122 | int mload_elf(void *my_elf, data_elf *data_elf); 123 | 124 | /*--------------------------------------------------------------------------------------------------------------*/ 125 | 126 | // run one thread (you can use to load modules or binary files) 127 | 128 | int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority); 129 | 130 | /*--------------------------------------------------------------------------------------------------------------*/ 131 | 132 | // fix starlet address to read/write (uses SEEK_SET, etc as mode) 133 | 134 | int mload_seek(int offset, int mode); 135 | 136 | /*--------------------------------------------------------------------------------------------------------------*/ 137 | 138 | // write bytes from starlet (it update the offset) 139 | 140 | int mload_write(const void * buf, u32 size); 141 | 142 | /*--------------------------------------------------------------------------------------------------------------*/ 143 | 144 | // fill a block (similar to memset) 145 | 146 | int mload_memset(void *starlet_addr, int set, int len); 147 | 148 | /*--------------------------------------------------------------------------------------------------------------*/ 149 | 150 | 151 | // to get IOS base for dev/es to create the cIOS 152 | 153 | int mload_get_IOS_base(); 154 | 155 | #ifdef __cplusplus 156 | } 157 | #endif 158 | 159 | 160 | #endif 161 | -------------------------------------------------------------------------------- /source/mload/mload_init.c: -------------------------------------------------------------------------------- 1 | #include "mload.h" 2 | #include "ehcmodule_5.h" 3 | #include "odip_frag.h" 4 | 5 | static u32 ios_36[16] ATTRIBUTE_ALIGN(32)= 6 | { 7 | 0, // DI_EmulateCmd 8 | 0, 9 | 0x2022DDAC, // dvd_read_controlling_data 10 | 0x20201010+1, // handle_di_cmd_reentry (thumb) 11 | 0x20200b9c+1, // ios_shared_alloc_aligned (thumb) 12 | 0x20200b70+1, // ios_shared_free (thumb) 13 | 0x20205dc0+1, // ios_memcpy (thumb) 14 | 0x20200048+1, // ios_fatal_di_error (thumb) 15 | 0x20202b4c+1, // ios_doReadHashEncryptedState (thumb) 16 | 0x20203934+1, // ios_printf (thumb) 17 | }; 18 | 19 | static u32 ios_38[16] ATTRIBUTE_ALIGN(32)= 20 | { 21 | 0, // DI_EmulateCmd 22 | 0, 23 | 0x2022cdac, // dvd_read_controlling_data 24 | 0x20200d38+1, // handle_di_cmd_reentry (thumb) 25 | 0x202008c4+1, // ios_shared_alloc_aligned (thumb) 26 | 0x20200898+1, // ios_shared_free (thumb) 27 | 0x20205b80+1, // ios_memcpy (thumb) 28 | 0x20200048+1, // ios_fatal_di_error (thumb) 29 | 0x20202874+1, // ios_doReadHashEncryptedState (thumb) 30 | 0x2020365c+1, // ios_printf (thumb) 31 | }; 32 | 33 | 34 | static u32 ios_37[16] ATTRIBUTE_ALIGN(32)= 35 | { 36 | 0, // DI_EmulateCmd 37 | 0, 38 | 0x2022DD60, // dvd_read_controlling_data 39 | 0x20200F04+1, // handle_di_cmd_reentry (thumb) 40 | 0x2020096C+1, // ios_shared_alloc_aligned (thumb) 41 | 0x2020093C+1, // ios_shared_free (thumb) 42 | 0x20205E54+1, // ios_memcpy (thumb) 43 | 0x20200048+1, // ios_fatal_di_error (thumb) 44 | 0x20202A70+1, // ios_doReadHashEncryptedState (thumb) 45 | 0x2020387C+1, // ios_printf (thumb) 46 | }; 47 | 48 | static u32 ios_57[16] ATTRIBUTE_ALIGN(32)= 49 | { 50 | 0, // DI_EmulateCmd 51 | 0, 52 | 0x2022cd60, // dvd_read_controlling_data 53 | 0x20200f04+1, // handle_di_cmd_reentry (thumb) 54 | 0x2020096c+1, // ios_shared_alloc_aligned (thumb) // no usado 55 | 0x2020093C+1, // ios_shared_free (thumb) // no usado 56 | 0x20205EF0+1, // ios_memcpy (thumb) 57 | 0x20200048+1, // ios_fatal_di_error (thumb) 58 | 0x20202944+1, // ios_doReadHashEncryptedState (thumb) 59 | 0x20203750+1, // ios_printf (thumb) 60 | }; 61 | 62 | static u32 ios_60[16] ATTRIBUTE_ALIGN(32)= 63 | { 64 | 0, // DI_EmulateCmd 65 | 0, 66 | 0x2022cd60, // dvd_read_controlling_data 67 | 0x20200f04+1, // handle_di_cmd_reentry (thumb) 68 | 0x2020096c+1, // ios_shared_alloc_aligned (thumb) // no usado 69 | 0x2020093C+1, // ios_shared_free (thumb) // no usado 70 | 0x20205e00+1, // ios_memcpy (thumb) 71 | 0x20200048+1, // ios_fatal_di_error (thumb) 72 | 0x20202944+1, // ios_doReadHashEncryptedState (thumb) 73 | 0x20203750+1, // ios_printf (thumb) 74 | }; 75 | 76 | 77 | static data_elf my_data_elf; 78 | 79 | int mload_Init() 80 | { 81 | if(mload_init() < 0) 82 | return -1; 83 | 84 | u8 *dip_plugin = (u8 *) odip_frag; 85 | u32 dip_plugin_size = odip_frag_size; 86 | 87 | mload_elf((u8 *) ehcmodule_5, &my_data_elf); 88 | int my_thread_id = mload_run_thread(my_data_elf.start, my_data_elf.stack, my_data_elf.size_stack, my_data_elf.prio); 89 | 90 | if(my_thread_id < 0) 91 | return -2; 92 | usleep(350*1000); 93 | 94 | // Test for IOS 95 | int is_ios = mload_get_IOS_base(); 96 | u32 dip_address = 0x1377C000; 97 | 98 | switch(is_ios) 99 | { 100 | 101 | case 36: 102 | 103 | memcpy(ios_36, dip_plugin, 4); // copy the entry_point 104 | memcpy(dip_plugin, ios_36, 4*10); // copy the adresses from the array 105 | 106 | mload_seek(dip_address, SEEK_SET); // copy dip_plugin in the starlet 107 | mload_write(dip_plugin, dip_plugin_size); 108 | 109 | // enables DIP plugin 110 | mload_seek(0x20209040, SEEK_SET); 111 | mload_write(ios_36, 4); 112 | break; 113 | 114 | case 37: 115 | 116 | memcpy(ios_37, dip_plugin, 4); // copy the entry_point 117 | memcpy(dip_plugin, ios_37, 4*10); // copy the adresses from the array 118 | 119 | mload_seek(dip_address, SEEK_SET); // copy dip_plugin in the starlet 120 | mload_write(dip_plugin,dip_plugin_size); 121 | 122 | // enables DIP plugin 123 | mload_seek(0x20209030, SEEK_SET); 124 | mload_write(ios_37, 4); 125 | break; 126 | 127 | case 38: 128 | 129 | memcpy(ios_38, dip_plugin, 4); // copy the entry_point 130 | memcpy(dip_plugin, ios_38, 4*10); // copy the adresses from the array 131 | 132 | mload_seek(dip_address, SEEK_SET); // copy dip_plugin in the starlet 133 | mload_write(dip_plugin,dip_plugin_size); 134 | 135 | // enables DIP plugin 136 | mload_seek(0x20208030, SEEK_SET); 137 | mload_write(ios_38, 4); 138 | break; 139 | 140 | case 57: 141 | 142 | memcpy(ios_57, dip_plugin, 4); // copy the entry_point 143 | memcpy(dip_plugin, ios_57, 4*10); // copy the adresses from the array 144 | 145 | mload_seek(dip_address, SEEK_SET); // copy dip_plugin in the starlet 146 | mload_write(dip_plugin,dip_plugin_size); 147 | 148 | // enables DIP plugin 149 | mload_seek(0x20208030, SEEK_SET); 150 | mload_write(ios_57, 4); 151 | break; 152 | 153 | case 60: 154 | 155 | memcpy(ios_60, dip_plugin, 4); // copy the entry_point 156 | memcpy(dip_plugin, ios_60, 4*10); // copy the adresses from the array 157 | 158 | mload_seek(dip_address, SEEK_SET); // copy dip_plugin in the starlet 159 | mload_write(dip_plugin,dip_plugin_size); 160 | 161 | // enables DIP plugin 162 | mload_seek(0x20208030, SEEK_SET); 163 | mload_write(ios_60, 4); 164 | break; 165 | 166 | } 167 | mload_close(); 168 | return 0; 169 | } 170 | -------------------------------------------------------------------------------- /source/otp.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "tools.h" 6 | #include "otp.h" 7 | 8 | #define HW_OTP_COMMAND (*(vu32*)0xcd8001ec) 9 | #define HW_OTP_DATA (*(vu32*)0xcd8001f0) 10 | #define OTP_SIZE 0x80 11 | 12 | static u8 otp_ptr[OTP_SIZE]; 13 | 14 | bool use_bootmii_data; 15 | 16 | u8 prng_key[16]; // otp_ptr @ 0x68 17 | u32 console_id; // otp_ptr @ 0x24 18 | 19 | u8 bootmii_prng[16]; 20 | u32 bootmii_cid; 21 | 22 | void OTP_Unmount() 23 | { 24 | memset(otp_ptr, 0, OTP_SIZE); 25 | } 26 | 27 | static bool OTP_Mount() 28 | { 29 | OTP_Unmount(); 30 | 31 | u8 addr; 32 | 33 | for (addr = 0; addr < 32; addr++) 34 | { 35 | HW_OTP_COMMAND = 0x80000000 | addr; 36 | *(((u32 *)otp_ptr) + addr) = HW_OTP_DATA; 37 | } 38 | 39 | return *otp_ptr; 40 | } 41 | 42 | s32 Get_OTP_data() 43 | { 44 | otp_t *otp_data = memalign(32, sizeof(otp_t)); 45 | if (!otp_data) 46 | { 47 | printf("Error allocating memory for otp_data!"); 48 | logfile("Error allocating memory for otp_data!"); 49 | return -2; 50 | } 51 | 52 | bool read_otp = OTP_Mount(); 53 | if (!read_otp) 54 | { 55 | OTP_Unmount(); 56 | free(otp_data); 57 | printf("Fatal error: OTP_Mount failed."); 58 | logfile("Fatal error: OTP_Mount failed."); 59 | return -2; 60 | } 61 | 62 | memcpy(otp_data, otp_ptr, sizeof(otp_t)); 63 | OTP_Unmount(); 64 | 65 | /* Copy PRNG Key */ 66 | memcpy(prng_key, otp_data->rng_key, 16); 67 | logfile("PRNG Key: "); 68 | hex_key_dump(prng_key, 16); 69 | logfile("... "); 70 | 71 | /* Copy Console ID */ 72 | memcpy(&console_id, otp_data->ng_id, 4); 73 | logfile("Console ID: %08lx... ", console_id); 74 | 75 | free(otp_data); 76 | 77 | return 0; 78 | } 79 | 80 | s32 Get_BootMii_data(u32 cntbin_cid) 81 | { 82 | if (bootmii_cid == 0) 83 | { 84 | bool is_nandbin = false; 85 | 86 | char filepath[20] = {0}; 87 | snprintf(filepath, MAX_CHARACTERS(filepath), "%s:/keys.bin", DEVICE(0)); 88 | 89 | printf("\nReading BootMii data from a different console... "); 90 | logfile("\r\nReading BootMii data from a different console... "); 91 | 92 | FILE *bootmii_file = fopen(filepath, "rb"); 93 | if (!bootmii_file) 94 | { 95 | snprintf(filepath, MAX_CHARACTERS(filepath), "%s:/nand.bin", DEVICE(0)); 96 | bootmii_file = fopen(filepath, "rb"); 97 | if (!bootmii_file) 98 | { 99 | printf("BootMii data not found!\n"); 100 | logfile("BootMii data not found!\r\n"); 101 | return -1; 102 | } else { 103 | is_nandbin = true; 104 | } 105 | } 106 | 107 | /* keys.bin layout */ 108 | /* Header (0x000): 0x100 bytes */ 109 | /* OTP data (0x100): 0x80 bytes */ 110 | /* Zero padding (0x180): 0x80 bytes */ 111 | /* SEEPROM data (0x200): 0x100 bytes */ 112 | /* Zero padding (0x300): 0x100 bytes */ 113 | 114 | /* nand.bin layout */ 115 | /* NAND dump + ECC data (0x00000000): 0x21000000 bytes (528 MB) */ 116 | /* Copy of keys.bin (0x21000000): 0x400 bytes */ 117 | /* NAND dumps created by old versions of BootMii do not have a copy of keys.bin */ 118 | 119 | if (is_nandbin) 120 | { 121 | fseek(bootmii_file, 0, SEEK_END); 122 | if (ftell(bootmii_file) < 0x21000400) 123 | { 124 | printf("\nThe available nand.bin file doesn't have a copy of keys.bin!\n"); 125 | logfile("The available nand.bin file doesn't have a copy of keys.bin!\r\n"); 126 | fclose(bootmii_file); 127 | return -1; 128 | } else { 129 | rewind(bootmii_file); 130 | } 131 | } 132 | 133 | otp_t *otp_data = memalign(32, sizeof(otp_t)); 134 | if (!otp_data) 135 | { 136 | printf("Error allocating memory for otp_data!"); 137 | logfile("Error allocating memory for otp_data!"); 138 | fclose(bootmii_file); 139 | return -2; 140 | } 141 | 142 | fseek(bootmii_file, (is_nandbin ? 0x21000100 : 0x100), SEEK_SET); 143 | __fread(otp_data, sizeof(otp_t), 1, bootmii_file); 144 | fclose(bootmii_file); 145 | 146 | /* Make sure that the keys are not zero-filled. Also, verify that they're not the same keys from this Wii */ 147 | if (is_empty(otp_data->rng_key, 16) || is_empty(otp_data->ng_id, 4)) 148 | { 149 | printf("\nError: The BootMii keys are null!\n"); 150 | logfile("Error: The BootMii keys are null!\r\n"); 151 | free(otp_data); 152 | return -1; 153 | } else 154 | if ((memcmp(otp_data->rng_key, prng_key, 16) == 0) || (memcmp(otp_data->ng_id, &console_id, 4) == 0)) 155 | { 156 | printf("\nError: The available BootMii data belongs to this console!\n"); 157 | logfile("Error: The available BootMii data belongs to this console!\r\n"); 158 | free(otp_data); 159 | return -1; 160 | } 161 | 162 | /* Copy PRNG Key */ 163 | memcpy(bootmii_prng, otp_data->rng_key, 16); 164 | logfile("BootMii PRNG Key: "); 165 | hex_key_dump(bootmii_prng, 16); 166 | logfile("... "); 167 | 168 | /* Copy Console ID */ 169 | memcpy(&bootmii_cid, otp_data->ng_id, 4); 170 | logfile("BootMii Console ID: %08lx... ", bootmii_cid); 171 | 172 | free(otp_data); 173 | 174 | printf("OK!\n"); 175 | logfile("OK!"); 176 | } else { 177 | printf("\nUsing previously loaded BootMii data.\n"); 178 | logfile("\r\nUsing previously loaded BootMii data.\r\n"); 179 | } 180 | 181 | if (cntbin_cid != bootmii_cid) 182 | { 183 | printf("Error: Console ID mismatch. This content.bin file neither was generated by\nthe Wii the BootMii data came from.\n"); 184 | logfile("Error: Console ID mismatch. This content.bin file neither was generated by the Wii the BootMii data came from.\r\n"); 185 | return -1; 186 | } 187 | 188 | use_bootmii_data = true; 189 | 190 | return 0; 191 | } 192 | -------------------------------------------------------------------------------- /portlibs/include/runtimeiospatch.h: -------------------------------------------------------------------------------- 1 | // This program is free software: you can redistribute it and/or modify 2 | // it under the terms of the GNU General Public License as published by 3 | // the Free Software Foundation, version 2.0. 4 | 5 | // This program is distributed in the hope that it will be useful, 6 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 7 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 8 | // GNU General Public License 2.0 for more details. 9 | 10 | // Copyright (C) 2010 Joseph Jordan 11 | // Copyright (C) 2012-2013 damysteryman 12 | // Copyright (C) 2012-2015 Christopher Bratusek 13 | // Copyright (C) 2013 DarkMatterCore 14 | // Copyright (C) 2014 megazig 15 | // Copyright (C) 2015 FIX94 16 | 17 | #ifndef __RUNTIMEIOSPATCH_H__ 18 | #define __RUNTIMEIOSPATCH_H__ 19 | 20 | /** 21 | * Version information for Libruntimeiospatch. 22 | */ 23 | #define LIB_RUNTIMEIOSPATCH_VERSION "1.5.4" 24 | 25 | //============================================================================== 26 | // HW_RVL header 27 | //============================================================================== 28 | #if defined(HW_RVL) /* defined(HW_RVL) */ 29 | 30 | /** 31 | *Returns true when HW_AHBPROT access can be applied 32 | */ 33 | #define AHBPROT_DISABLED (*(vu32*)0xcd800064 == 0xFFFFFFFF) 34 | 35 | //============================================================================== 36 | // Error code definitions: 37 | //============================================================================== 38 | #define ERROR_AHBPROT -5 39 | #define ERROR_PATCH -7 40 | 41 | //============================================================================== 42 | // C++ header 43 | //============================================================================== 44 | #ifdef __cplusplus 45 | extern "C" { 46 | #endif 47 | /* __cplusplus */ 48 | 49 | //============================================================================== 50 | // Patchsets: 51 | //============================================================================== 52 | /* 53 | Wii: 54 | * DI Readlimit 55 | * ISFS Permissions 56 | * ES SetUID 57 | * ES SetIdentify 58 | * Hash Check (aka Trucha) 59 | * New Hash Check (aka New Trucha) 60 | * SSL patches 61 | 62 | Sciifii: 63 | * MEM2 Prot 64 | * ES OpenTitleContent 1 & 2 65 | * ES ReadContent Prot 66 | * ES CloseContent 67 | * ES TitleVersionCheck 68 | * ES TitleDeleteCheck 69 | 70 | vWii: 71 | * Kill Anti-SystemTitle-Install 1, 2, 3, 4 & 5 72 | */ 73 | 74 | 75 | //============================================================================== 76 | // Functions: 77 | //============================================================================== 78 | 79 | /** 80 | * This function can be used to keep HW_AHBPROT access when going to reload IOS 81 | * @param verbose Flag determing whether or not to print messages on-screen 82 | * @example 83 | * if(AHBPROT_DISABLED) { 84 | * s32 ret; 85 | * ret = IosPatch_AHBPROT(false); 86 | * if (ret) { 87 | * IOS_ReloadIOS(36); 88 | * } else { 89 | * printf("IosPatch_AHBPROT failed."); 90 | * } 91 | * } 92 | * @return Signed 32bit integer representing code 93 | * > 0 : Success - return equals to number of applied patches 94 | * ERROR_AHBPROT : Error - No HW_AHBPROT access 95 | */ 96 | s32 IosPatch_AHBPROT(bool verbose); 97 | 98 | 99 | /** 100 | * This function applies patches on current IOS 101 | * @see Patchsets 102 | * @param wii Flag determing whether or not to apply Wii patches. 103 | * @param sciifii Flag determing whether or not to apply extra Sciifii patches. 104 | * @param vwii Flag determing whether or not to apply extra vWii patches. 105 | * @param verbose Flag determing whether or not to print messages on-screen. 106 | * @example if(AHBPROT_DISABLED) IosPatch_FULL(true, false, false, false); 107 | * @return Signed 32bit integer representing code 108 | * > 0 : Success - return equals to number of applied patches 109 | * ERROR_AHBPROT : Error - No HW_AHBPROT access 110 | * ERROR_PATCH : Error - Patching HW_AHBPROT access failed 111 | */ 112 | s32 IosPatch_RUNTIME(bool wii, bool sciifii, bool vwii, bool verbose); 113 | 114 | 115 | /** 116 | * This function combines IosPatch_AHBPROT + IOS_ReloadIOS + IosPatch_RUNTIME 117 | * @see Patchsets 118 | * @param wii Flag determing whether or not to apply Wii patches. 119 | * @param sciifii Flag determing whether or not to apply extra Sciifii patches. 120 | * @param vwii Flag determing whether or not to apply extra vWii patches. 121 | * @param verbose Flag determing whether or not to print messages on-screen. 122 | * @param IOS Which IOS to reload into. 123 | * @example if(AHBPROT_DISABLED) IosPatch_FULL(true, false, false, false, 58); 124 | * @return Signed 32bit integer representing code 125 | * > 0 : Success - return equals to number of applied patches 126 | * ERROR_AHBPROT : Error - No HW_AHBPROT access 127 | * ERROR_PATCH : Error - Patching HW_AHBPROT access failed 128 | */ 129 | s32 IosPatch_FULL(bool wii, bool sciifii, bool vwii, bool verbose, int IOS); 130 | 131 | //============================================================================== 132 | // C++ footer 133 | //============================================================================== 134 | #ifdef __cplusplus 135 | } 136 | #endif /* __cplusplus */ 137 | 138 | //============================================================================== 139 | // HW_RVL footer 140 | //============================================================================== 141 | #endif /* defined(HW_RVL) */ 142 | 143 | #endif 144 | -------------------------------------------------------------------------------- /source/mload/mload.c: -------------------------------------------------------------------------------- 1 | /* mload.c (for PPC) (c) 2009, Hermes 2 | 3 | This program is free software; you can redistribute it and/or modify 4 | it under the terms of the GNU General Public License as published by 5 | the Free Software Foundation; either version 2 of the License, or 6 | (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 16 | */ 17 | 18 | #include "mload.h" 19 | 20 | static const char mload_fs[] ATTRIBUTE_ALIGN(32) = "/dev/mload"; 21 | 22 | static s32 mload_fd = -1; 23 | static s32 hid = -1; 24 | 25 | /*--------------------------------------------------------------------------------------------------------------*/ 26 | 27 | // to init/test if the device is running 28 | 29 | int mload_init() 30 | { 31 | int n; 32 | 33 | if(hid<0) hid = iosCreateHeap(0x10000); 34 | 35 | if(hid<0) 36 | { 37 | if(mload_fd>=0) 38 | IOS_Close(mload_fd); 39 | 40 | mload_fd=-1; 41 | 42 | return hid; 43 | } 44 | 45 | if(mload_fd>=0) 46 | { 47 | return 0; 48 | } 49 | 50 | for(n=0;n<20;n++) // try 5 seconds 51 | { 52 | mload_fd=IOS_Open(mload_fs, 0); 53 | 54 | if(mload_fd>=0) break; 55 | 56 | usleep(250*1000); 57 | } 58 | 59 | return mload_fd; 60 | } 61 | 62 | /*--------------------------------------------------------------------------------------------------------------*/ 63 | 64 | // to close the device (remember call it when rebooting the IOS!) 65 | 66 | int mload_close() 67 | { 68 | int ret; 69 | 70 | if(mload_fd<0) return -1; 71 | 72 | ret=IOS_Close(mload_fd); 73 | 74 | mload_fd=-1; 75 | 76 | return ret; 77 | } 78 | 79 | /*--------------------------------------------------------------------------------------------------------------*/ 80 | 81 | // load a module from the PPC 82 | // the module must be a elf made with stripios 83 | 84 | int mload_elf(void *my_elf, data_elf *data_elf) 85 | { 86 | int n,m; 87 | int p; 88 | u8 *adr; 89 | u32 elf=(u32) my_elf; 90 | 91 | if(elf & 3) return -1; // aligned to 4 please! 92 | 93 | elfheader *head=(void *) elf; 94 | elfphentry *entries; 95 | 96 | if(head->ident0!=0x7F454C46) return -1; 97 | if(head->ident1!=0x01020161) return -1; 98 | if(head->ident2!=0x01000000) return -1; 99 | 100 | p=head->phoff; 101 | 102 | data_elf->start=(void *) head->entry; 103 | 104 | for(n=0; nphnum; n++) 105 | { 106 | entries=(void *) (elf+p); 107 | p+=sizeof(elfphentry); 108 | 109 | if(entries->type == 4) 110 | { 111 | adr=(void *) (elf + entries->offset); 112 | 113 | if(getbe32(0)!=0) return -2; // bad info (sure) 114 | 115 | for(m=4; (u32)m < entries->memsz; m+=8) 116 | { 117 | switch(getbe32(m)) 118 | { 119 | case 0x9: 120 | data_elf->start= (void *) getbe32(m+4); 121 | break; 122 | case 0x7D: 123 | data_elf->prio= getbe32(m+4); 124 | break; 125 | case 0x7E: 126 | data_elf->size_stack= getbe32(m+4); 127 | break; 128 | case 0x7F: 129 | data_elf->stack= (void *) (getbe32(m+4)); 130 | break; 131 | 132 | } 133 | 134 | } 135 | 136 | } 137 | else 138 | if(entries->type == 1 && entries->memsz != 0 && entries->vaddr!=0) 139 | { 140 | 141 | if(mload_memset((void *) entries->vaddr, 0, entries->memsz)<0) return -1; 142 | if(mload_seek(entries->vaddr, SEEK_SET)<0) return -1; 143 | if(mload_write((void *) (elf + entries->offset), entries->filesz)<0) return -1; 144 | 145 | } 146 | } 147 | 148 | return 0; 149 | } 150 | 151 | /*--------------------------------------------------------------------------------------------------------------*/ 152 | 153 | // run one thread (you can use to load modules or binary files) 154 | 155 | int mload_run_thread(void *starlet_addr, void *starlet_top_stack, int stack_size, int priority) 156 | { 157 | int ret; 158 | 159 | if(mload_init()<0) return -1; 160 | 161 | ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_RUN_THREAD, "iiii:", starlet_addr,starlet_top_stack, stack_size, priority); 162 | 163 | return ret; 164 | } 165 | 166 | /*--------------------------------------------------------------------------------------------------------------*/ 167 | 168 | // fix starlet address to read/write (uses SEEK_SET, etc as mode) 169 | 170 | int mload_seek(int offset, int mode) 171 | { 172 | if(mload_init()<0) return -1; 173 | 174 | return IOS_Seek(mload_fd, offset, mode); 175 | } 176 | 177 | /*--------------------------------------------------------------------------------------------------------------*/ 178 | 179 | // write bytes from starlet (it update the offset) 180 | 181 | int mload_write(const void * buf, u32 size) 182 | { 183 | if(mload_init()<0) return -1; 184 | 185 | return IOS_Write(mload_fd, buf, size); 186 | } 187 | 188 | /*--------------------------------------------------------------------------------------------------------------*/ 189 | 190 | // fill a block (similar to memset) 191 | 192 | int mload_memset(void *starlet_addr, int set, int len) 193 | { 194 | int ret; 195 | 196 | if(mload_init()<0) return -1; 197 | 198 | ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_MEMSET, "iii:", starlet_addr, set, len); 199 | 200 | return ret; 201 | } 202 | 203 | /*--------------------------------------------------------------------------------------------------------------*/ 204 | 205 | // to get IOS base for dev/es to create the cIOS 206 | 207 | int mload_get_IOS_base() 208 | { 209 | int ret; 210 | 211 | if(mload_init()<0) return -1; 212 | 213 | ret= IOS_IoctlvFormat(hid, mload_fd, MLOAD_GET_IOS_BASE, ":"); 214 | 215 | return ret; 216 | 217 | } 218 | 219 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | # Clear the implicit built in rules 3 | #--------------------------------------------------------------------------------- 4 | .SUFFIXES: 5 | #--------------------------------------------------------------------------------- 6 | ifeq ($(strip $(DEVKITPPC)),) 7 | $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=devkitPPC") 8 | endif 9 | 10 | include $(DEVKITPPC)/wii_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # INCLUDES is a list of directories containing extra header files 17 | #--------------------------------------------------------------------------------- 18 | TARGET := boot 19 | BUILD := build 20 | SOURCES := source source/mload 21 | DATA := data 22 | INCLUDES := 23 | 24 | #--------------------------------------------------------------------------------- 25 | # options for code generation 26 | #--------------------------------------------------------------------------------- 27 | 28 | CFLAGS = -g -O1 -Wall -mrvl $(MACHDEP) $(INCLUDE) 29 | CXXFLAGS = $(CFLAGS) 30 | 31 | LDFLAGS = -g $(MACHDEP) -Wl,-Map,$(notdir $@).map,-wrap,wiiuse_register 32 | 33 | #--------------------------------------------------------------------------------- 34 | # any extra libraries we wish to link with the project 35 | #--------------------------------------------------------------------------------- 36 | LIBS := -lfat -lwupc -lwiiuse -lbte -lm -logc -lruntimeiospatch 37 | 38 | 39 | #--------------------------------------------------------------------------------- 40 | # list of directories containing libraries, this must be the top level containing 41 | # include and lib 42 | #--------------------------------------------------------------------------------- 43 | LIBDIRS := $(CURDIR)/portlibs 44 | 45 | #--------------------------------------------------------------------------------- 46 | # no real need to edit anything past this point unless you need to add additional 47 | # rules for different file extensions 48 | #--------------------------------------------------------------------------------- 49 | ifneq ($(BUILD),$(notdir $(CURDIR))) 50 | #--------------------------------------------------------------------------------- 51 | 52 | export OUTPUT := $(CURDIR)/$(TARGET) 53 | 54 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 55 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 56 | 57 | export DEPSDIR := $(CURDIR)/$(BUILD) 58 | 59 | #--------------------------------------------------------------------------------- 60 | # automatically build a list of object files for our project 61 | #--------------------------------------------------------------------------------- 62 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 63 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 64 | sFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 65 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.S))) 66 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 67 | 68 | #--------------------------------------------------------------------------------- 69 | # use CXX for linking C++ projects, CC for standard C 70 | #--------------------------------------------------------------------------------- 71 | ifeq ($(strip $(CPPFILES)),) 72 | export LD := $(CC) 73 | else 74 | export LD := $(CXX) 75 | endif 76 | 77 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 78 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) \ 79 | $(sFILES:.s=.o) $(SFILES:.S=.o) 80 | 81 | #--------------------------------------------------------------------------------- 82 | # build a list of include paths 83 | #--------------------------------------------------------------------------------- 84 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 85 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 86 | -I$(CURDIR)/$(BUILD) \ 87 | -I$(LIBOGC_INC) 88 | 89 | #--------------------------------------------------------------------------------- 90 | # build a list of library paths 91 | #--------------------------------------------------------------------------------- 92 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) \ 93 | -L$(LIBOGC_LIB) 94 | 95 | export OUTPUT := $(CURDIR)/$(TARGET) 96 | .PHONY: $(BUILD) clean 97 | 98 | #--------------------------------------------------------------------------------- 99 | $(BUILD): 100 | @[ -d $@ ] || mkdir -p $@ 101 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 102 | #--------------------------------------------------------------------------------- 103 | clean: 104 | @echo clean ... 105 | @rm -fr $(BUILD) $(OUTPUT).elf $(OUTPUT).dol 106 | #--------------------------------------------------------------------------------- 107 | run: 108 | wiiload $(TARGET).elf debug=1 wiilight=1 109 | #--------------------------------------------------------------------------------- 110 | else 111 | 112 | DEPENDS := $(OFILES:.o=.d) 113 | 114 | #--------------------------------------------------------------------------------- 115 | # main targets 116 | #--------------------------------------------------------------------------------- 117 | $(OUTPUT).dol: $(OUTPUT).elf 118 | $(OUTPUT).elf: $(OFILES) 119 | 120 | #--------------------------------------------------------------------------------- 121 | # This rule links in binary data 122 | #--------------------------------------------------------------------------------- 123 | %.sys.o : %.sys 124 | @echo $(notdir $<) 125 | $(bin2o) 126 | 127 | -include $(DEPENDS) 128 | 129 | #--------------------------------------------------------------------------------- 130 | endif 131 | #--------------------------------------------------------------------------------- 132 | -------------------------------------------------------------------------------- /source/mload/usb2storage.c: -------------------------------------------------------------------------------- 1 | /*------------------------------------------------------------- 2 | 3 | usbstorage_starlet.c -- USB mass storage support, inside starlet 4 | Copyright (C) 2011 Dimok 5 | Copyright (C) 2011 Rodries 6 | Copyright (C) 2009 Kwiirk 7 | 8 | If this driver is linked before libogc, this will replace the original 9 | usbstorage driver by svpe from libogc 10 | This software is provided 'as-is', without any express or implied 11 | warranty. In no event will the authors be held liable for any 12 | damages arising from the use of this software. 13 | 14 | Permission is granted to anyone to use this software for any 15 | purpose, including commercial applications, and to alter it and 16 | redistribute it freely, subject to the following restrictions: 17 | 18 | 1. The origin of this software must not be misrepresented; you 19 | must not claim that you wrote the original software. If you use 20 | this software in a product, an acknowledgment in the product 21 | documentation would be appreciated but is not required. 22 | 23 | 2. Altered source versions must be plainly marked as such, and 24 | must not be misrepresented as being the original software. 25 | 26 | 3. This notice may not be removed or altered from any source 27 | distribution. 28 | 29 | -------------------------------------------------------------*/ 30 | /************************************************************** 31 | * Modified by DarkMatterCore [PabloACZ] * 32 | ***************************************************************/ 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include "usb2storage.h" 39 | 40 | /* IOCTL commands */ 41 | #define UMS_BASE (('U'<<24)|('M'<<16)|('S'<<8)) 42 | #define USB_IOCTL_UMS_INIT (UMS_BASE+0x1) 43 | #define USB_IOCTL_UMS_GET_CAPACITY (UMS_BASE+0x2) 44 | #define USB_IOCTL_UMS_READ_SECTORS (UMS_BASE+0x3) 45 | #define USB_IOCTL_UMS_WRITE_SECTORS (UMS_BASE+0x4) 46 | 47 | #define MAX_SECTOR_SIZE 4096 48 | #define MAX_BUFFER_SECTORS 64 49 | #define UMS_HEAPSIZE 2*1024 50 | 51 | /* Variables */ 52 | static char fs[] ATTRIBUTE_ALIGN(32) = "/dev/usb2"; 53 | static char fs2[] ATTRIBUTE_ALIGN(32) = "/dev/usb123"; 54 | static char fs3[] ATTRIBUTE_ALIGN(32) = "/dev/usb/ehc"; 55 | 56 | static s32 hid = -1, fd = -1; 57 | bool hddInUse = false; 58 | u32 hdd_sector_size = 512; 59 | 60 | s32 USBStorage2_Init() 61 | { 62 | if (hddInUse) return 0; 63 | 64 | /* Create heap */ 65 | if (hid < 0) 66 | { 67 | hid = iosCreateHeap(UMS_HEAPSIZE); 68 | if (hid < 0) return IPC_ENOMEM; 69 | } 70 | 71 | /* Open USB device */ 72 | if (fd < 0) fd = IOS_Open(fs, 0); 73 | if (fd < 0) fd = IOS_Open(fs2, 0); 74 | if (fd < 0) fd = IOS_Open(fs3, 0); 75 | if (fd < 0) return fd; 76 | 77 | /* Initialize USB storage */ 78 | s32 ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_INIT, ":"); 79 | if (ret >= 0) 80 | { 81 | /* Get device capacity */ 82 | ret = USBStorage2_GetCapacity(&hdd_sector_size); 83 | if (ret <= 0) ret = IPC_ENOENT; 84 | } 85 | 86 | if (ret < 0) 87 | { 88 | USBStorage2_Deinit(); 89 | } else { 90 | hddInUse = true; 91 | } 92 | 93 | return ret; 94 | } 95 | 96 | void USBStorage2_Deinit() 97 | { 98 | /* Close USB device */ 99 | if (fd >= 0) 100 | { 101 | IOS_Close(fd); 102 | fd = -1; 103 | } 104 | } 105 | 106 | s32 USBStorage2_GetCapacity(u32 *_sector_size) 107 | { 108 | if (fd >= 0) 109 | { 110 | s32 ret; 111 | u32 sector_size = 0; 112 | 113 | ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_GET_CAPACITY, ":i", §or_size); 114 | if (ret && _sector_size) *_sector_size = sector_size; 115 | 116 | return ret; 117 | } 118 | 119 | return IPC_ENOENT; 120 | } 121 | 122 | s32 USBStorage2_ReadSectors(u32 sector, u32 numSectors, void *buffer) 123 | { 124 | u8 *buf = (u8 *) buffer; 125 | s32 ret = -1; 126 | 127 | /* Device not opened */ 128 | if (fd < 0) return fd; 129 | 130 | s32 read_secs, read_size; 131 | while (numSectors > 0) 132 | { 133 | read_secs = ((numSectors > MAX_BUFFER_SECTORS) ? MAX_BUFFER_SECTORS : numSectors); 134 | read_size = (read_secs * hdd_sector_size); 135 | 136 | /* Read data */ 137 | ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_READ_SECTORS, "ii:d", sector, read_secs, buf, read_size); 138 | if (ret < 0) break; 139 | 140 | sector += read_secs; 141 | numSectors -= read_secs; 142 | buf += read_size; 143 | } 144 | 145 | return ret; 146 | } 147 | 148 | s32 USBStorage2_WriteSectors(u32 sector, u32 numSectors, const void *buffer) 149 | { 150 | u8 *buf = (u8 *) buffer; 151 | s32 ret = -1; 152 | 153 | /* Device not opened */ 154 | if (fd < 0) return fd; 155 | 156 | s32 write_size, write_secs; 157 | while (numSectors > 0) 158 | { 159 | write_secs = ((numSectors > MAX_BUFFER_SECTORS) ? MAX_BUFFER_SECTORS : numSectors); 160 | write_size = (write_secs * hdd_sector_size); 161 | 162 | /* Write data */ 163 | ret = IOS_IoctlvFormat(hid, fd, USB_IOCTL_UMS_WRITE_SECTORS, "ii:d", sector, write_secs, buf, write_size); 164 | if (ret < 0) break; 165 | 166 | sector += write_secs; 167 | numSectors -= write_secs; 168 | buf += write_size; 169 | } 170 | 171 | return ret; 172 | } 173 | 174 | static bool __usbstorage_Startup(void) 175 | { 176 | return (USBStorage2_Init() >= 0); 177 | } 178 | 179 | static bool __usbstorage_IsInserted(void) 180 | { 181 | return (USBStorage2_GetCapacity(NULL) > 0); 182 | } 183 | 184 | static bool __usbstorage_ReadSectors(u32 sector, u32 numSectors, void *buffer) 185 | { 186 | return (USBStorage2_ReadSectors(sector, numSectors, buffer) >= 0); 187 | } 188 | 189 | static bool __usbstorage_WriteSectors(u32 sector, u32 numSectors, const void *buffer) 190 | { 191 | return (USBStorage2_WriteSectors(sector, numSectors, buffer) >= 0); 192 | } 193 | 194 | static bool __usbstorage_ClearStatus(void) 195 | { 196 | return true; 197 | } 198 | 199 | static bool __usbstorage_Shutdown(void) 200 | { 201 | hddInUse = false; 202 | hdd_sector_size = 512; 203 | USBStorage2_Deinit(); 204 | return true; 205 | } 206 | 207 | const DISC_INTERFACE __io_usbstorage2 = { 208 | DEVICE_TYPE_WII_UMS, FEATURE_MEDIUM_CANREAD | FEATURE_MEDIUM_CANWRITE | FEATURE_WII_USB, 209 | (FN_MEDIUM_STARTUP) &__usbstorage_Startup, 210 | (FN_MEDIUM_ISINSERTED) &__usbstorage_IsInserted, 211 | (FN_MEDIUM_READSECTORS) &__usbstorage_ReadSectors, 212 | (FN_MEDIUM_WRITESECTORS) &__usbstorage_WriteSectors, 213 | (FN_MEDIUM_CLEARSTATUS) &__usbstorage_ClearStatus, 214 | (FN_MEDIUM_SHUTDOWN) &__usbstorage_Shutdown 215 | }; 216 | -------------------------------------------------------------------------------- /source/ssl.c: -------------------------------------------------------------------------------- 1 | /* Code taken from http://www.wiibrew.org/wiki//dev/net/ssl/code */ 2 | /* Made by Aruskano */ 3 | 4 | #include 5 | #include 6 | 7 | #include "ssl.h" 8 | 9 | #define ISALIGNED(x) ((((u32)(x)) & 0x1F) == 0) 10 | 11 | static char __ssl_fs[] ATTRIBUTE_ALIGN(32) = "/dev/net/ssl"; 12 | 13 | static s32 __ssl_fd = -1; 14 | static s32 __ssl_hid = -1; 15 | 16 | s32 ssl_init(void) 17 | { 18 | if (__ssl_hid < 0) 19 | { 20 | __ssl_hid = iosCreateHeap(SSL_HEAP_SIZE); 21 | if (__ssl_hid < 0) return __ssl_hid; 22 | } 23 | 24 | return 0; 25 | } 26 | 27 | s32 ssl_open(void) 28 | { 29 | s32 ret; 30 | 31 | if (__ssl_fd < 0) 32 | { 33 | ret = IOS_Open(__ssl_fs, 0); 34 | if (ret < 0) return ret; 35 | __ssl_fd = ret; 36 | } 37 | 38 | return 0; 39 | } 40 | 41 | s32 ssl_close(void) 42 | { 43 | s32 ret; 44 | 45 | if (__ssl_fd < 0) return 0; 46 | 47 | ret = IOS_Close(__ssl_fd); 48 | 49 | __ssl_fd = -1; 50 | 51 | if (ret < 0) return ret; 52 | 53 | return 0; 54 | } 55 | 56 | s32 ssl_new(u8 * CN, u32 ssl_verify_options) 57 | { 58 | s32 ret; 59 | s32 aContext[8] ATTRIBUTE_ALIGN(32); 60 | u32 aVerify_options[8] ATTRIBUTE_ALIGN(32); 61 | 62 | ret = ssl_open(); 63 | if (ret) return ret; 64 | 65 | aVerify_options[0] = ssl_verify_options; 66 | 67 | /* Avoid alignment if the input is aligned */ 68 | if (ISALIGNED(CN)) 69 | { 70 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, CN, 0x100); 71 | } else { 72 | u8 *aCN = NULL; 73 | aCN = iosAlloc(__ssl_hid, 0x100); 74 | if (!aCN) return IPC_ENOMEM; 75 | 76 | memcpy(aCN, CN, 0x100); 77 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_NEW, "d:dd", aContext, 0x20, aVerify_options, 0x20, aCN, 0x100); 78 | 79 | if (aCN) iosFree(__ssl_hid, aCN); 80 | } 81 | 82 | ssl_close(); 83 | 84 | return (ret ? ret : aContext[0]); 85 | } 86 | 87 | s32 ssl_setbuiltinclientcert(s32 ssl_context, s32 index) 88 | { 89 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 90 | s32 aIndex[8] ATTRIBUTE_ALIGN(32); 91 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 92 | s32 ret; 93 | 94 | ret = ssl_open(); 95 | if (ret) return ret; 96 | 97 | aSsl_context[0] = ssl_context; 98 | aIndex[0] = index; 99 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETBUILTINCLIENTCERT, "d:dd", aResponse, 32, aSsl_context, 32, aIndex, 32); 100 | ssl_close(); 101 | 102 | return (ret ? ret : aResponse[0]); 103 | } 104 | 105 | s32 ssl_setrootca(s32 ssl_context, const void *root, u32 length) 106 | { 107 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 108 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 109 | s32 ret; 110 | 111 | ret = ssl_open(); 112 | if (ret) return ret; 113 | 114 | aSsl_context[0] = ssl_context; 115 | 116 | /* Avoid alignment if the input is aligned */ 117 | if (ISALIGNED(root)) 118 | { 119 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, root, length); 120 | } else { 121 | u8 *aRoot = NULL; 122 | 123 | aRoot = iosAlloc(__ssl_hid, length); 124 | if (!aRoot) return IPC_ENOMEM; 125 | 126 | memcpy(aRoot, root, length); 127 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SETROOTCA, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aRoot, length); 128 | 129 | if (aRoot) iosFree(__ssl_hid, aRoot); 130 | } 131 | 132 | ssl_close(); 133 | 134 | return (ret ? ret : aResponse[0]); 135 | } 136 | 137 | s32 ssl_connect(s32 ssl_context, s32 socket) 138 | { 139 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 140 | s32 aSocket[8] ATTRIBUTE_ALIGN(32); 141 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 142 | s32 ret; 143 | 144 | ret = ssl_open(); 145 | if (ret) return ret; 146 | 147 | aSsl_context[0] = ssl_context; 148 | aSocket[0] = socket; 149 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_CONNECT, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aSocket, 0x20); 150 | ssl_close(); 151 | 152 | return (ret ? ret : aResponse[0]); 153 | } 154 | 155 | s32 ssl_handshake(s32 ssl_context) 156 | { 157 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 158 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 159 | s32 ret; 160 | 161 | ret = ssl_open(); 162 | if (ret) return ret; 163 | 164 | aSsl_context[0] = ssl_context; 165 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_HANDSHAKE, "d:d", aResponse, 0x20, aSsl_context, 0x20); 166 | ssl_close(); 167 | 168 | return (ret ? ret : aResponse[0]); 169 | } 170 | 171 | s32 ssl_read(s32 ssl_context, void* buffer, u32 length) 172 | { 173 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 174 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 175 | s32 ret; 176 | 177 | if (!buffer) return IPC_EINVAL; 178 | 179 | ret = ssl_open(); 180 | if (ret) return ret; 181 | 182 | u8 *aBuffer = NULL; 183 | aBuffer = iosAlloc(__ssl_hid, length); 184 | if (!aBuffer) return IPC_ENOMEM; 185 | 186 | aSsl_context[0] = ssl_context; 187 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_READ, "dd:d", aResponse, 0x20, aBuffer, length, aSsl_context, 0x20); 188 | ssl_close(); 189 | 190 | if (ret == IPC_OK) memcpy(buffer, aBuffer, aResponse[0]); 191 | 192 | if (aBuffer) iosFree(__ssl_hid, aBuffer); 193 | 194 | return (ret ? ret : aResponse[0]); 195 | } 196 | 197 | s32 ssl_write(s32 ssl_context, const void *buffer, u32 length) 198 | { 199 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 200 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 201 | s32 ret; 202 | 203 | if (!buffer) return IPC_EINVAL; 204 | 205 | ret = ssl_open(); 206 | if (ret) return ret; 207 | 208 | aSsl_context[0] = ssl_context; 209 | 210 | /* Avoid alignment if the input is aligned */ 211 | if (ISALIGNED(buffer)) 212 | { 213 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, buffer, length); 214 | } else { 215 | u8 *aBuffer = NULL; 216 | aBuffer = iosAlloc(__ssl_hid, length); 217 | if (!aBuffer) return IPC_ENOMEM; 218 | 219 | memcpy(aBuffer, buffer, length); 220 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_WRITE, "d:dd", aResponse, 0x20, aSsl_context, 0x20, aBuffer, length); 221 | } 222 | 223 | ssl_close(); 224 | 225 | return (ret ? ret : aResponse[0]); 226 | } 227 | 228 | s32 ssl_shutdown(s32 ssl_context) 229 | { 230 | s32 aSsl_context[8] ATTRIBUTE_ALIGN(32); 231 | s32 aResponse[8] ATTRIBUTE_ALIGN(32); 232 | s32 ret; 233 | 234 | ret = ssl_open(); 235 | if (ret) return ret; 236 | 237 | aSsl_context[0] = ssl_context; 238 | 239 | ret = IOS_IoctlvFormat(__ssl_hid, __ssl_fd, IOCTLV_SSL_SHUTDOWN, "d:d", aResponse, 0x20, aSsl_context, 0x20); 240 | 241 | ssl_close(); 242 | 243 | return (ret ? ret : aResponse[0]); 244 | } 245 | -------------------------------------------------------------------------------- /source/sha1.c: -------------------------------------------------------------------------------- 1 | /* 2 | * sha1.c 3 | * 4 | * Description: 5 | * This file implements the Secure Hashing Algorithm 1 as 6 | * defined in FIPS PUB 180-1 published April 17, 1995. 7 | * 8 | * The SHA-1, produces a 160-bit message digest for a given 9 | * data stream. It should take about 2**n steps to find a 10 | * message with the same digest as a given message and 11 | * 2**(n/2) to find any two messages with the same digest, 12 | * when n is the digest size in bits. Therefore, this 13 | * algorithm can serve as a means of providing a 14 | * "fingerprint" for a message. 15 | * 16 | * Portability Issues: 17 | * SHA-1 is defined in terms of 32-bit "words". This code 18 | * uses (included via "sha1.h" to define 32 and 8 19 | * bit unsigned integer types. If your C compiler does not 20 | * support 32 bit unsigned integers, this code is not 21 | * appropriate. 22 | * 23 | * Caveats: 24 | * SHA-1 is designed to work with messages less than 2^64 bits 25 | * long. Although SHA-1 allows a message digest to be generated 26 | * for messages of any number of bits less than 2^64, this 27 | * implementation only works with messages with a length that is 28 | * a multiple of the size of an 8-bit character. 29 | * 30 | */ 31 | 32 | #include "sha1.h" 33 | 34 | /* 35 | * Define the SHA1 circular left shift macro 36 | */ 37 | #define SHA1CircularShift(bits, word) (((word) << (bits)) | ((word) >> (32-(bits)))) 38 | 39 | /* Local Function Prototyptes */ 40 | void SHA1PadMessage(SHA1Context *context); 41 | void SHA1ProcessMessageBlock(SHA1Context *context); 42 | 43 | /* 44 | * SHA1Reset 45 | * 46 | * Description: 47 | * This function will initialize the SHA1Context in preparation 48 | * for computing a new SHA1 message digest. 49 | * 50 | * Parameters: 51 | * context: [in/out] 52 | * The context to reset. 53 | * 54 | * Returns: 55 | * sha Error Code. 56 | * 57 | */ 58 | int SHA1Reset(SHA1Context *context) 59 | { 60 | if (!context) return shaNull; 61 | 62 | context->Length_Low = 0; 63 | context->Length_High = 0; 64 | context->Message_Block_Index = 0; 65 | 66 | context->Intermediate_Hash[0] = 0x67452301; 67 | context->Intermediate_Hash[1] = 0xEFCDAB89; 68 | context->Intermediate_Hash[2] = 0x98BADCFE; 69 | context->Intermediate_Hash[3] = 0x10325476; 70 | context->Intermediate_Hash[4] = 0xC3D2E1F0; 71 | 72 | context->Computed = 0; 73 | context->Corrupted = 0; 74 | 75 | return shaSuccess; 76 | } 77 | 78 | /* 79 | * SHA1Result 80 | * 81 | * Description: 82 | * This function will return the 160-bit message digest into the 83 | * Message_Digest array provided by the caller. 84 | * NOTE: The first octet of hash is stored in the 0th element, 85 | * the last octet of hash in the 19th element. 86 | * 87 | * Parameters: 88 | * context: [in/out] 89 | * The context to use to calculate the SHA-1 hash. 90 | * Message_Digest: [out] 91 | * Where the digest is returned. 92 | * 93 | * Returns: 94 | * sha Error Code. 95 | * 96 | */ 97 | int SHA1Result(SHA1Context *context, uint8_t Message_Digest[SHA1HashSize]) 98 | { 99 | int i; 100 | 101 | if (!context || !Message_Digest) return shaNull; 102 | 103 | if (context->Corrupted) return context->Corrupted; 104 | 105 | if (!context->Computed) 106 | { 107 | SHA1PadMessage(context); 108 | for(i = 0; i < 64; ++i) 109 | { 110 | /* message may be sensitive, clear it out */ 111 | context->Message_Block[i] = 0; 112 | } 113 | 114 | context->Length_Low = 0; /* and clear length */ 115 | context->Length_High = 0; 116 | context->Computed = 1; 117 | } 118 | 119 | for(i = 0; i < SHA1HashSize; ++i) Message_Digest[i] = context->Intermediate_Hash[i >> 2] >> 8 * (3 - (i & 0x03)); 120 | 121 | return shaSuccess; 122 | } 123 | 124 | /* 125 | * SHA1Input 126 | * 127 | * Description: 128 | * This function accepts an array of octets as the next portion 129 | * of the message. 130 | * 131 | * Parameters: 132 | * context: [in/out] 133 | * The SHA context to update 134 | * message_array: [in] 135 | * An array of characters representing the next portion of 136 | * the message. 137 | * length: [in] 138 | * The length of the message in message_array 139 | * 140 | * Returns: 141 | * sha Error Code. 142 | * 143 | */ 144 | int SHA1Input(SHA1Context *context, uint8_t *message_array, unsigned length) 145 | { 146 | if (!length) return shaSuccess; 147 | 148 | if (!context || !message_array) return shaNull; 149 | 150 | if (context->Computed) 151 | { 152 | context->Corrupted = shaStateError; 153 | return shaStateError; 154 | } 155 | 156 | if (context->Corrupted) return context->Corrupted; 157 | 158 | while(length-- && !context->Corrupted) 159 | { 160 | context->Message_Block[context->Message_Block_Index++] = (*message_array & 0xFF); 161 | 162 | context->Length_Low += 8; 163 | if (context->Length_Low == 0) 164 | { 165 | context->Length_High++; 166 | if (context->Length_High == 0) 167 | { 168 | /* Message is too long */ 169 | context->Corrupted = 1; 170 | } 171 | } 172 | 173 | if (context->Message_Block_Index == 64) SHA1ProcessMessageBlock(context); 174 | 175 | message_array++; 176 | } 177 | 178 | return shaSuccess; 179 | } 180 | 181 | /* 182 | * SHA1ProcessMessageBlock 183 | * 184 | * Description: 185 | * This function will process the next 512 bits of the message 186 | * stored in the Message_Block array. 187 | * 188 | * Parameters: 189 | * None. 190 | * 191 | * Returns: 192 | * Nothing. 193 | * 194 | * Comments: 195 | 196 | * Many of the variable names in this code, especially the 197 | * single character names, were used because those were the 198 | * names used in the publication. 199 | * 200 | * 201 | */ 202 | void SHA1ProcessMessageBlock(SHA1Context *context) 203 | { 204 | /* Constants defined in SHA-1 */ 205 | const uint32_t K[] = { 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xCA62C1D6 }; 206 | 207 | int t; /* Loop counter */ 208 | uint32_t temp; /* Temporary word value */ 209 | uint32_t W[80]; /* Word sequence */ 210 | uint32_t A, B, C, D, E; /* Word buffers */ 211 | 212 | /* 213 | * Initialize the first 16 words in the array W 214 | */ 215 | for(t = 0; t < 16; t++) 216 | { 217 | W[t] = context->Message_Block[t * 4] << 24; 218 | W[t] |= context->Message_Block[t * 4 + 1] << 16; 219 | W[t] |= context->Message_Block[t * 4 + 2] << 8; 220 | W[t] |= context->Message_Block[t * 4 + 3]; 221 | } 222 | 223 | for(t = 16; t < 80; t++) W[t] = SHA1CircularShift(1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 224 | 225 | A = context->Intermediate_Hash[0]; 226 | B = context->Intermediate_Hash[1]; 227 | C = context->Intermediate_Hash[2]; 228 | D = context->Intermediate_Hash[3]; 229 | E = context->Intermediate_Hash[4]; 230 | 231 | for(t = 0; t < 20; t++) 232 | { 233 | temp = SHA1CircularShift(5, A) + ((B & C) | ((~B) & D)) + E + W[t] + K[0]; 234 | E = D; 235 | D = C; 236 | C = SHA1CircularShift(30, B); 237 | B = A; 238 | A = temp; 239 | } 240 | 241 | for(t = 20; t < 40; t++) 242 | { 243 | temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[1]; 244 | E = D; 245 | D = C; 246 | C = SHA1CircularShift(30, B); 247 | B = A; 248 | A = temp; 249 | } 250 | 251 | for(t = 40; t < 60; t++) 252 | { 253 | temp = SHA1CircularShift(5, A) + ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2]; 254 | E = D; 255 | D = C; 256 | C = SHA1CircularShift(30, B); 257 | B = A; 258 | A = temp; 259 | } 260 | 261 | for(t = 60; t < 80; t++) 262 | { 263 | temp = SHA1CircularShift(5, A) + (B ^ C ^ D) + E + W[t] + K[3]; 264 | E = D; 265 | D = C; 266 | C = SHA1CircularShift(30, B); 267 | B = A; 268 | A = temp; 269 | } 270 | 271 | context->Intermediate_Hash[0] += A; 272 | context->Intermediate_Hash[1] += B; 273 | context->Intermediate_Hash[2] += C; 274 | context->Intermediate_Hash[3] += D; 275 | context->Intermediate_Hash[4] += E; 276 | 277 | context->Message_Block_Index = 0; 278 | } 279 | 280 | /* 281 | * SHA1PadMessage 282 | * 283 | 284 | * Description: 285 | * According to the standard, the message must be padded to an even 286 | * 512 bits. The first padding bit must be a '1'. The last 64 287 | * bits represent the length of the original message. All bits in 288 | * between should be 0. This function will pad the message 289 | * according to those rules by filling the Message_Block array 290 | * accordingly. It will also call the ProcessMessageBlock function 291 | * provided appropriately. When it returns, it can be assumed that 292 | * the message digest has been computed. 293 | * 294 | * Parameters: 295 | * context: [in/out] 296 | * The context to pad 297 | * ProcessMessageBlock: [in] 298 | * The appropriate SHA*ProcessMessageBlock function 299 | * Returns: 300 | * Nothing. 301 | * 302 | */ 303 | 304 | void SHA1PadMessage(SHA1Context *context) 305 | { 306 | context->Message_Block[context->Message_Block_Index++] = 0x80; 307 | 308 | /* 309 | * Check to see if the current message block is too small to hold 310 | * the initial padding bits and length. If so, we will pad the 311 | * block, process it, and then continue padding into a second 312 | * block. 313 | */ 314 | if (context->Message_Block_Index > 55) 315 | { 316 | while(context->Message_Block_Index < 64) context->Message_Block[context->Message_Block_Index++] = 0; 317 | SHA1ProcessMessageBlock(context); 318 | } 319 | 320 | while(context->Message_Block_Index < 56) context->Message_Block[context->Message_Block_Index++] = 0; 321 | 322 | /* 323 | * Store the message length as the last 8 octets 324 | */ 325 | context->Message_Block[56] = context->Length_High >> 24; 326 | context->Message_Block[57] = context->Length_High >> 16; 327 | context->Message_Block[58] = context->Length_High >> 8; 328 | context->Message_Block[59] = context->Length_High; 329 | context->Message_Block[60] = context->Length_Low >> 24; 330 | context->Message_Block[61] = context->Length_Low >> 16; 331 | context->Message_Block[62] = context->Length_Low >> 8; 332 | context->Message_Block[63] = context->Length_Low; 333 | 334 | SHA1ProcessMessageBlock(context); 335 | } 336 | 337 | int SHA1(uint8_t *message_array, unsigned int length, uint8_t Message_Digest[SHA1HashSize]) 338 | { 339 | int ret; 340 | SHA1Context ctx; 341 | 342 | ret = SHA1Reset(&ctx); 343 | if (ret == shaSuccess) 344 | { 345 | ret = SHA1Input(&ctx, message_array, length); 346 | if (ret == shaSuccess) ret = SHA1Result(&ctx, Message_Digest); 347 | } 348 | 349 | return ret; 350 | } 351 | -------------------------------------------------------------------------------- /source/net.c: -------------------------------------------------------------------------------- 1 | /************************************************ 2 | * Download code by nicksasa * 3 | * Licensed under the GNU 2 * 4 | * Free to use, but give some credit * 5 | *************************************************/ 6 | /************************************************ 7 | * Modified by DarkMatterCore [PabloACZ] * 8 | *************************************************/ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "tools.h" 16 | #include "ssl.h" 17 | 18 | #define PERCENT (u32)(((double)cnt/len*100) + 1) 19 | #define NETWORK_PORT 443 20 | #define NETWORK_BLOCKSIZE 2048 21 | 22 | #define NETWORK_HOSTNAME "raw.githubusercontent.com" 23 | #define NETWORK_DOL_PATH "/DarkMatterCore/bluedump-mod/master/HBC/boot.dol" 24 | #define NETWORK_XML_PATH "/DarkMatterCore/bluedump-mod/master/HBC/meta.xml" 25 | #define NETWORK_VERSION_PATH "/DarkMatterCore/bluedump-mod/master/source/tools.h" 26 | 27 | #define MAX_INIT_RETRIES 3 28 | 29 | float latest_ver = 0.0; 30 | bool update = false; 31 | 32 | static char hostip[16] ATTRIBUTE_ALIGN(32); 33 | static u8 fileBuf[NETWORK_BLOCKSIZE] ATTRIBUTE_ALIGN(32); 34 | 35 | /* Network variables */ 36 | static s32 sockfd = -1; 37 | static s32 ssl_context = -1; 38 | 39 | s32 network_init(void) 40 | { 41 | if (!netw_init) 42 | { 43 | printf("Initializing network... "); 44 | logfile("Initializing network... "); 45 | s32 ret = if_config(hostip, NULL, NULL, true, MAX_INIT_RETRIES); 46 | if (ret < 0) 47 | { 48 | printf("Error! (ret = %d). Couldn't initialize the network!", ret); 49 | logfile("if_config failed (ret = %d).\r\n", ret); 50 | } else { 51 | printf("OK! IP: %s.\n", hostip); 52 | logfile("OK! IP: %s.\r\n", hostip); 53 | 54 | netw_init = true; 55 | } 56 | 57 | return ret; 58 | } else { 59 | printf("Network already initialized.\n"); 60 | logfile("Network already initialized.\r\n"); 61 | } 62 | 63 | return 0; 64 | } 65 | 66 | s32 network_connect(char *hostname) 67 | { 68 | struct hostent *he; 69 | struct sockaddr_in sa; 70 | 71 | s32 ret; 72 | 73 | if (sockfd >= 0) net_close(sockfd); 74 | 75 | sockfd = net_socket(AF_INET, SOCK_STREAM, IPPROTO_IP); 76 | if (sockfd < 0) 77 | { 78 | logfile("Error initializing TCP socket (sockfd = %d).\r\n", sockfd); 79 | return sockfd; 80 | } 81 | 82 | he = net_gethostbyname(hostname); 83 | if (!he) 84 | { 85 | logfile("Couldn't get hostname.\r\n"); 86 | return -1; 87 | } 88 | 89 | memset(&sa, 0, sizeof(struct sockaddr_in)); 90 | sa.sin_len = sizeof(struct sockaddr_in); 91 | sa.sin_family = AF_INET; 92 | sa.sin_port = htons(NETWORK_PORT); 93 | memcpy(&sa.sin_addr, he->h_addr_list[0], he->h_length); 94 | 95 | ret = net_connect(sockfd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)); 96 | if (ret < 0) 97 | { 98 | logfile("Error connecting to the hostname (ret = %d).\r\n", ret); 99 | return ret; 100 | } 101 | 102 | return 0; 103 | } 104 | 105 | s32 network_request(char *network_path, char *hostname) 106 | { 107 | char *ptr = NULL; 108 | char buf[1024], request[256]; 109 | 110 | u32 cnt, size; 111 | s32 ret; 112 | 113 | char *r = request; 114 | r += sprintf(r, "GET %s HTTP/1.1\r\n", network_path); 115 | r += sprintf(r, "User-Agent: bluedump-mod/%s (Nintendo Wii)\r\n", VERSION); 116 | r += sprintf(r, "Accept: */*\r\n"); 117 | r += sprintf(r, "Host: %s\r\n", hostname); 118 | r += sprintf(r, "Cache-Control: no-cache\r\n\r\n"); 119 | 120 | //printf("%s\n", request); 121 | //logfile("\r\n%s", request); 122 | 123 | ret = network_connect(hostname); 124 | if (ret < 0) return ret; 125 | 126 | /* HTTPS support */ 127 | if (NETWORK_PORT == 443) 128 | { 129 | ret = ssl_init(); 130 | if (ret < 0) 131 | { 132 | logfile("Error initializing SSL interface (ret = %d).\r\n", ret); 133 | return ret; 134 | } 135 | 136 | ssl_context = ssl_new((u8*)hostname, 0); 137 | if (ssl_context < 0) 138 | { 139 | logfile("Error initializing new SSL context (ssl_context = %d).\r\n", ssl_context); 140 | return ssl_context; 141 | } 142 | 143 | ret = ssl_setbuiltinclientcert(ssl_context, 0); 144 | if (ret < 0) 145 | { 146 | logfile("Error setting built-in SSL client cert (ret = %d).\r\n", ret); 147 | ssl_shutdown(ssl_context); 148 | return ret; 149 | } 150 | 151 | ret = ssl_connect(ssl_context, sockfd); 152 | if (ret < 0) 153 | { 154 | logfile("Error connecting to the hostname through SSL (ret = %d).\r\n", ret); 155 | ssl_shutdown(ssl_context); 156 | return ret; 157 | } 158 | 159 | ret = ssl_handshake(ssl_context); 160 | if (ret < 0) 161 | { 162 | logfile("Error doing a handshake to the hostname through SSL (ret = %d).\r\n", ret); 163 | ssl_shutdown(ssl_context); 164 | return ret; 165 | } 166 | 167 | ret = ssl_write(ssl_context, request, strlen(request)); 168 | if (ret < 0) 169 | { 170 | logfile("Error sending HTTPS request (ret = %d).\r\n", ret); 171 | return ret; 172 | } 173 | } else { 174 | ret = net_write(sockfd, request, strlen(request)); 175 | if (ret < 0) 176 | { 177 | logfile("Error sending HTTP request (ret = %d).\r\n", ret); 178 | return ret; 179 | } 180 | } 181 | 182 | memset(buf, 0, sizeof(buf)); 183 | 184 | for (cnt = 0; !strstr(buf, "\r\n\r\n"); cnt++) 185 | { 186 | if (NETWORK_PORT == 443) 187 | { 188 | ret = ssl_read(ssl_context, buf + cnt, 1); 189 | } else { 190 | ret = net_read(sockfd, buf + cnt, 1); 191 | } 192 | 193 | if (ret <= 0) 194 | { 195 | logfile("Error reading data from hostname (ret = %d).\r\n", ret); 196 | if (NETWORK_PORT == 443) ssl_shutdown(ssl_context); 197 | return ret; 198 | } 199 | } 200 | 201 | if (!strstr(buf, "HTTP/1.1 200 OK")) 202 | { 203 | logfile("\r\nHTTP status code:\r\n\r\n%s\r\n\r\n", buf); 204 | if (NETWORK_PORT == 443) ssl_shutdown(ssl_context); 205 | return -1; 206 | } 207 | 208 | ptr = strstr(buf, "Content-Length:"); 209 | if (!ptr) 210 | { 211 | logfile("Couldn't parse Content-Length.\r\n"); 212 | if (NETWORK_PORT == 443) ssl_shutdown(ssl_context); 213 | return -1; 214 | } 215 | 216 | sscanf(ptr, "Content-Length: %u", &size); 217 | //printf("Content-Length: %u bytes.\n", size); 218 | 219 | return size; 220 | } 221 | 222 | s32 network_read(void *buf, u32 len) 223 | { 224 | s32 read = 0, ret; 225 | 226 | while (read < len) 227 | { 228 | if (NETWORK_PORT == 443) 229 | { 230 | ret = ssl_read(ssl_context, buf + read, len - read); 231 | } else { 232 | ret = net_read(sockfd, buf + read, len - read); 233 | } 234 | 235 | if (ret <= 0) 236 | { 237 | logfile("Error reading data from hostname (ret = %d).\r\n", ret); 238 | if (NETWORK_PORT == 443) ssl_shutdown(ssl_context); 239 | return ret; 240 | } 241 | 242 | read += ret; 243 | } 244 | 245 | return read; 246 | } 247 | 248 | s32 ReadNetwork(FILE *file, char *network_path, char *hostname) 249 | { 250 | s32 ret = 0; 251 | u32 cnt, len, blksize = NETWORK_BLOCKSIZE, wrote; 252 | 253 | logfile("Getting \"%s%s\"... ", hostname, network_path); 254 | 255 | len = network_request(network_path, hostname); 256 | if (len < 0) return len; 257 | 258 | logfile("File length: %u bytes.\r\n", len); 259 | 260 | time_t start, end; 261 | char speed[1024]; 262 | 263 | time(&start); 264 | 265 | printf("\n"); 266 | 267 | for (cnt = 0; cnt < len; cnt += blksize) 268 | { 269 | if (blksize > len - cnt) blksize = len - cnt; 270 | 271 | time(&end); 272 | sprintf(speed, "%u", ((cnt / 1024) + 1)/(u32)(end - start)); 273 | 274 | Con_ClearLine(); 275 | printf("\t- Downloading %u KB @ %s KB/s. Progress: %u KB (%u%%).", (len / 1024) + 1, speed, (cnt / 1024) + 1, PERCENT); 276 | 277 | ret = network_read(fileBuf, blksize); 278 | if (ret != blksize) 279 | { 280 | ret = -1; 281 | break; 282 | } 283 | 284 | wrote = __fwrite(fileBuf, blksize, 1, file); 285 | if (wrote != 1) 286 | { 287 | ret = -1; 288 | break; 289 | } 290 | } 291 | 292 | printf("\n"); 293 | 294 | return ret; 295 | } 296 | 297 | s32 FileUpdate(char *path, bool is_dol) 298 | { 299 | s32 ret; 300 | char fpath[256] = {0}; 301 | snprintf(fpath, MAX_CHARACTERS(fpath), "%s/%s", path, (is_dol ? "boot.dol" : "meta.xml")); 302 | 303 | printf("\nUpdating %s... ", (is_dol ? "boot.dol" : "meta.xml")); 304 | logfile("Updating %s... ", (is_dol ? "boot.dol" : "meta.xml")); 305 | 306 | ret = remove(fpath); 307 | if (ret != 0) 308 | { 309 | printf("Error deleting previous %s! (ret = %d)\n\n", (is_dol ? "boot.dol" : "meta.xml"), ret); 310 | logfile("Error deleting previous %s! (ret = %d)\r\n", (is_dol ? "boot.dol" : "meta.xml"), ret); 311 | return -1; 312 | } 313 | 314 | FILE *yabdm_file = fopen(fpath, "wb"); 315 | if (!yabdm_file) 316 | { 317 | printf("Error opening \"%s\" for writing. Update aborted.", fpath); 318 | logfile("Error opening \"%s\" for writing. Update aborted.\r\n", fpath); 319 | return -1; 320 | } 321 | 322 | ret = ReadNetwork(yabdm_file, (is_dol ? NETWORK_DOL_PATH : NETWORK_XML_PATH), NETWORK_HOSTNAME); 323 | if (ret < 0) 324 | { 325 | printf("Error downloading data. Update aborted."); 326 | logfile("Error downloading data. Updated aborted.\r\n"); 327 | } 328 | 329 | if (yabdm_file) fclose(yabdm_file); 330 | 331 | return ret; 332 | } 333 | 334 | bool CheckLatestVersion(float cur_ver) 335 | { 336 | if (latest_ver == 0.0f) 337 | { 338 | s32 ret = 0; 339 | u32 cnt, len, blksize = NETWORK_BLOCKSIZE; 340 | 341 | printf("\nChecking if we are already running the latest version...\n"); 342 | logfile("Getting \"%s%s\" (version info)... ", NETWORK_HOSTNAME, NETWORK_VERSION_PATH); 343 | 344 | len = network_request(NETWORK_VERSION_PATH, NETWORK_HOSTNAME); 345 | if (len < 0) return len; 346 | 347 | logfile("File length: %u bytes.\r\n", len); 348 | 349 | for (cnt = 0; cnt < len; cnt += blksize) 350 | { 351 | if (blksize > len - cnt) blksize = len - cnt; 352 | 353 | ret = network_read(fileBuf, blksize); 354 | if (ret != blksize) 355 | { 356 | ret = -1; 357 | printf("Error downloading data.\n"); 358 | logfile("Error downloading data.\r\n"); 359 | break; 360 | } 361 | } 362 | 363 | if (ret < 0) return false; 364 | 365 | sscanf((char*)fileBuf, "#ifndef %*s #define %*s #include %*s #include %*s #include %*s #include %*s #include %*s #define VERSION \"%f\"", &latest_ver); 366 | } 367 | 368 | return (latest_ver > cur_ver); 369 | } 370 | 371 | void UpdateYABDM(char *lpath) 372 | { 373 | resetscreen(); 374 | printheadline(); 375 | 376 | if (lpath == NULL) 377 | { 378 | printf("Sorry, your launch path is empty.\n"); 379 | printf("The update procedure cannot be performed.\n"); 380 | printf("Did you launch the application using Wiiload?"); 381 | 382 | logfile("\r\n[UPDATEYABDM] Error: launch path is empty!\r\n"); 383 | } else 384 | if ((strncasecmp(lpath, "sd:", 3) != 0) && (strncasecmp(lpath, "usb:", 4) != 0)) 385 | { 386 | printf("\nThe launch path is invalid.\n"); 387 | printf("The update procedure cannot be performed.\n"); 388 | printf("Did you launch the application using Wiiload?"); 389 | 390 | logfile("\r\n[UPDATEYABDM] Error: launch path \"%s\" is invalid!\r\n", lpath); 391 | } else { 392 | s32 ret; 393 | 394 | /* Parse the launch directory */ 395 | char path[MAXPATHLEN] = {0}; 396 | char *first_slash = strrchr(lpath, '/'); 397 | strncpy(path, lpath, (first_slash != NULL ? (first_slash - lpath + 1) : strlen(lpath))); 398 | 399 | printf("Launch path: \"%s\".\n", path); 400 | logfile("\r\n[UPDATEYABDM] Launch path: %s.\r\n", path); 401 | 402 | ret = network_init(); 403 | if (ret >= 0) 404 | { 405 | /* Check if we are already running the latest version */ 406 | if (!update && CheckLatestVersion(atof(VERSION))) 407 | { 408 | printf("Version available on server: %g. Starting update procedure.\n", latest_ver); 409 | logfile("Version available on server: %g. Starting update procedure.\r\n", latest_ver); 410 | 411 | /* Update boot.dol */ 412 | ret = FileUpdate(path, true); 413 | if (ret >= 0) 414 | { 415 | logfile("boot.dol successfully updated.\r\n"); 416 | 417 | /* Update meta.xml */ 418 | ret = FileUpdate(path, false); 419 | if (ret >= 0) 420 | { 421 | logfile("meta.xml successfully updated.\r\n"); 422 | 423 | resetscreen(); 424 | printheadline(); 425 | 426 | printf("Update completed! Go back to the launcher and load\n"); 427 | printf("the application again to reflect the changes.\n"); 428 | printf("Please refer to the meta.xml file if you want to see the changelog."); 429 | 430 | update = true; 431 | } 432 | } 433 | } else { 434 | if (update) 435 | { 436 | printf("You already updated the application. Restart in order for the new changes to make effect."); 437 | logfile("You already updated the application. Restart in order for the new changes to make effect.\r\n"); 438 | } else { 439 | if (latest_ver > 0) 440 | { 441 | printf("Version available on server: %g. You already have the latest version.", latest_ver); 442 | logfile("Version available on server: %g. You already have the latest version.\r\n", latest_ver); 443 | } 444 | } 445 | } 446 | } 447 | } 448 | 449 | waitforbuttonpress(); 450 | } 451 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Yet Another BlueDump MOD (YABDM) 2 | YABDM is a modification of BlueDump capable of dumping any type of title installed in your Wii console to a WAD file in a SD Card or an USB storage device. It can also backup and restore savegames in their unencrypted form, and convert content.bin files generated by the System Menu on the SD card to WAD files. 3 | 4 | This version was heavily modified to fix bugs and add some corrections that make the WAD dumping process more accurate; that means, the resulting files now match with the WADs obtained with NUS Downloader and other PC programs. Thus, YABDM can actually recreate the original WAD used to install certain title. 5 | 6 | Main features 7 | -------------- 8 | 9 | * Compatibility with FAT32-formatted SD cards and USB storage devices. 10 | * Compatibility with WiiMote, Classic Controller (Pro), GameCube Controller and Wii U Pro Controller (through libwupc). 11 | * Enhanced WAD dumping capabilities from BlueDump that include a faster encryption/decryption process (through the use of a different AES implementation), SHA-1 verification and appropiate 16 and 64 byte padding. 12 | * Ability to convert content.bin files stored on SD:/private/wii/title straight to WAD files. 13 | - They must have been generated by the Wii the application is being run on in order to work. 14 | - Otherwise, make sure to have a copy of the BootMii dump data (either keys.bin or nand.bin) from the original console on the root directory of the output device, and a copy of the Ticket file on /YABDM/Tickets. 15 | * Ability to fakesign the Ticket and/or the TMD of the output WAD. 16 | * Region-changing options that allow to modify the region of the output WAD. 17 | * Ability to apply IOS patches at runtime if full hardware access is granted (HW_AHBPROT register disabled), through libruntimeiospatch. 18 | * IOS selection menu which allows you to manually reload to a different IOS, automatically skipping critical system titles and stub IOSes. 19 | - If full hardware access is enabled, the new IOS will inherit these access rights. 20 | - Also, if an Hermes cIOS is loaded, the additional ehcmodule will be enabled, too. 21 | * Compatibility with USB 2.0 devices when using a cIOS (max. 10 seconds timeout). 22 | * Ability to read application arguments passed from the loader (0 = disabled / 1 = enabled). 23 | - debug: Enables the debug mode, which creates a logfile called "YABDM.log" in the root directory of the selected device, with technical information about the application's performance. 24 | - wiilight: Activates the Wii disc light as a read/write indicator for the output device. 25 | * Updater that allows you to download a new version of the application straight from the GitHub repo (if available). 26 | * Ability to generate a proper System Menu WAD even if Priiloader is already installed. 27 | * Change between hexadecimal and ASCII Title IDs while browsing the title list. 28 | * Improved internal name reading capabilities that are compatible not only with regular content files and savegames, but also with DLCs and content.bin files. The read names will be displayed in the language set on the Wii Options Menu (whenever possible). 29 | * Custom 512-char font that is capable of displaying special latin characters. 30 | * Ability to dump and rearrange DLCs with missing contents. 31 | 32 | Usage 33 | -------------- 34 | 35 | * **Savedata:** When you load YABDM, you'll see the main menu with different categories available. If you want to backup the savegame from a disc-based game (assuming you own it and have played it at least once), set the arrow and press A on "00010000 - Disc Savedata". Then, set the arrow on the game and press 1. An options menu will open; from there you can use the right and left arrow to switch between the available functions. Select Backup Savedata and press A. Voilà, now you have a backup of your savedata for that game in the /YABDM/Savedata directory on the output device. 36 | 37 | - The same things applies if you want, for example, to backup the savedata for a VC title: just go to "00010001 - Installed Channel Titles". The extracted savedata can be installed on any Wii. 38 | 39 | * **Titles:** The procedure is the same as the one used for dumping savegames, except that you'll have to choose "Backup to WAD" on the last options menu. You'll then be prompted to select if you want to fakesign the Ticket and/or TMD of the output WAD, or to change its region. Wait for the process to end and you'll have the WAD on the /YABDM/WAD directory on the output device. 40 | 41 | * **content.bin files:** Assuming you have inserted an SD card with content.bin files, enter the content.bin conversion mode by pressing +/R, and select the title you want to convert. The rest of the process is pretty much the same as the WAD dumping procedure. 42 | 43 | Thanks to 44 | -------------- 45 | 46 | * WiiPower, for helping out nicksasa. 47 | * TriiForce and FSToolBox projects (WiiPower and nicksasa). 48 | * JoostinOnline, for his continuous help and ideas. 49 | * The folks at HacksDen.com, for testing every new release. Special mention to stomp_442. 50 | * Vincent Rijmen, Antoon Bosselaers and Paulo Barreto, for their "rijndael-alg-fast" AES implementation. 51 | * FIX94, for his libwupc library, used in the application to add support with Wii U Pro Controllers. 52 | * Excelsiior, for his libruntimeiospatch library, used to apply IOS patches at runtime. 53 | * Dimok, Rodries, Kwiirk and svpe, for their work on the USB storage driver. 54 | * Hermes, for his mload implementation for PPC. 55 | 56 | Changelog 57 | -------------- 58 | 59 | **YABDM v1.86 (February 4th, 2024 - DarkMatterCore):** 60 | 61 | * Fix building with latest devkitPPC + libogc releases. 62 | * Remove vWii common key based crypto for vWii system title dumps. Fixes installations with modern WAD Managers. 63 | * A Wii U side WAD Manager shall be created to facilitate the installation of vanilla vWii system titles. It seems vIOS ES modules don't support common key index 0x02. 64 | 65 | This codebase is begging for a full rewrite. My eyes have witnessed the atrocities of my past sins. Don't expect any further updates. 66 | 67 | **YABDM v1.85 (June 29th, 2018 - DarkMatterCore):** 68 | 69 | * Fixed building warnings and errors with latest devkitPro + libogc. 70 | * Increased path char array sizes to hopefully fix a storage corruption bug. 71 | 72 | **YABDM v1.84 (May 12th, 2017 - DarkMatterCore):** 73 | 74 | * Fixed sorting method for the IOS selection screen. IOS version numbers are now properly displayed. 75 | * Replaced Steve Reid's SHA-1 C implementation with the standard SHA-1 C implementation from RFC 3174 (with some modifications). This fixes the hash calculation error. 76 | 77 | I apologize for these mistakes. I don't have a TV anymore, so I wasn't able to test the previous release. 78 | 79 | **YABDM v1.83 (May 4th, 2017 - DarkMatterCore):** 80 | 81 | * Added support for the vWii Common Key. System Titles dumped from a vWii will now retain proper AES encryption and their tickets won't be fakesigned by default anymore. An updated WAD Manager shall be needed in order to install these WADs. 82 | * Updated libruntimeiospatch to v1.5.4. 83 | * Updated libwupc to r3 mod 2 (made by Cyan). 84 | * Fixed building with latest devkitPPC + libogc. 85 | 86 | **YABDM v1.82 (June 6th, 2015 - DarkMatterCore):** 87 | 88 | * Reapplied the fixes made to libruntimeiospatch by JoostinOnline in later versions of the library, since it appears the revision stored on GitHub (the one my fork is based on) was an old one. 89 | 90 | **YABDM v1.81 (June 5th, 2015 - DarkMatterCore):** 91 | 92 | * Codebase exported to GitHub. The network code has been updated to support SSL connections and file downloads from raw.githubusercontent.com. 93 | * libruntimeiospatch updated to v1.5.2, which includes IOS SSL patches made by FIX94 required to properly establish HTTPS connections. 94 | * Some minor tweaks. 95 | 96 | **YABDM v1.8 (December 9th, 2014 - DarkMatterCore):** 97 | 98 | * Fixed a bug where garbled text was being displayed for titles that use 0xFF instead of 0x00 as the preceding byte for each character in their name field (fixes MEGA MAN 9 DLC, possibly others). 99 | * If a given title only has whitespaces on its description field, the application will no longer display them (fixes Dead Space Extraction, possibly others). 100 | * Added compatibility with custom USB 2.0 modules from various cIOS, using a modified version of the usb2storage.c driver from WiiXplorer. 101 | * The USB mounting process now has a 10 seconds timeout, instead of using a retry system. 102 | * The ehcmodule will be loaded into Starlet using mload if the loaded IOS is an Hermes cIOS. 103 | * IOS reload option added to the Settings Menu. 104 | * If the hardware protection is disabled, the current IOS is patched before an IOS reload is performed to keep the access rights. 105 | * Changed the default IOS selection menu value to IOS249. 106 | * License upgraded to GNU-GPL v3. 107 | 108 | **YABDM v1.7 (November 28th, 2014 - DarkMatterCore):** 109 | 110 | * The application's code flow was modified to remove the overuse of the exit function and to deal with unhandled memory exceptions. Thanks to this, the goodbye() function has now been removed, and only a single call to Reboot() is performed. 111 | * An additional settings menu has been implemented. It can be entered by pressing button -/L. There, you can either choose to switch storage devices through the Device Menu, or to update the application. 112 | * It is now verified if the console keys collected from the BootMii data are null (zero-filled) or belong to the console the application is being run on before using them. 113 | * Added compatibility with Priiloader. Thanks to this, the application can now generate valid System Menu WADs even if Priiloader has been installed. 114 | * LoadTikFromDevice() is now merged with GetTicket() (it should have been like this from the beginning). 115 | * The IOS selection menu now also skips BootMii IOS and stub IOSes. 116 | 117 | **YABDM v1.6 (November 16th, 2014 - DarkMatterCore):** 118 | 119 | * Added support for vWii System Menu versions 608, 609 and 610. 120 | * Added support for mauifrog's System Menu 4.1 modified versions. 121 | * Updated the internal name list to add support for vWii hidden channels. 122 | * The update procedure now checks if you already have the latest YABDM version. 123 | * The logfile now shows if the application is running under vWii. 124 | * The reset_log() function was removed. Now, a line formed by dashes is used to divide each subsequent logging session from another. 125 | * The application is now able to use the BootMii dump data from another Wii in the content.bin conversion process. It'll only look for the files if the content.bin's Console ID doesn't match the one from the console the application is being run on. Please keep in mind that you'll also need to have a copy of the Ticket file on your NAND, or either manually place it under /YABDM/Tickets/ in the selected output device, using the following naming scheme: TITLE_HIGH-TITLE_LOW.tik (e.g. sd:/YABDM/Tickets/00010001-57475345.tik). If you choose not to fakesign the output WAD, it'll retain the signature from its original console. 126 | * Some other minor fixes and corrections. 127 | 128 | **YABDM v1.5 (October 13th, 2014 - DarkMatterCore):** 129 | 130 | * Fixed the region change procedure for DLC titles. Their Title IDs will now reflect the selected new region (in order to make them detectable by their corresponding game/channel). 131 | * The region change prompt will now always be displayed. Keep in mind that if you enable this option, the Ticket and/or TMD will be fakesigned automatically, depending on the category of the selected title (even if you choose not to). 132 | * If the application detects that the Common Key Index is different than 0, it will automatically fakesign the Ticket (even if you choose not to), instead of only changing its value. 133 | * Reimplemented the Wii disc light feature as an optional read/write indicator. You can enable it through the use of the "wiilight" argument in the meta.xml file. 134 | * Reimplemented the ability to update the application straight from the Google Code SVN repository, by pressing buttons A and B at the same time. The meta.xml file will also get updated. 135 | 136 | **YABDM v1.41 (September 21st, 2014 - DarkMatterCore):** 137 | 138 | * Quick fix for the SHA-1 calculation during the content.bin conversion process. 139 | 140 | **YABDM v1.4 (September 21st, 2014 - DarkMatterCore):** 141 | 142 | * Removed the use of strcpy/strncpy to avoid possible buffer overflows. 143 | * Now, argv[0] is also checked when looking for the "debug" argument, since it appears it gets passed here if Wiiload is launched from a batch script. 144 | * Added BC-NAND (1-200) and BC-WFS (1-201) vWii titles to the internal name list, previously listed as IOS 512 and 513, respectively. Thanks to larsenv for noticing this. 145 | * SHA-1 hash verification is now performed during the dumping process for every regular content file. 146 | * Improved the logfile code. Now, the debug file is only opened/closed when absolutely necessary; each consequent debug string is flushed to the file while it is kept open, which greatly reduces the time needed to write info to the output device. Strings longer than 256 characters are now also allowed. Thanks again to JoostinOnline! 147 | * Added compatibility with Wii U Pro Controllers. Thanks to FIX94 for his libwupc library! Also thanks to my good friend Dimitry Valencia for testing. 148 | 149 | **YABDM v1.3 (June 25th, 2014 - DarkMatterCore):** 150 | 151 | * Fixed the directory sorting function by doing a string comparison without case sensivity, using stricmp(). I don't know how didn't I notice that before. 152 | * Fixed a bug where the content.bin conversion mode would not be entered, with no error message displayed. 153 | * Directory entries without a content.bin file won't be shown anymore. 154 | 155 | **YABDM v1.2 (May 16th, 2014 - DarkMatterCore):** 156 | 157 | * Updated all the debug code to use the Carriage Return + Line Feed combo, in order to make the logfile readable under Windows. 158 | * Unpadded Ticket size is now always set to 0x2A4 bytes. Some PC applications aren't even compatible with bigger Ticket sizes. 159 | * If a DLC content (type 0x4001) for the selected title is not present, it is now skipped and its info struct is removed from the TMD (which is also fakesigned in the process). The output file is also rearranged when all the available contents have been dumped. Thanks to szczuru from GBAtemp for doing **a lot** of testing. 160 | 161 | **YABDM v1.1 (May 5th, 2014 - DarkMatterCore):** 162 | 163 | * Fixed the left/right buttons behaviour in the content.bin conversion menu (oops). 164 | * An output device selection menu will now be displayed after pressing -/L, instead of just remounting the storage devices. Device swapping is also allowed, but only in the main menu. 165 | * Compiled with the latest devkitPPC, libOGC (with custom font) and libFAT. 166 | 167 | **YABDM v1.0 (March 25th, 2014 - DarkMatterCore):** 168 | 169 | * Eliminated the need for realloc() in pad_data(), since allocate_memory() generates buffers with sizes rounded to a 64-bite boundary; this is most likely safer. The function is now used only to write zeros. 170 | * The IOS buffered list is now freed before reloading to a new IOS. 171 | * Fixed a bug in the directory navigation code where garbled text would be printed if there were no items in the selected directory (after pressing A). 172 | * Fixed left/right buttons functionality for lists with equal to or less than 4 elements. 173 | * The region change prompt now won't be displayed if a system title was selected. 174 | * Button -/L can now be used to remount the storage devices. 175 | * Some minor changes to the AES code. 176 | 177 | **YABDM v0.93 (March 1st, 2014 - DarkMatterCore):** 178 | 179 | * The RemoveIllegalCharacters() function now also replaces non-ASCII characters with an underscore (_), since libFAT apparently has problems opening/writing files with names that include them. Thanks to erickmaniche from Emudesc for letting me know. 180 | * The getdir_info() and getdir_device() functions will now end early if no files are detected when reading the directory the first time. This fixes some small problems related to save dumping/restoring. 181 | * Logfile output cleanup (mostly, missing newlines). 182 | * General code cleanup. Fixed some small things I previously overlooked. 183 | * Exit sequence cleanup: instead of calling Unmount_Devices() and Reboot() all over again, now just goodbye() is used. 184 | 185 | **YABDM v0.92 (February 27th, 2014 - DarkMatterCore):** 186 | 187 | * Reimplemented the DetectInput() function, now fixed by JoostinOnline. 188 | * Rewrote the GetASCII() function to discard non-valid ASCII characters. 189 | * Button A can no longer be used in the content.bin conversion mode if the selected directory doesn't have a content.bin file inside. 190 | 191 | **YABDM v0.91 (February 26th, 2014 - DarkMatterCore):** 192 | 193 | * Fixed a very silly regression bug in the name reading code. 194 | * Fixed GCN Controller compatibility. For some odd reason, the controller input acts erratically using the DetectInput() function, so for now I'm just reverting back to the old waitforbuttonpress(). I swear I received my controller just a moment ago; otherwise, I wouldn't have noticed that. 195 | 196 | **YABDM v0.9 (February 26th, 2014 - DarkMatterCore):** 197 | 198 | * Rewrote the title name reading functions from scratch. The application can now read multilingual names and descriptions from contents stored on the NAND filesystem and content.bin files using the IMET and WIBN structs from Wiibrew, and the __convertWiiString() function from AnyTitle Deleter by bushing. 199 | * Improvements to the save dumping/flashing code. 200 | * Minor cleanup to the WAD dumping code. The application will now also check if the Ticket and/or TMD data is already fakesigned before trying to wipe the signature. 201 | * If you choose to fakesign the TMD, the application will now display a prompt asking if you want to change the WAD region. This is done by modifying the value @ 0x19D in the TMD, just like FreeTheWads on PC. 202 | * A "(vWii)" suffix will be displayed along with the System Menu version if the application is running under vWii (thanks to JoostinOnline and crediar for their IsWiiU() check). 203 | * Updated libruntimeiospatch to v1.5.1. 204 | * Updated application headline and meta.xml credits to reference HacksDen.com. 205 | 206 | **YABDM v0.8 (September 24th, 2013 - DarkMatterCore):** 207 | 208 | * Added support for title 00010000-HAZA. It is the responsible for controlling the Photo Channel "swap" between versions 1.0 and 1.1. When it is present, v1.1 is displayed in the System Menu; otherwise, v1.0 is used. Since it gets installed to the savedata directory, it was not being treated as a title, thus its dumping was not allowed; now this behaviour is fixed. Thanks to Iwatasan for noticing this! 209 | * Compiled with the latest libogc git revision from 09/04/2013. 210 | * Now using the latest libruntimeiospatch revision. The previous version was not properly patching the hash_old[] pattern because it had the same value as new_hash_old[]. I informed Excelsiior about this and the change has now been made to the GitHub repository. 211 | 212 | **YABDM v0.7 (September 15th, 2013 - DarkMatterCore):** 213 | 214 | * Changed application name to YABDM (Yet Another BlueDump MOD). 215 | * Added a proper fix for DetectInput(): now calling VIDEO_WaitVSync() instead of using a while loop (thanks to JoostinOnline!). 216 | * Changed the AES / Rijndael implementation from Mike Scott in favor of a faster one by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto (slightly modified by Jouni Malinen), known as "rijndael-alg-fst". This one uses previously created AES tables instead of generating them everytime an encryption / decryption operation is done, and it also allows the use of a single memory block to be modified 'in-place'. Thus, the dumping process is now faster. 217 | * The OTP memory is now mounted once instead of accessing its data everytime Content_bin_Dump() is called in the application. 218 | * The application now generates a name list for all the entries in a directory everytime the current path is changed. This is mainly done to reduce loading times, and to avoid reading ALL the names again when a D-Pad button is pressed. Because of this, the names for the content.bin files saved in the SD card are now properly displayed on screen; you'll only have to wait a bit after pressing +/R. 219 | * Thanks to the previous point, I noticed a memory leak in getdir_info(), because the *ent pointer was used to allocate memory with malloc() regardless if it already pointed to a memory address. It is now freed before reusing it. 220 | * Some other optimizations. 221 | 222 | **MOD v0.6 (September 7th, 2013 - DarkMatterCore and JoostinOnline):** 223 | 224 | * Added compatibility with content.bin files stored in SD:/private/wii/title. You can switch between normal WAD dumping and content.bin conversion modes with +/R. 225 | * Added code to read the OTP contents and copy them to a previously aligned memory block. This is needed to access both the PRNG Key and the Console ID, which are used in the content.bin conversion process. 226 | * Added compatibility with Classic Controllers (thanks to JoostinOnline!). 227 | * Optimized name reading functions. Instead of allocating a memory block and then returning it (which is unsafe), now a single global character string is used, with its current value being updated by using snprintf() (thanks to JoostinOnline!). 228 | * Added meta.xml argument support to enable or disable the logfile creation without having to recompile the entire application (thanks to JoostinOnline!). 229 | * New sexy, smexy icon (thanks to JoostinOnline!). 230 | * Some other changes and simplifications that reduce the overall CPU use (thanks to JoostinOnline!). 231 | 232 | **MOD v0.5 (August 27th, 2013 - DarkMatterCore):** 233 | 234 | * read_name_from_banner_app() and read_dlc_name() functions are now merged. 235 | * Fixed a bug in the read_name() function which would return wrong text if the title has contents smaller than the size of the chunk read into memory (e.g. YouTube Channel, it has two 'dummy' contents of 0x40 bytes each). 236 | * Fixed a *possible* buffer overflow in the read_name*() functions, since they were allocating 'length+10' bytes for the name buffer and then the description string was concatenated to it (which is usually longer than 10 bytes). Now, they're just allocating enough space for what they need. 237 | * Fixed left button behaviour. 238 | * More code changes. 239 | 240 | **MOD v0.4 (August 26th, 2013 - DarkMatterCore):** 241 | 242 | * Ability to read the internal channel descriptions. Not all channels have this, though, but it still is a nice feature. 243 | * Button 2 / X is now used to change the view mode between hexadecimal IDs and ASCII IDs. 244 | * Added padding to 64-byte boundary for the footer data (I noticed that the official WADs from game discs have this, so why not?). 245 | * Mostly, code optimizations. 246 | 247 | **MOD v0.3 (August 24th, 2013 - DarkMatterCore):** 248 | 249 | * Fixed a very silly bug in the GetContent() function that would improperly dump content files smaller than 16KB using a null IV in the encryption process (I used the Mario Kart Channel to test this behaviour, since it has two contents that match this case). 250 | * The WAD backup section of the dump_menu() function was completely revamped to avoid redundancy (it seriously had a lot of unnecessary code). Plus, the name scheme of the dumped WADs was changed to be the same from CustomizeMii and similar applications. 251 | * Now using conditional operators for most checks on the 'isSD' value. 252 | * Some other little corrections. 253 | 254 | **MOD v0.2 (August 15th, 2013 - DarkMatterCore):** 255 | 256 | * Now using libruntimeiospatch by Excelsiior to apply patches to the current IOS. 257 | * Fixed illegal FAT characters on dumped savegames. They are now replaced with an underscore (_). 258 | * Added full support for contents bigger than 45MB. The GetContent() function was completely rewritten to dump each regular content file in chunks of 16KB, which are read, encrypted and saved to the output WAD. Because of this, the encrypt_buffer() function is not used anymore in GetContent(), since we need to change the Initialization Vector (IV) for each chunk. 259 | * Other minor fixes and corrections. 260 | 261 | **MOD v0.1 (August 1st, 2013 - DarkMatterCore):** 262 | 263 | * Full hardware access through the HW_AHBPROT flag (must use HBC v1.1.0 or later!). The IOS patches applied include the "KillAntiSysTitleInstall" set from damysteryman, so the application is also fully compatible with the vWii mode available in Wii U. 264 | * Added an IOS selection screen at startup (you can select whether you want to use the full hardware access, or a patched IOS). 265 | * Full compatibility with USB storage devices and GCN controllers. 266 | * Ability to choose if you want to fakesign the WAD ticket and/or TMD before starting the dumping process (no secondary version needed anymore). 267 | * If you select to fakesign the WAD ticket, the application now wipes the console ID and the ECDH data from it; both of those can prevent a successful WAD installation on another Wii. It is also verified if the Common Key Index value (0x1F1) is set to 0x01 or 0x02; if so, it is changed to 0x00. 268 | * The certificate chain (cert.sys) is now embedded on the code, to avoid reading it every time from the NAND. 269 | * Complete overhaul in the name reading functions for channel banners and banner.bin file from savegames. Plus, the application now can also read names from installed DLCs. 270 | * The WAD footer is now added to every title dumped from the application. Its size is added to the WAD header @ 0x1C, too. 271 | * The content.map file is now read into memory once for every dumping process, instead of accessing it every time the application dumps a shared content. 272 | * Compatibility with content type 0x4001 (which is only present in DLCs, AFAIK). 273 | * Fixed a bug in GetContent() where the application would allocate memory for two different buffers with the same size, which could exceed the console memory limit if the content size was greater than ~22.5 MB. Now, a single memory buffer is used for all the dumping, padding and encrypting operations. 274 | * The pad_data_32() function is now called pad_data(). It uses a bool value to determine if the input buffer will be padded to a 16-byte (0x10) boundary, or a 64-byte boundary (0x40). To avoid memory problems, it now uses realloc() to change the size of the already-allocated input buffer, instead of allocating memory for a new buffer. 275 | * The decrypted memory buffer is now padded to a 16-byte boundary before encrypting. Then, the encrypted memory buffer is padded to a 64-byte boundary. That way, the WAD structure used by NUS Downloader can be easily recreated, with amazing results (just see it by yourself). 276 | * Before reading the internal name of a given title, it is now verified which type of title is it to use the appropiate function for its case. That way, the logfile won't be full of ISFS_Open() -106 errors when trying to read the banner.bin file for everything. lol 277 | * Added a switch case function to properly output the System Menu version in the browser screen (e.g. "v513" is now displayed as "v4.3U"). 278 | * Ability to use the LEFT/RIGHT buttons in the browser screen (why didn't nicksasa add that...?). 279 | * Output font replaced with another that has full Unicode support. That way, the title names can be displayed properly if you have set your console in Spanish or a different language. 280 | * Compiled with the latest libogc, devkitPPC and libfat versions (as of August 1st, 2013: v1.8.12, r26 and v1.0.12, respectively). 281 | * Compatibility with the new WiiMote Plus (RVL-CNT-01-TR). 282 | 283 | **Alpha 3:** 284 | 285 | * Show IOS names (for example, IOS36). 286 | * Show IOS versions (for example, IOS 249 v18). 287 | * Disabled logging by default. 288 | * Code cleanup. 289 | * Creating folders correctly now if they don't exist. 290 | * Some more stuff I forgot. 291 | 292 | **Alpha 2:** 293 | 294 | * Backup savedata from VC/WiiWare and Disc games. 295 | * Restore savedata from VC/WiiWare and Disc games. 296 | * Backup title's to WAD (correctly signed, will only work on your own wii if you use the normal version!). 297 | 298 | **Alpha 1:** 299 | 300 | * Never released. 301 | -------------------------------------------------------------------------------- /HBC/meta.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Yet Another BlueDump MOD (YABDM) 4 | nicksasa, DarkMatterCore 5 | v1.86 6 | 20240204000000 7 | Title and save manager 8 | YABDM is a modification of BlueDump capable of dumping any type of title installed in your Wii console to a WAD file in a SD Card or an USB storage device. It can also backup and restore savegames in their unencrypted form, and convert content.bin files generated by the System Menu on the SD card to WAD files. 9 | 10 | This version was heavily modified to fix bugs and add some corrections that make the WAD dumping process more accurate; that means, the resulting files now match with the WADs obtained with NUS Downloader and other PC programs. Thus, YABDM can actually recreate the original WAD used to install certain title. 11 | 12 | === Main features === 13 | 14 | * Compatibility with FAT32-formatted SD cards and USB storage devices. 15 | * Compatibility with WiiMote, Classic Controller (Pro), GameCube Controller and Wii U Pro Controller (through libwupc). 16 | * Enhanced WAD dumping capabilities from BlueDump that include a faster encryption/decryption process (through the use of a different AES implementation), SHA-1 verification and appropiate 16 and 64 byte padding. 17 | * Ability to convert content.bin files stored on SD:/private/wii/title straight to WAD files. 18 | - They must have been generated by the Wii the application is being run on in order to work. 19 | - Otherwise, make sure to have a copy of the BootMii dump data (either keys.bin or nand.bin) from the original console on the root directory of the output device, and a copy of the Ticket file on /YABDM/Tickets. 20 | * Ability to fakesign the Ticket and/or the TMD of the output WAD. 21 | * Region-changing options that allow to modify the region of the output WAD. 22 | * Ability to apply IOS patches at runtime if full hardware access is granted (HW_AHBPROT register disabled), through libruntimeiospatch. 23 | * IOS selection menu which allows you to manually reload to a different IOS, automatically skipping critical system titles and stub IOSes. 24 | - If full hardware access is enabled, the new IOS will inherit these access rights. 25 | - Also, if an Hermes cIOS is loaded, the additional ehcmodule will be enabled, too. 26 | * Compatibility with USB 2.0 devices when using a cIOS (max. 10 seconds timeout). 27 | * Ability to read application arguments passed from the loader (0 = disabled / 1 = enabled). 28 | - debug: Enables the debug mode, which creates a logfile called "YABDM.log" in the root directory of the selected device, with technical information about the application's performance. 29 | - wiilight: Activates the Wii disc light as a read/write indicator for the output device. 30 | * Updater that allows you to download a new version of the application straight from the GitHub repo (if available). 31 | * Ability to generate a proper System Menu WAD even if Priiloader is already installed. 32 | * Change between hexadecimal and ASCII Title IDs while browsing the title list. 33 | * Improved internal name reading capabilities that are compatible not only with regular content files and savegames, but also with DLCs and content.bin files. The read names will be displayed in the language set on the Wii Options Menu (whenever possible). 34 | * Custom 512-char font that is capable of displaying special latin characters. 35 | * Ability to dump and rearrange DLCs with missing contents. 36 | 37 | === Usage === 38 | 39 | * Savedata: When you load YABDM, you'll see the main menu with different categories available. If you want to backup the savegame from a disc-based game (assuming you own it and have played it at least once), set the arrow and press A on "00010000 - Disc Savedata". Then, set the arrow on the game and press 1. An options menu will open; from there you can use the right and left arrow to switch between the available functions. Select Backup Savedata and press A. Voilà, now you have a backup of your savedata for that game in the /YABDM/Savedata directory on the output device. 40 | 41 | The same things applies if you want, for example, to backup the savedata for a VC title: just go to "00010001 - Installed Channel Titles". The extracted savedata can be installed on any Wii. 42 | 43 | * Titles: The procedure is the same as the one used for dumping savegames, except that you'll have to choose "Backup to WAD" on the last options menu. You'll then be prompted to select if you want to fakesign the Ticket and/or TMD of the output WAD, or to change its region. Wait for the process to end and you'll have the WAD on the /YABDM/WAD directory on the output device. 44 | 45 | * content.bin files: Assuming you have inserted an SD card with content.bin files, enter the content.bin conversion mode by pressing +/R, and select the title you want to convert. The rest of the process is pretty much the same as the WAD dumping procedure. 46 | 47 | === Thanks to === 48 | 49 | * WiiPower, for helping out nicksasa. 50 | * TriiForce and FSToolBox projects (WiiPower and nicksasa). 51 | * JoostinOnline, for his continuous help and ideas. 52 | * The folks at HacksDen.com, for testing every new release. Special mention to stomp_442. 53 | * Vincent Rijmen, Antoon Bosselaers and Paulo Barreto, for their "rijndael-alg-fast" AES implementation. 54 | * FIX94, for his libwupc library, used in the application to add support with Wii U Pro Controllers. 55 | * Excelsiior, for his libruntimeiospatch library, used to apply IOS patches at runtime. 56 | * Dimok, Rodries, Kwiirk and svpe, for their work on the USB storage driver. 57 | * Hermes, for his mload implementation for PPC. 58 | 59 | === Changelog === 60 | 61 | YABDM v1.86 (February 4th, 2024 - DarkMatterCore): 62 | 63 | * Fix building with latest devkitPPC + libogc releases. 64 | * Remove vWii common key based crypto for vWii system title dumps. Fixes installations with modern WAD Managers. 65 | * A Wii U side WAD Manager shall be created to facilitate the installation of vanilla vWii system titles. It seems vIOS ES modules don't support common key index 0x02. 66 | 67 | This codebase is begging for a full rewrite. My eyes have witnessed the atrocities of my past sins. Don't expect any further updates. 68 | 69 | YABDM v1.85 (June 29th, 2018 - DarkMatterCore): 70 | 71 | * Fixed building warnings and errors with latest devkitPro + libogc. 72 | * Increased path char array sizes to hopefully fix a storage corruption bug. 73 | 74 | YABDM v1.84 (May 12th, 2017 - DarkMatterCore): 75 | 76 | * Fixed sorting method for the IOS selection screen. IOS version numbers are now properly displayed. 77 | * Replaced Steve Reid's SHA-1 C implementation with the standard SHA-1 C implementation from RFC 3174 (with some modifications). This fixes the hash calculation error. 78 | 79 | I apologize for these mistakes. I don't have a TV anymore, so I wasn't able to test the previous release. 80 | 81 | YABDM v1.83 (May 4th, 2017 - DarkMatterCore): 82 | 83 | * Added support for the vWii Common Key. System Titles dumped from a vWii will now retain proper AES encryption and their tickets won't be fakesigned by default anymore. An updated WAD Manager shall be needed in order to install these WADs. 84 | * Updated libruntimeiospatch to v1.5.4. 85 | * Updated libwupc to r3 mod 2 (made by Cyan). 86 | * Fixed building with latest devkitPPC + libogc. 87 | 88 | YABDM v1.82 (June 6th, 2015 - DarkMatterCore): 89 | 90 | * Reapplied the fixes made to libruntimeiospatch by JoostinOnline in later versions of the library, since it appears the revision stored on GitHub (the one my fork is based on) was an old one. 91 | 92 | YABDM v1.81 (June 5th, 2015 - DarkMatterCore): 93 | 94 | * Codebase exported to GitHub. The network code has been updated to support SSL connections and file downloads from raw.githubusercontent.com. 95 | * libruntimeiospatch updated to v1.5.2, which includes IOS SSL patches made by FIX94 required to properly establish HTTPS connections. 96 | * Some minor tweaks. 97 | 98 | YABDM v1.8 (December 9th, 2014 - DarkMatterCore): 99 | 100 | * Fixed a bug where garbled text was being displayed for titles that use 0xFF instead of 0x00 as the preceding byte for each character in their name field (fixes MEGA MAN 9 DLC, possibly others). 101 | * If a given title only has whitespaces on its description field, the application will no longer display them (fixes Dead Space Extraction, possibly others). 102 | * Added compatibility with custom USB 2.0 modules from various cIOS, using a modified version of the usb2storage.c driver from WiiXplorer. 103 | * The USB mounting process now has a 10 seconds timeout, instead of using a retry system. 104 | * The ehcmodule will be loaded into Starlet using mload if the loaded IOS is an Hermes cIOS. 105 | * IOS reload option added to the Settings Menu. 106 | * If the hardware protection is disabled, the current IOS is patched before an IOS reload is performed to keep the access rights. 107 | * Changed the default IOS selection menu value to IOS249. 108 | * License upgraded to GNU-GPL v3. 109 | 110 | YABDM v1.7 (November 28th, 2014 - DarkMatterCore): 111 | 112 | * The application's code flow was modified to remove the overuse of the exit function and to deal with unhandled memory exceptions. Thanks to this, the goodbye() function has now been removed, and only a single call to Reboot() is performed. 113 | * An additional settings menu has been implemented. It can be entered by pressing button -/L. There, you can either choose to switch storage devices through the Device Menu, or to update the application. 114 | * It is now verified if the console keys collected from the BootMii data are null (zero-filled) or belong to the console the application is being run on before using them. 115 | * Added compatibility with Priiloader. Thanks to this, the application can now generate valid System Menu WADs even if Priiloader has been installed. 116 | * LoadTikFromDevice() is now merged with GetTicket() (it should have been like this from the beginning). 117 | * The IOS selection menu now also skips BootMii IOS and stub IOSes. 118 | 119 | YABDM v1.6 (November 16th, 2014 - DarkMatterCore): 120 | 121 | * Added support for vWii System Menu versions 608, 609 and 610. 122 | * Added support for mauifrog's System Menu 4.1 modified versions. 123 | * Updated the internal name list to add support for vWii hidden channels. 124 | * The update procedure now checks if you already have the latest YABDM version. 125 | * The logfile now shows if the application is running under vWii. 126 | * The reset_log() function was removed. Now, a line formed by dashes is used to divide each subsequent logging session from another. 127 | * The application is now able to use the BootMii dump data from another Wii in the content.bin conversion process. It'll only look for the files if the content.bin's Console ID doesn't match the one from the console the application is being run on. Please keep in mind that you'll also need to have a copy of the Ticket file on your NAND, or either manually place it under /YABDM/Tickets/ in the selected output device, using the following naming scheme: TITLE_HIGH-TITLE_LOW.tik (e.g. sd:/YABDM/Tickets/00010001-57475345.tik). If you choose not to fakesign the output WAD, it'll retain the signature from its original console. 128 | * Some other minor fixes and corrections. 129 | 130 | YABDM v1.5 (October 13th, 2014 - DarkMatterCore): 131 | 132 | * Fixed the region change procedure for DLC titles. Their Title IDs will now reflect the selected new region (in order to make them detectable by their corresponding game/channel). 133 | * The region change prompt will now always be displayed. Keep in mind that if you enable this option, the Ticket and/or TMD will be fakesigned automatically, depending on the category of the selected title (even if you choose not to). 134 | * If the application detects that the Common Key Index is different than 0, it will automatically fakesign the Ticket (even if you choose not to), instead of only changing its value. 135 | * Reimplemented the Wii disc light feature as an optional read/write indicator. You can enable it through the use of the "wiilight" argument in the meta.xml file. 136 | * Reimplemented the ability to update the application straight from the Google Code SVN repository, by pressing buttons A and B at the same time. The meta.xml file will also get updated. 137 | 138 | YABDM v1.41 (September 21st, 2014 - DarkMatterCore): 139 | 140 | * Quick fix for the SHA-1 calculation during the content.bin conversion process. 141 | 142 | YABDM v1.4 (September 21st, 2014 - DarkMatterCore): 143 | 144 | * Removed the use of strcpy/strncpy to avoid possible buffer overflows. 145 | * Now, argv[0] is also checked when looking for the "debug" argument, since it appears it gets passed here if Wiiload is launched from a batch script. 146 | * Added BC-NAND (1-200) and BC-WFS (1-201) vWii titles to the internal name list, previously listed as IOS 512 and 513, respectively. Thanks to larsenv for noticing this. 147 | * SHA-1 hash verification is now performed during the dumping process for every regular content file. 148 | * Improved the logfile code. Now, the debug file is only opened/closed when absolutely necessary; each consequent debug string is flushed to the file while it is kept open, which greatly reduces the time needed to write info to the output device. Strings longer than 256 characters are now also allowed. Thanks again to JoostinOnline! 149 | * Added compatibility with Wii U Pro Controllers. Thanks to FIX94 for his libwupc library! Also thanks to my good friend Dimitry Valencia for testing. 150 | 151 | YABDM v1.3 (June 25th, 2014 - DarkMatterCore): 152 | 153 | * Fixed the directory sorting function by doing a string comparison without case sensivity, using stricmp(). I don't know how didn't I notice that before. 154 | * Fixed a bug where the content.bin conversion mode would not be entered, with no error message displayed. 155 | * Directory entries without a content.bin file won't be shown anymore. 156 | 157 | YABDM v1.2 (May 16th, 2014 - DarkMatterCore): 158 | 159 | * Updated all the debug code to use the Carriage Return + Line Feed combo, in order to make the logfile readable under Windows. 160 | * Unpadded Ticket size is now always set to 0x2A4 bytes. Some PC applications aren't even compatible with bigger Ticket sizes. 161 | * If a DLC content (type 0x4001) for the selected title is not present, it is now skipped and its info struct is removed from the TMD (which is also fakesigned in the process). The output file is also rearranged when all the available contents have been dumped. Thanks to szczuru from GBAtemp for doing **a lot** of testing. 162 | 163 | YABDM v1.1 (May 5th, 2014 - DarkMatterCore): 164 | 165 | * Fixed the left/right buttons behaviour in the content.bin conversion menu (oops). 166 | * An output device selection menu will now be displayed after pressing -/L, instead of just remounting the storage devices. Device swapping is also allowed, but only in the main menu. 167 | * Compiled with the latest devkitPPC, libOGC (with custom font) and libFAT. 168 | 169 | YABDM v1.0 (March 25th, 2014 - DarkMatterCore): 170 | 171 | * Eliminated the need for realloc() in pad_data(), since allocate_memory() generates buffers with sizes rounded to a 64-bite boundary; this is most likely safer. The function is now used only to write zeros. 172 | * The IOS buffered list is now freed before reloading to a new IOS. 173 | * Fixed a bug in the directory navigation code where garbled text would be printed if there were no items in the selected directory (after pressing A). 174 | * Fixed left/right buttons functionality for lists with equal to or less than 4 elements. 175 | * The region change prompt now won't be displayed if a system title was selected. 176 | * Button -/L can now be used to remount the storage devices. 177 | * Some minor changes to the AES code. 178 | 179 | YABDM v0.93 (March 1st, 2014 - DarkMatterCore) (I already know I'm getting annoying, you don't have to tell me twice): 180 | 181 | * The RemoveIllegalCharacters() function now also replaces non-ASCII characters with an underscore (_), since libFAT apparently has problems opening/writing files with names that include them. Thanks to erickmaniche from Emudesc for letting me know. 182 | * The getdir_info() and getdir_device() functions will now end early if no files are detected when reading the directory the first time. This fixes some small problems related to save dumping/restoring. 183 | * Logfile output cleanup (mostly, missing newlines). 184 | * General code cleanup. Fixed some small things I previously overlooked. 185 | * Exit sequence cleanup: instead of calling Unmount_Devices() and Reboot() all over again, now just goodbye() is used. 186 | 187 | YABDM v0.92 (February 27th, 2014 - DarkMatterCore): 188 | 189 | * Reimplemented the DetectInput() function, now fixed by JoostinOnline. 190 | * Rewrote the GetASCII() function to discard non-valid ASCII characters. 191 | * Button A can no longer be used in the content.bin conversion mode if the selected directory doesn't have a content.bin file inside. 192 | 193 | YABDM v0.91 (February 26th, 2014 - DarkMatterCore): 194 | 195 | * Fixed a very silly regression bug in the name reading code. 196 | * Fixed GCN Controller compatibility. For some odd reason, the controller input acts erratically using the DetectInput() function, so for now I'm just reverting back to the old waitforbuttonpress(). I swear I received my controller just a moment ago; otherwise, I wouldn't have noticed that. 197 | 198 | YABDM v0.9 (February 26th, 2014 - DarkMatterCore): 199 | 200 | * Rewrote the title name reading functions from scratch. The application can now read multilingual names and descriptions from contents stored on the NAND filesystem and content.bin files using the IMET and WIBN structs from Wiibrew, and the __convertWiiString() function from AnyTitle Deleter by bushing. 201 | * Improvements to the save dumping/flashing code. 202 | * Minor cleanup to the WAD dumping code. The application will now also check if the Ticket and/or TMD data is already fakesigned before trying to wipe the signature. 203 | * If you choose to fakesign the TMD, the application will now display a prompt asking if you want to change the WAD region. This is done by modifying the value @ 0x19D in the TMD, just like FreeTheWads on PC. 204 | * A "(vWii)" suffix will be displayed along with the System Menu version if the application is running under vWii (thanks to JoostinOnline and crediar for their IsWiiU() check). 205 | * Updated libruntimeiospatch to v1.5.1. 206 | * Updated application headline and meta.xml credits to reference HacksDen.com. 207 | 208 | YABDM v0.8 (September 24th, 2013 - DarkMatterCore): 209 | 210 | * Added support for title 00010000-HAZA. It is the responsible for controlling the Photo Channel "swap" between versions 1.0 and 1.1. When it is present, v1.1 is displayed in the System Menu; otherwise, v1.0 is used. Since it gets installed to the savedata directory, it was not being treated as a title, thus its dumping was not allowed; now this behaviour is fixed. Thanks to Iwatasan for noticing this! 211 | * Compiled with the latest libogc git revision from 09/04/2013. 212 | * Now using the latest libruntimeiospatch revision. The previous version was not properly patching the hash_old[] pattern because it had the same value as new_hash_old[]. I informed Excelsiior about this and the change has now been made to the GitHub repository. 213 | 214 | YABDM v0.7 (September 15th, 2013 - DarkMatterCore): 215 | 216 | * Changed application name to YABDM (Yet Another BlueDump MOD). 217 | * Added a proper fix for DetectInput(): now calling VIDEO_WaitVSync() instead of using a while loop (thanks to JoostinOnline!). 218 | * Changed the AES / Rijndael implementation from Mike Scott in favor of a faster one by Vincent Rijmen, Antoon Bosselaers and Paulo Barreto (slightly modified by Jouni Malinen), known as "rijndael-alg-fst". This one uses previously created AES tables instead of generating them everytime an encryption / decryption operation is done, and it also allows the use of a single memory block to be modified 'in-place'. Thus, the dumping process is now faster. 219 | * The OTP memory is now mounted once instead of accessing its data everytime Content_bin_Dump() is called in the application. 220 | * The application now generates a name list for all the entries in a directory everytime the current path is changed. This is mainly done to reduce loading times, and to avoid reading ALL the names again when a D-Pad button is pressed. Because of this, the names for the content.bin files saved in the SD card are now properly displayed on screen; you'll only have to wait a bit after pressing +/R. 221 | * Thanks to the previous point, I noticed a memory leak in getdir_info(), because the *ent pointer was used to allocate memory with malloc() regardless if it already pointed to a memory address. It is now freed before reusing it. 222 | * Some other optimizations. 223 | 224 | MOD v0.6 (September 7th, 2013 - DarkMatterCore and JoostinOnline): 225 | 226 | * Added compatibility with content.bin files stored in SD:/private/wii/title. You can switch between normal WAD dumping and content.bin conversion modes with +/R. 227 | * Added code to read the OTP contents and copy them to a previously aligned memory block. This is needed to access both the PRNG Key and the Console ID, which are used in the content.bin conversion process. 228 | * Added compatibility with Classic Controllers (thanks to JoostinOnline!). 229 | * Optimized name reading functions. Instead of allocating a memory block and then returning it (which is unsafe), now a single global character string is used, with its current value being updated by using snprintf() (thanks to JoostinOnline!). 230 | * Added meta.xml argument support to enable or disable the logfile creation without having to recompile the entire application (thanks to JoostinOnline!). 231 | * New sexy, smexy icon (thanks to JoostinOnline!). 232 | * Some other changes and simplifications that reduce the overall CPU use (thanks to JoostinOnline!). 233 | 234 | MOD v0.5 (August 27th, 2013 - DarkMatterCore): 235 | 236 | * read_name_from_banner_app() and read_dlc_name() functions are now merged. 237 | * Fixed a bug in the read_name() function which would return wrong text if the title has contents smaller than the size of the chunk read into memory (e.g. YouTube Channel, it has two 'dummy' contents of 0x40 bytes each). 238 | * Fixed a *possible* buffer overflow in the read_name*() functions, since they were allocating 'length+10' bytes for the name buffer and then the description string was concatenated to it (which is usually longer than 10 bytes). Now, they're just allocating enough space for what they need. 239 | * Fixed left button behaviour. 240 | * More code changes. 241 | 242 | MOD v0.4 (August 26th, 2013 - DarkMatterCore): 243 | 244 | * Ability to read the internal channel descriptions. Not all channels have this, though, but it still is a nice feature. 245 | * Button 2 / X is now used to change the view mode between hexadecimal IDs and ASCII IDs. 246 | * Added padding to 64-byte boundary for the footer data (I noticed that the official WADs from game discs have this, so why not?). 247 | * Mostly, code optimizations. 248 | 249 | MOD v0.3 (August 24th, 2013 - DarkMatterCore): 250 | 251 | * Fixed a very silly bug in the GetContent() function that would improperly dump content files smaller than 16KB using a null IV in the encryption process (I used the Mario Kart Channel to test this behaviour, since it has two contents that match this case). 252 | * The WAD backup section of the dump_menu() function was completely revamped to avoid redundancy (it seriously had a lot of unnecessary code). Plus, the name scheme of the dumped WADs was changed to be the same from CustomizeMii and similar applications. 253 | * Now using conditional operators for most checks on the 'isSD' value. 254 | * Some other little corrections. 255 | 256 | MOD v0.2 (August 15th, 2013 - DarkMatterCore): 257 | 258 | * Now using libruntimeiospatch by Excelsiior to apply patches to the current IOS. 259 | * Fixed illegal FAT characters on dumped savegames. They are now replaced with an underscore (_). 260 | * Added full support for contents bigger than 45MB. The GetContent() function was completely rewritten to dump each regular content file in chunks of 16KB, which are read, encrypted and saved to the output WAD. Because of this, the encrypt_buffer() function is not used anymore in GetContent(), since we need to change the Initialization Vector (IV) for each chunk. 261 | * Other minor fixes and corrections. 262 | 263 | MOD v0.1 (August 1st, 2013 - DarkMatterCore): 264 | 265 | * Full hardware access through the HW_AHBPROT flag (must use HBC v1.1.0 or later!). The IOS patches applied include the "KillAntiSysTitleInstall" set from damysteryman, so the application is also fully compatible with the vWii mode available in Wii U. 266 | * Added an IOS selection screen at startup (you can select whether you want to use the full hardware access, or a patched IOS). 267 | * Full compatibility with USB storage devices and GCN controllers. 268 | * Ability to choose if you want to fakesign the WAD ticket and/or TMD before starting the dumping process (no secondary version needed anymore). 269 | * If you select to fakesign the WAD ticket, the application now wipes the console ID and the ECDH data from it; both of those can prevent a successful WAD installation on another Wii. It is also verified if the Common Key Index value (0x1F1) is set to 0x01 or 0x02; if so, it is changed to 0x00. 270 | * The certificate chain (cert.sys) is now embedded on the code, to avoid reading it every time from the NAND. 271 | * Complete overhaul in the name reading functions for channel banners and banner.bin file from savegames. Plus, the application now can also read names from installed DLCs. 272 | * The WAD footer is now added to every title dumped from the application. Its size is added to the WAD header @ 0x1C, too. 273 | * The content.map file is now read into memory once for every dumping process, instead of accessing it every time the application dumps a shared content. 274 | * Compatibility with content type 0x4001 (which is only present in DLCs, AFAIK). 275 | * Fixed a bug in GetContent() where the application would allocate memory for two different buffers with the same size, which could exceed the console memory limit if the content size was greater than ~22.5 MB. Now, a single memory buffer is used for all the dumping, padding and encrypting operations. 276 | * The pad_data_32() function is now called pad_data(). It uses a bool value to determine if the input buffer will be padded to a 16-byte (0x10) boundary, or a 64-byte boundary (0x40). To avoid memory problems, it now uses realloc() to change the size of the already-allocated input buffer, instead of allocating memory for a new buffer. 277 | * The decrypted memory buffer is now padded to a 16-byte boundary before encrypting. Then, the encrypted memory buffer is padded to a 64-byte boundary. That way, the WAD structure used by NUS Downloader can be easily recreated, with amazing results (just see it by yourself). 278 | * Before reading the internal name of a given title, it is now verified which type of title is it to use the appropiate function for its case. That way, the logfile won't be full of ISFS_Open() -106 errors when trying to read the banner.bin file for everything. lol 279 | * Added a switch case function to properly output the System Menu version in the browser screen (e.g. "v513" is now displayed as "v4.3U"). 280 | * Ability to use the LEFT/RIGHT buttons in the browser screen (why didn't nicksasa add that...?). 281 | * Output font replaced with another that has full Unicode support. That way, the title names can be displayed properly if you have set your console in Spanish or a different language. 282 | * Compiled with the latest libogc, devkitPPC and libfat versions (as of August 1st, 2013: v1.8.12, r26 and v1.0.12, respectively). 283 | * Compatibility with the new WiiMote Plus (RVL-CNT-01-TR). 284 | 285 | Alpha 3: 286 | 287 | * Show IOS names (for example, IOS36). 288 | * Show IOS versions (for example, IOS 249 v18). 289 | * Disabled logging by default. 290 | * Code cleanup. 291 | * Creating folders correctly now if they don't exist. 292 | * Some more stuff I forgot. 293 | 294 | Alpha 2: 295 | 296 | * Backup savedata from VC/WiiWare and Disc games. 297 | * Restore savedata from VC/WiiWare and Disc games. 298 | * Backup title's to WAD (correctly signed, will only work on your own wii if you use the normal version!). 299 | 300 | Alpha 1: 301 | 302 | * Never released. 303 | 304 | 305 | debug=0 306 | wiilight=1 307 | 308 | 309 | -------------------------------------------------------------------------------- /source/tools.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "tools.h" 11 | #include "net.h" 12 | #include "mload/usb2storage.h" 13 | #include "mload/mload_init.h" 14 | 15 | extern DISC_INTERFACE __io_usbstorage; 16 | 17 | static void *xfb = NULL; 18 | static GXRModeObj *rmode = NULL; 19 | static FILE *debug_file = NULL; 20 | 21 | static vu32 *_wiilight_reg = (u32*)0xCD0000C0; 22 | 23 | const char *languages[10] = { "Japanese", "English", "German", "French", "Spanish", "Italian", "Dutch", "Simp. Chinese", "Trad. Chinese", "Korean" }; 24 | 25 | map_entry_t *cm; 26 | size_t content_map_size; 27 | size_t content_map_items; 28 | 29 | int lang; 30 | bool SDmnt, USBmnt, isSD, isUSB2, __debug, __wiilight, vwii, netw_init; 31 | 32 | char launch_path[MAXPATHLEN]; 33 | 34 | bool IsWiiU(void) 35 | { 36 | s32 ret; 37 | u32 x; 38 | 39 | ret = ES_GetTitleContentsCount(TITLEID_200, &x); 40 | 41 | if (ret < 0) return false; // title was never installed 42 | 43 | if (x <= 0) return false; // title was installed but deleted via Channel Management 44 | 45 | return true; 46 | } 47 | 48 | void WiiDiscLight(bool turn_on) 49 | { 50 | if (__wiilight) 51 | { 52 | *_wiilight_reg = ((*_wiilight_reg & ~0x20) | (turn_on ? 0x20 : 0x00)); 53 | } 54 | } 55 | 56 | u32 __fread(void *out, u32 size, u32 cnt, FILE *src) 57 | { 58 | WiiDiscLight(true); 59 | u32 ret = fread(out, size, cnt, src); 60 | WiiDiscLight(false); 61 | 62 | return ret; 63 | } 64 | 65 | u32 __fwrite(const void *src, u32 size, u32 cnt, FILE *out) 66 | { 67 | WiiDiscLight(true); 68 | u32 ret = fwrite(src, size, cnt, out); 69 | WiiDiscLight(false); 70 | 71 | return ret; 72 | } 73 | 74 | bool is_empty(void *buf, u32 size) 75 | { 76 | u8 *zero = calloc(size, 1); 77 | bool i = (memcmp(zero, buf, size) == 0); 78 | free(zero); 79 | return i; 80 | } 81 | 82 | void Reboot() 83 | { 84 | if (*(u32*)0x80001800) exit(0); 85 | SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0); 86 | } 87 | 88 | /* Big thanks to JoostinOnline for the new controller code */ 89 | u32 DetectInput(u8 DownOrHeld) 90 | { 91 | u32 pressed = 0; 92 | u32 gcpressed = 0; 93 | 94 | VIDEO_WaitVSync(); 95 | 96 | // WiiMote, Classic Controller and Wii U Pro Controller take precedence over the GCN Controller to save time 97 | if (WUPC_UpdateButtonStats() > WPAD_ERR_NONE) 98 | { 99 | if (DownOrHeld == DI_BUTTONS_DOWN) 100 | { 101 | pressed = WUPC_ButtonsDown(0) | WUPC_ButtonsDown(1) | WUPC_ButtonsDown(2) | WUPC_ButtonsDown(3); // Store pressed buttons 102 | } else { 103 | pressed = WUPC_ButtonsHeld(0) | WUPC_ButtonsHeld(1) | WUPC_ButtonsHeld(2) | WUPC_ButtonsHeld(3); // Store held buttons 104 | } 105 | } else 106 | if (WPAD_ScanPads() > WPAD_ERR_NONE) 107 | { 108 | if (DownOrHeld == DI_BUTTONS_DOWN) 109 | { 110 | pressed = WPAD_ButtonsDown(0) | WPAD_ButtonsDown(1) | WPAD_ButtonsDown(2) | WPAD_ButtonsDown(3); // Store pressed buttons 111 | } else { 112 | pressed = WPAD_ButtonsHeld(0) | WPAD_ButtonsHeld(1) | WPAD_ButtonsHeld(2) | WPAD_ButtonsHeld(3); // Store held buttons 113 | } 114 | } 115 | 116 | // Convert to WiiMote values 117 | if (pressed & WPAD_CLASSIC_BUTTON_ZR) pressed |= WPAD_BUTTON_PLUS; 118 | if (pressed & WPAD_CLASSIC_BUTTON_ZL) pressed |= WPAD_BUTTON_MINUS; 119 | 120 | if (pressed & WPAD_CLASSIC_BUTTON_PLUS) pressed |= WPAD_BUTTON_PLUS; 121 | if (pressed & WPAD_CLASSIC_BUTTON_MINUS) pressed |= WPAD_BUTTON_MINUS; 122 | 123 | if (pressed & WPAD_CLASSIC_BUTTON_A) pressed |= WPAD_BUTTON_A; 124 | if (pressed & WPAD_CLASSIC_BUTTON_B) pressed |= WPAD_BUTTON_B; 125 | if (pressed & WPAD_CLASSIC_BUTTON_X) pressed |= WPAD_BUTTON_2; 126 | if (pressed & WPAD_CLASSIC_BUTTON_Y) pressed |= WPAD_BUTTON_1; 127 | if (pressed & WPAD_CLASSIC_BUTTON_HOME) pressed |= WPAD_BUTTON_HOME; 128 | 129 | if (pressed & WPAD_CLASSIC_BUTTON_UP) pressed |= WPAD_BUTTON_UP; 130 | if (pressed & WPAD_CLASSIC_BUTTON_DOWN) pressed |= WPAD_BUTTON_DOWN; 131 | if (pressed & WPAD_CLASSIC_BUTTON_LEFT) pressed |= WPAD_BUTTON_LEFT; 132 | if (pressed & WPAD_CLASSIC_BUTTON_RIGHT) pressed |= WPAD_BUTTON_RIGHT; 133 | 134 | // Return WiiMote / Classic Controller / Wii U Pro Controller values 135 | if (pressed) return pressed; 136 | 137 | // No buttons on the WiiMote or Classic Controller were pressed 138 | if (PAD_ScanPads() > PAD_ERR_NONE) 139 | { 140 | if (DownOrHeld == DI_BUTTONS_DOWN) 141 | { 142 | gcpressed = PAD_ButtonsDown(0) | PAD_ButtonsDown(1) | PAD_ButtonsDown(2) | PAD_ButtonsDown(3); // Store pressed buttons 143 | } else { 144 | gcpressed = PAD_ButtonsHeld(0) | PAD_ButtonsHeld(1) | PAD_ButtonsHeld(2) | PAD_ButtonsHeld(3); // Store held buttons 145 | } 146 | 147 | // Convert to WiiMote values 148 | if (gcpressed & PAD_TRIGGER_R) pressed |= WPAD_BUTTON_PLUS; 149 | if (gcpressed & PAD_TRIGGER_L) pressed |= WPAD_BUTTON_MINUS; 150 | if (gcpressed & PAD_BUTTON_A) pressed |= WPAD_BUTTON_A; 151 | if (gcpressed & PAD_BUTTON_B) pressed |= WPAD_BUTTON_B; 152 | if (gcpressed & PAD_BUTTON_X) pressed |= WPAD_BUTTON_2; 153 | if (gcpressed & PAD_BUTTON_Y) pressed |= WPAD_BUTTON_1; 154 | if (gcpressed & PAD_BUTTON_MENU) pressed |= WPAD_BUTTON_HOME; 155 | if (gcpressed & PAD_BUTTON_UP) pressed |= WPAD_BUTTON_UP; 156 | if (gcpressed & PAD_BUTTON_DOWN) pressed |= WPAD_BUTTON_DOWN; 157 | if (gcpressed & PAD_BUTTON_LEFT) pressed |= WPAD_BUTTON_LEFT; 158 | if (gcpressed & PAD_BUTTON_RIGHT) pressed |= WPAD_BUTTON_RIGHT; 159 | } 160 | 161 | return pressed; 162 | } 163 | 164 | void waitforbuttonpress() 165 | { 166 | printf("\n\nPress any button to go back to the menu."); 167 | fflush(stdout); 168 | 169 | while(true) 170 | { 171 | if (DetectInput(DI_BUTTONS_DOWN) != 0) break; 172 | } 173 | } 174 | 175 | void Init_Console() 176 | { 177 | // Initialise the video system 178 | VIDEO_Init(); 179 | 180 | // Obtain the preferred video mode from the system 181 | // This will correspond to the settings in the Wii menu 182 | rmode = VIDEO_GetPreferredMode(NULL); 183 | 184 | // Allocate memory for the display in the uncached region 185 | xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); 186 | 187 | // Set up the video registers with the chosen mode 188 | VIDEO_Configure(rmode); 189 | 190 | // Tell the video hardware where our display memory is 191 | VIDEO_SetNextFramebuffer(xfb); 192 | 193 | // Make the display visible 194 | VIDEO_SetBlack(FALSE); 195 | 196 | // Flush the video register changes to the hardware 197 | VIDEO_Flush(); 198 | 199 | // Wait for Video setup to complete 200 | VIDEO_WaitVSync(); 201 | if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); 202 | 203 | // Set console parameters 204 | int x = 24, y = 32, w, h; 205 | w = rmode->fbWidth - (32); 206 | h = rmode->xfbHeight - (48); 207 | 208 | // Initialize the console - CON_InitEx works after VIDEO_ calls 209 | CON_InitEx(rmode, x, y, w, h); 210 | 211 | // Clear the garbage around the edges of the console 212 | VIDEO_ClearFrameBuffer(rmode, xfb, COLOR_BLACK); 213 | } 214 | 215 | void printheadline() 216 | { 217 | int rows, cols; 218 | CON_GetMetrics(&cols, &rows); 219 | 220 | printf("Yet Another BlueDump MOD v%s.", VERSION); 221 | 222 | char buf[64]; 223 | sprintf(buf, "IOS%d (v%d)", IOS_GetVersion(), IOS_GetRevision()); 224 | printf("\x1b[%d;%dH", 0, cols-strlen(buf)-1); 225 | printf(buf); 226 | 227 | printf("\nOriginal code by nicksasa and WiiPower."); 228 | printf("\nUpdated by DarkMatterCore. Additional code by JoostinOnline."); 229 | printf("\nHacksDen.com, The Hacking Resource Community (2013-2017).\n\n"); 230 | } 231 | 232 | void set_highlight(bool highlight) 233 | { 234 | if (highlight) 235 | { 236 | printf("\x1b[%u;%um", 47, false); 237 | printf("\x1b[%u;%um", 30, false); 238 | } else { 239 | printf("\x1b[%u;%um", 37, false); 240 | printf("\x1b[%u;%um", 40, false); 241 | } 242 | } 243 | 244 | void Con_ClearLine() 245 | { 246 | int cols, rows; 247 | u32 cnt; 248 | 249 | printf("\r"); 250 | fflush(stdout); 251 | 252 | /* Get console metrics */ 253 | CON_GetMetrics(&cols, &rows); 254 | 255 | /* Erase line */ 256 | for (cnt = 1; cnt < cols; cnt++) 257 | { 258 | printf(" "); 259 | fflush(stdout); 260 | } 261 | 262 | printf("\r"); 263 | fflush(stdout); 264 | } 265 | 266 | bool PriiloaderCheck(u64 id) 267 | { 268 | if (TITLE_UPPER(id) == 1 && TITLE_LOWER(id) == 2) 269 | { 270 | char pl_tmd[ISFS_MAXPATH]; 271 | snprintf(pl_tmd, MAX_CHARACTERS(pl_tmd), "/title/00000001/00000002/content/title_or.tmd"); 272 | s32 cfd = ISFS_Open(pl_tmd, ISFS_OPEN_READ); 273 | if (cfd >= 0) 274 | { 275 | ISFS_Close(cfd); 276 | printf("Priiloader detected in System Menu!\n"); 277 | logfile("Priiloader detected in System Menu!\r\n"); 278 | return true; 279 | } 280 | } 281 | 282 | return false; 283 | } 284 | 285 | bool IsPriiloaderCnt(u16 cid) 286 | { 287 | char priiloader_cnt[ISFS_MAXPATH]; 288 | snprintf(priiloader_cnt, MAX_CHARACTERS(priiloader_cnt), "/title/00000001/00000002/content/%08x.app", (u32)((1 << 28) | cid)); 289 | s32 cfd = ISFS_Open(priiloader_cnt, ISFS_OPEN_READ); 290 | if (cfd >= 0) 291 | { 292 | ISFS_Close(cfd); 293 | printf("Priiloader content detected!\n"); 294 | logfile("Priiloader content detected! Original System Menu content file: %08x.app.\r\n", (u32)((1 << 28) | cid)); 295 | return true; 296 | } 297 | 298 | return false; 299 | } 300 | 301 | void Close_SD() 302 | { 303 | fatUnmount("sd"); 304 | __io_wiisd.shutdown(); 305 | } 306 | 307 | void Init_SD() 308 | { 309 | //Close_SD(); 310 | SDmnt = fatMountSimple("sd", &__io_wiisd); 311 | printf("\n\t- SD Card: %s.", (SDmnt ? "OK" : "FAILED")); 312 | } 313 | 314 | void Close_USB() 315 | { 316 | fatUnmount("usb"); 317 | 318 | if (isUSB2) 319 | { 320 | __io_usbstorage2.shutdown(); 321 | } else { 322 | __io_usbstorage.shutdown(); 323 | } 324 | } 325 | 326 | void Init_USB() 327 | { 328 | //Close_USB(); 329 | 330 | printf("\n"); 331 | if (AHBPROT_DISABLED && !USB_PORT_CONNECTED) 332 | { 333 | USBmnt = false; 334 | } else { 335 | bool started = false; 336 | isUSB2 = (IOS_GetVersion() >= 200); 337 | 338 | time_t tStart = time(0); 339 | while ((time(0) - tStart) < 10) // 10 seconds timeout 340 | { 341 | Con_ClearLine(); 342 | printf("\t- USB drive: %.f...", difftime(time(0), tStart)); 343 | 344 | if (isUSB2) 345 | { 346 | started = (__io_usbstorage2.startup() && __io_usbstorage2.isInserted()); 347 | } else { 348 | started = (__io_usbstorage.startup() && __io_usbstorage.isInserted()); 349 | } 350 | 351 | if (started) break; 352 | 353 | usleep(50000); 354 | } 355 | 356 | USBmnt = (started && fatMountSimple("usb", (isUSB2 ? &__io_usbstorage2 : &__io_usbstorage))); 357 | Con_ClearLine(); 358 | } 359 | 360 | printf("\t- USB drive: %s.\n\n", (USBmnt ? "OK" : "FAILED")); 361 | } 362 | 363 | void Unmount_Devices() 364 | { 365 | if (debug_file) fclose(debug_file); 366 | if (SDmnt) Close_SD(); 367 | if (USBmnt) Close_USB(); 368 | } 369 | 370 | int Mount_Devices() 371 | { 372 | printf("\n\nMounting available storage devices...\n"); 373 | 374 | Init_SD(); 375 | Init_USB(); 376 | 377 | if (!SDmnt && !USBmnt) 378 | { 379 | printf("No device detected..."); 380 | return -2; 381 | } else 382 | if ((SDmnt && !USBmnt) || (!SDmnt && USBmnt)) 383 | { 384 | isSD = (SDmnt && !USBmnt); 385 | printf("The %s will be used as the storage device.", (isSD ? "SD card" : "USB drive")); 386 | sleep(2); 387 | } else { 388 | u32 pressed; 389 | printf("Press A to use the SD Card.\n"); 390 | printf("Press B to use the USB device.\n"); 391 | 392 | while(true) 393 | { 394 | pressed = DetectInput(DI_BUTTONS_DOWN); 395 | 396 | if (pressed == WPAD_BUTTON_A) 397 | { 398 | isSD = true; 399 | break; 400 | } 401 | 402 | if (pressed == WPAD_BUTTON_B) 403 | { 404 | isSD = false; 405 | break; 406 | } 407 | } 408 | } 409 | 410 | return 0; 411 | } 412 | 413 | void KeepAccessRightsAndReload(s32 ios, bool verbose) 414 | { 415 | s32 ret; 416 | 417 | if (AHBPROT_DISABLED) 418 | { 419 | /* There should be nothing to worry about if this fails, as long as the new IOS is patched */ 420 | if (verbose) printf("\t- Patching IOS%d to keep hardware access rights... ", IOS_GetVersion()); 421 | ret = IosPatch_AHBPROT(false); 422 | if (verbose) printf("%s.\n", (ret < 0 ? "FAILED" : "OK")); 423 | } 424 | 425 | if (verbose) printf("\t- Reloading to IOS%d... ", ios); 426 | WUPC_Shutdown(); 427 | WPAD_Shutdown(); 428 | IOS_ReloadIOS(ios); 429 | //sleep(2); 430 | PAD_Init(); 431 | WUPC_Init(); 432 | WPAD_Init(); 433 | WPAD_SetDataFormat(WPAD_CHAN_0, WPAD_FMT_BTNS_ACC_IR); 434 | if (verbose) printf("done."); 435 | 436 | if (AHBPROT_DISABLED) 437 | { 438 | if (verbose) printf("\n\t- Applying runtime patches to IOS%d... ", IOS_GetVersion()); 439 | ret = IosPatch_RUNTIME(true, false, vwii, false); 440 | if (verbose) printf("%s.\n", (ret < 0 ? "FAILED" : "OK")); 441 | } 442 | 443 | if (IsHermesIOS(ios)) 444 | { 445 | mload_Init(); 446 | if (verbose) printf("\n\t- Hermes cIOS detected! ehcmodule loaded through mload."); 447 | } 448 | } 449 | 450 | int Device_Menu(bool swap) 451 | { 452 | u32 pressed; 453 | int i, selection = 0; 454 | char *dev_opt[2] = { "SD Card", "USB Storage" }; 455 | 456 | while(true) 457 | { 458 | resetscreen(); 459 | printheadline(); 460 | 461 | printf("Current device: %s.\n\n", DEVICE(1)); 462 | printf("Select the new output device. "); 463 | printf("%s.\n\n", (swap ? "Press B to swap/remount the storage devices" : "Device swapping is not allowed")); 464 | 465 | for (i = 0; i <= 1; i++) 466 | { 467 | printf("%s %s %s\n", ((selection == i) ? ARROW : " "), dev_opt[i], (((i == 0 && SDmnt) || (i == 1 && USBmnt)) ? "(available)" : "(not available)")); 468 | } 469 | 470 | pressed = DetectInput(DI_BUTTONS_DOWN); 471 | 472 | if (pressed == WPAD_BUTTON_UP) 473 | { 474 | if (selection > 0) selection--; 475 | } 476 | 477 | if (pressed == WPAD_BUTTON_DOWN) 478 | { 479 | if (selection < 1) selection++; 480 | } 481 | 482 | if (pressed == WPAD_BUTTON_A) 483 | { 484 | /* Do not exit this screen if the user attempts to select an unavailable storage device */ 485 | if ((selection == 0 && SDmnt) || (selection == 1 && USBmnt)) 486 | { 487 | /* Detect if the selected device is being already used */ 488 | if ((selection == 0 && !isSD) || (selection == 1 && isSD)) 489 | { 490 | /* Do the magic */ 491 | isSD ^= 1; 492 | 493 | if (debug_file) 494 | { 495 | fclose(debug_file); 496 | logfile_header(); 497 | logfile("Device changed from %s to %s.\r\n\r\n", (selection == 0 ? "USB" : "SD"), DEVICE(1)); 498 | } 499 | } 500 | 501 | return 0; 502 | } 503 | } 504 | 505 | if (pressed == WPAD_BUTTON_B) 506 | { 507 | if (swap) break; 508 | } 509 | } 510 | 511 | resetscreen(); 512 | printheadline(); 513 | 514 | Unmount_Devices(); 515 | 516 | printf("Swap the current storage devices if you want to use different ones.\n"); 517 | printf("Press A when you're done to mount them.\n"); 518 | printf("Otherwise, you can just remount the devices already connected."); 519 | 520 | while(true) 521 | { 522 | pressed = DetectInput(DI_BUTTONS_DOWN); 523 | if (pressed == WPAD_BUTTON_A) break; 524 | } 525 | 526 | /* If the currently running IOS is a Waninkoko/d2x cIOS, we have to reload it before we can retry the USB ports */ 527 | s32 ios = IOS_GetVersion(); 528 | if (ios >= 200 && !IsHermesIOS(ios)) 529 | { 530 | /* Unmount NAND */ 531 | ISFS_Deinitialize(); 532 | 533 | /* Do our thing */ 534 | KeepAccessRightsAndReload(ios, false); 535 | 536 | /* Remount NAND */ 537 | ISFS_Initialize(); 538 | } 539 | 540 | int ret = Mount_Devices(); 541 | if (ret < 0) return ret; 542 | 543 | logfile_header(); 544 | return 0; 545 | } 546 | 547 | int __s32Cmp(const void *a, const void *b) 548 | { 549 | return *(s32 *)a-*(s32 *)b; 550 | } 551 | 552 | s32 *get_ioslist(u32 *cnt) 553 | { 554 | u64 *buf = 0; 555 | s32 res; 556 | u32 i, k = 0, tcnt = 0, icnt = 0; 557 | s32 *ioses = NULL; 558 | 559 | bool skip_title; 560 | 561 | /* Get stored IOS versions */ 562 | res = ES_GetNumTitles(&tcnt); 563 | if (res < 0) 564 | { 565 | printf("\t- ES_GetNumTitles: Error! (result = %d).\n", res); 566 | return 0; 567 | } 568 | 569 | buf = memalign(32, sizeof(u64) * tcnt); 570 | if (!buf) 571 | { 572 | printf("\t- Error allocating titlelist memory buffer!\n"); 573 | return 0; 574 | } 575 | 576 | res = ES_GetTitles(buf, tcnt); 577 | if (res < 0) 578 | { 579 | printf("\t- ES_GetTitles: Error! (result = %d).\n", res); 580 | free(buf); 581 | return 0; 582 | } 583 | 584 | for (i = 0; i < tcnt; i++) 585 | { 586 | /* Skip BC, MIOS, System Menu, BootMii IOS, BC-NAND, BC-WFS and stub IOSses */ 587 | if ((TITLE_UPPER(buf[i - k]) == 1) && (TITLE_LOWER(buf[i - k]) > 2) && (TITLE_LOWER(buf[i - k]) < 0xFE)) 588 | { 589 | u32 tmdSize = 0; 590 | tmd *iosTMD = NULL; 591 | signed_blob *iosTMDBuffer = NULL; 592 | 593 | /* Get stored TMD size */ 594 | res = ES_GetStoredTMDSize(buf[i - k], &tmdSize); 595 | if (res < 0) 596 | { 597 | printf("\t- ES_GetStoredTMDSize: Error! (result = %d / IOS%u).\n", res, ((u32)buf[i - k])); 598 | break; 599 | } 600 | 601 | iosTMDBuffer = (signed_blob*)memalign(32, (tmdSize+31)&(~31)); 602 | if (!iosTMDBuffer) 603 | { 604 | res = -1; 605 | printf("\t- Error allocating IOS%u TMD buffer (size = %u bytes).\n", ((u32)buf[i - k]), tmdSize); 606 | break; 607 | } 608 | 609 | memset(iosTMDBuffer, 0, tmdSize); 610 | 611 | /* Get stored TMD */ 612 | res = ES_GetStoredTMD(buf[i - k], iosTMDBuffer, tmdSize); 613 | if (res < 0) 614 | { 615 | printf("\t- ES_GetStoredTMD: Error! (result = %d / IOS%u).\n", res, ((u32)buf[i - k])); 616 | free(iosTMDBuffer); 617 | break; 618 | } 619 | 620 | iosTMD = (tmd*)SIGNATURE_PAYLOAD(iosTMDBuffer); 621 | 622 | /* Calculate title size */ 623 | u16 j; 624 | u32 titleSize = 0; 625 | for (j = 0; j < iosTMD->num_contents; j++) 626 | { 627 | tmd_content *content = &iosTMD->contents[j]; 628 | 629 | /* Add content size */ 630 | titleSize += content->size; 631 | } 632 | 633 | /* Check if this IOS is a stub */ 634 | skip_title = (titleSize < 0x100000); 635 | 636 | free(iosTMDBuffer); 637 | } else { 638 | skip_title = true; 639 | } 640 | 641 | if (!skip_title) 642 | { 643 | icnt++; 644 | } else { 645 | /* Move around memory blocks */ 646 | if ((tcnt - 1) > i) 647 | { 648 | memmove(&(buf[i - k]), &(buf[i - k + 1]), (sizeof(u64) * (tcnt - i - 1))); 649 | k++; 650 | } 651 | } 652 | } 653 | 654 | if (res < 0) 655 | { 656 | free(buf); 657 | return 0; 658 | } 659 | 660 | u64 *tmp_buf = realloc(buf, sizeof(u64) * icnt); 661 | if (!tmp_buf) 662 | { 663 | printf("\t- Error reallocating titlelist memory block!\n"); 664 | free(buf); 665 | return 0; 666 | } 667 | 668 | buf = tmp_buf; 669 | tmp_buf = NULL; 670 | 671 | ioses = (s32 *)malloc(sizeof(s32) * icnt); 672 | if (!ioses) 673 | { 674 | printf("\t- Error allocating IOS memory buffer!\n"); 675 | free(buf); 676 | return 0; 677 | } 678 | 679 | for (i = 0; i < icnt; i++) ioses[i] = (s32)buf[i]; 680 | 681 | free(buf); 682 | qsort(ioses, icnt, sizeof(s32), __s32Cmp); 683 | *cnt = icnt; 684 | 685 | return ioses; 686 | } 687 | 688 | s32 ios_selectionmenu(s32 default_ios) 689 | { 690 | u32 pressed, i, ioscount, selection = 0; 691 | 692 | s32 *list = get_ioslist(&ioscount); 693 | if (list == 0) return -1; 694 | 695 | for (i = 0; i < ioscount; i++) 696 | { 697 | /* Default to default_ios if found, else the loaded IOS */ 698 | if (list[i] == default_ios) 699 | { 700 | selection = i; 701 | break; 702 | } 703 | 704 | if (list[i] == IOS_GetVersion()) selection = i; 705 | } 706 | 707 | resetscreen(); 708 | printheadline(); 709 | 710 | s32 ios; 711 | 712 | while (true) 713 | { 714 | printf("\x1b[%d;%dH", 5, 0); // move console cursor to y/x 715 | printf("Select the IOS version to use: \b\b\b\b\b\b"); 716 | 717 | set_highlight(true); 718 | printf("IOS%d", list[selection]); 719 | set_highlight(false); 720 | 721 | printf("\n\nPress LEFT/RIGHT to change IOS version."); 722 | printf("\nPress A button to load the selected IOS."); 723 | printf("\nPress B to continue without IOS Reload."); 724 | printf("\nPress HOME or Start to exit.\n\n"); 725 | 726 | pressed = DetectInput(DI_BUTTONS_DOWN); 727 | 728 | if (pressed == WPAD_BUTTON_LEFT) 729 | { 730 | if (selection > 0) 731 | { 732 | selection--; 733 | } else { 734 | selection = ioscount - 1; 735 | } 736 | } 737 | 738 | if (pressed == WPAD_BUTTON_RIGHT) 739 | { 740 | if (selection < ioscount -1) 741 | { 742 | selection++; 743 | } else { 744 | selection = 0; 745 | } 746 | } 747 | 748 | if (pressed == WPAD_BUTTON_A) 749 | { 750 | ios = list[selection]; 751 | break; 752 | } 753 | 754 | if (pressed == WPAD_BUTTON_B) 755 | { 756 | ios = 0; 757 | break; 758 | } 759 | 760 | if (pressed == WPAD_BUTTON_HOME) 761 | { 762 | ios = -2; 763 | break; 764 | } 765 | } 766 | 767 | free(list); 768 | return ios; 769 | } 770 | 771 | s32 Settings_Menu() 772 | { 773 | s32 ret = 0; 774 | u32 pressed; 775 | int i, selection = 0; 776 | char *menu_opt[3] = { "Device menu", "Update application", "Reload to another IOS (device remount required)" }; 777 | 778 | while(true) 779 | { 780 | resetscreen(); 781 | printheadline(); 782 | 783 | printf("Select an option. Press B to go back to the menu.\n\n"); 784 | 785 | for (i = 0; i <= 2; i++) 786 | { 787 | printf("%s %s\n", ((selection == i) ? ARROW : " "), menu_opt[i]); 788 | } 789 | 790 | pressed = DetectInput(DI_BUTTONS_DOWN); 791 | 792 | if (pressed == WPAD_BUTTON_UP) 793 | { 794 | if (selection > 0) selection--; 795 | } 796 | 797 | if (pressed == WPAD_BUTTON_DOWN) 798 | { 799 | if (selection < 2) selection++; 800 | } 801 | 802 | if (pressed == WPAD_BUTTON_A) 803 | { 804 | switch (selection) 805 | { 806 | case 0: 807 | /* Device menu */ 808 | ret = Device_Menu(true); 809 | break; 810 | case 1: 811 | /* Update application */ 812 | UpdateYABDM(launch_path); 813 | break; 814 | case 2: 815 | /* IOS reload */ 816 | ret = ios_selectionmenu(249); 817 | if (ret > 0) 818 | { 819 | if (ret != IOS_GetVersion()) 820 | { 821 | /* Unmount devices */ 822 | ISFS_Deinitialize(); 823 | Unmount_Devices(); 824 | 825 | KeepAccessRightsAndReload(ret, true); 826 | 827 | /* Remount devices */ 828 | ISFS_Initialize(); 829 | ret = Mount_Devices(); 830 | if (ret != -2) logfile_header(); 831 | } else { 832 | printf("\t- IOS reload aborted (IOS%d is already loaded).", ret); 833 | waitforbuttonpress(); 834 | } 835 | } else 836 | if (ret == 0) 837 | { 838 | printf("\t- Proceeding without IOS reload..."); 839 | waitforbuttonpress(); 840 | } 841 | 842 | break; 843 | default: 844 | break; 845 | } 846 | 847 | break; 848 | } 849 | 850 | if (pressed == WPAD_BUTTON_B) break; 851 | } 852 | 853 | return ret; 854 | } 855 | 856 | s32 ahbprot_menu() 857 | { 858 | s32 ret; 859 | u32 pressed; 860 | 861 | /* HW_AHBPROT check */ 862 | if (AHBPROT_DISABLED) 863 | { 864 | printf("Hardware protection is disabled!\n"); 865 | printf("Current IOS: %d.\n\n", IOS_GetVersion()); 866 | 867 | printf("Press A button to use full hardware access.\n"); 868 | printf("Press B button to reload to another IOS.\n"); 869 | printf("Press HOME or Start to exit.\n\n"); 870 | 871 | for (;;) 872 | { 873 | pressed = DetectInput(DI_BUTTONS_DOWN); 874 | 875 | /* A button */ 876 | if (pressed == WPAD_BUTTON_A) 877 | { 878 | printf("Initializing IOS patches... "); 879 | ret = IosPatch_RUNTIME(true, false, vwii, false); 880 | if (ret < 0) 881 | { 882 | /* This is a very, very weird error */ 883 | printf("ERROR!\n\n"); 884 | printf("\tUnable to load the initial patches. Maybe the loaded IOS isn't\n"); 885 | printf("\tvulnerable for an unknown reason.\n"); 886 | sleep(4); 887 | printf("\tThis error is very uncommon. I already checked if the hardware\n"); 888 | printf("\tprotection was disabled. You should report this to me as soon as\n"); 889 | printf("\tyou can.\n"); 890 | sleep(4); 891 | printf("\tI'll let you reload to another IOS instead of kicking you out\n"); 892 | printf("\tto the loader..."); 893 | sleep(4); 894 | } else { 895 | printf("OK!"); 896 | } 897 | 898 | break; 899 | } 900 | 901 | /* B button */ 902 | if (pressed == WPAD_BUTTON_B) 903 | { 904 | ret = -1; 905 | break; 906 | } 907 | 908 | /* HOME/Start button */ 909 | if (pressed == WPAD_BUTTON_HOME) return -1; 910 | } 911 | } else { 912 | ret = -1; 913 | } 914 | 915 | if (ret < 0) 916 | { 917 | ret = ios_selectionmenu(249); 918 | if (ret > 0) 919 | { 920 | if (ret != IOS_GetVersion()) 921 | { 922 | KeepAccessRightsAndReload(ret, true); 923 | } else { 924 | printf("\t- IOS reload aborted (IOS%d is already loaded).", ret); 925 | } 926 | } else 927 | if (ret == 0) 928 | { 929 | printf("\t- Proceeding without IOS reload..."); 930 | } else { 931 | return ret; 932 | } 933 | } 934 | 935 | return 0; 936 | } 937 | 938 | void logfile(const char *format, ...) 939 | { 940 | if (__debug) 941 | { 942 | if (!debug_file) 943 | { 944 | char logpath[20]; 945 | snprintf(logpath, MAX_CHARACTERS(logpath), "%s:/YABDM.log", DEVICE(0)); 946 | debug_file = fopen(logpath, "a"); 947 | if (!debug_file) return; 948 | } 949 | 950 | WiiDiscLight(true); 951 | 952 | va_list args; 953 | va_start(args, format); 954 | vfprintf(debug_file, format, args); 955 | fflush(debug_file); 956 | va_end(args); 957 | 958 | WiiDiscLight(false); 959 | } 960 | } 961 | 962 | void logfile_header() 963 | { 964 | logfile("\r\n\r\n*---------------------------------------------------------------------------------------------------------------------------*\r\n"); 965 | logfile("\r\n\r\nYet Another BlueDump MOD v%s - Logfile.\r\n", VERSION); 966 | logfile("SDmnt(%d), USBmnt(%d), isUSB2(%d), isSD(%d), vwii(%d), __wiilight(%d).\r\n", SDmnt, USBmnt, isUSB2, isSD, vwii, __wiilight); 967 | logfile("Using IOS%d v%d.\r\n", IOS_GetVersion(), IOS_GetRevision()); 968 | logfile("Console language: %d (%s).\r\n\r\n", lang, languages[lang]); 969 | } 970 | 971 | void hexdump_log(void *d, int len) 972 | { 973 | if (__debug) 974 | { 975 | int i, f, off; 976 | u8 *data = (u8*)d; 977 | for (off = 0; off < len; off += 16) 978 | { 979 | logfile("%08x: ", (u32)(16 * (off / 16))); 980 | for (f = 0; f < 16; f += 4) 981 | { 982 | for (i = 0; i < 4; i++) 983 | { 984 | if ((i + off) >= len) 985 | { 986 | logfile(" "); 987 | } else { 988 | logfile("%02x", data[off + f + i]); 989 | } 990 | } 991 | logfile(" "); 992 | } 993 | logfile("\r\n"); 994 | } 995 | logfile("\r\n"); 996 | } 997 | } 998 | 999 | void hex_key_dump(void *d, int len) 1000 | { 1001 | if (__debug) 1002 | { 1003 | int i; 1004 | u8 *data = (u8*)d; 1005 | for (i = 0; i < len; i++) logfile("%02x ", data[i]); 1006 | } 1007 | } 1008 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------