]> Chaos Git - corbenik/corbenik.git/commitdiff
Firmlaunch code is now working.
authorchaoskagami <chaos.kagami@gmail.com>
Mon, 5 Sep 2016 14:06:55 +0000 (10:06 -0400)
committerchaoskagami <chaos.kagami@gmail.com>
Mon, 5 Sep 2016 14:06:55 +0000 (10:06 -0400)
It's also fairly modularized and standalone now, so feel free to reuse it -
it doesn't depend on corbenik's other code.

36 files changed:
Makefile.am
common.mk
host/Makefile
host/generate_keys.sh [deleted file]
host/key_char.c [deleted file]
include/firm/firm.h
include/firm/headers.h
include/firm/internal.h [new file with mode: 0644]
include/std/abort.h
include/std/memory.h
source/chainloader.c
source/firm/decryptor.c
source/firm/firm.c
source/firm/firmlaunch.c
source/firm/keys.c
source/firm/keys/Y05.gen [deleted file]
source/firm/keys/Y11_95.gen [deleted file]
source/firm/keys/Y11_96.gen [deleted file]
source/firm/keys/Y3D_0.gen [deleted file]
source/firm/keys/Y3D_1.gen [deleted file]
source/firm/keys/Y3D_2.gen [deleted file]
source/firm/keys/Y3D_3.gen [deleted file]
source/firm/keys/Y3D_4.gen [deleted file]
source/firm/keys/Y3D_5.gen [deleted file]
source/firm/util.c
source/firm/version.c
source/interpreter.c
source/interrupt.c
source/main.c
source/patch/emunand.c
source/patch/reboot.c
source/patcher.c
source/std/abort.c
source/std/allocator.c
source/std/draw.c
source/std/memory.c

index d7f4b632bf642c82ed188bef68ffad081fe70f14..3e9fef340e92c51fc6985c2c73178f71fe364dc7 100644 (file)
@@ -31,18 +31,18 @@ all-local:
        chmod +x out/generate_localeemu.sh
        echo "#!/bin/bash" > out/o3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000002/00000052 -O .@libdir@/firmware/native"       >> out/o3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000002/cetk     -O .@datarootdir@/keys/native.cetk" >> out/o3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000002/cetk     -O .@libdir@/firmware/native.cetk" >> out/o3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000102/00000016 -O .@libdir@/firmware/twl"       >> out/o3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000102/cetk     -O .@datarootdir@/keys/twl.cetk" >> out/o3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000102/cetk     -O .@libdir@/firmware/twl.cetk" >> out/o3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000202/0000000B -O .@libdir@/firmware/agb"       >> out/o3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000202/cetk     -O .@datarootdir@/keys/agb.cetk" >> out/o3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013800000202/cetk     -O .@libdir@/firmware/agb.cetk" >> out/o3ds_firm.sh
        echo "#!/bin/bash" > out/n3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000002/00000021 -O .@libdir@/firmware/native"       >> out/n3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000002/cetk     -O .@datarootdir@/keys/native.cetk" >> out/n3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000002/cetk     -O .@libdir@/firmware/native.cetk" >> out/n3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000102/00000000 -O .@libdir@/firmware/twl"       >> out/n3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000102/cetk     -O .@datarootdir@/keys/twl.cetk" >> out/n3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000102/cetk     -O .@libdir@/firmware/twl.cetk" >> out/n3ds_firm.sh
        echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000202/00000000 -O .@libdir@/firmware/agb"       >> out/n3ds_firm.sh
-       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000202/cetk     -O .@datarootdir@/keys/agb.cetk" >> out/n3ds_firm.sh
+       echo "wget http://nus.cdn.c.shop.nintendowifi.net/ccs/download/0004013820000202/cetk     -O .@libdir@/firmware/agb.cetk" >> out/n3ds_firm.sh
        chmod 755 out/*.sh
        cp README.md LICENSE.txt out/
 
index 912ed0579599a9ab3b0cac1632c1b63b70bd0c39..538fabc61c0cfa322b90ef1c4de006d28ae9af81 100644 (file)
--- a/common.mk
+++ b/common.mk
@@ -16,8 +16,9 @@ AM_CFLAGS= -std=gnu11 -Os -g -ffast-math \
        -fno-builtin -std=gnu11 -DREVISION=\"$(REVISION)\" \
        -DFW_NAME=\"corbenik\" $(PATHARGS) -DMALLOC_DEBUG=1
 
+# -fsanitize=undefined
 
-AM_LDFLAGS=-Wl,--use-blx,--pic-veneer,-q -nostdlib -nodefaultlibs -Wl,-z,defs -lgcc \
-       -lc -L$(top_srcdir)/external/libctr9/src
+AM_LDFLAGS=-Wl,--use-blx,--pic-veneer,-q -Wl,-z,defs \
+       -L$(top_srcdir)/external/libctr9/src
 
 OCFLAGS=--set-section-flags .bss=alloc,load,contents
index 8cdd2e3f979c87bcf655eeba356080276950ca70..9835ece2ce3f61311ff7f0dc2dabd17d71a8afbf 100644 (file)
@@ -1,7 +1,6 @@
 all: bdfe font misc
 
 misc:
-       gcc -o key_char key_char.c -lcrypto -g -O0
        gcc -o error_decoder error_decoder.c -g -O0
 
 bdfe_dir:
diff --git a/host/generate_keys.sh b/host/generate_keys.sh
deleted file mode 100755 (executable)
index 1c7ba5d..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/bin/bash
-
-# Okay, so obviously this file would be non-redistributable if I put the keys here.
-# You'll need to get them yourself (in plaintext) and put them in the correct place.
-
-# Optionally, you can call this file with an option
-# and the output binary will contain the keys. DO NOT do this unless you know
-# you will NOT share the binaries; the resultant output is NOT MY PROBLEM, and
-# logs will be marked as "Tainted key loading used". If I have any reason to believe
-# you have enabled this option, NO SUPPORT will be provided unless you go and use
-# a build with that off.
-
-if [ "$1" == "--tainted-no-support" ]; then
-       WELP_USER_IS_A_WEIRDO_BUT_WHATEVER="$1"
-fi
-
-function key() {
-    if [ -e "keys/$1.txt" ]; then
-               echo "Generating key metadata..."
-           mkdir -p ../source/firm/keys
-               ./key_char $WELP_USER_IS_A_WEIRDO_BUT_WHATEVER $(cat keys/$1.txt | tr -d '\n') > ../source/firm/keys/$1.gen
-       else
-               echo "Key not found, generating stub..."
-        echo -n "{}" > ../source/firm/keys/$1.gen
-       fi
-
-    echo "$2" >> ../source/firm/keys/$1.gen
-}
-
-key Y11_95 ","
-key Y11_96 ""
-
-key Y05 ""
-
-key Y3D_0 ","
-key Y3D_1 ","
-key Y3D_2 ","
-key Y3D_3 ","
-key Y3D_4 ","
-key Y3D_5 ""
diff --git a/host/key_char.c b/host/key_char.c
deleted file mode 100644 (file)
index 88e2fda..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <openssl/sha.h>
-
-static const char  digits[] = "0123456789abcdef";
-static char ascii_to_digit[256] = {0};
-
-#define HASH_LEN 32 // Sha256
-void hexdump(uint8_t* text, uint8_t* bin, int bin_len)
-{
-    for(int i=0; i < bin_len; text += 2, bin++, i++) {
-        text[0]   = digits[(bin[0] >> 4) & 0xf];
-        text[1]   = digits[bin[0] & 0xf];
-       }
-}
-
-void unhexdump(uint8_t* bin, uint8_t* str, int bin_len)
-{
-    for(int i=0; i < bin_len; bin++, str += 2, i++) {
-        bin[0] = (ascii_to_digit[str[0]] << 4) | ascii_to_digit[str[1]];
-       }
-}
-
-uint8_t* sha256(uint8_t* data, uint32_t len) {
-    uint8_t *hash = malloc(SHA256_DIGEST_LENGTH);
-
-    SHA256_CTX sha256;
-
-    SHA256_Init(&sha256);
-    SHA256_Update(&sha256, data, len);
-    SHA256_Final(hash, &sha256);
-
-    return hash;
-}
-
-void init() {
-    ascii_to_digit['0'] = 0;
-    ascii_to_digit['1'] = 1;
-    ascii_to_digit['2'] = 2;
-    ascii_to_digit['3'] = 3;
-    ascii_to_digit['4'] = 4;
-    ascii_to_digit['5'] = 5;
-    ascii_to_digit['6'] = 6;
-    ascii_to_digit['7'] = 7;
-    ascii_to_digit['8'] = 8;
-    ascii_to_digit['9'] = 9;
-
-    ascii_to_digit['A'] = 0xa;
-    ascii_to_digit['B'] = 0xb;
-    ascii_to_digit['C'] = 0xc;
-    ascii_to_digit['D'] = 0xd;
-    ascii_to_digit['E'] = 0xe;
-    ascii_to_digit['F'] = 0xf;
-
-    ascii_to_digit['a'] = 0xa;
-    ascii_to_digit['b'] = 0xb;
-    ascii_to_digit['c'] = 0xc;
-    ascii_to_digit['d'] = 0xd;
-    ascii_to_digit['e'] = 0xe;
-    ascii_to_digit['f'] = 0xf;
-}
-
-uint16_t get_roll(uint8_t* data) {
-    uint16_t roll = 0;
-    for (int i=0; i < 16; i++) {
-        roll += data[i];
-    }
-
-    return roll;
-}
-
-int main(int c, char **v) {
-    uint8_t data[16];
-    char textsha[65] = {0};
-
-    if (c < 2) {
-        printf("Usage: %s <key>\n", v[0]);
-        return 1;
-    }
-
-    init();
-
-    unhexdump(data, v[1], 16);
-
-    uint16_t roll = get_roll(data);
-
-    uint8_t* sha = sha256(data, 16);
-
-       printf("{.roll = 0x%03X, .sha = {", v[1], roll);
-
-    for (int i=0; i < 32; i++) {
-        printf("0x%02X", sha[i]);
-        if (i != 31)
-            printf(", ");
-    }
-    printf("} }");
-
-    free(sha);
-
-    return 0;
-}
index 5a40af607d03b8782e053f0b7d6e21180c626921..93023f30369d9715ac8ef0467ad0597c8eef8286 100644 (file)
@@ -31,13 +31,9 @@ struct firm_signature
  */
 struct firm_signature *get_firm_info(firm_h *firm);
 
