]> Chaos Git - corbenik/corbenik.git/commitdiff
Now we have injector. Good night, cakes.
authorroot <chaos.kagami@gmail.com>
Tue, 17 May 2016 20:17:05 +0000 (16:17 -0400)
committerroot <chaos.kagami@gmail.com>
Tue, 17 May 2016 20:17:05 +0000 (16:17 -0400)
16 files changed:
.gitignore
copy.sh
external/Makefile
external/loader/Makefile
external/loader/source/config.h
external/loader/source/memory.h
external/loader/source/patcher.c
external/service/backdoor.s [moved from asm/backdoor.s with 100% similarity]
source/config.c
source/config.h
source/firm/fcram.h
source/menu.c
source/patch/base.c [new file with mode: 0644]
source/patch/module.c [new file with mode: 0644]
source/patch_format.h
source/patcher.c

index ec5ff8a7e23efde63a0a600b4a489893d40c3f8c..c9c9684180c2ea3a4adc8c525fb90dc165a6fc81 100644 (file)
@@ -1,6 +1,4 @@
 out
-CakeHax
-CakeBrah
 build
 *.bin
 *.3dsx
@@ -9,4 +7,5 @@ build
 *.o
 *.d
 *.elf
-*.bat
\ No newline at end of file
+*.bat
+input
diff --git a/copy.sh b/copy.sh
index 2872f61e76434de8bdc86cabf46b71bdd8024e7a..53b5e83bdfd74af8d28311cd0708f1eff0992854 100644 (file)
--- a/copy.sh
+++ b/copy.sh
@@ -4,5 +4,6 @@ cp out/arm9loaderhax.bin /media/cd/anim/boot/none.bin || exit 0
 cp out/arm9loaderhax.bin /media/cd/anim/boot/r.bin || exit 0
 cp out/arm9loaderhax.bin /media/cd/anim/boot/l.bin || exit 0
 cp -r out/corbenik /media/cd/ || exit 0
+cp -r input/corbenik /media/cd/ || exit 0
 umount /media/cd || exit 0
 eject /dev/sdb || exit 0
index 087842fb036d8f0fe3ec17b2bbb8a08f859ee0be..c623d56a85ce7a8b797af3a23dc7edab42a97bad 100644 (file)
@@ -1,11 +1,11 @@
 .PHONY: all copyout
 all: loader
-       mkdir -p ../out/corbenik/module
-       cp loader/loader.cxi ../out/corbenik/module/loader.cxi
+       mkdir -p ../out/corbenik/lib/module
+       cp loader/loader.cxi ../out/corbenik/lib/module/loader.cxi
 
 .PHONY: clean
 clean: clean_loader
-       rm -rf ../out/corbenik/module
+       rm -rf ../out/corbenik/bin
 
 .PHONY: loader
 loader:
index 43eb971b19a76831aa47d2fc44a56e345cb58e58..decb4e020d0c5418946da12094b6b5a8221a6af1 100644 (file)
@@ -31,6 +31,7 @@ INCLUDES      :=      include
 #---------------------------------------------------------------------------------
 ARCH   :=      -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
 
+ERROR   := -Werror
 CFLAGS := -flto -Wall -Os -mword-relocations \
                        -fomit-frame-pointer -ffunction-sections -fdata-sections -fshort-wchar \
                        $(ARCH)
index aee78c0ddf139fd6800a7be64649a9ddd9a69b59..c40d2f3b17056d13352d117ba5242c8679cedefd 100644 (file)
@@ -1,20 +1,89 @@
-#pragma once
+#ifndef __CONFIG_H
+#define __CONFIG_H
 
-#include <stdint.h>
+static unsigned int config_version = 1;
 
+#define CONFIG_MAGIC "OVAN"
+
+// Structure of config file
 struct config_file {
-    unsigned int config_ver;
-    unsigned int firm_ver;
-    uint8_t firm_console;
-    uint32_t emunand_location;
+    char magic[4];              // "OVAN" for shits and giggles again.
+    uint32_t config_ver;        // Config file version.
+
+    uint8_t  options[256];      // Options in the menu - deliberately large to avoid config version bumps.
+
+    uint64_t patch_ids[256];    // What patches are enabled by UUID. 256 is an arbitrary limit - contact me if you hit it.
+}__attribute__((packed));
+
+/*
+extern struct config_file config;
+
+enum type {
+       boolean_val, // Toggle
+       ranged_val   // N1 - N2, left and right to pick.
+       mask_val     // Bitmask allowed values.
+};
+
+struct range_str {
+       int a, b;
+};
+
+struct option {
+       int config_index;
+       char name_text[64];
+       enum type allowed;
+       uint32_t a, b;
+}__attribute__((packed));
+
+
+static struct options[] = {
+       { 0, "Signature Patch", boolean_val, 0 },
+       { 1, "FIRM Protection", boolean_val, 0 },
+       { 2, "SysModule Replacement", boolean_val, 0 },
+       { 3, "Service Replacement", boolean_val, 0 },
+       { 4, "ARM9 Thread", boolean_val, 0 },
+
+       { 5, "Autoboot", boolean_val, 0 },
+       { 6, "Silence w/ Autoboot", boolean_val, 0 },
+       { 7, "Step through with button", boolean_val, 0 },
+
+       { 8, "Don't draw background color", boolean_val, 0 },
+       { 9, "Preserve framebuffer data", boolean_val, 0 },
+
+       { 10, "Hide Help from menu", boolean_val, 0 },
+
+       { 11, "Loader: CPU L2 enable", boolean_val, 0 },
+       { 12, "Loader: CPU 800Mhz mode", boolean_val, 0 },
+       { 13, "Loader: Language Emulation", boolean_val, 0 },
+
+       { 14, "No dependency tracking", boolean_val, 0 },
+       { 15, "Allow unsafe options", boolean_val, 0 },
+}
+*/
+#define OPTION_SIGPATCH     0  // Use builtin signature patch.
+#define OPTION_FIRMPROT     1  // Protect firmware from writes.
+#define OPTION_LOADER       2  // Use builtin loader module replacer.
+#define OPTION_SERVICES     3  // Inject services (including backdoor for 11)
+#define OPTION_ARM9THREAD   4  // Use builtin ARM9 thread injector.
+
+#define OPTION_AUTOBOOT     5  // Skip menu unless L is held.
+#define OPTION_SILENCE      6  // Don't print debug information.
+#define OPTION_TRACE        7  // Pause for A key on each step.
+
+#define OPTION_TRANSP_BG    8  // Background color is not drawn under text.
+#define OPTION_NO_CLEAR_BG  9  // Framebuffer is preserved from whatever ran before us.
+#define OPTION_READ_ME      10 // Remove Help/Readme from menu.
+
+#define OPTION_LOADER_CPU_L2   11   // Enable L2 cache.
+#define OPTION_LOADER_CPU_800MHZ 12 // Enable 800Mhz mode.
+#define OPTION_LOADER_LANGEMU  13 // Enable 800Mhz mode.
 
