rendered paste body#include <arm9_utils.h>
#include <misc.h>
#include <sha1.h>
#include <tea.h>
#include <tokendefs.h>
#define NOR ((unsigned char *) 0xA0000000)
#define NORWORD ((unsigned short int *) 0xA0000000)
#define CHIPID_LOC ((unsigned char *) 0xF440006C)
#define CHIPID_LEN 12
#define NORID_LOC ((unsigned char *) 0xFFFF3BE2)
#define NORID_LEN 8
#define CHRISFL_OFFSET 0x3E0000
#define SECZONE_OFFSET 0x3FA000
#define SECZONE_SIZE 0x1000
#define LOCK_TABLE_OFFSET 0xC10
#define LOCK_TABLE_SIZE 0x210
void eraseblock(int addr);
void writeblock(int block, int length);
const unsigned char virgin[] = {
0x00,0x01,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x01,0x05,0x01,0x00,0x00,0x00,0x00,
0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
unsigned char *payload = (unsigned char *)0xB0000000;
void fredtool_main() __attribute__ ((section (".fredtool_entry")));
void
fredtool_entry()
{
int i;
unsigned char NOR_ID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
unsigned char CHIP_ID[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
unsigned long sha1[5], key[4], *ltp;
sha1_context ctx;
dcache_sync_clean();
dcache_disable();
icache_disable();
for(i = 0; i < 1024;) {
payload[i++] = 1;
payload[i++] = 2;
payload[i++] = 3;
payload[i++] = 4;
}
#if 0
/* Copy the original seczone */
memcpy(payload, (unsigned char *)SECZONE_OFFSET, SECZONE_SIZE);
/* Set a pointer to the lock table */
ltp = (unsigned long *)(payload + LOCK_TABLE_OFFSET);
/* Zero out lock table */
memset((unsigned char *)ltp, 0, LOCK_TABLE_SIZE);
/* Copy the NOR and HWID */
memcpy(NOR_ID, NORID_LOC, NORID_LEN);
memcpy(CHIP_ID, CHIPID_LOC, CHIPID_LEN);
/* Create the hash */
sha1_starts(&ctx);
sha1_update(&ctx, NOR_ID, NORID_LEN);
sha1_update(&ctx, CHIP_ID, CHIPID_LEN);
sha1_finish(&ctx, (void *)sha1);
/* Endian swap the first 16 bits of the SHA1 output */
key[0] = htonl(sha1[0]);
key[1] = htonl(sha1[1]);
key[2] = htonl(sha1[2]);
key[3] = htonl(sha1[3]);
/* Re-encrypt the lock table */
encrypt_cbc(ltp, LOCK_TABLE_SIZE, key, ltp);
memcpy(payload, NORID_LOC, NORID_LEN);
memcpy(payload + NORID_LEN + 4, CHIPID_LOC, CHIPID_LEN);
#endif
eraseblock(CHRISFL_OFFSET);
writeblock(CHRISFL_OFFSET, 1024);
/* Hang until reset */
arm9_stop_mode();
}
void
eraseblock(int addr)
{
NOR[addr] = 0xFF;
NOR[addr] = 0x60;
NOR[addr] = 0xD0; /* Unlock */
NOR[addr] = 0x20;
NOR[addr] = 0xD0; /* Erase */
NOR[addr] = 0x50;
while(NOR[addr] != 0x80); /* Wait for it to be ready */
}
void
writeblock(int addr, int length)
{
extern unsigned char *payload;
unsigned int i;
unsigned short int j;
/* First unlock the blocks */
for(i = 0; i < length; i+= 0x4000) {
NOR[addr + i] = 0xFF;
NOR[addr + i] = 0x60;
/* Unlock */
NOR[addr + i] = 0xD0;
NOR[addr + i] = 0xFF;
}
NOR[0] = 0xFF;
for(i = 0; i < length; i += 4) {
j = *(payload++);
j |= (*(payload++) << 8);
NOR[addr + i] = 0x40;
NORWORD[(addr + i) / 2] = j; //0x1100
NOR[addr] = 0x70;
/* Wait for it to be ready */
while(NOR[addr] != 0x80);
NOR[addr] = 0xFF;
j = *(payload++); //2
j |= (*(payload++) << 8); //3
NOR[addr + i] = 0x40;
NORWORD[((addr + i) / 2) + 1] = j; //0x3322
NOR[addr] = 0x70;
/* Wait for it to be ready */
while(NOR[addr] != 0x80);
NOR[addr] = 0xFF;
}
}