-/* Boots native FIRM - do not call directly.
+/* Boots the CFW, generating caches and applying patches as-needed to the specified FIRM
  */
-void boot_firm();
-
-/* Boots the CFW, generating caches and applying patches as-needed
- */
-void boot_cfw();
+int boot_cfw(char *firm_path);
 
 /* Loads a firmware off disk, returning it. The memory should be free()'d when done, unless you plan to boot.
  */
index 09fba3c590d105463646e45d57446886f2ae722a..887d83ec1e153aa48e10e07424e448d1bb2d4e7e 100644 (file)
@@ -28,8 +28,7 @@ typedef struct firm_section_h
 
 typedef struct firm_h
 {
-    uint32_t magic; // FIRM
-    uint32_t reserved1;
+    char magic[8];     // "FIRM" normally, but D9 has this as "DECFIRM"
     uint32_t a11Entry; // ARM11 entry
     uint32_t a9Entry;  // ARM9 entry
     uint8_t reserved2[0x30];
@@ -185,7 +184,7 @@ typedef struct arm9bin_h
     char size[8];
     uint8_t pad[8];
     uint8_t ctl_block[0x10];
-    uint8_t unk[0x10];
+    uint8_t unk[0x10]; // 3dbrew: Added with 9.5.0-X. Only used for hardware debugging: a nop instruction is executed with r0=0 and r1=<address of this data>.
     uint8_t slot0x16keyX[0x10];
 } arm9bin_h;
 
diff --git a/include/firm/internal.h b/include/firm/internal.h
new file mode 100644 (file)
index 0000000..a9b567b
--- /dev/null
@@ -0,0 +1,39 @@
+#ifdef FIRM_INTERNAL_CODE
+
+#ifndef __FIRM_INTENAL
+#define __FIRM_INTERNAL
+
+#define SECTOR_SIZE 0x200
+
+#define ROLL_WINDOW    AES_BLOCK_SIZE
+#define MODULO_WINDOW  (ROLL_WINDOW / 2)
+
+typedef void (*void_call)();
+
+void     firmlaunch(firm_h* firm);
+uint8_t* slice_roll_search(uint8_t *mem, uint32_t size, key_find_t* find);
+
+int set_Y3D_cetk(uint32_t commonKeyIndex);
+int set_N11_K9L(uint32_t index);
+
+int      decrypt_k9l(arm9bin_h *header, enum firm_type type, uint32_t k9l);
+
+int      patch_entry(firm_h *firm, enum firm_type type);
+
+void*    find_section_key(firm_h *firm_loc);
+int      patch_section_keys(firm_h* firm_loc, uint32_t k9l);
+
+int      dec_k9l(firm_h* firm);
+
+uint8_t* get_titlekey(char *cetk_filename);
+
+//int      decrypt_ncch(ncch_h *ncch, uint8_t* titlekey, size_t size);
+//exefs_h *get_exefs(ncch_h *ncch);
+//int      decrypt_exefs(ncch_h *ncch);
+
+firm_h  *extract_firm_from_ncch(ncch_h *ncch, uint8_t* titlekey, size_t size);
+
+#endif
+#else
+  #error "Do not include internal headers directly."
+#endif
index 04b0d580b0c6ca7cf992ad58046440e0f630a5a8..ad55a3f7d9bec30e454ef8f2e59cd4f65cc8a3a8 100644 (file)
@@ -10,6 +10,6 @@
  * \param ... Format operands, see printf manpage
  */
 
-void abort(const char* x, ...) __attribute__ ((format (printf, 1, 2)));
+void panic(const char* x, ...) __attribute__ ((format (printf, 1, 2)));
 
 #endif
