#include #include #include #include #include #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 *NOR_ID = (unsigned char *)0xB0000000; unsigned char *CHIP_ID = (unsigned char *)0xB0000100; unsigned char *payload = (unsigned char *)0xB0000200; 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, 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); eraseblock(CHRISFL_OFFSET); writeblock(CHRISFL_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; } }