-    unsigned int autoboot_enabled: 1;
-       unsigned int n3ds_clock: 1;
-       unsigned int n3ds_l2: 1;
-       unsigned int language_emu: 1;
+#define IGNORE_PATCH_DEPS    14  // Ignore patch UUID dependencies. Not recommended.
+#define IGNORE_BROKEN_SHIT   15 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
 
-       /* The cakes_count and cakes data
-          is excluded because loader has
-       no use for it. */
-} __attribute__((packed));
+//#define HEADER_COLOR        12 // Color of header text.
+//#define BG_COLOR            13 // Color of background.
+//#define TEXT_COLOR          14 // Color of most text.
+//#define ARROW_COLOR         15 // Color of Arrow.
 
+#endif
index 76d58c7b32619b6117bee7da89ffa05485f1942a..265306368670832aebca7f39af2d4855caa8703e 100644 (file)
@@ -1,5 +1,8 @@
-#pragma once
+#ifndef __MEMORY_H__
+#define __MEMORY_H__
 
 #include <3ds/types.h>
 
 void memcpy(void *dest, const void *src, u32 size);
+
+#endif
index 35ee5c80e47923b81cc19e602414f94904227cdf..bd21e9357d033e2f2285790698ba882bf43daf02 100644 (file)
@@ -8,6 +8,7 @@
 #define _MAX_LFN 255
 #endif
 #include "config.h"
