mirror of
https://github.com/modmii/YAWM-ModMii-Edition.git
synced 2025-02-16 12:59:15 +01:00
putting this here for now
This commit is contained in:
parent
c25148a416
commit
a4b6f965a8
11
source/otp.c
11
source/otp.c
@ -8,14 +8,11 @@
|
||||
#define HW_OTP_DATA (*(vu32*)0xCD8001F0)
|
||||
|
||||
#define HW_OTP_BLK_SIZE 4
|
||||
#define HW_OTP_BLK_CNT (OTP_BANK_SIZE / HW_OTP_BLK_SIZE)
|
||||
#define HW_OTP_BLK_CNT (OTP_SIZE / HW_OTP_BLK_SIZE)
|
||||
|
||||
u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size)
|
||||
u8 otp_read(void *dst, u8 offset, u8 size)
|
||||
{
|
||||
if (!dst || bank > 7 || offset >= OTP_BANK_SIZE || !size || (offset + size) > OTP_BANK_SIZE) return 0;
|
||||
|
||||
/* This is not a Wii U. */
|
||||
if (bank != 0 && read16(0xCD8005A0) != 0xCAFE) return 0;
|
||||
if (!dst || offset >= OTP_SIZE || !size || (offset + size) > OTP_SIZE) return 0;
|
||||
|
||||
u8 cur_offset = 0;
|
||||
|
||||
@ -42,7 +39,7 @@ u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size)
|
||||
if (cur_offset >= size) break;
|
||||
|
||||
// Send command + address
|
||||
HW_OTP_COMMAND = (0x80000000 | bank << 8 | i);
|
||||
HW_OTP_COMMAND = (0x80000000 | i);
|
||||
|
||||
// Receive data
|
||||
*((u32*)val) = HW_OTP_DATA;
|
||||
|
19
source/otp.h
19
source/otp.h
@ -1,19 +1,9 @@
|
||||
#ifndef __OTP_H__
|
||||
#define __OTP_H__
|
||||
|
||||
#include <gctypes.h>
|
||||
#define OTP_SIZE 0x80
|
||||
|
||||
#define OTP_BANK_SIZE 0x80
|
||||
|
||||
// I want to add a structure for Bank 1 but the only thing that matters to me is the vWii common key in there.
|
||||
#define VWII_COMMON_KEY_OFFSET 0x50
|
||||
typedef enum
|
||||
{
|
||||
BANK_WII,
|
||||
BANK_WIIU,
|
||||
} OTPBank;
|
||||
|
||||
struct OTP
|
||||
typedef struct
|
||||
{
|
||||
u8 boot1_hash[20];
|
||||
u8 common_key[16];
|
||||
@ -32,9 +22,8 @@ struct OTP
|
||||
u8 rng_key[16];
|
||||
u32 unk1;
|
||||
u32 unk2; // 0x00000007
|
||||
};
|
||||
_Static_assert(sizeof(struct OTP) == OTP_BANK_SIZE, "OTP struct size incorrect!");
|
||||
} otp_t;
|
||||
|
||||
u8 otp_read(void *dst, OTPBank bank, u8 offset, u8 size);
|
||||
u8 otp_read(void *dst, u8 offset, u8 size);
|
||||
|
||||
#endif /* __OTP_H__ */
|
||||
|
@ -27,9 +27,12 @@ typedef struct
|
||||
|
||||
char _padding[16];
|
||||
} cIOSInfo;
|
||||
_Static_assert(sizeof(cIOSInfo) == 0x40, "Incorrect cIOSInfo struct size, do i really need to pack this..?");
|
||||
// _Static_assert(sizeof(cIOSInfo) == 0x40, "Incorrect cIOSInfo struct size, do i really need to pack this..?");
|
||||
|
||||
#define IS_WIIU (*(vu16*)0xCD005A0 == 0xCAFE)
|
||||
|
||||
extern u32 boot2version;
|
||||
|
||||
/* Prototypes */
|
||||
bool isIOSstub(u8 ios_number);
|
||||
bool tmdIsStubIOS(tmd*);
|
||||
|
@ -3,9 +3,11 @@
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <ogcsys.h>
|
||||
#include <ogc/es.h>
|
||||
|
||||
#include "sha1.h"
|
||||
#include "utils.h"
|
||||
#include "otp.h"
|
||||
#include "malloc.h"
|
||||
|
||||
s32 Title_ZeroSignature(signed_blob *p_sig)
|
||||
@ -315,3 +317,28 @@ out:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
__attribute__((aligned(0x10)))
|
||||
aeskey WiiCommonKey, vWiiCommonKey;
|
||||
|
||||
void Title_SetupCommonKeys(void)
|
||||
{
|
||||
static bool keys_ok = false;
|
||||
if (keys_ok)
|
||||
return;
|
||||
|
||||
// Grab the Wii common key...
|
||||
otp_read(WiiCommonKey, offsetof(otp_t, common_key), sizeof(aeskey));
|
||||
|
||||
// ...and decrypt the vWii common key with it.
|
||||
static const unsigned char vwii_key_enc_bin[0x10] = { 0x6e, 0x18, 0xdb, 0x23, 0x84, 0x7c, 0xba, 0x6c, 0x19, 0x31, 0xa4, 0x17, 0x9b, 0xaf, 0x8e, 0x09 };
|
||||
unsigned char iv[0x10] = {};
|
||||
|
||||
memcpy(vWiiCommonKey, vwii_key_enc_bin, sizeof(vwii_key_enc_bin));
|
||||
AES_Init();
|
||||
AES_Decrypt(WiiCommonKey, sizeof(aeskey), iv, sizeof(iv), vWiiCommonKey, vWiiCommonKey, sizeof(aeskey));
|
||||
AES_Close();
|
||||
|
||||
keys_ok = true;
|
||||
return;
|
||||
};
|
@ -1,9 +1,14 @@
|
||||
#ifndef _TITLE_H_
|
||||
#define _TITLE_H_
|
||||
|
||||
#include <ogc/es.h>
|
||||
|
||||
/* Constants */
|
||||
#define BLOCK_SIZE 0x4000
|
||||
|
||||
/* Variables */
|
||||
extern aeskey WiiCommonKey, vWiiCommonKey;
|
||||
|
||||
/* Prototypes */
|
||||
s32 Title_ZeroSignature(signed_blob *);
|
||||
s32 Title_FakesignTik(signed_blob *);
|
||||
|
352
source/wad.c
352
source/wad.c
@ -578,17 +578,13 @@ bool __Wad_FixTicket(signed_blob *s_tik)
|
||||
iv[0] = p_tik->titleid;
|
||||
iv[1] = 0;
|
||||
|
||||
if (!otp_read(commonkey, BANK_WIIU, VWII_COMMON_KEY_OFFSET, sizeof(commonkey)))
|
||||
return false;
|
||||
|
||||
AES_Init();
|
||||
AES_Decrypt(commonkey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf));
|
||||
AES_Decrypt(vWiiCommonKey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf));
|
||||
|
||||
otp_read(commonkey, BANK_WII, offsetof(struct OTP, common_key), sizeof(commonkey));
|
||||
iv[0] = p_tik->titleid;
|
||||
iv[1] = 0;
|
||||
|
||||
AES_Encrypt(commonkey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf));
|
||||
AES_Encrypt(WiiCommonKey, 0x10, iv, 0x10, tkeybuf, tkeybuf, sizeof(tkeybuf));
|
||||
|
||||
memcpy(p_tik->cipher_title_key, tkeybuf, sizeof(tkeybuf));
|
||||
AES_Close();
|
||||
@ -598,7 +594,7 @@ bool __Wad_FixTicket(signed_blob *s_tik)
|
||||
Title_FakesignTik(s_tik);
|
||||
}
|
||||
|
||||
return true;
|
||||
return fixvWiiKey;
|
||||
}
|
||||
|
||||
bool __Wad_VerifyHeader(wadHeader* header)
|
||||
@ -677,13 +673,7 @@ s32 Wad_Install(FILE *fp)
|
||||
if (ret != 1)
|
||||
goto err;
|
||||
|
||||
if (!__Wad_FixTicket(p_tik))
|
||||
{
|
||||
printf("\n This WAD is for the vWii (Wii U) only.\n\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
bool isvWiiTitle = __Wad_FixTicket(p_tik);
|
||||
|
||||
offset += round_up(header->tik_len, 64);
|
||||
|
||||
@ -699,204 +689,222 @@ s32 Wad_Install(FILE *fp)
|
||||
/* Get TMD info */
|
||||
|
||||
tmd_data = (tmd *)SIGNATURE_PAYLOAD(p_tmd);
|
||||
|
||||
if(TITLE_LOWER(tmd_data->sys_version) != 0 && isIOSstub(TITLE_LOWER(tmd_data->sys_version)))
|
||||
|
||||
if (TITLE_UPPER(tmd_data->sys_version) == 0) // IOS
|
||||
{
|
||||
printf("\n This Title wants IOS%i but the installed version\n is a stub.\n", TITLE_LOWER(tmd_data->sys_version));
|
||||
ret = -1036;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(1, 2)))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
if (isvWiiTitle && !IS_WIIU)
|
||||
{
|
||||
printf("\n I won't install a stub System Menu IOS\n");
|
||||
printf("\n Cannot install vWii IOS on Wii.\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
else if ((tid == TITLE_ID(1, 70) || tid == TITLE_ID(1, 80)))
|
||||
if(tid == get_title_ios(TITLE_ID(1, 2)))
|
||||
{
|
||||
/* Check build tag here */
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K')))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n I won't install a stub EULA IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J')) || tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K')))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n I won't install a stub rgnsel IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449)))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n Are you sure you wan't to install a stub HBC IOS?\n");
|
||||
printf("\n Press A to continue.\n");
|
||||
printf(" Press B skip.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (!(buttons & WPAD_BUTTON_A))
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
ret = -998;
|
||||
printf("\n I won't install a stub System Menu IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
else if (tid == TITLE_ID(1, 70) || tid == TITLE_ID(1, 80))
|
||||
{
|
||||
/* Check build tag here */
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'E'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'P'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'J'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414B00 | 'K')))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n I won't install a stub EULA IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if(tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'E'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'P'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'J'))
|
||||
|| tid == get_title_ios(TITLE_ID(0x10008, 0x48414C00 | 'K')))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n I won't install a stub rgnsel IOS\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (tid == get_title_ios(TITLE_ID(0x10001, 0x48415858)) || tid == get_title_ios(TITLE_ID(0x10001, 0x4A4F4449)))
|
||||
{
|
||||
if (tmdIsStubIOS(tmd_data))
|
||||
{
|
||||
printf("\n Are you sure you wan't to install a stub HBC IOS?\n");
|
||||
printf("\n Press A to continue.\n");
|
||||
printf(" Press B skip.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (!(buttons & WPAD_BUTTON_A))
|
||||
{
|
||||
ret = -998;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tid == TITLE_ID(1, 2))
|
||||
else // not IOS
|
||||
{
|
||||
if (skipRegionSafetyCheck || gForcedInstall)
|
||||
goto skipChecks;
|
||||
|
||||
char region = 0;
|
||||
u16 version = 0;
|
||||
|
||||
GetSysMenuRegion(&version, ®ion);
|
||||
|
||||
if (tmd_data->vwii_title)
|
||||
if (isIOSstub(TITLE_LOWER(tmd_data->sys_version)))
|
||||
{
|
||||
printf("\n I won't install a vWii SM by default.\n\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
|
||||
ret = -999;
|
||||
printf("\n This Title wants IOS%i but the installed version\n is a stub.\n", TITLE_LOWER(tmd_data->sys_version));
|
||||
ret = -1036;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(region == 0)
|
||||
|
||||
|
||||
if (tid == TITLE_ID(1, 2))
|
||||
{
|
||||
printf("\n Unknown System menu region\n Please check the site for updates\n");
|
||||
if (skipRegionSafetyCheck || gForcedInstall)
|
||||
goto skipChecks;
|
||||
|
||||
char region = 0;
|
||||
u16 version = 0;
|
||||
|
||||
GetSysMenuRegion(&version, ®ion);
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
if (isvWiiTitle || tmd_data->vwii_title) // && !IS_WIIU ? :thinking:
|
||||
{
|
||||
printf("\n I won't install a vWii SM by default.\n\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
|
||||
if (!VersionIsOriginal(tmd_data->title_version))
|
||||
{
|
||||
printf("\n I won't install an unkown SM versions by default.\n\n");
|
||||
printf("\n Are you installing a tweaked system menu?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(region != RegionLookupTable[(tmd_data->title_version & 0x0F)])
|
||||
{
|
||||
printf("\n I won't install the wrong regions SM by default.\n\n");
|
||||
printf("\n Are you region changing?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
if(region == 0)
|
||||
{
|
||||
printf("\n Unknown System menu region\n Please check the site for updates\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!VersionIsOriginal(tmd_data->title_version))
|
||||
{
|
||||
printf("\n I won't install an unkown SM versions by default.\n\n");
|
||||
printf("\n Are you installing a tweaked system menu?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(region != RegionLookupTable[(tmd_data->title_version & 0x0F)])
|
||||
{
|
||||
printf("\n I won't install the wrong regions SM by default.\n\n");
|
||||
printf("\n Are you region changing?\n");
|
||||
printf("\n If you're really sure what you're doing, next time\n");
|
||||
printf(" select your device using Konami...\n\n");
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((tmd_data->title_version & 0x1F) != 0x6 // 0x6 = KR
|
||||
&& (tmd_data->title_version >> 5) >= 15) // 4.2 or later
|
||||
{
|
||||
cIOSInfo ios_info;
|
||||
|
||||
if (!Sys_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) ||
|
||||
(ios_info.ios_base != 60 && ES_CheckHasKoreanKey()))
|
||||
{
|
||||
printf("\n"
|
||||
" Installing this System menu will brick your Wii.\n"
|
||||
" Please remove the Korean key via KoreanKii,\n"
|
||||
" then try again.\n\n"
|
||||
);
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
skipChecks:
|
||||
/* Put this before or after skipChecks? */
|
||||
if ((tmd_data->title_version & 0x1F) != 0x6 // 0x6 = KR
|
||||
&& (tmd_data->title_version >> 5) >= 15) // 4.2 or later
|
||||
{
|
||||
cIOSInfo ios_info;
|
||||
|
||||
if (!Sys_GetcIOSInfo(TITLE_LOWER(tmd_data->sys_version), &ios_info) ||
|
||||
(ios_info.ios_base != 60 && ES_CheckHasKoreanKey()))
|
||||
if (tmd_data->title_version < 416)
|
||||
{
|
||||
printf("\n"
|
||||
" Installing this System menu will brick your Wii.\n"
|
||||
" Please remove the Korean key via KoreanKii,\n"
|
||||
" then try again.\n\n"
|
||||
);
|
||||
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (tmd_data->title_version < 416)
|
||||
{
|
||||
if(boot2version == 4)
|
||||
{
|
||||
printf("\n This version of the System Menu\n is not compatible with your Wii\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!gForcedInstall && AHBPROT_DISABLED && IsPriiloaderInstalled())
|
||||
{
|
||||
cleanupPriiloader = true;
|
||||
printf("\n Priiloader is installed next to the system menu.\n\n");
|
||||
printf(" It is recommended to retain Priiloader as it can\n");
|
||||
printf(" protect your console from being bricked.\n\n");
|
||||
printf(" Press A to retain Priiloader or B to remove.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if ((buttons & WPAD_BUTTON_A))
|
||||
{
|
||||
retainPriiloader = (BackUpPriiloader() && CompareHashes(true));
|
||||
if (retainPriiloader)
|
||||
if(boot2version == 4)
|
||||
{
|
||||
SetPriiloaderOption(true);
|
||||
Con_ClearLine();
|
||||
printf("\r[+] Priiloader will be retained.\n");
|
||||
fflush(stdout);
|
||||
printf("\n This version of the System Menu\n is not compatible with your Wii\n");
|
||||
ret = -999;
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
if (!gForcedInstall && AHBPROT_DISABLED && IsPriiloaderInstalled())
|
||||
{
|
||||
cleanupPriiloader = true;
|
||||
printf("\n Priiloader is installed next to the system menu.\n\n");
|
||||
printf(" It is recommended to retain Priiloader as it can\n");
|
||||
printf(" protect your console from being bricked.\n\n");
|
||||
printf(" Press A to retain Priiloader or B to remove.");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if ((buttons & WPAD_BUTTON_A))
|
||||
{
|
||||
Con_ClearLine();
|
||||
printf("\r Couldn't backup Priiloader.\n");
|
||||
fflush(stdout);
|
||||
printf("\n Press A to continue or B to skip");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (!(buttons & WPAD_BUTTON_A))
|
||||
retainPriiloader = (BackUpPriiloader() && CompareHashes(true));
|
||||
if (retainPriiloader)
|
||||
{
|
||||
ret = -990;
|
||||
goto err;
|
||||
SetPriiloaderOption(true);
|
||||
Con_ClearLine();
|
||||
printf("\r[+] Priiloader will be retained.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
Con_ClearLine();
|
||||
printf("\r Couldn't backup Priiloader.\n");
|
||||
fflush(stdout);
|
||||
printf("\n Press A to continue or B to skip");
|
||||
|
||||
u32 buttons = WaitButtons();
|
||||
|
||||
if (!(buttons & WPAD_BUTTON_A))
|
||||
{
|
||||
ret = -990;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!retainPriiloader)
|
||||
if (!retainPriiloader)
|
||||
{
|
||||
SetPriiloaderOption(false);
|
||||
Con_ClearLine();
|
||||
printf("\r[+] Priiloader will be removed.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPriiloaderOption(false);
|
||||
Con_ClearLine();
|
||||
printf("\r[+] Priiloader will be removed.\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (gForcedInstall)
|
||||
{
|
||||
SetPriiloaderOption(false);
|
||||
gForcedInstall = false;
|
||||
cleanupPriiloader = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (gForcedInstall)
|
||||
{
|
||||
gForcedInstall = false;
|
||||
cleanupPriiloader = true;
|
||||
}
|
||||
|
||||
printf("\t\t>> Installing ticket...");
|
||||
fflush(stdout);
|
||||
|
Loading…
x
Reference in New Issue
Block a user