index 0a14425ed17c2ffae52754350bf9937647032005..464b847cae7e7f81bb0f4569b8e9e38a8b252c8a 100644 (file)
@@ -19,4 +19,6 @@ uint8_t *memfind(uint8_t *startPos, uint32_t size, const void *pattern, uint32_t
  */
 char* strdup_self(const char* str);
 
+char* strdupcat(const char* str, const char *cat);
+
 #endif
index 754d5b2863e269106e0af0a7120e117be0e5bd73..6a0323ed9951449d5c6fadc0fe32c3e14c98f457 100644 (file)
@@ -28,7 +28,7 @@ void chainload_file(void* data)
     FILE* f = fopen(code_file, "r");
     if (!f) {
         // File missing.
-        abort("Missing chainloader.\n");
+        panic("Missing chainloader.\n");
     }
 
     b_size = fsize(f);
@@ -40,7 +40,7 @@ void chainload_file(void* data)
     f = fopen(chain_file, "r");
     if (!f) {
         // File missing.
-        abort("Missing program to chainload?\n");
+        panic("Missing program to chainload?\n");
     }
 
     size = fsize(f);
index aaab3a858f585153fa2155c7678a81d1e488a3ba..871dd484650e2fd12aac040409123ace5fb4f21d 100644 (file)
@@ -2,6 +2,9 @@
 #include <ctr9/aes.h>
 #include <ctr9/sha.h>
 
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
+
 void
 ncch_getctr(const ncch_h *ncch, uint8_t *ctr, uint8_t type)
 {
index f98e061587571cb4ec86c46413bd3bc808cd8a21..8b01b10519343c8a30f04385c039a1ab75d7d30b 100644 (file)
 #include <ctr9/sha.h>
 #include <common.h>
 
-__attribute__ ((noreturn))
-void
-boot_firm(firm_h* firm)
-{
-    abort("Temporarily not implemented\n");
-    while(1);
-}
-
-int firm_loaded = 0;
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
 
 firm_h*
 load_firm(const char *path)
 {
-    return NULL;
+    int success = 0;
+
+    FILE *firm_file = fopen(path, "r");
+    if (!firm_file) {
+        return NULL;
+    }
+
+    size_t size = fsize(firm_file);
+
+    uint8_t* mem = malloc(size);
+
+    firm_h *firm = (firm_h*)mem;
+
+    fread(mem, 1, size, firm_file);
+
+    fclose(firm_file);
+
+    if (!memcmp(firm->magic, "DECFIRM", 7)) {
+        // Fully decrypted FIRM, courtesy D9. Fix the entrypoint and we're good.
+        firm = (firm_h*)mem;
+
+        struct firm_signature* sig = get_firm_info(firm);
+
+        patch_entry(firm, sig->type);
+        if (patch_section_keys(firm, sig->k9l)) {
+            free(mem);
+            return NULL;
+        }
+
+        free(sig);
+    } else if (!memcmp(firm->magic, "FIRM", 4)) {
+        // O3DS fully decrypted FIRM
+
+        firm = (firm_h*)mem;
+    } else {
+        // Encrypted.
+        char *cetk_path = strdupcat(path, ".cetk");
+
+        uint8_t* firmkey = get_titlekey(cetk_path);
+
+        free(cetk_path);
+
+        if (firmkey) {
+            firm = extract_firm_from_ncch((ncch_h*)mem, firmkey, size);
+
+            if (firm) {
+                struct firm_signature* sig = get_firm_info(firm);
+
+                if (sig->console == console_n3ds) {
+                    if(dec_k9l(firm)) {
+                        panic("K9L?");
+                        free(firm);
+                        free(mem);
+                        return NULL;
+                    }
+
+                    patch_entry(firm, sig->type);
+
+                    if (patch_section_keys(firm, sig->k9l)) {
+                        panic("Section keys?");
+                        free(firm);
+                        free(mem);
+                        return NULL;
+                    }
+                }
+
+                free(sig);
+            }
+        }
+        free(mem);
+    }
+
+    return firm;
 }
 
 
-void
+int
 boot_cfw(char* firm_path)
 {
     firm_h* firm = load_firm(firm_path);
 
-    fprintf(stderr, "Patching firmware...\n");
-    if (patch_firm_all(firm) != 0)
-        return;
+    if (firm == NULL)
+        panic("Invalid FIRM?");
+
+//    if (patch_firm_all(firm) != 0)
+//        return 1;
+
+    firmlaunch(firm);
 
-    boot_firm(firm);
+    return 0;
 }
index a0acdcff00a77046c5eb36ab0ff2d1c35a20eacc..62a22f67762696cfa859e2b62e9db0101b99c660 100644 (file)
@@ -2,7 +2,8 @@
 #include <ctr9/aes.h>
 #include <ctr9/sha.h>
 
-typedef void (*void_call)();
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
 
 static volatile uint32_t *const a11_entry = (volatile uint32_t *)0x1FFFFFF8;
 
index e7a441ff7955ffbcd35966deb8bc319cff616093..7894c64e81219a4f9c014ab2b0861e5d0862af93 100644 (file)
 #include <ctr9/aes.h>
 #include <ctr9/sha.h>
 
-key_find_t Y11_sec;
-key_find_t X11_sec;
-
-key_find_t Y11[] = {
-    #include "keys/Y11_95.gen"
-    #include "keys/Y11_96.gen"
-};
-
-key_find_t Y3D[] = {
-    #include "keys/Y3D_0.gen"
-    #include "keys/Y3D_1.gen"
-    #include "keys/Y3D_2.gen"
-    #include "keys/Y3D_3.gen"
-    #include "keys/Y3D_4.gen"
-    #include "keys/Y3D_5.gen"
-};
-
-key_find_t Y05 =
-#include "keys/Y05.gen"
-;
-
-#define ROLL_WINDOW    AES_BLOCK_SIZE
-#define MODULO_WINDOW  (ROLL_WINDOW / 2)
-uint8_t* slice_roll_search(uint8_t *mem, uint32_t size, key_find_t* find) {
-    uint16_t roll = 0;
-    uint32_t i = 0;
-    uint8_t hash[32];
-
-    // Initial window.
-    for(; i < ROLL_WINDOW; i++) {
-        roll += mem[i];
-    }
-
-    // Loop through, moving the window.
-    for(i = ROLL_WINDOW; i < size; i++) {
-        if (find->roll == roll) {
-            // Yes. Check hash.
-            sha256sum(hash, &mem[i], 0x10);
-
-            if(!memcmp(find->sha, hash, 0x20)) {
-                return & mem[i];
-            }
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
+
+int set_N11_K9L(uint32_t index) {
+       static uint8_t ss_keyn[2][16] = {
+        { 0 }, // 9.5
+        { 0 }, // 9.6+
+    };
+
+    if (ss_keyn[0][0] == 0) {
+        ss_keyn[0][0] = 1;
+        FILE* key = fopen(PATH_SLOT0X11KEY95, "r");
+        if (key) {
+            fread(ss_keyn[0], 1, AES_BLOCK_SIZE, key);
+            fclose(key);
         }
-
-        roll -= mem[i-16];
-        roll += mem[i];
-    }
-    return NULL;
-}
-
-int get_Y11_sec() {
-    // FIXME; this only handles the case of K9LH. Needs more sanity checks.
-
-    uint8_t hash[32];
-
-    // We know better here than GCC.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic warning "-Wdiscarded-qualifiers"
-    memcpy(hash, (volatile void*)REG_SHAHASH, 32);
-#pragma GCC diagnostic pop
-
-    memcpy(X11_sec.key, hash, 16);
-    memcpy(Y11_sec.key, hash + 16, 16);
-
-    return 0;
-}
-
-int get_Y11_K9L(firm_h *firm, int index) {
-    // A9LH corrupts this one. Can't do much here.
-    int level = 0;
-
-    uint8_t key[AES_BLOCK_SIZE];
-    FILE* f;
-
-    // 9.5 key (K9L1)
-    f = fopen(PATH_SLOT0X11KEY95, "r");
-    if (!f) {
-        level |= 1;
-        goto next;
-    }
-
-    fread(Y11[0].key, 1, AES_BLOCK_SIZE, f);
-    fclose(f);
-
-next:
-    // 9.6 key (K9L2)
-    f = fopen(PATH_SLOT0X11KEY96, "r");
-    if (!f) {
-        level |= 2;
-        goto end;
     }
 
-    fread(Y11[1].key, 1, AES_BLOCK_SIZE, f);
-    fclose(f);
-
-end:
-    return level;
-}
-
-int get_Y3D(firm_h *firm, int index) {
-    uint8_t* key_loc     = (uint8_t*)firm + firm->section[2].offset; // ARM9 segment
-    uint32_t search_size = firm->section[2].size;
-
-    uint8_t mem[16] __attribute__((aligned(16))) = {0};
-
-    uint8_t* key_data = slice_roll_search(key_loc, search_size, & Y3D[0]);
-
-    if (!key_data)
-        return 1;
-
-    memcpy(mem, key_data, 16);
-
-    return 0;
-}
-
-int get_Y05(firm_h *firm) {
-    uint8_t* key_loc     = (uint8_t*)firm + firm->section[2].offset; // ARM9 segment
-    uint32_t search_size = firm->section[2].size;
-
-    uint8_t mem[16] __attribute__((aligned(16))) = {0};
-
-    uint8_t* key_data = slice_roll_search(key_loc, search_size, &Y05);
-
-    if (!key_data)
-        return 1;
-
-    fprintf(stderr, "  0x05 KeyY at %lx in FIRM1\n", (uint32_t)key_data - (uint32_t)key_loc);
-
-    memcpy(mem, key_data, 16);
-
-    return 0;
-}
-
-int extract_keys() {
-    int level = 0;
-
-       if (get_Y11_sec()) {// MUST be done first. Otherwise, sha register gets clobbered.
-        // At best, a warning.
-        level |= 1;
-    }
-
-#if 0
-    if (get_Y11_K9L()) { // For decrypting K9L.
-        // Also a warning, but potentially fatal if an N3DS.
-        level |= 2;
-    }
-
-    if (get_Y3D()) {
-        // No cetk decryption.
-        level |= 4;
+    if (ss_keyn[1][0] == 0) {
+        ss_keyn[1][0] = 1;
+        FILE* key = fopen(PATH_SLOT0X11KEY96, "r");
+        if (key) {
+            fread(ss_keyn[1], 1, AES_BLOCK_SIZE, key);
+            fclose(key);
+        }
     }
 
-    if (get_Y05()) {
-        // Pretty much a warning and nothing else atm.
-        level |= 8;
-    }
-#endif
+    setup_aeskey(0x11, (void*) ss_keyn[index]);
 
-    return level;
-}
-
-int set_Y3D_common(int commonKeyIndex) {
-       setup_aeskeyY(0x3D, (void*) Y3D[commonKeyIndex].key);
-
-       use_aeskey(0x3D);
+       use_aeskey(0x11);
 
        return 0;
 }
 
-int set_Y05() {
-    // N3DS nand key
-    setup_aeskeyY(0x05, Y05.key);
-
-       use_aeskey(0x05);
+int set_Y3D_cetk(uint32_t index) {
+       // From https://github.com/profi200/Project_CTR/blob/master/makerom/pki/prod.h#L19
+       static uint8_t common_keyy[6][16] = {
+               {0xD0, 0x7B, 0x33, 0x7F, 0x9C, 0xA4, 0x38, 0x59, 0x32, 0xA2, 0xE2, 0x57, 0x23, 0x23, 0x2E, 0xB9} , // 0 - eShop Titles
+               {0x0C, 0x76, 0x72, 0x30, 0xF0, 0x99, 0x8F, 0x1C, 0x46, 0x82, 0x82, 0x02, 0xFA, 0xAC, 0xBE, 0x4C} , // 1 - System Titles
+               {0xC4, 0x75, 0xCB, 0x3A, 0xB8, 0xC7, 0x88, 0xBB, 0x57, 0x5E, 0x12, 0xA1, 0x09, 0x07, 0xB8, 0xA4} , // 2
+               {0xE4, 0x86, 0xEE, 0xE3, 0xD0, 0xC0, 0x9C, 0x90, 0x2F, 0x66, 0x86, 0xD4, 0xC0, 0x6F, 0x64, 0x9F} , // 3
+               {0xED, 0x31, 0xBA, 0x9C, 0x04, 0xB0, 0x67, 0x50, 0x6C, 0x44, 0x97, 0xA3, 0x5B, 0x78, 0x04, 0xFC} , // 4
+               {0x5E, 0x66, 0x99, 0x8A, 0xB4, 0xE8, 0x93, 0x16, 0x06, 0x85, 0x0F, 0xD7, 0xA1, 0x6D, 0xD7, 0x55} , // 5
+       };
 
-       return 0;
-}
+       setup_aeskeyY(0x3D, (void*) common_keyy[index]);
 
-int set_Y11_K9L(int index) {
-    setup_aeskey(0x11, Y11[index].key);
-
-       use_aeskey(0x11);
+       use_aeskey(0x3D);
 
        return 0;
 }
diff --git a/source/firm/keys/Y05.gen b/source/firm/keys/Y05.gen
deleted file mode 100644 (file)
index 0967ef4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/source/firm/keys/Y11_95.gen b/source/firm/keys/Y11_95.gen
deleted file mode 100644 (file)
index 174e1e6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{},
diff --git a/source/firm/keys/Y11_96.gen b/source/firm/keys/Y11_96.gen
deleted file mode 100644 (file)
index 9bba4bb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0x5D1D533A, .sha = {0x8B, 0xB9, 0x77, 0x76, 0x86, 0xBD, 0xCC, 0xFF, 0x30, 0xE9, 0x4D, 0xC6, 0x5F, 0x23, 0x43, 0xF7, 0x41, 0x2E, 0x3D, 0x6C, 0x19, 0x12, 0xE3, 0x18, 0xDA, 0x9F, 0x17, 0x35, 0x96, 0xB9, 0xE8, 0x98} }
diff --git a/source/firm/keys/Y3D_0.gen b/source/firm/keys/Y3D_0.gen
deleted file mode 100644 (file)
index 7753ffd..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0x9EFCCA41, .sha = {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} },
diff --git a/source/firm/keys/Y3D_1.gen b/source/firm/keys/Y3D_1.gen
deleted file mode 100644 (file)
index b170fd7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0x65D5C908, .sha = {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} },
diff --git a/source/firm/keys/Y3D_2.gen b/source/firm/keys/Y3D_2.gen
deleted file mode 100644 (file)
index 78e28ff..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0xC1F558D6, .sha = {0xF7, 0x12, 0x1A, 0xCA, 0x63, 0x61, 0xC0, 0x9C, 0x10, 0xBB, 0x62, 0x8D, 0x69, 0x85, 0x23, 0x08, 0xCB, 0x81, 0xDB, 0x22, 0x9E, 0xFD, 0xC1, 0xAB, 0xF5, 0x7B, 0xA3, 0x8E, 0xDA, 0x64, 0x56, 0x74} },
diff --git a/source/firm/keys/Y3D_3.gen b/source/firm/keys/Y3D_3.gen
deleted file mode 100644 (file)
index 99c8698..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0x67D738E, .sha = {0xD8, 0xCF, 0x95, 0x7D, 0x88, 0x46, 0x6C, 0x7C, 0x42, 0x50, 0x7C, 0xA5, 0x53, 0xD2, 0x37, 0x34, 0x65, 0x0E, 0x34, 0x32, 0x3A, 0x58, 0x80, 0x76, 0x7E, 0xB5, 0x3A, 0x07, 0xEB, 0x5E, 0x00, 0xFD} },
diff --git a/source/firm/keys/Y3D_4.gen b/source/firm/keys/Y3D_4.gen
deleted file mode 100644 (file)
index ae21926..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0xCC1BE763, .sha = {0x75, 0x71, 0x64, 0x46, 0x3B, 0xDA, 0xEC, 0x71, 0x57, 0x95, 0x85, 0x17, 0xDF, 0x9B, 0x1D, 0xC7, 0xF3, 0x6A, 0x87, 0x22, 0x09, 0x70, 0x60, 0xD9, 0x48, 0xCC, 0x01, 0xFF, 0x72, 0x0F, 0xEE, 0x56} },
diff --git a/source/firm/keys/Y3D_5.gen b/source/firm/keys/Y3D_5.gen
deleted file mode 100644 (file)
index 3999b71..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{.roll = 0xC7A98491, .sha = {0xA4, 0x5B, 0x06, 0xC3, 0x37, 0xB7, 0x51, 0x6D, 0xF7, 0xA7, 0xCD, 0x87, 0xC2, 0x1D, 0x5F, 0xFC, 0x22, 0xA4, 0xAA, 0xB6, 0x48, 0x10, 0x2B, 0x98, 0x7E, 0x00, 0xD5, 0xC2, 0x48, 0x39, 0x6C, 0xF8} }
index c94bb0f8ff2d0c8146182c7ec006c17a6e918c31..3ba183cac6d50fc09296a1bac53f475891bed1ab 100644 (file)
@@ -6,17 +6,19 @@
 #include <ctr9/sha.h>
 #include <common.h>
 
-#define SECTOR_SIZE 0x200
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
 
-int decrypt_k9l(arm9bin_h *header, enum firm_type type) {
+int decrypt_k9l(arm9bin_h *header, enum firm_type type, uint32_t k9l) {
     uint8_t slot = 0x15;
 
-    if (type == type_native) {
+    if (type == type_native && k9l) {
         uint8_t decrypted_keyx[AES_BLOCK_SIZE];
 
         slot = 0x16;
 
-        use_aeskey(0x11);
+        set_N11_K9L(k9l - 1);
+
         ecb_decrypt(header->slot0x16keyX, decrypted_keyx, 1, AES_CNT_ECB_DECRYPT_MODE);
         setup_aeskeyX(slot, decrypted_keyx);
     }
@@ -32,91 +34,169 @@ int decrypt_k9l(arm9bin_h *header, enum firm_type type) {
 
     ctr_decrypt(arm9bin, arm9bin, (size_t)size / AES_BLOCK_SIZE, AES_CNT_CTRNAND_MODE, header->ctr);
 
-    if (type == type_native && *(uint32_t *)arm9bin == ARM9BIN_MAGIC)
-        return 0;
-    else if (*(uint32_t *)arm9bin == LGY_ARM9BIN_MAGIC)
-        return 0;
+    if (type == type_native)
+        return *(uint32_t *)arm9bin != ARM9BIN_MAGIC;
 
-    return 1; // Failed.
+    return *(uint32_t *)arm9bin != LGY_ARM9BIN_MAGIC;
 }
 
-void fix_entry(firm_h* firm, enum firm_type type) {
-    // Patch the entrypoint to skip arm9loader
+int patch_entry(firm_h *firm, enum firm_type type) {
     if (type == type_native)
         firm->a9Entry = 0x0801B01C;
     else
         firm->a9Entry = 0x0801301C;
 
-    // The entrypoints seem to be the same across different FIRM versions,
-    //  so we don't change them.
+    return 0;
 }
 
-// 0x0B130000 = start of FIRM0 partition, 0x400000 = size of FIRM partition (4MB)
-firm_h* dump_firm(firm_h* buffer, uint8_t index) {
-    firm_h* firm;
+uint8_t*
+get_titlekey(char *cetk_filename)
+{
+    FILE* f = fopen(cetk_filename, "r");
+    size_t size = fsize(f);
+
+    uint8_t* cetk = malloc(size);
+
+    fread(cetk, 1, size, f);
 
-    // NOTE - Cast, because GCC is making assumptions about 'index'.
-    uint32_t firm_offset = (uint32_t)(0x0B130000 + (index % 2) * 0x400000),
-             firm_b_size = 0x00100000; // 1MB, because
+    fclose(f);
 
-    firm = malloc(firm_b_size);
+       uint8_t iv[AES_BLOCK_SIZE] = { 0 };
+       uint32_t sigtype = __builtin_bswap32(*(const uint32_t *)cetk);
 
-    uint8_t ctr[0x10],
-            cid[0x10],
-            sha_t[0x20];
+       if (sigtype != SIG_TYPE_RSA2048_SHA256) {
+        free(cetk);
+               return NULL;
+    }
 
-    if (sdmmc_nand_readsectors(firm_offset / SECTOR_SIZE, firm_b_size / SECTOR_SIZE, (uint8_t*)firm))
-        goto failure;
+       const ticket_h *ticket = (const ticket_h *)((const uint8_t*)cetk + sizeof(sigtype) + 0x13C);
 
-    sdmmc_get_cid(1, (uint32_t*)cid);
-    sha256sum(sha_t, cid, 0x10);
-    memcpy(ctr, sha_t, 0x10);
-    add_ctr(ctr, firm_offset / AES_BLOCK_SIZE);
+    set_Y3D_cetk(1);
 
-    use_aeskey(0x06);
-    set_ctr(ctr);
-    ctr_decrypt(firm, firm, firm_b_size / AES_BLOCK_SIZE, AES_CNT_CTRNAND_MODE, ctr);
+    uint8_t *key = malloc(AES_BLOCK_SIZE);
 
-    if (memcmp((char*) & firm->magic, "FIRM", 4))
-        goto failure;
+       memcpy(iv, ticket->titleID, sizeof(ticket->titleID));
+       memcpy(key, ticket->titleKey, sizeof(ticket->titleKey));
 
-    return firm;
+       cbc_decrypt(key, key, 1, AES_CNT_TITLEKEY_DECRYPT_MODE, iv);
 
-failure:
-    free(firm);
+    free(cetk);
 
-    return NULL;
+       return key;
 }
 
-uint8_t* find_section_key(firm_h *firm_loc) {
-    // The key will be dword-aligned (I think? Verify this. May need new NFIRM to check assumption. Go, Nintendo!)
-#if 0
-    // 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};
+int dec_k9l(firm_h* firm) {
+    firm_section_h *arm9 = NULL;
+    for (firm_section_h* section = firm->section; section < firm->section + 4; section++) {
+        if (section->type == FIRM_TYPE_ARM9) { // ARM9
+            arm9 = section;
+            break;
+        }
+    }
 
-    uint8_t* key_loc = (uint8_t*)firm_loc + firm_loc->section[2].offset;
-    uint32_t search_size = firm_loc->section[2].size;
+    if (arm9 == NULL)
+        return 1;
 
-    uint8_t* key_data = key_search(key_loc, search_size, sha256, 0xDD);
+    struct firm_signature* sig = get_firm_info(firm);
+
+    if (decrypt_k9l((arm9bin_h*)((uint8_t*)firm + arm9->offset), sig->type, sig->k9l))
+        return 1;
 
-    if (!key_data)
-        abort("  FIRM Section key not found!\n");
+    // Recalc section hash.
+    sha256sum(arm9->hash, (uint8_t*)firm + arm9->offset, arm9->size);
 
-    fprintf(stderr, "  FIRM Section key at %lx in FIRM\n", (uint32_t)key_data - (uint32_t)key_loc);
-    return key_data;
-#endif
-    return NULL;
+    // Magic like D9.
+    memcpy(firm->magic, "DECFIRM", 7);
+
+    free(sig);
+
+    return 0;
 }
 
-int set_section_keys(firm_h* firm_loc) {
+firm_h*
+extract_firm_from_ncch(ncch_h *ncch, uint8_t *titlekey, size_t size)
+{
+       uint8_t firm_iv[16] = { 0 };
+       uint8_t exefs_key[16] = { 0 };
+       uint8_t exefs_iv[16] = { 0 };
+
+       setup_aeskey(0x16, titlekey);
+       use_aeskey(0x16);
+       cbc_decrypt(ncch, ncch, size / AES_BLOCK_SIZE, AES_CNT_CBC_DECRYPT_MODE, firm_iv);
+
+       if (ncch->magic != NCCH_MAGIC) {
+               return NULL;
+    }
+
+       memcpy(exefs_key, ncch, AES_BLOCK_SIZE);
+       ncch_getctr(ncch, exefs_iv, NCCHTYPE_EXEFS);
+
+       // Get the exefs offset and size from the NCCH
+       exefs_h *exefs = (exefs_h *)((uint8_t *)ncch + ncch->exeFSOffset * MEDIA_UNITS);
+       uint32_t exefs_size = ncch->exeFSSize * MEDIA_UNITS;
+
+       setup_aeskeyY(0x2C, exefs_key);
+       use_aeskey(0x2C);
+       ctr_decrypt(exefs, exefs, exefs_size / AES_BLOCK_SIZE, AES_CNT_CTRNAND_MODE, exefs_iv);
+
+       // Get the decrypted FIRM
+       // We assume the firm.bin is always the first file
+       firm_h *firm = (firm_h *)&exefs[1]; // The offset right behind the exefs
+
+       // header; the first file.
+       size = exefs->fileHeaders[0].size;
+       if (memcmp(firm->magic, "FIRM", 4)) {
+               return NULL;
+    }
+
+    firm_h* dest = malloc(size);
+
+       memcpy(dest, firm, size);
+
+       return dest;
+}
+
+uint8_t* key_search(uint8_t* mem, uint32_t size, uint8_t* sha256, uint8_t byte) {
+       uint8_t hash[0x20] = {0};
+       // Search for key.
+       for(uint32_t j = 0; j < size; j++) {
+               // Is candidate?
+               if (mem[j] == byte) {
+                       // Yes. Check hash.
+                       sha256sum(hash, &mem[j], 0x10);
+                       if(!memcmp(sha256, hash, 0x20)) {
+                               return &mem[j];
+                       }
+               }
+       }
+       return NULL;
+}
+
+void* find_section_key(firm_h* firm_loc) {
+       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)
+               return NULL;
+
+       return key_data;
+}
+
+int patch_section_keys(firm_h* firm_loc, uint32_t k9l) {
     // Set up the keys needed to boot a few firmwares, due to them being unset,
     // depending on which firmware you're booting from.
+
     uint8_t *keydata = find_section_key(firm_loc);
     if (!keydata)
         return 1;
 
-    use_aeskey(0x11);
+    set_N11_K9L(k9l - 1);
+
     uint8_t keyx[AES_BLOCK_SIZE];
     for (int slot = 0x19; slot < 0x20; slot++) {
         ecb_decrypt(keydata, keyx, 1, AES_CNT_ECB_DECRYPT_MODE);
index 9db7067b9f62c40a9345d81ca351cf83ed5bdaf4..176244861412e6aa965f6063ee8be8bcf5508b65 100644 (file)
@@ -1,5 +1,8 @@
 #include <common.h>
 
+#define FIRM_INTERNAL_CODE
+#include <firm/internal.h>
+
 struct firm_signature *
 get_firm_info(firm_h *firm)
 {
@@ -29,15 +32,9 @@ get_firm_info(firm_h *firm)
         // Check for the presence of a TWL/AGB only sysmodule
         if( memfind((uint8_t*)firm + firm->section[0].offset, firm->section[0].size, "TwlBg", 5)) {
             signature->type = type_twl;
-            fprintf(stderr, "  TwlBg module found; probably TWL\n");
         } else if( memfind((uint8_t*)firm + firm->section[0].offset, firm->section[0].size, "AgbBg", 5)) {
             signature->type = type_agb;
-            fprintf(stderr, "  AgbBg module found; probably AGB\n");
-        } else {
-            fprintf(stderr, "  Warning: Native, but there is a 4th section. Report this IMMEDIATELY.\n");
         }
-    } else {
-        fprintf(stderr, "  Section #4 is empty; this is probably native\n");
     }
 
     for (firm_section_h *section = firm->section; section < firm->section + 4; section++) {
@@ -51,10 +48,8 @@ get_firm_info(firm_h *firm)
                 //        Only N3DS FIRMs have this property.
                 uint8_t* k9l = (uint8_t*)memfind((uint8_t*)firm + section->offset, section->size, "K9L", 3);
                 if (k9l == NULL) { // O3DS.
-                    fprintf(stderr, "  No K9L; this is likely an O3DS FIRM\n");
                     signature->console = console_o3ds;
                 } else { // N3DS.
-                    fprintf(stderr, "  K9L found; this is likely an N3DS FIRM\n");
                     signature->console = console_n3ds;
                     signature->k9l = (unsigned int)(k9l[3] - '0'); // String is "K9LN" where N is the version
                 }
@@ -66,10 +61,8 @@ get_firm_info(firm_h *firm)
                 //        which allows determining which console it is intended for.
                 if (section->address == 0x08006800) { // O3DS entry
                     signature->console = console_o3ds;
-                    fprintf(stderr, "  Entry point seems correct for O3DS\n");
                 } else if (section->address == 0x08006000) { // N3DS entry
                     signature->console = console_n3ds;
-                    fprintf(stderr, "  Entry point seems correct for N3DS\n");
                 }
             }
 
index 4d1f5dc36a97eae2050384a04b3c379cbd81ecaf..0602309379b0ae26604863d399ba646f304193b1 100644 (file)
@@ -49,7 +49,7 @@
 
 #ifdef LOADER
   #define log(a) logstr(a)
-  #define abort(a)                                                                                                                                               \
+  #define panic(a)                                                                                                                                               \
       {                                                                                                                                                          \
           logstr(a);                                                                                                                                             \
           svcBreak(USERBREAK_ASSERT);                                                                                                                            \
@@ -419,49 +419,49 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si
                 if (debug)
                     log("abort\n");
 
-                abort("abort triggered, halting VM!\n");
+                panic("abort triggered, halting VM!\n");
                 break;
             case OP_ABORTEQ:
                 code++;
                 if (debug)
                     log("aborteq\n");
                 if (eq)
-                    abort("eq flag not set, halting VM!\n");
+                    panic("eq flag not set, halting VM!\n");
                 break;
             case OP_ABORTNE:
                 code++;
                 if (debug)
                     log("abortlt\n");
                 if (!eq)
-                    abort("eq flag not set, halting VM!\n");
+                    panic("eq flag not set, halting VM!\n");
                 break;
             case OP_ABORTLT:
                 code++;
                 if (debug)
                     log("abortlt\n");
                 if (lt)
-                    abort("lt flag set, halting VM!\n");
+                    panic("lt flag set, halting VM!\n");
                 break;
             case OP_ABORTGT:
                 code++;
                 if (debug)
                     log("abortgt\n");
                 if (gt)
-                    abort("gt flag set, halting VM!\n");
+                    panic("gt flag set, halting VM!\n");
                 break;
             case OP_ABORTF:
                 code++;
                 if (debug)
                     log("abortf\n");
                 if (found)
-                    abort("f flag set, halting VM!\n");
+                    panic("f flag set, halting VM!\n");
                 break;
             case OP_ABORTNF:
                 code++;
                 if (debug)
                     log("abortnf\n");
                 if (!found)
-                    abort("f flag is not set, halting VM!\n");
+                    panic("f flag is not set, halting VM!\n");
                 break;
             case OP_NEXT:
                 if (debug) {
@@ -524,7 +524,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si
                         (uint32_t)code,
                         *code);
 #endif
-                abort("Halting startup.\n");
+                panic("Halting startup.\n");
                 break;
         }
 
@@ -532,7 +532,7 @@ exec_bytecode(uint8_t *bytecode, uint32_t len, uint8_t* stack, uint32_t stack_si
 #ifndef LOADER
             fprintf(stderr, " -> %lx", offset);
 #endif
-            abort("seeked out of bounds\n");
+            panic("seeked out of bounds\n");
         }
 
 #ifndef LOADER
index 94c5242704d1062defac12230bb6ca00319464ec..5bbb62eec712783a1152ce7c69fba922ecdec98a 100644 (file)
@@ -3,7 +3,7 @@
 #include <ctr9/ctr_irq.h>
 
 void dump_state_printf(uint32_t* regs) {
-    fprintf(stderr, "  cpsr:%x sp:%x lr:%x\n"
+    fprintf(stderr, "  cpsr:%x sp:%x pc:%x\n"
                     "  r0:%x r1:%x r2:%x r3:%x\n"
                     "  r4:%x r5:%x r6:%x r7:%x\n"
                     "  r8:%x r9:%x r10:%x r11:%x\n"
@@ -22,7 +22,7 @@ void reset_INT(_UNUSED uint32_t* regs) {
 void undef_INT(uint32_t* regs) {
     fprintf(stderr, "Undefined instruction.\n");
     dump_state_printf(regs);
-    abort("Cannot continue. Halting.\n");
+    panic("Cannot continue. Halting.\n");
 }
 
 void swi_INT(_UNUSED uint32_t* regs) {
@@ -30,22 +30,21 @@ void swi_INT(_UNUSED uint32_t* regs) {
 }
 
 void preabrt_INT(uint32_t* regs) {
-    fprintf(stderr, "Prefetch Abort.\n");
+    fprintf(stderr, "Prefetch abort.\n");
     dump_state_printf(regs);
-    abort("Cannot continue. Halting.\n");
+    panic("Cannot continue. Halting.\n");
 }
 
 void databrt_INT(uint32_t* regs) {
     fprintf(stderr, "Data abort.\n");
     dump_state_printf(regs);
-    abort("Cannot continue. Halting.\n");
+    panic("Cannot continue. Halting.\n");
 }
 
 void fiq_INT(_UNUSED uint32_t* regs) {
     fprintf(stderr, "FIQ called. Returning.\n");
 }
 
-
 void install_interrupts() {
     ctr_interrupt_prepare();
     ctr_irq_initialize();
index f0988f537fa20ca811404f7fcb1d98b10e92a5bc..7da5e7715ebea1584d323ee27d04451c35d40efb 100644 (file)
@@ -63,5 +63,7 @@ main(int argc, char** argv)
         generate_patch_cache();
     }
 
-    boot_cfw();
+    boot_cfw(config->firm[0]);
+
+    panic("Firmlaunch failed!\n");
 }
index 06591635aa8986e2bd7f2c5fa1b856d7b028123e..8c18055f701ccaf270a9331f246ffd0baa536724 100644 (file)
@@ -34,7 +34,7 @@ verify_emunand(uint32_t index, uint32_t *off, uint32_t *head)
         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");
+        panic("emunand: selected NAND image is not valid.\n");
     }
 
     free(emunand_temp);
@@ -82,7 +82,7 @@ patchNANDRW(uint8_t *pos, uint32_t size, uint32_t branchOffset)
     uint16_t *writeOffset = (uint16_t *)memfind((uint8_t*)(readOffset + 5), 0x100, pattern, 4) - 3;
 
     if (!readOffset || !writeOffset)
-        abort("emunand: pattern for r/w missing!\n");
+        panic("emunand: pattern for r/w missing!\n");
 
     readOffset[0] = nandRedir[0];
     readOffset[1] = nandRedir[1];
@@ -127,11 +127,11 @@ patch_emunand(firm_h* firm_loc, uint32_t index)
     // Copy emuNAND code
     void *emuCodeOffset = getEmuCode(arm9Section, arm9SectionSize);
     if (!emuCodeOffset)
-        abort("emunand: code missing from arm9?\n");
+        panic("emunand: code missing from arm9?\n");
 
     FILE *f = fopen(PATH_EMUNAND_CODE, "r");
     if (!f)
-        abort("emunand: code not found on SD.\n");
+        panic("emunand: code not found on SD.\n");
 
     uint32_t emunand_size = fsize(f);
     fread(emuCodeOffset, 1, emunand_size, f);
@@ -147,7 +147,7 @@ patch_emunand(firm_h* firm_loc, uint32_t index)
              *pos_sdmmc  = (uint32_t *)memfind(emuCodeOffset, emunand_size, "SDMC", 4);
 
     if (!pos_offset || !pos_head || !pos_sdmmc)
-        abort("emunand: couldn't find pattern in hook?\n");
+        panic("emunand: couldn't find pattern in hook?\n");
 
     verify_emunand(index, pos_offset, pos_head);
 
index f448056f740fefed3ed3209620d039ad55a699c1..332d9bfb39bccd62cf163ce6a6e5ae228c2bf517 100644 (file)
@@ -42,7 +42,7 @@ patch_reboot(firm_h* firm_loc)
     // Copy firmlaunch code
     FILE *f = fopen(PATH_REBOOT_HOOK, "r");
     if (!f)
-        abort("reboot: hook not found on SD\n");
+        panic("reboot: hook not found on SD\n");
 
     uint32_t size = fsize(f);
     fread(off, 1, size, f);
@@ -51,7 +51,7 @@ patch_reboot(firm_h* firm_loc)
     // Put the fOpen offset in the right location
     uint32_t *pos_fopen = (uint32_t *)memfind(off, size, "open", 4);
     if (!pos_fopen)
-        abort("reboot: fopen location missing\n");
+        panic("reboot: fopen location missing\n");
 
     *pos_fopen = fOpenOffset;
 
@@ -60,7 +60,7 @@ patch_reboot(firm_h* firm_loc)
     uint32_t *pos_agb = (uint32_t *)memfind(off, size, "AGBF", 4);
 
     if (!pos_native && !pos_twl && !pos_agb)
-        abort("reboot: missing string placeholder?\n");
+        panic("reboot: missing string placeholder?\n");
 
     fprintf(stderr, "reboot: NATF @ %lx\n", (uint32_t)pos_native);
     fprintf(stderr, "reboot: TWLF @ %lx\n", (uint32_t)pos_twl);
@@ -104,7 +104,7 @@ patch_reboot(firm_h* firm_loc)
 
     f = fopen(PATH_REBOOT_CODE, "r");
     if (!f)
-        abort("reboot: boot not found on SD\n");
+        panic("reboot: boot not found on SD\n");
 
     fread(mem, 1, fsize(f), f);
     fclose(f);
index f5992a6bcdcce23679598cfa03552eeb06320d4a..5e0a62e2f9cd82740716ac83b62f5f960723980d 100644 (file)
@@ -30,7 +30,7 @@ patch_cache_func(char* fpath)
         if (enable_list[p.uuid]) {
             // Patch is enabled. Cache it.
             if (execb(fpath, 1)) {
-                abort("Failed to cache:\n  %s\n", fpath);
+                panic("Failed to cache:\n  %s\n", fpath);
             }
 
             wait();
@@ -75,7 +75,7 @@ patch_firm_all(firm_h* firm)
     // Inject services?
     if (get_opt_u32(OPTION_SVCS)) {
         if (patch_svc_calls(firm)) {
-            abort("Fatal. Svc inject has failed.");
+            panic("Fatal. Svc inject has failed.");
         }
         wait();
     }
@@ -83,7 +83,7 @@ patch_firm_all(firm_h* firm)
     // Replace loader?
     if (get_opt_u32(OPTION_LOADER)) {
         if (patch_modules(firm)) {
-            abort("Fatal. Loader inject has failed.");
+            panic("Fatal. Loader inject has failed.");
         }
         // This requires OPTION_SIGPATCH.
         wait();
index 48db2f1476cbf72fc322fea290fe5173e1e4a15c..fcc387b7ebae6f65f8e2cbd5edf69b66748360c3 100644 (file)
@@ -4,7 +4,7 @@
 #include <stdarg.h>
 #include <common.h>
 
-void abort(char* x, ...) {
+void panic(char* x, ...) {
     va_list ap;
     va_start(ap, x);
 
index e0c4eecfdeb2f29d73357fe1954d85fcd9a4fd13..4b21ed90196f2e2743bfaeb1abc208c1f8a4f144 100644 (file)
@@ -118,7 +118,7 @@ void free(void* ptr) {
 
 #ifdef MALLOC_DEBUG
     if (block->canary != 0x1337d00d) {
-        abort("%s: Attempt free non-pointer.\n", info);
+        panic("%s: Attempt free non-pointer.\n", info);
     }
 
     ++free_count;
index 2da58663c41826014ee8354923d26b76ff92f9fc..901f03e0836f11d9853d6435993968ee4b9dd427 100644 (file)
@@ -179,7 +179,7 @@ void set_font(const char* filename) {
 
     FILE* f = fopen(filename, "r");
 
-    if (!f) abort("Failed to load font file!\n");
+    if (!f) panic("Failed to load font file!\n");
 
     unsigned int new_w, new_h;
 
@@ -187,7 +187,7 @@ void set_font(const char* filename) {
     fread(&new_h, 1, 4, f);
 
     if (new_w == 0 || new_h == 0) {
-        abort("Invalid font file: w/h is 0 - not loaded\n");
+        panic("Invalid font file: w/h is 0 - not loaded\n");
     }
 
     unsigned int c_font_w = (new_w / 8) + ((new_w % 8) ? 1 : 0);
@@ -641,9 +641,10 @@ vfprintf(void *channel, const char *format, va_list ap)
 {
     if ((channel == stdout || channel == stderr) && kill_output)
         return;
-
-    char *copy = strdup_self(format);
-    char *ref = copy;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic warning "-Wdiscarded-qualifiers"
+    char *ref = format;
+#pragma GCC diagnostic pop
 
     unsigned char *color = NULL;
     if (channel == TOP_SCREEN)
@@ -709,8 +710,6 @@ vfprintf(void *channel, const char *format, va_list ap)
         }
         ++ref;
     }
-
-    free(copy);
 }
 
 void
index 5a039b0c05c12b32e8392bd9e4791280670010d8..977e7f9b243d33336a6c87d1db79306437c37bae 100644 (file)
@@ -12,6 +12,17 @@ strdup_self(const char* str)
     return new_st;
 }
 
+char*
+strdupcat(const char* str, const char *cat)
+{
+       size_t l_str = strlen(str);
+       size_t l_cat = strlen(cat);
+    char *out = malloc(l_str + l_cat + 1);
+    memcpy(out, str, l_str);
+    memcpy(out + l_str, cat, l_cat + 1);
+    return out;
+}
+
 int
 atoi(const char *str)
 {