All pastes #745648 Raw Edit

Mine

public text v1 · immutable
·published 2007-10-22 15:54 UTC
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 NORID_LOC		((unsigned char *) 0xFFFF3BE2)

#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);

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,
    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,
    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
};

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 char payload[SECZONE_SIZE];

void fredtool_main() __attribute__ ((section (".fredtool_entry")));

void
fredtool_entry()
{
    unsigned long sha1[5], key[4], *ltp;
    sha1_context ctx;

    /* 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, sizeof(NOR_ID));
    memcpy(CHIP_ID, CHIPID_LOC, sizeof(CHIP_ID));
    
    /* Create the hash */
    sha1_starts(&ctx); 
    sha1_update(&ctx, NOR_ID, sizeof(NOR_ID));
    sha1_update(&ctx, CHIP_ID, sizeof(CHIP_ID));
    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);

    eraseblock(SECZONE_OFFSET);
    writeblock(SECZONE_OFFSET, SECZONE_SIZE);

    /* Hang until reset */
    arm9_stop_mode();

    /* This should never be reached */
    return;
}

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;
    }
}