174 lines
4.0 KiB
C
174 lines
4.0 KiB
C
|
/* xyzzy -- keydumper for Wii
|
||
|
|
||
|
Copyright (C) 2008 bushing
|
||
|
Copyright (C) 2011 R2-D2199
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, version 2.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program; if not, write to the Free Software
|
||
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||
|
*/
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <malloc.h>
|
||
|
#include <gccore.h>
|
||
|
#include <unistd.h>
|
||
|
#include <fat.h>
|
||
|
#include <ogc/machine/processor.h>
|
||
|
|
||
|
#include "hollywood.h"
|
||
|
#include "gpio.h"
|
||
|
#include "xyzzy.h"
|
||
|
|
||
|
#define eeprom_delay() udelay(5)
|
||
|
#define HAVE_AHBPROT ((*(vu32*)0xcd800064 == 0xFFFFFFFF) ? 1 : 0)
|
||
|
|
||
|
keys *keys_bin;
|
||
|
void udelay(int us);
|
||
|
|
||
|
|
||
|
|
||
|
static inline void set32(u32 addr, u32 set)
|
||
|
{
|
||
|
write32(addr, read32(addr) | set);
|
||
|
}
|
||
|
|
||
|
static inline void clear32(u32 addr, u32 clear)
|
||
|
{
|
||
|
write32(addr, read32(addr)&(~clear));
|
||
|
}
|
||
|
|
||
|
void send_bits(int b, int bits)
|
||
|
{
|
||
|
while(bits--)
|
||
|
{
|
||
|
if(b & (1 << bits))
|
||
|
set32(HW_GPIO1OUT, GP_EEP_MOSI);
|
||
|
else
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_MOSI);
|
||
|
eeprom_delay();
|
||
|
set32(HW_GPIO1OUT, GP_EEP_CLK);
|
||
|
eeprom_delay();
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||
|
eeprom_delay();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int recv_bits(int bits)
|
||
|
{
|
||
|
int res = 0;
|
||
|
while(bits--)
|
||
|
{
|
||
|
res <<= 1;
|
||
|
set32(HW_GPIO1OUT, GP_EEP_CLK);
|
||
|
eeprom_delay();
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||
|
eeprom_delay();
|
||
|
res |= !!(read32(HW_GPIO1IN) & GP_EEP_MISO);
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
int seeprom_read(void *dst, int offset, int size)
|
||
|
{
|
||
|
int i;
|
||
|
u16 *ptr = (u16 *)dst;
|
||
|
u16 recv;
|
||
|
|
||
|
if(size & 1)
|
||
|
return -1;
|
||
|
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_CLK);
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_CS);
|
||
|
eeprom_delay();
|
||
|
|
||
|
for(i = 0; i < size; ++i)
|
||
|
{
|
||
|
set32(HW_GPIO1OUT, GP_EEP_CS);
|
||
|
send_bits((0x600 | (offset + i)), 11);
|
||
|
recv = recv_bits(16);
|
||
|
*ptr++ = recv;
|
||
|
clear32(HW_GPIO1OUT, GP_EEP_CS);
|
||
|
eeprom_delay();
|
||
|
}
|
||
|
|
||
|
return size;
|
||
|
}
|
||
|
|
||
|
void crypto_read_otp(void)
|
||
|
{
|
||
|
otp_t *otpd = memalign(32, sizeof(otp_t));
|
||
|
u32 buffer[0x20];
|
||
|
int i;
|
||
|
for (i=0; i< 0x20; i++) {
|
||
|
write32(HW_OTPCMD,0x80000000|i);
|
||
|
buffer[i] = read32(HW_OTPDATA);
|
||
|
}
|
||
|
memcpy(otpd, buffer, sizeof(otp_t));
|
||
|
memcpy(keys_bin->boot1Hash, otpd->boot1_hash, sizeof(otpd->boot1_hash));
|
||
|
memcpy(keys_bin->commonKey, otpd->common_key, sizeof(otpd->common_key));
|
||
|
keys_bin->consoleID = otpd->ng_id;
|
||
|
snprintf(keys_bin->text, sizeof(keys_bin->text), "YAWMM_DE, ConsoleID: %08x", otpd->ng_id);
|
||
|
memset(keys_bin->text+29, 0, sizeof(keys_bin->text)-30);
|
||
|
memcpy(keys_bin->privateKey, otpd->ng_priv, sizeof(otpd->ng_priv));
|
||
|
memcpy(keys_bin->nandHmac, otpd->nand_hmac, sizeof(otpd->nand_hmac));
|
||
|
memcpy(keys_bin->nandKey, otpd->nand_key, sizeof(otpd->nand_key));
|
||
|
memcpy(keys_bin->rngKey, otpd->rng_key, sizeof(otpd->rng_key));
|
||
|
memcpy(keys_bin->nandKey, otpd->nand_key, sizeof(otpd->nand_key));
|
||
|
keys_bin->unk1 = otpd->unk1;
|
||
|
keys_bin->unk2 = otpd->unk2;
|
||
|
free(otpd);
|
||
|
}
|
||
|
|
||
|
void seeprom_read_seeprom(void) {
|
||
|
u32 buffer[sizeof(seeprom_t) / 4];
|
||
|
seeprom_t *seeprom = memalign(32, sizeof(seeprom_t));
|
||
|
seeprom_read(&buffer, 0, sizeof(seeprom_t) / 2);
|
||
|
memcpy(seeprom, buffer, sizeof(seeprom_t));
|
||
|
|
||
|
memset(keys_bin->blank, 0, 136);
|
||
|
keys_bin->ngKeyID = seeprom->ng_key_id;
|
||
|
memcpy(keys_bin->ngSig, seeprom->ng_sig, sizeof(seeprom->ng_sig));
|
||
|
memset(keys_bin->blank2, 0, 440);
|
||
|
free(seeprom);
|
||
|
}
|
||
|
|
||
|
int keydump() {
|
||
|
static char buf[128];
|
||
|
snprintf(buf, 128, "sd:/keys.bin");
|
||
|
FILE *fp = NULL;
|
||
|
fp = fopen(buf, "r");
|
||
|
if (fp) {
|
||
|
fclose(fp);
|
||
|
return 0;
|
||
|
}
|
||
|
printf(" Dumpe keys.bin");
|
||
|
keys_bin = memalign(32, sizeof(keys));
|
||
|
printf(".");
|
||
|
crypto_read_otp();
|
||
|
printf(".");
|
||
|
seeprom_read_seeprom();
|
||
|
printf(".");
|
||
|
|
||
|
fp = fopen(buf, "wb");
|
||
|
printf(".");
|
||
|
if (fp)
|
||
|
{
|
||
|
fwrite((u8 *)keys_bin, 1, sizeof(keys), fp);
|
||
|
fclose(fp);
|
||
|
}
|
||
|
free(keys_bin);
|
||
|
printf("OK\n");
|
||
|
return 0;
|
||
|
}
|