+#include "../../../source/patch_format.h"
 
 static int memcmp(const void *buf1, const void *buf2, u32 size)
 {
@@ -59,6 +60,7 @@ static u32 patchMemory(u8 *start, u32 size, const void *pattern, u32 patSize, in
 
         if(found == NULL) break;
 
+               // FIXME - This is throwing on Werror.
         memcpy(found + offset, replace, repSize);
 
         u32 at = (u32)(found - start);
@@ -115,50 +117,74 @@ static u32 secureInfoExists(void)
     return secureInfoExists;
 }
 
-static unsigned int config_ver = 4;
-static struct config_file config;
-static int failed_load_config = 1;
-void load_config() {
-    // Make sure we don't get random values if the config file doesn't load
-       for(int i=0;i<sizeof(struct config_file);i++) ((char*)&config)[i]=0;
+struct config_file config;
+int failed_load_config = 1;
+
+void clear_config() {
+       // Basically; memset.
+       for(int i=0;i<sizeof(struct config_file);i++)
+               ((char*)&config)[i]=0;
+}
 
+void load_config() {
        IFile file;
     u64 total;
 
        // Open file.
-    if (!fileOpen(&file, ARCHIVE_SDMC, "/corbenik/config.dat", FS_OPEN_READ)) {
+    if (!fileOpen(&file, ARCHIVE_SDMC, PATH_CONFIG, FS_OPEN_READ)) {
                // Failed to open.
                failed_load_config = 1;
-        return;
+        goto ret_fail;
     }
 
        // Read file.
     if(!IFile_Read(&file, &total, &config, sizeof(struct config_file))) {
                // Failed to read.
-               failed_load_config = 1;
-               for(int i=0;i<sizeof(struct config_file);i++) ((char*)&config)[i]=0;
-               return;
+               goto ret_fail;
+       }
+
+       IFile_Close(&file); // Read to memory.
+
+       if (config.magic[0] != 'O' || config.magic[1] != 'V' || config.magic[2] != 'A' || config.magic[3] != 'N') {
+               // Incorrect magic.
+               // Failed to read.
+               goto ret_fail;
        }
 
-    if (config.config_ver != config_ver) {
+       if (config.config_ver != config_version) {
                // Invalid version.
-               failed_load_config = 1;
-               for(int i=0;i<sizeof(struct config_file);i++) ((char*)&config)[i]=0;
-        return;
+               goto ret_fail;
     }
 
-       IFile_Close(&file);
-       // Loaded okay.
+       failed_load_config = 0;
+
+       return;
+
+ret_fail:
+       clear_config();
+
+       return;
 }
 
 static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
 {
-    /* Here we look for "/cfw/locale/[u64 titleID in hex, uppercase].txt"
+       // FIXME - Rewrite this function to use a single line-based config
+       // Directory seeks have severe issues on FAT and
+       // dumping configs based on 3dsdb (more than 1000) causes things
+       // to kind a choke.
+
+    /* Here we look for "/corbenik/locale/[u64 titleID in hex, uppercase].txt"
        If it exists it should contain, for example, "EUR IT" */
 
     char path[] = "/corbenik/locales/0000000000000000.txt";
 
-    u32 i = strlen(path) - 21;
+       u32 i = 0, j = 0;
+       while(path[j] != 0) {
+               if (path[j] == '/')
+                       i = j;
+               j++;
+       }
+       i += 1;
 
     while(progId > 0)
     {
@@ -181,6 +207,9 @@ static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
 
         for(u32 i = 0; i < 7; ++i)
         {
+                       // TODO - Permit alternative names. They're using fixed strings for ease of use;
+                       // we need to permit names like 'Japan', 'Europe', etc
+                       // Maybe read locale data from the FS? http://cldr.unicode.org/
             static const char *regions[] = {"JPN", "USA", "EUR", "AUS", "CHN", "KOR", "TWN"};
 
             if(memcmp(buf, regions[i], 3) == 0)
@@ -192,6 +221,7 @@ static int loadTitleLocaleConfig(u64 progId, u8 *regionId, u8 *languageId)
 
         for(u32 i = 0; i < 12; ++i)
         {
+                       // TODO - Same as above.
             static const char *languages[] = {"JP", "EN", "FR", "DE", "IT", "ES", "ZH", "KO", "NL", "PT", "RU", "TW"};
 
             if(memcmp(buf + 4, languages[i], 2) == 0)
@@ -316,9 +346,124 @@ static void patchCfgGetRegion(u8 *code, u32 size, u8 regionId, u32 CFGUHandleOff
     }
 }
 
+void region_patch(u64 progId, u8 *code, u32 size) {
+       static const u8 regionFreePattern[] = {0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3};
+       static const u8 regionFreePatch[]   = {0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1};
+
+       //Patch SMDH region checks
+       patchMemory(code, size,
+               regionFreePattern,
+               sizeof(regionFreePattern), -16,
+               regionFreePatch,
+               sizeof(regionFreePatch), 1
+    );
+}
+
+void disable_nim_updates(u64 progId, u8 *code, u32 size) {
+       static const u8 blockAutoUpdatesPattern[] = {0x25, 0x79, 0x0B, 0x99};
+       static const u8 blockAutoUpdatesPatch[]   = {0xE3, 0xA0};
+
+       //Block silent auto-updates
+       patchMemory(code, size,
+               blockAutoUpdatesPattern,
+               sizeof(blockAutoUpdatesPattern), 0,
+               blockAutoUpdatesPatch,
+               sizeof(blockAutoUpdatesPatch), 1
+       );
+}
+
+void disable_eshop_updates(u64 progId, u8 *code, u32 size) {
+       static const u8 skipEshopUpdateCheckPattern[] = {0x30, 0xB5, 0xF1, 0xB0};
+       static const u8 skipEshopUpdateCheckPatch[]   = {0x00, 0x20, 0x08, 0x60, 0x70, 0x47};
+
+       //Skip update checks to access the EShop
+       patchMemory(code, size,
+               skipEshopUpdateCheckPattern,
+               sizeof(skipEshopUpdateCheckPattern), 0,
+               skipEshopUpdateCheckPatch,
+               sizeof(skipEshopUpdateCheckPatch), 1
+       );
+}
+
+void fake_friends_version(u64 progId, u8 *code, u32 size) {
+       static const u8 fpdVerPattern[] = {0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01};
+       static const u8 fpdVerPatch = 0x06; // Latest version.
+
+       //Allow online access to work with old friends modules
+       patchMemory(code, size,
+               fpdVerPattern,
+               sizeof(fpdVerPattern), 9,
+               &fpdVerPatch,
+               sizeof(fpdVerPatch), 1
+       );
+}
+
+void settings_string(u64 progId, u8 *code, u32 size) {
+       static const u16 verPattern[] = u"Ver.";
+       static const u16 verPatch[] = u".hax";
+
+       //Patch Ver. string
+       patchMemory(code, size,
+               verPattern,
+               sizeof(verPattern) - sizeof(u16), 0,
+               verPatch,
+               sizeof(verPatch) - sizeof(u16), 1
+       );
+}
+
+void disable_cart_updates(u64 progId, u8 *code, u32 size) {
+       static const u8 stopCartUpdatesPattern[] = {0x0C, 0x18, 0xE1, 0xD8};
+       static const u8 stopCartUpdatesPatch[]   = {0x0B, 0x18, 0x21, 0xC8};
+
+       //Disable updates from foreign carts (makes carts region-free)
+       patchMemory(code, size,
+               stopCartUpdatesPattern,
+               sizeof(stopCartUpdatesPattern), 0,
+               stopCartUpdatesPatch,
+               sizeof(stopCartUpdatesPatch), 2
+       );
+}
+
+void adjust_cpu_settings(u64 progId, u8 *code, u32 size) {
+       if (!failed_load_config) {
+               u32 cpuSetting = 0;
+               // L2
+               cpuSetting |= config.options[OPTION_LOADER_CPU_L2];
+               // Speed
+               cpuSetting |= config.options[OPTION_LOADER_CPU_800MHZ] << 1;
+
+           if(cpuSetting) {
+                       static const u8 cfgN3dsCpuPattern[] = {0x00, 0x40, 0xA0, 0xE1, 0x07, 0x00};
+
+                       u32 *cfgN3dsCpuLoc = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern));
+
+                       //Patch N3DS CPU Clock and L2 cache setting
+                       if(cfgN3dsCpuLoc != NULL) {
+                               *(cfgN3dsCpuLoc + 1) = 0xE1A00000;
+                               *(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting;
+                       }
+               }
+       }
+}
+
+void secureinfo_sigpatch(u64 progId, u8 *code, u32 size) {
+       static const u8 secureinfoSigCheckPattern[] = {0x06, 0x46, 0x10, 0x48, 0xFC};
+       static const u8 secureinfoSigCheckPatch[]   = {0x00, 0x26};
+
+       //Disable SecureInfo signature check
+       patchMemory(code, size,
+               secureinfoSigCheckPattern,
+               sizeof(secureinfoSigCheckPattern), 0,
+               secureinfoSigCheckPatch,
+               sizeof(secureinfoSigCheckPatch), 1
+       );
+}
+
 void patchCode(u64 progId, u8 *code, u32 size)
 {
-    load_config(); // Load cakes.dat
+       // FIXME - Config loading breaks loader. WTF is this?
+       // Maybe the memcpy?
+       // load_config();
 
     switch(progId)
     {
@@ -329,74 +474,20 @@ void patchCode(u64 progId, u8 *code, u32 size)
         case 0x000400300000A902LL: // KOR Menu
         case 0x000400300000B102LL: // TWN Menu
         {
-            static const u8 regionFreePattern[] = {
-                0x00, 0x00, 0x55, 0xE3, 0x01, 0x10, 0xA0, 0xE3
-            };
-            static const u8 regionFreePatch[] = {
-                0x01, 0x00, 0xA0, 0xE3, 0x1E, 0xFF, 0x2F, 0xE1
-            };
-
-            //Patch SMDH region checks
-            patchMemory(code, size,
-                regionFreePattern,
-                sizeof(regionFreePattern), -16,
-                regionFreePatch,
-                sizeof(regionFreePatch), 1
-            );
-
+                       region_patch(progId, code, size);
             break;
         }
 
         case 0x0004013000002C02LL: // NIM
         {
-            static const u8 blockAutoUpdatesPattern[] = {
-                0x25, 0x79, 0x0B, 0x99
-            };
-            static const u8 blockAutoUpdatesPatch[] = {
-                0xE3, 0xA0
-            };
-            static const u8 skipEshopUpdateCheckPattern[] = {
-                0x30, 0xB5, 0xF1, 0xB0
-            };
-            static const u8 skipEshopUpdateCheckPatch[] = {
-                0x00, 0x20, 0x08, 0x60, 0x70, 0x47
-            };
-
-            //Block silent auto-updates
-            patchMemory(code, size,
-                blockAutoUpdatesPattern,
-                sizeof(blockAutoUpdatesPattern), 0,
-                blockAutoUpdatesPatch,
-                sizeof(blockAutoUpdatesPatch), 1
-            );
-
-            //Skip update checks to access the EShop
-            patchMemory(code, size,
-                skipEshopUpdateCheckPattern,
-                sizeof(skipEshopUpdateCheckPattern), 0,
-                skipEshopUpdateCheckPatch,
-                sizeof(skipEshopUpdateCheckPatch), 1
-            );
-
+                       disable_nim_updates(progId, code, size);
+                       disable_eshop_updates(progId, code, size);
             break;
         }
 
         case 0x0004013000003202LL: // FRIENDS
         {
-            static const u8 fpdVerPattern[] = {
-                0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x01, 0x01, 0x01
-            };
-
-            static const u8 fpdVerPatch = 0x05;
-
-            //Allow online access to work with old friends modules
-            patchMemory(code, size,
-                fpdVerPattern,
-                sizeof(fpdVerPattern), 9,
-                &fpdVerPatch,
-                sizeof(fpdVerPatch), 1
-            );
-
+                       fake_friends_version(progId, code, size);
             break;
         }
 
@@ -407,96 +498,24 @@ void patchCode(u64 progId, u8 *code, u32 size)
         case 0x0004001000027000LL: // KOR MSET
         case 0x0004001000028000LL: // TWN MSET
         {
-            static const u16 verPattern[] = u"Ver.";
-
-            //Patch Ver. string
-            patchMemory(code, size,
-                verPattern,
-                sizeof(verPattern) - sizeof(u16), 0,
-                u".hax",
-                sizeof(verPattern) - sizeof(u16), 1
-            );
+                       settings_string(progId, code, size);
             break;
         }
-
         case 0x0004013000008002LL: // NS
         {
-            static const u8 stopCartUpdatesPattern[] = {
-                0x0C, 0x18, 0xE1, 0xD8
-            };
-            static const u8 stopCartUpdatesPatch[] = {
-                0x0B, 0x18, 0x21, 0xC8
-            };
-
-            //Disable updates from foreign carts (makes carts region-free)
-            patchMemory(code, size, 
-                stopCartUpdatesPattern, 
-                sizeof(stopCartUpdatesPattern), 0, 
-                stopCartUpdatesPatch,
-                sizeof(stopCartUpdatesPatch), 2
-            );
-
-                       if (!failed_load_config) {
-                   u32 cpuSetting = 0;
-                               cpuSetting += config.n3ds_clock ? 0x1 : 0x0;
-                               cpuSetting += config.n3ds_l2    ? 0x2 : 0x0;
-
-                   if(cpuSetting)
-               {
-                       static const u8 cfgN3dsCpuPattern[] = {
-                       0x00, 0x40, 0xA0, 0xE1, 0x07, 0x00
-                       };
-
-                       u32 *cfgN3dsCpuLoc = (u32 *)memsearch(code, cfgN3dsCpuPattern, size, sizeof(cfgN3dsCpuPattern));
-
-                   //Patch N3DS CPU Clock and L2 cache setting
-                       if(cfgN3dsCpuLoc != NULL)
-                   {
-                           *(cfgN3dsCpuLoc + 1) = 0xE1A00000;
-                       *(cfgN3dsCpuLoc + 8) = 0xE3A00000 | cpuSetting;
-                       }
-               }
-                       }
+                       disable_cart_updates(progId, code, size);
+                       adjust_cpu_settings(progId, code, size);
             break;
         }
 
         case 0x0004013000001702LL: // CFG
         {
-            static const u8 secureinfoSigCheckPattern[] = {
-                0x06, 0x46, 0x10, 0x48, 0xFC
-            };
-            static const u8 secureinfoSigCheckPatch[] = {
-                0x00, 0x26
-            };
-
-            //Disable SecureInfo signature check
-            patchMemory(code, size,
-                secureinfoSigCheckPattern,
-                sizeof(secureinfoSigCheckPattern), 0,
-                secureinfoSigCheckPatch,
-                sizeof(secureinfoSigCheckPatch), 1
-            );
-
-            if(secureInfoExists())
-            {
-                static const u16 secureinfoFilenamePattern[] = u"SecureInfo_";
-                static const u16 secureinfoFilenamePatch[] = u"C";
-
-                //Use SecureInfo_C
-                patchMemory(code, size,
-                    secureinfoFilenamePattern,
-                    sizeof(secureinfoFilenamePattern) - sizeof(u16),
-                    sizeof(secureinfoFilenamePattern) - sizeof(u16),
-                    secureinfoFilenamePatch,
-                    sizeof(secureinfoFilenamePatch) - sizeof(u16), 2
-                );
-            }
-
+                       secureinfo_sigpatch(progId, code, size);
             break;
         }
-        default:
+/*        default:
                {
-            if(!failed_load_config && config.language_emu)
+            if(!failed_load_config && config.options[OPTION_LOADER_LANGEMU])
             {
                 u32 tidHigh = (progId & 0xFFFFFFF000000000LL) >> 0x24;
 
@@ -522,8 +541,7 @@ void patchCode(u64 progId, u8 *code, u32 size)
                     }
                 }
             }
-
             break;
-        }
+        } */
     }
 }
similarity index 100%
rename from asm/backdoor.s
rename to external/service/backdoor.s
index 0b692daf0b3674efef2e432f58dcb3e1bd0b97c2..b8687bf65379975f645a5cfcf0754399338cb18b 100644 (file)
@@ -6,9 +6,9 @@ struct config_file config;
 
 void regenerate_config() {
        f_mkdir(PATH_CFW);
+       f_mkdir(PATH_CFW "/lib");
     f_mkdir(PATH_FIRMWARES);
     f_mkdir(PATH_PATCHES);
-    f_mkdir(PATH_LOCEMU);
     f_mkdir(PATH_TEMP);
     f_mkdir(PATH_KEYS);
     f_mkdir(PATH_EXEFS);
index bb2a94906d2ebdae0717c95c6f9a1e28f13ae72e..261ac4d30331bc36d1282bcadf15532dc3b6b5be 100644 (file)
@@ -17,6 +17,23 @@ struct config_file {
 
 extern struct config_file config;
 
+enum type {
+       boolean_val, // Toggle
+       ranged_val,   // N1 - N2, left and right to pick.
+       mask_val     // Bitmask allowed values.
+};
+
+struct range_str {
+       int a, b;
+};
+
+struct options_s {
+       int index;
+       char name[64];
+       enum type allowed;
+       uint32_t a, b;
+}__attribute__((packed));
+
 #define OPTION_SIGPATCH     0  // Use builtin signature patch.
 #define OPTION_FIRMPROT     1  // Protect firmware from writes.
 #define OPTION_LOADER       2  // Use builtin loader module replacer.
@@ -31,8 +48,12 @@ extern struct config_file config;
 #define OPTION_NO_CLEAR_BG  9  // Framebuffer is preserved from whatever ran before us.
 #define OPTION_READ_ME      10 // Remove Help/Readme from menu.
 
-#define IGNORE_PATCH_DEPS   11  // Ignore patch UUID dependencies. Not recommended.
-#define IGNORE_BROKEN_SHIT  12 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
+#define OPTION_LOADER_CPU_L2   11   // Enable L2 cache.
+#define OPTION_LOADER_CPU_800MHZ 12 // Enable 800Mhz mode.
+#define OPTION_LOADER_LANGEMU  13 // Enable 800Mhz mode.
+
+#define IGNORE_PATCH_DEPS    14  // Ignore patch UUID dependencies. Not recommended.
+#define IGNORE_BROKEN_SHIT   15 // Allow enabling patches which are marked as 'incompatible'. Chances are there's a reason.
 
 //#define HEADER_COLOR        12 // Color of header text.
 //#define BG_COLOR            13 // Color of background.
index e82a8ee0da150dd19674667c3326b793eb09f6ca..80f7b57d227082ad0f60251c375a12b15675da12 100644 (file)
@@ -24,4 +24,7 @@ extern void *fcram_temp;
 // patch.c
 #define FCRAM_PATCHBIN_EXEC_LOC (FCRAM_START + FCRAM_SPACING * 4)
 
+// Throwaway temporary space. Don't expect it to stay sane.
+#define FCRAM_JUNK_LOCATION (FCRAM_START + FCRAM_SPACING * 5)
+
 #endif
index aa07f6c73fbf3d4eebca3b6cdb7698f6e5bc22fd..d891c2414620e2a6b2e39add6bcd9d4b2d008ee8 100644 (file)
@@ -1,7 +1,6 @@
 #include "common.h"
 #include "firm/firm.h"
 #include "firm/headers.h"
-#define MENU_BOOTME  -1
 #define MENU_MAIN     1
 
 #define MENU_OPTIONS  2
@@ -10,6 +9,32 @@
 #define MENU_HELP     5
 #define MENU_RESET    6
 #define MENU_POWER    7
+#define MENU_BOOTME   8
+
+static struct options_s options[] = {
+       { 0, "Signature Patch", boolean_val, 0, 0 },
+       { 1, "FIRM Protection", boolean_val, 0, 0 },
+       { 2, "SysModule Replacement", boolean_val, 0, 0 },
+       { 3, "Service Replacement", boolean_val, 0, 0 },
+       { 4, "ARM9 Thread", boolean_val, 0, 0 },
+
+       { 5, "Autoboot", boolean_val, 0, 0 },
+       { 6, "Silence w/ Autoboot", boolean_val, 0, 0 },
+       { 7, "Step through with button", boolean_val, 0, 0 },
+
+       { 8, "Don't draw background color", boolean_val, 0, 0 },
+       { 9, "Preserve framebuffer data", boolean_val, 0, 0 },
+
+       { 10, "Hide Help from menu", boolean_val, 0, 0 },
+
+       { 11, "Loader: CPU L2 enable", boolean_val, 0, 0 },
+       { 12, "Loader: CPU 800Mhz mode", boolean_val, 0, 0 },
+       { 13, "Loader: Language Emulation", boolean_val, 0, 0 },
+
+       { 14, "No dependency tracking", boolean_val, 0, 0 },
+       { 15, "Allow unsafe options", boolean_val, 0, 0 },
+       { -1, "", 0, 0, 0},
+};
 
 static int cursor_y = 0;
 static int which_menu = 1;
@@ -40,44 +65,26 @@ int menu_patches() { return MENU_MAIN; }
 int menu_options() {
     set_cursor(TOP_SCREEN, 0, 0);
 
-    const char *list[] = {
-        "Signature Patch",
-        "FIRM Write Protection",
-        "Inject Loader (NYI)",
-               "Inject Services",
-        "Enable ARM9 Thread",
-
-        "Autoboot",
-        "Silence debug w/ autoboot",
-        "Pause for input on steps",
-
-        "Don't draw background color (NYI)",
-        "Preserve current framebuffer (NYI)",
-        "Hide Readme/Help from menu",
-
-        "Ignore dependencies (NYI)",
-        "Allow enabling broken (NYI)",
-    };
-    const int menu_max = 12;
-
     header();
 
-    for(int i=0; i < menu_max; i++) {
+       int i = 0;
+    while(options[i].index != -1) { // -1 Sentinel.
         if (cursor_y == i)
             fprintf(TOP_SCREEN, "\x1b[32m>>\x1b[0m ");
         else
             fprintf(TOP_SCREEN, "   ");
 
         if (need_redraw)
-                       fprintf(TOP_SCREEN, "[%c] %s\n", (config.options[i] ? 'X' : ' '), list[i]);
+                       fprintf(TOP_SCREEN, "[%c] %s\n", (config.options[options[i].index] ? 'X' : ' '), options[i].name);
                else {
                        // Yes, this is weird. printf does a large number of extra things we don't
                        // want computed at the moment; this is faster.
                        putc(TOP_SCREEN, '[');
-                       putc(TOP_SCREEN, (config.options[i] ? 'X' : ' '));
+                       putc(TOP_SCREEN, (config.options[options[i].index] ? 'X' : ' '));
                        putc(TOP_SCREEN, ']');
                        putc(TOP_SCREEN, '\n');
                }
+               ++i;
     }
 
        need_redraw = 0;
@@ -87,13 +94,17 @@ int menu_options() {
     switch(key) {
         case BUTTON_UP:
             cursor_y -= 1;
+                       if (cursor_y < 0)
+                               cursor_y = 0;
             break;
         case BUTTON_DOWN:
             cursor_y += 1;
+                       if (options[cursor_y].index == -1)
+                               cursor_y -= 1;
             break;
         case BUTTON_A:
             // TODO - Value options
-            config.options[cursor_y] = !config.options[cursor_y];
+            config.options[options[cursor_y].index] = !config.options[options[cursor_y].index];
             break;
         case BUTTON_B:
                        need_redraw = 1;
@@ -103,12 +114,6 @@ int menu_options() {
             break;
     }
 
-    // Loop around the cursor.
-    if (cursor_y < 0)
-        cursor_y = menu_max - 1;
-    if (cursor_y > menu_max - 1)
-        cursor_y = 0;
-
     return 0;
 }
 
@@ -246,7 +251,7 @@ int menu_main() {
         case BUTTON_A:
                        need_redraw = 1;
                        cursor_y = 0;
-            if (ret == menu_max + 2)
+            if (ret == MENU_BOOTME)
                                return MENU_BOOTME; // Boot meh, damnit!
             return ret;
     }
@@ -284,6 +289,9 @@ int menu_handler() {
             menu_reset();
         case MENU_POWER:
             menu_poweroff();
+               default:
+                       fprintf(stderr, "Attempt to enter wrong menu!\n");
+                       to_menu = MENU_MAIN;
     }
 
     if (to_menu != 0)
diff --git a/source/patch/base.c b/source/patch/base.c
new file mode 100644 (file)
index 0000000..fd12e79
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdint.h>
+#include "../std/unused.h"
+#include "../std/memory.h"
+#include "../firm/firm.h"
+#include "../config.h"
+#include "../common.h"
+
+int patch_test() {
+       fprintf(stderr, "Testing, testing, 1, 2, 3, 4..\n");
+
+       return 0;
+}
+
diff --git a/source/patch/module.c b/source/patch/module.c
new file mode 100644 (file)
index 0000000..fecadf1
--- /dev/null
@@ -0,0 +1,76 @@
+#include <stdint.h>
+#include "../std/unused.h"
+#include "../std/memory.h"
+#include "../firm/firm.h"
+#include "../firm/fcram.h"
+#include "../config.h"
+#include "../common.h"
+
+int patch_modules() {
+       // TODO - load module cxi here
+       FILE* f = fopen(PATH_MODULES "/loader.cxi", "r");
+       if (!f) {
+               fprintf(stderr, "Module: loader.cxi not found on FS\n");
+               return 2;
+       }
+
+       uint32_t size = fsize(f);
+       fread((uint8_t*)FCRAM_JUNK_LOCATION, 1, size, f);
+       fclose(f);
+
+       // Look for the section that holds all the sysmodules
+       firm_section_h *sysmodule_section = NULL;
+       for (firm_section_h *section = firm_loc->section; section < firm_loc->section + 4; section++) {
+               if (section->address == 0x1FF00000 && section->type == FIRM_TYPE_ARM11) {
+                       sysmodule_section = section;
+                       break;
+               }
+       }
+
+       if (!sysmodule_section) {
+               fprintf(stderr, "Module: sysmodule section not found\n");
+               return 1;
+       }
+
+       ncch_h *module = (ncch_h*)FCRAM_JUNK_LOCATION;
+       ncch_h *sysmodule = (ncch_h *)((uint32_t)firm_loc + sysmodule_section->offset);
+
+       // Check if we want to replace an existing sysmodule
+       while (sysmodule->magic == NCCH_MAGIC) {
+               if (memcmp(sysmodule->programID, module->programID, 8) == 0) {
+                       // Expand firmware module size if needed to accomodate replacement.
+                       if (module->contentSize > sysmodule->contentSize) {
+                               // Location to shuffle to.
+                               uint32_t need_units = (module->contentSize - sysmodule->contentSize);
+                               uint8_t* move_to = ((uint8_t*)sysmodule + (module->contentSize + need_units) * 0x200);
+                               uint8_t* move_from = ((uint8_t*)sysmodule + module->contentSize * 0x200);
+
+                               uint32_t copy_size = 0x10000; // FIXME - Add a safe way to properly calculate the half of NCCH we need to copy. This is okay for now.
+
+                               memmove(move_to, move_from, copy_size);
+                               // TODO - This is hackish and possibly incorrect. It needs testing.
+                       }
+
+                       // Move the remaining modules closer
+                       if (module->contentSize < sysmodule->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 - Sysmodule section) =>
+                               memmove((uint8_t*)sysmodule + module->contentSize * 0x200, (uint8_t*)sysmodule + sysmodule->contentSize * 0x200, remaining_size);
+                               // Move end of section to be adjacent
+                       }
+
+                       // Copy the module into the firm
+                       memcpy(sysmodule, module, module->contentSize * 0x200);
+                       break;
+               }
+               sysmodule = (ncch_h *)((uintptr_t)sysmodule + sysmodule->contentSize * 0x200);
+       }
+
+       fprintf(stderr, "Module: injected modules.\n");
+
+       return 0;
+}
+
index 301f4e890462a37bd3c73774b286d516a2412da8..b0ae99db7a3a5f08c8c5e521afc8ac29e22ee548 100644 (file)
@@ -2,6 +2,8 @@
 #define __PATCH_FORMAT_H
 
 // The following are titleids which are handled specially for one reason or another.
+// We use titleIDs to be generic; it ensures that patches can share the same format
+// regardless of whether they're intended for loader or not. Simple logistics.
 #define NATIVE_FIRM_TITLEID      0x0004013800000002llu // NATIVE_FIRM
 #define NATIVE_FIRM_N3DS_TITLEID 0x0004013820000002llu // NATIVE_FIRM, n3ds
 
 #define PATCH_FAIL_ABORT (1 << 1) // If patch fails to apply, abort and show an error.
 #define PATCH_DISABLED   (1 << 2) // Do not allow changing this patch's status. With PATCH_MANDATORY, this prevents disabling it.
 
-#define PATH_CFW        "/corbenik"                // CFW root directory.
-#define PATH_CONFIG     PATH_CFW "/main.conf"      // Config file.
-#define PATH_LOCEMU     PATH_CFW "/locale.conf"    // Locale emulation config
-#define PATH_CPU_CFG    PATH_CFW "/cpu.conf"       // CPU settings config
+// You can redefine this in the Makefile, if you'd like.
+// Recommended names for being silly:
+//   Windows
+//   system
+#ifndef PATH_CFW
+  #define PATH_CFW        "/corbenik"                       // CFW root directory.
+#endif
+
+#define PATH_CONFIG_DIR PATH_CFW "/etc"                   // Config file directory.
+#define PATH_CONFIG     PATH_CONFIG_DIR "/main.conf"      // Config file.
+#define PATH_LOCEMU     PATH_CONFIG_DIR "/locale.conf"    // Locale emulation config
+#define PATH_CPU_CFG    PATH_CONFIG_DIR "/cpu.conf"       // CPU settings config
 
-#define PATH_FIRMWARES  PATH_CFW "/firm"       // Firmware folder.
 #define PATH_PATCHES    PATH_CFW "/bin"            // Patch binary folder.
-#define PATH_TEMP       PATH_CFW "/temp"           // Files that are transient (user can delete them and they will be regenerated)
-#define PATH_KEYS       PATH_CFW "/keys"           // Keyfiles will be loaded from this dir, and additionally the root if not found.
-#define PATH_EXEFS      PATH_CFW "/exefs"          // ExeFS overrides, named like '<titleid>.exefs'
+#define PATH_FIRMWARES  PATH_CFW "/lib/firmware"   // Firmware folder.
+#define PATH_MODULES    PATH_CFW "/lib/module"     // Sysmodule location
+#define PATH_SERVICES   PATH_CFW "/lib/svc"        // Service code location.
+#define PATH_TEMP       PATH_CFW "/tmp"            // Files that are transient (user can delete them and they will be regenerated)
+#define PATH_KEYS       PATH_CFW "/share/keys"     // Keyfiles will be loaded from this dir, and additionally the root if not found.
+#define PATH_EXEFS      PATH_CFW "/lib/exe"        // ExeFS overrides, named like '<titleid>.exefs'
 
 #define PATH_NATIVE_F   PATH_FIRMWARES "/native"
 #define PATH_AGB_F      PATH_FIRMWARES "/agb"
 #define PATH_TWL_F      PATH_FIRMWARES "/twl"
 
-#define PATH_NATIVE_CETK       PATH_KEYS "/native.cetk"
-#define PATH_NATIVE_FIRMKEY    PATH_KEYS "/native.key"
+#define PATH_NATIVE_CETK       PATH_FIRMWARES "/native.cetk"
+
+#define PATH_TWL_CETK       PATH_FIRMWARES "/twl.cetk"
 
-#define PATH_TWL_CETK       PATH_KEYS "/twl.cetk"
-#define PATH_TWL_FIRMKEY    PATH_KEYS "/twl.key"
+#define PATH_AGB_CETK       PATH_FIRMWARES "/agb.cetk"
 
-#define PATH_AGB_CETK       PATH_KEYS "/agb.cetk"
-#define PATH_AGB_FIRMKEY    PATH_KEYS "/agb.key"
+#define PATH_NATIVE_FIRMKEY    PATH_KEYS "/native.key"
+#define PATH_TWL_FIRMKEY       PATH_KEYS "/twl.key"
+#define PATH_AGB_FIRMKEY       PATH_KEYS "/agb.key"
 
-#define PATH_SLOT0X11KEY96  PATH_KEYS "/11.key"
+// These are used with O3DS units. Keep in mind I have no way to test this.
+#define PATH_NATIVE_FIRMKEY_2    PATH_KEYS "/native_old.key"
+#define PATH_TWL_FIRMKEY_2       PATH_KEYS "/twl_old.key"
+#define PATH_AGB_FIRMKEY_2       PATH_KEYS "/agb_old.key"
 
-#define PATH_ALT_SLOT0X11KEY96 "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up paths.
+#define PATH_SLOT0X11KEY96     PATH_KEYS "/11.key"
 
-#define PATH_MEMBIN     PATH_TEMP "/memory_p"        // Memory binary
-#define PATH_NATIVE_P   PATH_TEMP "/native_p"   // Native FIRM patched
-#define PATH_AGB_P      PATH_TEMP "/agb_firm_p"      // AGB FIRM patched
-#define PATH_TWL_P      PATH_TEMP "/twl_firm_p"      // TWL FIRM patched
+#define PATH_ALT_SLOT0X11KEY96 "/slot0x11key96.bin" // Hey, your perrogative, buddy. I like cleaned up paths.
 
 // Structure of a patch file.
 struct system_patch {
@@ -73,20 +86,5 @@ struct system_patch {
 struct patch_opcode {
 } __attribute__((packed));
 
-/*
-[PATCH]
-version=1
-cfw_version=1
-
-name=Signature Check
-desc=Disables firmware signature checking.
-uuid=1
-title_id=0004013800000002
-[DEPENDS]
-none
-[DATA]
-<BYTECODE AS HEX>
-*/
-
 #endif
 
index 5cccb03f98e5fb14031bb086ba89de0e322b77e4..f8782cad11d49eef0cb3d59784fc4cef627371d4 100644 (file)
@@ -13,6 +13,7 @@ int execp(char* path);
 extern int patch_signatures();
 extern int patch_firmprot();
 extern int patch_services();
+extern int patch_modules();
 
 // A portion of this file is inherited from Luma3DS.
 /*u32 getLoader(u8 *pos, u32 *loaderSize) {
@@ -75,12 +76,15 @@ int patch_firm_all() {
 
        // Replace loader?
        if (config.options[OPTION_LOADER]) {
-               // Yes.
-
+               if(patch_modules()) {
+                       abort("Fatal. Service patch has failed.");
+               }
                // This requires OPTION_SIGPATCH.
        }
 
-       // Replace loader?
+       wait();
+
+       // Inject services?
        if (config.options[OPTION_SERVICES]) {
                if(patch_services()) {
                        abort("Fatal. Service patch has failed.");
@@ -94,5 +98,7 @@ int patch_firm_all() {
                // FIXME - NYI
        }
 
+       wait();
+
        return 0;
 }