* Fixed a boatload of warnings.
* Initialize 0x3D Common Y #1/0x05 KeyY from FIRM0/FIRM1
* This means that CETKs can be used during boot.
* Additionally, I can read NAND for future use.
Thanks to the good people on #Cakey for helping get this working.
@d0k3, @gemarcano and @dark-samus all gave advice.
Some of this is roughly based on @Wolfvak's code.
PATH := $(PATH):$(DEVKITARM)/bin
-all: backdoor.bin stub.bin emunand.bin reboot_hook.bin reboot_code.bin chain.bin
+SOURCES=$(wildcard *.s)
+OBJECTS=$(patsubst %.s, %.bin, $(SOURCES))
+
+all: $(OBJECTS)
%.o: %.s
arm-none-eabi-as -o $@ $<
--- /dev/null
+Subproject commit 0e8bb5d3c55b3cab5eb704da1c25e4321423039d
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+const static char* get_desc(unsigned int index) {
+ const static char *strs[] = {
+ "Not found",
+ "Exists already",
+ "Out of space",
+ "Invalidated archive",
+ "Unacceptable",
+ "Verification Failure",
+ "Not supported",
+ "Unknown",
+ "Success,"
+ };
+
+ if (index == 0)
+ return strs[8];
+
+ if (index >= 100 && index < 180)
+ return strs[0];
+ else if (index >= 180 && index < 200)
+ return strs[1];
+ else if (index >= 200 && index < 220)
+ return strs[2];
+ else if (index >= 220 && index < 230)
+ return strs[3];
+ else if (index >= 230 && index < 340)
+ return strs[4];
+ else if (index >= 390 && index < 400)
+ return strs[5];
+ else if (index >= 760 && index < 780)
+ return strs[6];
+ return strs[7];
+}
+
+
+
+int main(int c, char** v) {
+ unsigned int error, desc, module, summary, level;
+ sscanf(v[1], "%08x", &error);
+ printf("Code: %08x\n", error);
+
+ desc = error & 0b1111111111;
+ module = (error >> 10) & 0b11111111;
+ summary = (error >> 21) & 0b111111;
+ level = (error >> 27) & 0b11111;
+
+ printf("Desc: %s (%u)\n", get_desc(desc), desc);
+
+ return 0;
+}
#include <stddef.h>
#include "../common.h"
-#include "../misc/sha256.h"
#include "../fatfs/sdmmc.h"
firm_h *firm_loc = (firm_h *)FCRAM_FIRM_LOC;
static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
-void
-slot0x11key96_init()
-{
- // 9.6 crypto may need us to get the key from somewhere else.
- // Unless the console already has the key initialized, that is.
- uint8_t key[AES_BLOCK_SIZE];
- if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0 || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0) {
- // Read key successfully.
- aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
-
- // Tell boot_firm it needs to regenerate the keys.
- update_96_keys = 1;
- }
- // If we can't read the key, we assume it's not needed, and the firmware is
- // the right version.
- // Otherwise, we make sure the error message for decrypting arm9bin mentions
- // this.
-}
-
// Fwd decl
int decrypt_arm9bin(arm9bin_h *header, uint64_t firm_title, uint8_t version);
-// The following two functions are loosely based on code from @Wolfvak's KGB CFW.
-void extract_firms() {
- // 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB)
- uint32_t firm0_offset = 0x0B530000, // FIRM1 (AKA Safe Mode FIRM)
- firm1_offset = 0x0B530000, // FIRM1 (AKA Safe Mode FIRM)
+#define SECTOR_SIZE 0x200
+
+// 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB)
+void dump_firm(firm_h** buffer, uint8_t index) {
+ if (*buffer != NULL) return;
+
+ uint32_t firm_offset = 0x0B130000 + (index % 2) * 0x400000,
firm_size = 0x00100000; // 1MB, because
- firm0 = (firm_h*)static_allocate(firm_size);
- firm1 = (firm_h*)static_allocate(firm_size);
+ buffer[0] = static_allocate(firm_size);
- uint8_t ctr[0x10] = {0},
- cid[0x10] = {0},
- sha[0x20] = {0};
+ uint8_t ctr[0x10],
+ cid[0x10],
+ sha_t[0x20];
- if (sdmmc_nand_readsectors(firm0_offset / 0x200, firm_size / 0x200, (uint8_t*)firm0)) {
- abort("Failed to read FIRM1 off NAND!\n");
- }
+ firm_h* firm = buffer[0];
- if (sdmmc_nand_readsectors(firm1_offset / 0x200, firm_size / 0x200, (uint8_t*)firm1)) {
- abort("Failed to read FIRM1 off NAND!\n");
- }
+ if (sdmmc_nand_readsectors(firm_offset / SECTOR_SIZE, firm_size / SECTOR_SIZE, (uint8_t*)firm))
+ abort("Failed to read NAND!\n");
+
+ fprintf(stderr, "Read FIRM%u off NAND.\n", index);
- // Common.
sdmmc_get_cid(1, (uint32_t*)cid);
- Sha256Data(cid, 0x10, sha);
- memcpy(ctr, sha, 0x10);
+ sha(sha_t, cid, 0x10, SHA_256_MODE);
+ memcpy(ctr, sha_t, 0x10);
+ aes_advctr(ctr, firm_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
- // FIRM0
- aes_advctr(ctr, firm0_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
aes_use_keyslot(0x06);
- aes_setiv(ctr, AES_INPUT_BE | AES_INPUT_NORMAL);
- aes((uint8_t*)firm0, (uint8_t*)firm0, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ aes_setiv(ctr, AES_INPUT_BE|AES_INPUT_NORMAL);
+ aes((uint8_t*)firm, (uint8_t*)firm, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
- // FIXME: First off, don't hardcode the section index. Second, the version.
- if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm0 + firm0->section[2].offset), firm0->section[2].size, 0x10)) {
- abort("Failed to decrypt FIRM0 arm9loader.\n");
- }
+ fprintf(stderr, "AES decrypted FIRM%u.\n", index);
- // We don't check magic on FIRM0 since it's like, you know, fucked up. Deliberately.
+ if (memcmp((char*) & firm->magic, "FIRM", 4))
+ abort("Decryption failed on FIRM.\n");
- // Common.
- sdmmc_get_cid(1, (uint32_t*)cid);
- Sha256Data(cid, 0x10, sha);
- memcpy(ctr, sha, 0x10);
+ fprintf(stderr, "Magic is intact on FIRM%u.\n", index);
- // FIRM1
- aes_advctr(ctr, firm1_offset / AES_BLOCK_SIZE, AES_INPUT_BE | AES_INPUT_NORMAL);
- aes_use_keyslot(0x06);
- aes_setiv(ctr, AES_INPUT_BE | AES_INPUT_NORMAL);
- aes((uint8_t*)firm1, (uint8_t*)firm1, firm_size / AES_BLOCK_SIZE, ctr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
+ uint8_t detver = 0;
- if (memcmp(& firm1->magic, "FIRM", 4)) {
- abort("FIRM1 magic is missing!\n");
- }
+ if(index == 1)
+ detver = 0x10;
- // FIXME: First off, don't hardcode the section index. Second, the version.
- if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm1 + firm1->section[2].offset), firm1->section[2].size, 0x10)) {
- abort("Failed to decrypt FIRM1 arm9loader.\n");
+ if(decrypt_arm9bin((arm9bin_h*)((uint8_t*)firm + firm->section[2].offset), NATIVE_FIRM_TITLEID, detver)) {
+ abort("\rFailed to decrypt FIRM%u arm9loader.\n", index);
}
- fprintf(stderr, "\rExtracted FIRM off NAND.\n");
- // FIXME - "\r": Workaround because decrypt_arm9bin wasn't intended to be used outside of normal FIRM decryption.
- // Causes output when we don't want that here.
+ fprintf(stderr, "\rDecrypted FIRM%u arm9loader.\n", index);
+}
+
+void
+slot0x11key96_init()
+{
+ // 9.6 crypto may need us to get the key from somewhere else.
+ // Unless the console already has the key initialized, that is.
+ uint8_t key[AES_BLOCK_SIZE];
+ if (read_file(key, PATH_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0 || read_file(key, PATH_ALT_SLOT0X11KEY96, AES_BLOCK_SIZE) != 0) {
+ // Read key successfully.
+ aes_setkey(0x11, key, AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
+
+ // Tell boot_firm it needs to regenerate the keys.
+ update_96_keys = 1;
+ }
}
uint8_t* key_search(uint8_t* mem, uint32_t size, uint8_t* sha256, uint8_t byte) {
uint8_t hash[0x20] = {0};
- // Search ARM9 for NAND key.
- for(; size > 0; size -= 4) {
+ // Search ARM9 for key.
+ for(uint32_t j = 0; j < size; j ++) {
// Is candidate?
- if (mem[size] == byte) {
+ if (mem[j] == byte) {
// Yes. Check hash.
- Sha256Data(&mem[size], 16, hash);
+ sha(hash, &mem[j], 0x10, SHA_256_MODE);
- if(memcmp(sha256, hash, 0x20))
- return &mem[size];
+ if(!memcmp(sha256, hash, 0x20)) {
+ return &mem[j];
+ }
}
}
}
void extract_slot0x05keyY() {
- if (firm0 == NULL || firm1 == NULL)
- extract_firms();
+ if (firm1 == NULL)
+ dump_firm(&firm1, 1);
uint8_t sha256[] = {0x98, 0x24, 0x27, 0x14, 0x22, 0xB0, 0x6B, 0xF2, 0x10, 0x96, 0x9C, 0x36, 0x42, 0x53, 0x7C, 0x86,
0x62, 0x22, 0x5C, 0xFD, 0x6F, 0xAE, 0x9B, 0x0A, 0x85, 0xA5, 0xCE, 0x21, 0xAA, 0xB6, 0xC8, 0x4D};
uint8_t* key_loc = (uint8_t*)firm1 + firm1->section[2].offset;
- uint32_t search_size = firm1->section[2].size - 16;
+ uint32_t search_size = firm1->section[2].size;
- uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xDD);
+ uint8_t mem[16] __attribute__((aligned(4))) = {0};
+
+ uint8_t* key_data = key_search(key_loc, search_size, sha256, 0x4D);
if (!key_data)
abort("0x05 KeyY not found!\n");
- fprintf(stderr, "0x05 KeyY at %x in FIRM1\n", (uint32_t)key_data - (uint32_t)key_loc);
+ fprintf(stderr, "0x05 KeyY at %lx in FIRM1\n", (uint32_t)key_data - (uint32_t)key_loc);
+
+ memcpy(mem, key_data, 16);
+ aes_setkey(0x05, mem, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
}
void extract_slot0x3DkeyY() {
- if (firm0 == NULL || firm1 == NULL)
- extract_firms();
+ if (firm0 == NULL)
+ dump_firm(&firm0, 0);
- uint8_t sha256[] = {0x0a, 0x1c, 0x7b, 0x55, 0x86, 0x05, 0x89, 0xb0, 0xed, 0xd8, 0x87, 0x4b, 0x50, 0x55, 0xe3, 0x47,
- 0x16, 0xa2, 0xcd, 0xe2, 0x5b, 0xad, 0x12, 0x48, 0xbb, 0xbb, 0xee, 0xd1, 0xb3, 0x40, 0xb1, 0xb8};
+ uint8_t sha256[] = {0x21, 0x12, 0xf4, 0x50, 0x78, 0x6d, 0xce, 0x64, 0x39, 0xfd, 0xb8, 0x71, 0x14, 0x74, 0x41, 0xf4,
+ 0x69, 0xb6, 0xc4, 0x70, 0xa4, 0xb1, 0x5f, 0x7d, 0xfd, 0xe8, 0xcc, 0xe4, 0xc4, 0x62, 0x82, 0x5b};
uint8_t* key_loc = (uint8_t*)firm0 + firm0->section[2].offset;
- uint32_t search_size = firm0->section[2].size - 16;
+ uint32_t search_size = firm0->section[2].size;
- uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xD0);
+ uint8_t mem[16] __attribute__((aligned(4))) = {0};
+
+ uint8_t* key_data = key_search(key_loc, search_size, sha256, 0x0C);
if (!key_data)
- abort("0x3D KeyY not found!\n");
+ abort("0x3D KeyY #1 not found!\n");
+
+ fprintf(stderr, "0x3D KeyY #1 at %lx in FIRM0\n", (uint32_t)key_data - (uint32_t)key_loc);
+
+ memcpy(mem, key_data, 16);
- fprintf(stderr, "0x3D KeyY at %x in FIRM0\n", (uint32_t)key_data - (uint32_t)key_loc);
+ aes_setkey(0x3D, mem, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
+}
+
+void* find_section_key() {
+ // The key will be dword-aligned (I think? Verify this. May need new NFIRM to check assumption. Go, Nintendo!)
+
+ // The hash of the key. Can't give the key itself out, obviously.
+ uint8_t sha256[] = {0xb9, 0x4d, 0xb1, 0xb1, 0xc3, 0xe0, 0x11, 0x08, 0x9c, 0x19, 0x46, 0x06, 0x4a, 0xbc, 0x40, 0x2a,
+ 0x7c, 0x66, 0xf4, 0x4a, 0x74, 0x6f, 0x71, 0x50, 0x32, 0xfd, 0xff, 0x03, 0x74, 0xd7, 0x45, 0x2c};
+ uint8_t* key_loc = (uint8_t*)firm_loc + firm_loc->section[2].offset;
+ uint32_t search_size = firm_loc->section[2].size;
+
+ uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xDD);
+
+ if (!key_data)
+ abort("FIRM Section key not found!\n");
+
+ fprintf(stderr, "FIRM Section key at %lx in FIRM\n", (uint32_t)key_data - (uint32_t)key_loc);
+
+ return key_data;
}
int
decrypt_cetk_key(void *key, const void *cetk)
{
- static int common_key_y_init = 0;
uint8_t iv[AES_BLOCK_SIZE] = { 0 };
uint32_t sigtype = __builtin_bswap32(*(uint32_t *)cetk);
if (ticket->ticketCommonKeyYIndex != 1)
return 1;
- if (!common_key_y_init) {
- uint8_t common_key_y[AES_BLOCK_SIZE] = { 0 };
- uint8_t *p9_base = (uint8_t *)0x08028000;
- uint8_t *i;
- for (i = p9_base + 0x70000 - AES_BLOCK_SIZE; i >= p9_base; i--) {
- if (i[0] == 0xD0 && i[4] == 0x9C && i[8] == 0x32 && i[12] == 0x23) {
- // At i, there's 7 keys with 4 bytes padding between them.
- // We only need the 2nd.
- memcpy(common_key_y, i + AES_BLOCK_SIZE + 4, sizeof(common_key_y));
- fprintf(stderr, "y");
- break;
- }
- }
-
- if (i < p9_base)
- return 1;
-
- aes_setkey(0x3D, common_key_y, AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
- common_key_y_init = 1;
- }
-
aes_use_keyslot(0x3D);
memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
{
uint8_t slot = 0x15;
- fprintf(BOTTOM_SCREEN, "9");
-
if (firm_title == NATIVE_FIRM_TITLEID && version > 0x0F) {
uint8_t decrypted_keyx[AES_BLOCK_SIZE];
if (firm_title == NATIVE_FIRM_TITLEID)
return *(uint32_t *)arm9bin != ARM9BIN_MAGIC;
+
else if (firm_title == AGB_FIRM_TITLEID || firm_title == TWL_FIRM_TITLEID)
return *(uint32_t *)arm9bin != LGY_ARM9BIN_MAGIC;
- else
- return 0;
+
+ return 1;
}
int
extern void wait();
-void* find_section_key() {
- // The key will be dword-aligned (I think? Verify this. May need new NFIRM to check assumption. Go, Nintendo!)
- uint8_t* key_loc = (uint8_t*)firm_loc + firm_loc->section[2].offset - 16;
- uint32_t search_size = firm_loc->section[2].size - 16;
-
- key_loc = (uint8_t*)((uint32_t)key_loc & 0xFFFFFFF8); // Align to 4bytes.
-
- // The hash of the key. Can't give the key itself out, obviously.
- uint32_t sha256boot[32] = {0xb9, 0x4d, 0xb1, 0xb1, 0xc3, 0xe0, 0x11, 0x08,
- 0x9c, 0x19, 0x46, 0x06, 0x4a, 0xbc, 0x40, 0x2a,
- 0x7c, 0x66, 0xf4, 0x4a, 0x74, 0x6f, 0x71, 0x50,
- 0x32, 0xfd, 0xff, 0x03, 0x74, 0xd7, 0x45, 0x2c};
- uint8_t sha256check[32] = {0};
-
- for(; search_size > 0; search_size -= 4) {
- // Is candidate?
- if (key_loc[search_size] == 0xDD) {
- // Yes. Check hash.
- Sha256Data(&key_loc[search_size], 16, sha256check);
- if(memcmp(sha256boot, sha256check, 32)) {
- fprintf(stderr, "Key at %x\n", (uint32_t)(&key_loc[search_size]) - (uint32_t)key_loc);
- return &key_loc[search_size];
- }
- }
- }
- return NULL;
-}
-
void
boot_firm()
{
struct mode
{
uint8_t *memory;
- size_t size;
+ uint32_t size;
};
struct mode modes[21];
int init_bytecode = 0;
memset(stack, 0, stack_size); // Clear stack.
- _UNUSED size_t top = stack_size - 1;
+ _UNUSED uint32_t top = stack_size - 1;
#ifdef LOADER
- size_t set_mode = 18;
+ uint32_t set_mode = 18;
#else
- size_t set_mode = 3;
+ uint32_t set_mode = 3;
#endif
struct mode *current_mode = &modes[set_mode];
- size_t offset = 0, new_offset = 0;
+ uint32_t offset = 0, new_offset = 0;
- size_t i;
+ uint32_t i;
int eq = 0, gt = 0, lt = 0, found = 0; // Flags.
#ifdef LOADER
log("rel\n");
#else
- fprintf(stderr, "rel %u\n", *(code+1));
+ fprintf(stderr, "rel %hhu\n", code[1]);
#endif
}
code++;
#ifdef LOADER
log("find\n");
#else
- fprintf(stderr, "find %u ...\n", code[1]);
+ fprintf(stderr, "find %hhu ...\n", code[1]);
#endif
}
found = 0;
#ifdef LOADER
log("back\n");
#else
- fprintf(stderr, "back %u\n", *(code+1));
+ fprintf(stderr, "back %hhu\n", code[1]);
#endif
}
offset -= code[1];
#ifdef LOADER
log("fwd\n");
#else
- fprintf(stderr, "fwd %u\n", *(code+1));
+ fprintf(stderr, "fwd %u\n", code[1]);
#endif
}
offset += code[1];
#ifdef LOADER
log("seek\n");
#else
- fprintf(stderr, "seek %u\n", offset);
+ fprintf(stderr, "seek %lu\n", offset);
#endif
}
code += 4;
#ifndef LOADER
// Panic; not proper opcode.
fprintf(stderr, "Invalid opcode. State:\n"
- " Relative: %u\n"
- " Actual: %x:%u\n"
- " Memory: %x\n"
- " Actual: %x\n"
- " Code Loc: %x\n"
- " Actual: %x\n"
- " Opcode: %u\n",
- set_mode, current_mode->memory, current_mode->size, offset, current_mode->memory + offset, code - bytecode, code, *code);
+ " Relative: %lu\n"
+ " Actual: %lx:%lu\n"
+ " Memory: %lx\n"
+ " Actual: %lx\n"
+ " Code Loc: %lx\n"
+ " Actual: %lx\n"
+ " Opcode: %hhu\n",
+ (uint32_t)set_mode,
+ (uint32_t)current_mode->memory,
+ (uint32_t)current_mode->size,
+ (uint32_t)offset,
+ (uint32_t)(current_mode->memory + offset),
+ (uint32_t)(code - bytecode),
+ (uint32_t)code,
+ *code);
#endif
abort("Halting startup.\n");
break;
if (offset > current_mode->size) { // Went out of bounds. Error.
#ifndef LOADER
- fprintf(stderr, " -> %x", offset);
+ fprintf(stderr, " -> %lx", offset);
#endif
abort("seeked out of bounds\n");
}
#ifndef LOADER
if (debug) {
- fprintf(stderr, "l:%u g:%u e:%u f:%u m:%u o:0x%x\nc:0x%x m:0x%x n:%x\n", lt, gt, eq, found, set_mode, offset, code - bytecode, current_mode->memory + offset, code);
+ fprintf(stderr, "l:%d g:%d e:%d f:%d m:%lu o:0x%lx\nc:0x%lx m:0x%lx n:%lx\n",
+ lt, gt, eq, found,
+ set_mode,
+ (uint32_t)offset, (uint32_t)(code - bytecode), (uint32_t)(current_mode->memory + offset), (uint32_t)code);
wait();
}
#endif
// File wasn't found. The user didn't enable anything.
return 0;
}
- size_t len = fsize(f);
+ uint32_t len = fsize(f);
fread((uint8_t *)FCRAM_PATCH_LOC, 1, len, f);
fclose(f);
load_config(); // Load configuration.
+ config.options[OPTION_SAVE_LOGS] = 1;
+
extract_slot0x05keyY();
extract_slot0x3DkeyY();
+++ /dev/null
-/* Crypto/Sha256.c -- SHA-256 Hash function
-2008-11-06 : Igor Pavlov : Public domain
-This code is based on public domain code from Wei Dai's Crypto++ library. */
-
-#include "sha256.h"
-
-#define rotlFixed(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-#define rotrFixed(x, n) (((x) >> (n)) | ((x) << (32 - (n))))
-
-
-/* define it for speed optimization */
-/* #define _SHA256_UNROLL */
-/* #define _SHA256_UNROLL2 */
-
-void Sha256_Init(CSha256 *p)
-{
- p->state[0] = 0x6a09e667;
- p->state[1] = 0xbb67ae85;
- p->state[2] = 0x3c6ef372;
- p->state[3] = 0xa54ff53a;
- p->state[4] = 0x510e527f;
- p->state[5] = 0x9b05688c;
- p->state[6] = 0x1f83d9ab;
- p->state[7] = 0x5be0cd19;
- p->count = 0;
-}
-
-#define S0(x) (rotrFixed(x, 2) ^ rotrFixed(x,13) ^ rotrFixed(x, 22))
-#define S1(x) (rotrFixed(x, 6) ^ rotrFixed(x,11) ^ rotrFixed(x, 25))
-#define s0(x) (rotrFixed(x, 7) ^ rotrFixed(x,18) ^ (x >> 3))
-#define s1(x) (rotrFixed(x,17) ^ rotrFixed(x,19) ^ (x >> 10))
-
-#define blk0(i) (W[i] = data[i])
-#define blk2(i) (W[i&15] += s1(W[(i-2)&15]) + W[(i-7)&15] + s0(W[(i-15)&15]))
-
-#define Ch(x,y,z) (z^(x&(y^z)))
-#define Maj(x,y,z) ((x&y)|(z&(x|y)))
-
-#define a(i) T[(0-(i))&7]
-#define b(i) T[(1-(i))&7]
-#define c(i) T[(2-(i))&7]
-#define d(i) T[(3-(i))&7]
-#define e(i) T[(4-(i))&7]
-#define f(i) T[(5-(i))&7]
-#define g(i) T[(6-(i))&7]
-#define h(i) T[(7-(i))&7]
-
-
-#ifdef _SHA256_UNROLL2
-
-#define R(a,b,c,d,e,f,g,h, i) h += S1(e) + Ch(e,f,g) + K[i+j] + (j?blk2(i):blk0(i));\
- d += h; h += S0(a) + Maj(a, b, c)
-
-#define RX_8(i) \
- R(a,b,c,d,e,f,g,h, i); \
- R(h,a,b,c,d,e,f,g, i+1); \
- R(g,h,a,b,c,d,e,f, i+2); \
- R(f,g,h,a,b,c,d,e, i+3); \
- R(e,f,g,h,a,b,c,d, i+4); \
- R(d,e,f,g,h,a,b,c, i+5); \
- R(c,d,e,f,g,h,a,b, i+6); \
- R(b,c,d,e,f,g,h,a, i+7)
-
-#else
-
-#define R(i) h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j?blk2(i):blk0(i));\
- d(i) += h(i); h(i) += S0(a(i)) + Maj(a(i), b(i), c(i))
-
-#ifdef _SHA256_UNROLL
-
-#define RX_8(i) R(i+0); R(i+1); R(i+2); R(i+3); R(i+4); R(i+5); R(i+6); R(i+7);
-
-#endif
-
-#endif
-
-const UInt32 K[64] = {
- 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
- 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
- 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
- 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
- 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
- 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
- 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
- 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
- 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
- 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
- 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
- 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
- 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
- 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
- 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
- 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
-};
-
-static void Sha256_Transform(UInt32 *state, const UInt32 *data)
-{
- UInt32 W[16];
- unsigned j;
- #ifdef _SHA256_UNROLL2
- UInt32 a,b,c,d,e,f,g,h;
- a = state[0];
- b = state[1];
- c = state[2];
- d = state[3];
- e = state[4];
- f = state[5];
- g = state[6];
- h = state[7];
- #else
- UInt32 T[8];
- for (j = 0; j < 8; j++)
- T[j] = state[j];
- #endif
-
- for (j = 0; j < 64; j += 16)
- {
- #if defined(_SHA256_UNROLL) || defined(_SHA256_UNROLL2)
- RX_8(0); RX_8(8);
- #else
- unsigned i;
- for (i = 0; i < 16; i++) { R(i); }
- #endif
- }
-
- #ifdef _SHA256_UNROLL2
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
- state[4] += e;
- state[5] += f;
- state[6] += g;
- state[7] += h;
- #else
- for (j = 0; j < 8; j++)
- state[j] += T[j];
- #endif
-
- /* Wipe variables */
- /* memset(W, 0, sizeof(W)); */
- /* memset(T, 0, sizeof(T)); */
-}
-
-#undef S0
-#undef S1
-#undef s0
-#undef s1
-
-static void Sha256_WriteByteBlock(CSha256 *p)
-{
- UInt32 data32[16];
- unsigned i;
- for (i = 0; i < 16; i++)
- data32[i] =
- ((UInt32)(p->buffer[i * 4 ]) << 24) +
- ((UInt32)(p->buffer[i * 4 + 1]) << 16) +
- ((UInt32)(p->buffer[i * 4 + 2]) << 8) +
- ((UInt32)(p->buffer[i * 4 + 3]));
- Sha256_Transform(p->state, data32);
-}
-
-void Sha256_Update(CSha256 *p, const Byte *data, size_t size)
-{
- UInt32 curBufferPos = (UInt32)p->count & 0x3F;
- while (size > 0)
- {
- p->buffer[curBufferPos++] = *data++;
- p->count++;
- size--;
- if (curBufferPos == 64)
- {
- curBufferPos = 0;
- Sha256_WriteByteBlock(p);
- }
- }
-}
-
-void Sha256_Final(CSha256 *p, Byte *digest)
-{
- UInt64 lenInBits = (p->count << 3);
- UInt32 curBufferPos = (UInt32)p->count & 0x3F;
- unsigned i;
- p->buffer[curBufferPos++] = 0x80;
- while (curBufferPos != (64 - 8))
- {
- curBufferPos &= 0x3F;
- if (curBufferPos == 0)
- Sha256_WriteByteBlock(p);
- p->buffer[curBufferPos++] = 0;
- }
- for (i = 0; i < 8; i++)
- {
- p->buffer[curBufferPos++] = (Byte)(lenInBits >> 56);
- lenInBits <<= 8;
- }
- Sha256_WriteByteBlock(p);
-
- for (i = 0; i < 8; i++)
- {
- *digest++ = (Byte)((p->state[i] >> 24) & 0xFF);
- *digest++ = (Byte)((p->state[i] >> 16) & 0xFF);
- *digest++ = (Byte)((p->state[i] >> 8) & 0xFF);
- *digest++ = (Byte)((p->state[i]) & 0xFF);
- }
- Sha256_Init(p);
-}
-
-unsigned char *Sha256Data (const unsigned char *data, unsigned int len, unsigned char *buf) {
- CSha256 ctx;
-
- Sha256_Init(&ctx);
- Sha256_Update(&ctx,data,len);
- Sha256_Final(&ctx, buf);
-
- return buf;
-}
+++ /dev/null
-/* Crypto/Sha256.h -- SHA-256 Hash function
-2008-10-04 : Igor Pavlov : Public domain */
-
-#ifndef __CRYPTO_SHA256_H
-#define __CRYPTO_SHA256_H
-
-#include <stdint.h>
-#include <stddef.h>
-
-/* Types.h -- Basic types
-2008-11-23 : Igor Pavlov : Public domain */
-
-#define SZ_OK 0
-#define SZ_ERROR_DATA 1
-#define SZ_ERROR_MEM 2
-#define SZ_ERROR_CRC 3
-#define SZ_ERROR_UNSUPPORTED 4
-#define SZ_ERROR_PARAM 5
-#define SZ_ERROR_INPUT_EOF 6
-#define SZ_ERROR_OUTPUT_EOF 7
-#define SZ_ERROR_READ 8
-#define SZ_ERROR_WRITE 9
-#define SZ_ERROR_PROGRESS 10
-#define SZ_ERROR_FAIL 11
-#define SZ_ERROR_THREAD 12
-
-#define SZ_ERROR_ARCHIVE 16
-#define SZ_ERROR_NO_ARCHIVE 17
-
-typedef int SRes;
-
-typedef int WRes;
-
-#ifndef RINOK
-#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
-#endif
-
-typedef unsigned char Byte;
-typedef short Int16;
-typedef unsigned short UInt16;
-
-#ifdef _LZMA_UINT32_IS_ULONG
-typedef long Int32;
-typedef unsigned long UInt32;
-#else
-typedef int Int32;
-typedef unsigned int UInt32;
-#endif
-
-#ifdef _SZ_NO_INT_64
-
-/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
- NOTES: Some code will work incorrectly in that case! */
-
-typedef long Int64;
-typedef unsigned long UInt64;
-
-#else
-
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
-
-#endif
-
-#ifdef _LZMA_NO_SYSTEM_SIZE_T
-typedef UInt32 SizeT;
-#else
-typedef size_t SizeT;
-#endif
-
-typedef int Bool;
-#define True 1
-#define False 0
-
-
-#define MY_CDECL
-#define MY_STD_CALL
-#define MY_FAST_CALL
-
-/* The following interfaces use first parameter as pointer to structure */
-
-typedef struct
-{
- SRes (*Read)(void *p, void *buf, size_t *size);
- /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
- (output(*size) < input(*size)) is allowed */
-} ISeqInStream;
-
-/* it can return SZ_ERROR_INPUT_EOF */
-SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
-SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
-SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
-
-typedef struct
-{
- size_t (*Write)(void *p, const void *buf, size_t size);
- /* Returns: result - the number of actually written bytes.
- (result < size) means error */
-} ISeqOutStream;
-
-typedef enum
-{
- SZ_SEEK_SET = 0,
- SZ_SEEK_CUR = 1,
- SZ_SEEK_END = 2
-} ESzSeek;
-
-typedef struct
-{
- SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
- SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} ISeekInStream;
-
-typedef struct
-{
- SRes (*Look)(void *p, void **buf, size_t *size);
- /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
- (output(*size) > input(*size)) is not allowed
- (output(*size) < input(*size)) is allowed */
- SRes (*Skip)(void *p, size_t offset);
- /* offset must be <= output(*size) of Look */
-
- SRes (*Read)(void *p, void *buf, size_t *size);
- /* reads directly (without buffer). It's same as ISeqInStream::Read */
- SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
-} ILookInStream;
-
-SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
-SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
-
-/* reads via ILookInStream::Read */
-SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
-SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
-
-#define LookToRead_BUF_SIZE (1 << 14)
-
-typedef struct
-{
- ILookInStream s;
- ISeekInStream *realStream;
- size_t pos;
- size_t size;
- Byte buf[LookToRead_BUF_SIZE];
-} CLookToRead;
-
-void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
-void LookToRead_Init(CLookToRead *p);
-
-typedef struct
-{
- ISeqInStream s;
- ILookInStream *realStream;
-} CSecToLook;
-
-void SecToLook_CreateVTable(CSecToLook *p);
-
-typedef struct
-{
- ISeqInStream s;
- ILookInStream *realStream;
-} CSecToRead;
-
-void SecToRead_CreateVTable(CSecToRead *p);
-
-typedef struct
-{
- SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
- /* Returns: result. (result != SZ_OK) means break.
- Value (UInt64)(Int64)-1 for size means unknown value. */
-} ICompressProgress;
-
-typedef struct
-{
- void *(*Alloc)(void *p, size_t size);
- void (*Free)(void *p, void *address); /* address can be 0 */
-} ISzAlloc;
-
-#define SHA256_DIGEST_SIZE 32
-
-typedef struct
-{
- UInt32 state[8];
- UInt64 count;
- Byte buffer[64];
-} CSha256;
-
-void Sha256_Init(CSha256 *p);
-void Sha256_Update(CSha256 *p, const Byte *data, size_t size);
-void Sha256_Final(CSha256 *p, Byte *digest);
-unsigned char *Sha256Data (const unsigned char *data, unsigned int len, unsigned char *buf);
-
-#endif
*off = offset + 1;
*head = offset + 1;
- fprintf(stderr, "emunand: found NCSD magic for %u\n", index);
+ fprintf(stderr, "emunand: found NCSD magic for %lu\n", index);
fprintf(stderr, "emunand: layout is normal\n");
}
// Check for GW EmuNAND on SD
*off = offset;
*head = offset + nandSize;
- fprintf(stderr, "emunand: found NCSD magic for %u\n", index);
+ fprintf(stderr, "emunand: found NCSD magic for %lu\n", index);
fprintf(stderr, "emunand: layout is gateway\n");
} else {
abort("emunand: selected NAND image is not valid.\n");
uint8_t *ret = memfind(pos + 0x13500, size - 0x13500, pattern, 6) + 0x455;
if (ret) {
- fprintf(stderr, "emunand: free space @ %x\n", ret);
- fprintf(stderr, "emunand: size is %u bytes\n", (uint8_t *)ret - pos);
+ fprintf(stderr, "emunand: free space @ %lx\n", (uint32_t)ret);
+ fprintf(stderr, "emunand: size is %lu bytes\n", (uint32_t) (ret - pos));
}
return ret;
uint32_t ret = *(uint32_t *)(off + 9) + *(uint32_t *)(off + 0xD);
- fprintf(stderr, "emunand: SDMMC code @ %x\n", ret);
+ fprintf(stderr, "emunand: SDMMC code @ %lx\n", ret);
return ret;
}
writeOffset[1] = nandRedir[1];
((uint32_t *)writeOffset)[1] = branchOffset;
- fprintf(stderr, "emunand: write @ %x\n", writeOffset);
- fprintf(stderr, "emunand: read @ %x\n", readOffset);
+ fprintf(stderr, "emunand: write @ %lx\n", (uint32_t)writeOffset);
+ fprintf(stderr, "emunand: read @ %lx\n", (uint32_t)readOffset);
}
static void
off[6] = mpuPatch[1];
off[9] = mpuPatch[2];
- fprintf(stderr, "emunand: mpu @ %x\n", off);
+ fprintf(stderr, "emunand: mpu @ %lx\n", (uint32_t)off);
}
void
verify_emunand(index, pos_offset, pos_head);
- fprintf(stderr, "emunand: nand is on sector %u\n", *pos_offset);
- fprintf(stderr, "emunand: head is on sector %u\n", *pos_head);
+ fprintf(stderr, "emunand: nand is on sector %lu\n", *pos_offset);
+ fprintf(stderr, "emunand: head is on sector %lu\n", *pos_head);
// Add emuNAND hooks
patchNANDRW(process9Offset, process9Size, branchOffset);
}
}
- fprintf(stderr, "module: Grow %d units\n", need_units);
+ fprintf(stderr, "module: Grow %lu units\n", need_units);
}
// Move the remaining modules closer
else if (module->contentSize < sysmodule->contentSize) {
// NOTE - This doesn't change the sysmodule section size; it isn't needed to do so.
- fprintf(stderr, "Module: Shrink %d units\n", sysmodule->contentSize - module->contentSize);
+ fprintf(stderr, "Module: Shrink %lu units\n", sysmodule->contentSize - module->contentSize);
int remaining_size =
sysmodule_section->size - (((uint32_t)sysmodule + sysmodule->contentSize * 0x200) - ((uint32_t)firm_loc + sysmodule_section->offset));
// Sysmodule section size - (End location of this sysmodule -
// Move end of section to be adjacent
}
- fprintf(stderr, "Module: Injecting %llu\n", module->programID);
+ fprintf(stderr, "Module: Injecting module\n");
// Copy the module into the firm
memcpy(sysmodule, module, module->contentSize * 0x200);
}
uint8_t *process9Offset =
getProcess9((uint8_t *)firm_loc + firm_loc->section[2].offset + 0x15000, firm_loc->section[2].size - 0x15000, &process9Size, &process9MemAddr);
- fprintf(stderr, "reboot: proc9 mem @ %x\n", process9MemAddr);
+ fprintf(stderr, "reboot: proc9 mem @ %lx\n", (uint32_t)process9MemAddr);
wait();
uint8_t *off = memfind(process9Offset, process9Size, pattern, 4) - 0x10;
- fprintf(stderr, "reboot: firmlaunch @ %x\n", off);
+ fprintf(stderr, "reboot: firmlaunch @ %lx\n", (uint32_t)off);
// Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
uint32_t fOpenOffset = (uint32_t)(off + 9 - (-((*(uint32_t *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - process9Offset + process9MemAddr);
- fprintf(stderr, "reboot: fopen @ %x\n", fOpenOffset);
+ fprintf(stderr, "reboot: fopen @ %lx\n", fOpenOffset);
wait();
if (!pos_native && !pos_twl && !pos_agb)
abort("reboot: missing string placeholder?\n");
- fprintf(stderr, "reboot: NATF @ %x\n", pos_native);
- fprintf(stderr, "reboot: TWLF @ %x\n", pos_twl);
- fprintf(stderr, "reboot: AGBF @ %x\n", pos_agb);
+ fprintf(stderr, "reboot: NATF @ %lx\n", (uint32_t)pos_native);
+ fprintf(stderr, "reboot: TWLF @ %lx\n", (uint32_t)pos_twl);
+ fprintf(stderr, "reboot: AGBF @ %lx\n", (uint32_t)pos_agb);
uint8_t *mem = (uint8_t *)0x01FF8000; // 0x8000 space that will be resident. This is AXI WRAM. We have about 0x3700 bytes here.
// According to 3dbrew, this space's props from userland:
uint32_t *pos_rebc = (uint32_t *)memfind(off, size, "rebc", 4);
*pos_rebc = (uint32_t)mem;
- fprintf(stderr, "reboot: rebc @ %x\n", pos_rebc);
+ fprintf(stderr, "reboot: rebc @ %lx\n", (uint32_t)pos_rebc);
f = fopen(PATH_REBOOT_CODE, "r");
if (!f)
FILE *data = fopen(PATH_BACKDOOR, "r");
uint32_t size = fsize(data);
- fprintf(stderr, "Svc: backdoor is %d bytes\n", size);
- fprintf(stderr, "Svc: Read code to %x\n", (uint32_t)svc_tab_open);
+ fprintf(stderr, "Svc: backdoor is %lu bytes\n", size);
+ fprintf(stderr, "Svc: Read code to %lx\n", (uint32_t)svc_tab_open);
fread(svc_tab_open, 1, size, data);
#ifndef __ABORT_H
#define __ABORT_H
-void abort(const char* x, ...);
+void abort(const char* x, ...) __attribute__ ((format (printf, 1, 2)));
#endif
// Formats are also supported (but are subject to replacement)
// %p - unsigned char, changes color of text (will be replaced with ANSI codes
// eventually)
-void fprintf(void *channel, const char *format, ...);
+void fprintf(void *channel, const char *format, ...) __attribute__ ((format (printf, 2, 3)));
void vfprintf(void *channel, const char *format, va_list ap);