diff --git a/Makefile b/Makefile index 705882c..853f98c 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ LD = $(DEVKITARM)/bin/arm-none-eabi-ld OBJCOPY = $(DEVKITARM)/bin/arm-none-eabi-objcopy name := ReiNX +ver := 1.6 dir_source := src dir_data := data @@ -17,7 +18,7 @@ dir_out := out dir_sysmod := NX_Sysmodules ARCH := -march=armv4t -mtune=arm7tdmi -mthumb -mthumb-interwork -CFLAGS = $(ARCH) -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -fno-builtin -std=gnu11# -Wall +CFLAGS = $(ARCH) -DVERSION='"$(ver)"' -Os -nostdlib -ffunction-sections -fdata-sections -fomit-frame-pointer -fno-inline -fno-builtin -std=gnu11# -Wall LDFLAGS = $(ARCH) -nostartfiles -lgcc -Wl,--nmagic,--gc-sections objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \ diff --git a/link.ld b/link.ld index 10f17ee..e49cdc7 100644 --- a/link.ld +++ b/link.ld @@ -2,8 +2,8 @@ ENTRY(_start) SECTIONS { - PROVIDE(__ipl_start = 0x40003000); - . = __ipl_start; + PROVIDE(payload_start = 0x40003000); + . = payload_start; .text.start : { *(.text.start) @@ -18,7 +18,7 @@ SECTIONS *(.rodata*); } . = ALIGN(0x10); - __ipl_end = .; + payload_end = .; .bss : { __bss_start = .; diff --git a/src/bootloader.c b/src/bootloader.c index 8afa02e..afb8ad8 100644 --- a/src/bootloader.c +++ b/src/bootloader.c @@ -15,7 +15,6 @@ */ #include "hwinit.h" -#include "fuse.h" #include "error.h" #include "bootloader.h" @@ -24,6 +23,31 @@ void check_sku() { panic(); } +u32 get_unknown_config() { + u32 res = 0; + u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4)); + u32 config = ((deviceInfo & 4u) >> 2) | 2 * ((deviceInfo & 0x100u) >> 8); + + if(config == 1) + return 0; + if(config == 2) + return 1; + if(config || (res = FUSE(FUSE_SPARE_BIT_5)) != 0) + res = 3; + return res; +} + +u32 get_unit_type() { + u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4)); + u32 deviceType = deviceInfo & 3 | 4 * ((deviceInfo & 0x200u) >> 9); + + if(deviceType == 3) + return 0; + if(deviceType == 4) + return 1; + return 2; +} + void check_config_fuses() { u32 config = get_unknown_config(); u32 unitType = get_unit_type(); diff --git a/src/bootrom.c b/src/bootrom.c index 7e6b109..01d4c07 100644 --- a/src/bootrom.c +++ b/src/bootrom.c @@ -36,5 +36,4 @@ void bootrom(void) { // Clear the boot reason to avoid problems later PMC(APBDEV_PMC_SCRATCH200) = 0x0; PMC(APBDEV_PMC_RST_STATUS_0) = 0x0; - //PMC(APBDEV_PMC_SCRATCH49_0) = 0x0; } \ No newline at end of file diff --git a/src/error.c b/src/error.c index 669bab4..6dcd62b 100644 --- a/src/error.c +++ b/src/error.c @@ -32,5 +32,5 @@ void panic() { void error(char *errStr) { gfx_con_setcol(&gfx_con, RED, 0, 0); print("Error: %s", errStr); - gfx_con_setcol(&gfx_con, ORANGE, 0, 0); + gfx_con_setcol(&gfx_con, DEFAULT_TEXT_COL, 0, 0); } \ No newline at end of file diff --git a/src/error.h b/src/error.h index 63fabe5..297d55d 100644 --- a/src/error.h +++ b/src/error.h @@ -17,7 +17,6 @@ #pragma once #include "hwinit/types.h" -#include "hwinit/gfx.h" void panic(); void error(char *errStr); \ No newline at end of file diff --git a/src/firmware.c b/src/firmware.c index 6c46115..0bb3acc 100644 --- a/src/firmware.c +++ b/src/firmware.c @@ -17,31 +17,13 @@ #include #include #include "hwinit.h" -#include "hwinit/gfx.h" #include "fs.h" -#include "fuse.h" #include "package.h" #include "error.h" #include "firmware.h" -#include "kippatches.h" - -#define VERSION "v1.0" static pk11_offs *pk11Offs = NULL; -static void SE_lock() { - for (u32 i = 0; i < 16; i++) - se_key_acc_ctrl(i, 0x15); - - for (u32 i = 0; i < 2; i++) - se_rsa_acc_ctrl(i, 1); - - SE(0x4) = 0; // Make this reg secure only. - SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only. - SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all rsa access regs secure only. - SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only. -} - void drawSplash() { // Draw splashscreen to framebuffer. if(fopen("/ReiNX/splash.bin", "rb") != 0) { @@ -68,7 +50,6 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { uPtr *sha2_ptr = NULL; switch(pk11->kb) { case KB_FIRMWARE_VERSION_100_200: { - //u8 rlcPattern[] = {0xE0, 0xFF, 0x1D, 0xF0, 0x00, 0x00, 0x00, 0x91}; //TODO: relocator patch for 1.0.0 u8 verPattern[] = {0x19, 0x00, 0x36, 0xE0, 0x03, 0x08, 0x91}; u8 hdrSigPattern[] = {0xFF, 0x97, 0xC0, 0x00, 0x00, 0x34, 0xA1, 0xFF, 0xFF}; u8 sha2Pattern[] = {0xE0, 0x03, 0x08, 0x91, 0xE1, 0x03, 0x13, 0xAA}; @@ -103,7 +84,7 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { sha2_ptr = (uPtr*)memsearch((void *)pk11->secmon_base, 0x10000, sha2Pattern, sizeof(sha2Pattern)); break; } - default: { + case KB_FIRMWARE_VERSION_500: { u8 verPattern[] = {0x00, 0x01, 0x00, 0x36, 0xFD, 0x7B, 0x41, 0xA9}; u8 hdrSigPattern[] = {0x86, 0xFE, 0xFF, 0x97, 0x80, 0x00, 0x00, 0x36}; u8 sha2Pattern[] = {0xF2, 0xFB, 0xFF, 0x97, 0xE0, 0x03}; @@ -111,13 +92,22 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { ver_ptr = (uPtr*)memsearch((void *)pk11->secmon_base, 0x10000, verPattern, sizeof(verPattern)); pk21_ptr = (uPtr*)((u32)ver_ptr - 0xC); hdrsig_ptr = (uPtr*)(memsearch((void *)pk11->secmon_base, 0x10000, hdrSigPattern, sizeof(hdrSigPattern)) + 0x4); - sha2_ptr = (uPtr*)memsearch((void *)pk11->secmon_base, 0x10000, sha2Pattern, sizeof(sha2Pattern)); + sha2_ptr = (uPtr*)(memsearch((void *)pk11->secmon_base, 0x10000, sha2Pattern, sizeof(sha2Pattern))); + break; + } + default: { + u8 verPattern[] = {0x00, 0x01, 0x00, 0x36, 0xFD, 0x7B, 0x41, 0xA9}; + u8 hdrSigPattern[] = { 0x9A, 0xFF, 0xFF, 0x97, 0x80, 0x00, 0x00, 0x36}; + u8 sha2Pattern[] = {0x81, 0x00, 0x80, 0x72, 0xB5, 0xFB, 0xFF, 0x97}; + + ver_ptr = (uPtr*)memsearch((void *)pk11->secmon_base, 0x10000, verPattern, sizeof(verPattern)); + pk21_ptr = (uPtr*)((u32)ver_ptr - 0xC); + hdrsig_ptr = (uPtr*)(memsearch((void *)pk11->secmon_base, 0x10000, hdrSigPattern, sizeof(hdrSigPattern)) + 0x4); + sha2_ptr = (uPtr*)(memsearch((void *)pk11->secmon_base, 0x10000, sha2Pattern, sizeof(sha2Pattern)) + 0x4); break; } } - /*if (pre2x) { //TODO: relocator patch for 1.0.0 - *rlc_ptr = ADRP(0, 0x3BFE8020); - };*/ + if (pk11->kb != KB_FIRMWARE_VERSION_100_200) { *pk21_ptr = NOP; }; @@ -147,15 +137,7 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { } u8 kipHash[0x20]; - char *patchFilter[] = { "nosigchk", "nocmac", "nogc", NULL }; - - // enable nogc if there's a file called "nogc" in /ReiNX/ - //(I expect the 1% of people this effects can read the guide) - if (!fopen("/ReiNX/nogc", "rb")) { - patchFilter[2] = NULL; - fclose(); - } - + //Patch FS module (truly not my proudest code TODO cleanup) LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips, link) { //Patch FS @@ -180,12 +162,8 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { if (!pset) { print(" could not find patchset with matching hash\n"); } else { - int res = kippatch_apply_set(kipDecompText, moddedKip->sections[i].size_decomp, pset, patchFilter); - if (res) { - gfx_con_setcol(&gfx_con, RED, 0, 0); - print("Error: kippatch_apply_set() returned %d\n", res); - gfx_con_setcol(&gfx_con, ORANGE, 0, 0); - } + int res = kippatch_apply_set(kipDecompText, moddedKip->sections[i].size_decomp, pset); + if (res) error("kippatch_apply_set() failed\n"); } moddedKip->flags &= ~1; @@ -255,6 +233,7 @@ int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw) { break; case KB_FIRMWARE_VERSION_500: + case KB_FIRMWARE_VERSION_600: default: se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx); se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); @@ -271,15 +250,13 @@ int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw) { u8 loadFirm() { sdmmc_storage_t storage; sdmmc_t sdmmc; - u32 ret = 0; + //Init nand sdmmc_storage_init_mmc(&storage, &sdmmc, SDMMC_4, SDMMC_BUS_WIDTH_8, 4); sdmmc_storage_set_mmc_partition(&storage, 1); // Read package1. - print("Reading Package1...\n"); - u8 *package1 = (u8 *)malloc(0x40000); - sdmmc_storage_read(&storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, package1); + u8 *package1 = ReadPackage1(&storage); // Setup firmware specific data. pk11Offs = pkg11_offsentify(package1); @@ -297,33 +274,8 @@ u8 loadFirm() { PMC(APBDEV_PMC_SCRATCH1) = pk11Offs->warmboot_base; free(package1); - // Read GPT partition. - LIST_INIT(gpt); - sdmmc_storage_set_mmc_partition(&storage, 0); - print("Parsing GPT...\n"); - nx_emmc_gpt_parse(&gpt, &storage); - emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); - nx_emmc_gpt_free(&gpt); - if (!pkg2_part) { - error("Failed to read GPT!\n"); - return 1; - } - - // Read Package2. - u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE); - print("Reading Package2 size...\n"); - nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp); - u32 *hdr = (u32 *)(tmp + 0x100); - u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3]; - free(tmp); - u8 *pkg2 = malloc(ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE)); - print("Reading Package2...\n"); - ret = nx_emmc_part_read(&storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE) / NX_EMMC_BLOCKSIZE, pkg2); - sdmmc_storage_end(&storage); - if (!ret) { - error("Failed to read Package2!\n"); - return 1; - } + //Read package2 + u8 *pkg2 = ReadPackage2(&storage); // Unpack Package2. print("Unpacking package2...\n"); @@ -339,7 +291,7 @@ u8 loadFirm() { char **sysmods = NULL; size_t cnt = enumerateDir(&sysmods, "/ReiNX/sysmodules", "*.kip"); for (u32 i = 0; i < cnt ; i++) { - print("%kLoading %s\n%k", YELLOW, sysmods[i], ORANGE); + print("%kLoading %s\n%k", YELLOW, sysmods[i], DEFAULT_TEXT_COL); loadKip(&kip1_info, sysmods[i]); free(sysmods[i]); } @@ -349,6 +301,19 @@ u8 loadFirm() { buildFirmwarePackage(dec_pkg2->data, dec_pkg2->sec_size[PKG2_SEC_KERNEL], &kip1_info); } +static void SE_lock() { + for (u32 i = 0; i < 16; i++) + se_key_acc_ctrl(i, 0x15); + + for (u32 i = 0; i < 2; i++) + se_rsa_acc_ctrl(i, 1); + + SE(0x4) = 0; // Make this reg secure only. + SE(SE_KEY_TABLE_ACCESS_LOCK_OFFSET) = 0; // Make all key access regs secure only. + SE(SE_RSA_KEYTABLE_ACCESS_LOCK_OFFSET) = 0; // Make all rsa access regs secure only. + SE(SE_SECURITY_0) &= 0xFFFFFFFB; // Make access lock regs secure only. +} + void launch() { u8 pre4x = pk11Offs->kb < KB_FIRMWARE_VERSION_400; @@ -396,7 +361,7 @@ void firmware() { gfx_init_ctxt(&gfx_ctxt, display_init_framebuffer(), 720, 1280, 768); gfx_clear_color(&gfx_ctxt, 0xFF000000); gfx_con_init(&gfx_con, &gfx_ctxt); - gfx_con_setcol(&gfx_con, ORANGE, 0, 0); + gfx_con_setcol(&gfx_con, DEFAULT_TEXT_COL, 0, 0); while (!sdMount()) { error("Failed to init SD card!\n"); @@ -406,16 +371,18 @@ void firmware() { btn_wait(); } - if(PMC(APBDEV_PMC_SCRATCH49_0) != 69 && fopen("/ReiNX.bin", "rb")) { + if(PMC(APBDEV_PMC_SCRATCH49) != 69 && fopen("/ReiNX.bin", "rb")) { fread((void*)PAYLOAD_ADDR, fsize(), 1); fclose(); sdUnmount(); display_end(); CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_V) |= 0x400; // Enable AHUB clock. CLOCK(CLK_RST_CONTROLLER_CLK_OUT_ENB_Y) |= 0x40; // Enable APE clock. - PMC(APBDEV_PMC_SCRATCH49_0) = 69; + PMC(APBDEV_PMC_SCRATCH49) = 69; ((void (*)())PAYLOAD_ADDR)(); } + SYSREG(AHB_AHB_SPARE_REG) = (volatile vu32)0xFFFFFF9F; + PMC(APBDEV_PMC_SCRATCH49) = 0; print("Welcome to ReiNX %s!\n", VERSION); loadFirm(); diff --git a/src/firmware.h b/src/firmware.h index 525e142..3ca6143 100644 --- a/src/firmware.h +++ b/src/firmware.h @@ -28,10 +28,6 @@ #define PAYLOAD_ADDR 0xCFF00000 -//Instructions -#define NOP 0xD503201F -#define ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) - // TODO: Maybe find these with memsearch static const pk11_offs _pk11_offs[] = { //{ "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x4002B020, 0x8000D000, 1 }, //TODO: relocator patch for 1.0.0 @@ -41,16 +37,17 @@ static const pk11_offs _pk11_offs[] = { { "20170710161758", 2, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //3.0.1 - 3.0.2 { "20170921172629", 3, 0x1800, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0 }, //4.0.0 - 4.1.0 { "20180220163747", 4, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003B000, 0 }, //5.0.0 - 5.0.2 + { "20180802162753", 5, 0x1900, 0x3FE0, { 1, 2, 0 }, 0x4002B000, 0x4003D800, 0 }, //6.0.0 { NULL, 0, 0, 0, 0 } // End. }; -#define NUM_KEYBLOB_KEYS 5 -static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][0x10] = { +static const u8 keyblob_keyseeds[][0x10] = { { 0xDF, 0x20, 0x6F, 0x59, 0x44, 0x54, 0xEF, 0xDC, 0x70, 0x74, 0x48, 0x3B, 0x0D, 0xED, 0x9F, 0xD3 }, //1.0.0 { 0x0C, 0x25, 0x61, 0x5D, 0x68, 0x4C, 0xEB, 0x42, 0x1C, 0x23, 0x79, 0xEA, 0x82, 0x25, 0x12, 0xAC }, //3.0.0 { 0x33, 0x76, 0x85, 0xEE, 0x88, 0x4A, 0xAE, 0x0A, 0xC2, 0x8A, 0xFD, 0x7D, 0x63, 0xC0, 0x43, 0x3B }, //3.0.1 { 0x2D, 0x1F, 0x48, 0x80, 0xED, 0xEC, 0xED, 0x3E, 0x3C, 0xF2, 0x48, 0xB5, 0x65, 0x7D, 0xF7, 0xBE }, //4.0.0 - { 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 } //5.0.0 + { 0xBB, 0x5A, 0x01, 0xF9, 0x88, 0xAF, 0xF5, 0xFC, 0x6C, 0xFF, 0x07, 0x9E, 0x13, 0x3C, 0x39, 0x80 }, //5.0.0 + { 0xD8, 0xCC, 0xE1, 0x26, 0x6A, 0x35, 0x3F, 0xCC, 0x20, 0xF3, 0x2D, 0x3B, 0x51, 0x7D, 0xE9, 0xC0 } //6.0.0 }; static const u8 cmac_keyseed[0x10] = { 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 }; diff --git a/src/fs.c b/src/fs.c index 3e762c3..112e2ec 100644 --- a/src/fs.c +++ b/src/fs.c @@ -17,7 +17,6 @@ #include #include #include "hwinit.h" -#include "hwinit/gfx.h" #include "hwinit/ff.h" #include "error.h" #include "fs.h" @@ -40,10 +39,10 @@ u32 sdMount() { } void sdUnmount() { + if (!sd_mounted) return; f_mount(NULL, "", 1); sdmmc_storage_end(&sd_storage); sd_mounted = 0; - } u32 fopen(const char *path, const char *mode) { diff --git a/src/fuse.c b/src/fuse.c deleted file mode 100644 index 0239048..0000000 --- a/src/fuse.c +++ /dev/null @@ -1,47 +0,0 @@ -/* -* Copyright (c) 2018 Reisyukaku -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#include "hwinit/t210.h" -#include "fuse.h" - -u32 get_unknown_config() { - u32 res = 0; - u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4)); - u32 config = ((deviceInfo & 4u) >> 2) | 2 * ((deviceInfo & 0x100u) >> 8); - - if(config == 1) - return 0; - if(config == 2) - return 1; - if(config || (res = FUSE(FUSE_SPARE_BIT_5)) != 0) - res = 3; - return res; -} - -u32 get_unit_type() { - u32 deviceInfo = FUSE(FUSE_RESERVED_ODMX(4)); - u32 deviceType = deviceInfo & 3 | 4 * ((deviceInfo & 0x200u) >> 9); - - if(deviceType == 3) - return 0; - if(deviceType == 4) - return 1; - return 2; -} - -u32 master_key_ver() { - return FUSE(FUSE_SPARE_BIT_5) & 1; -} \ No newline at end of file diff --git a/src/fuse.h b/src/fuse.h deleted file mode 100644 index 0d3640e..0000000 --- a/src/fuse.h +++ /dev/null @@ -1,21 +0,0 @@ -/* -* Copyright (c) 2018 Reisyukaku -* -* This program is free software; you can redistribute it and/or modify it -* under the terms and conditions of the GNU General Public License, -* version 2, as published by the Free Software Foundation. -* -* This program is distributed in the hope it will be useful, but WITHOUT -* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -* more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -*/ - -#pragma once - -u32 get_unknown_config(); -u32 get_unit_type(); -u32 master_key_ver(); \ No newline at end of file diff --git a/src/hwinit.h b/src/hwinit.h index ce641ca..b4d1ef7 100644 --- a/src/hwinit.h +++ b/src/hwinit.h @@ -41,4 +41,7 @@ #include "hwinit/nx_emmc.h" #include "hwinit/se.h" #include "hwinit/se_t210.h" -#include "hwinit/mmc.h" \ No newline at end of file +#include "hwinit/mmc.h" +#include "hwinit/gfx.h" + +#define DEFAULT_TEXT_COL ORANGE \ No newline at end of file diff --git a/src/hwinit/pmc.h b/src/hwinit/pmc.h index 1c62f5e..de4deb8 100644 --- a/src/hwinit/pmc.h +++ b/src/hwinit/pmc.h @@ -45,6 +45,6 @@ #define APBDEV_PMC_SCRATCH200 0x840 #define APBDEV_PMC_RST_STATUS_0 0x1B4 #define APBDEV_PMC_SECURE_SCRATCH49_0 0x3A4 -#define APBDEV_PMC_SCRATCH49_0 0x244 +#define APBDEV_PMC_SCRATCH49 0x244 #endif diff --git a/src/hwinit/types.h b/src/hwinit/types.h index 6282cbe..bde691c 100644 --- a/src/hwinit/types.h +++ b/src/hwinit/types.h @@ -52,6 +52,7 @@ enum KB_FIRMWARE_VERSION { KB_FIRMWARE_VERSION_301 = 2, KB_FIRMWARE_VERSION_400 = 3, KB_FIRMWARE_VERSION_500 = 4, + KB_FIRMWARE_VERSION_600 = 5, KB_FIRMWARE_VERSION_MAX }; diff --git a/src/hwinit/util.c b/src/hwinit/util.c index 2bcd12a..0c5003c 100644 --- a/src/hwinit/util.c +++ b/src/hwinit/util.c @@ -64,6 +64,19 @@ uPtr memsearch(const u8 *startPos, u32 searchSize, const void *pattern, u32 patt return 0; } +//probably could be more optimized :< +uPtr getFreeSpace(void *start, size_t space, size_t searchSize) { + for(int i = 0; i < searchSize; i++) { + if(*(u8*)(start+i) == 0) { + for(int j=0;j. -*/ - -#include - -#include "hwinit/types.h" -#include "hwinit/util.h" -#include "kippatches.h" -#include "fs.h" -#include "kippatches/fs.inc" - -#define NOP 0xD503201F - - -// TODO: get full hashes somewhere and not just the first 16 bytes -// every second one is the exfat version -kippatchset_t kip_patches[] = { - { "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe\x68\xdc\xb2\x0b\x41\x09\x5b\xb4", fs_kip_patches_100 }, - { "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96\x4a\x12\x1f\x04\xb6\x1b\x17\x5e", fs_kip_patches_100 }, - { "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28\xf6\x2f\x19\xfa\x79\x45\x53\x5b", fs_kip_patches_200 }, - { "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9\xfd\xd6\x8e\x43\x63\x16\x18\x18", fs_kip_patches_200 }, - { "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c\x0b\x96\x3f\x9a\xff\xdd\xe5\x66", fs_kip_patches_210 }, - { "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8\x30\x51\xc6\x64\xe6\x45\x2d\x32", fs_kip_patches_210 }, - { "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b\x23\xda\xb5\xb4\xdb\xba\xef\xe7", fs_kip_patches_300 }, - { "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7\xbc\xde\x75\x31\x81\xd9\x01\xa6", fs_kip_patches_300 }, - { "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31\x3f\x4d\x83\x76\x53\xcc\xc3\x71", fs_kip_patches_301 }, - { "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89\x83\xbc\x7a\xdd\x93\x2b\xe3\xd1", fs_kip_patches_301 }, - { "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c\x62\x46\xff\x70\x94\x6f\x10\xfb", fs_kip_patches_401 }, - { "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9\xf3\xfd\x1f\x19\xea\xce\x4a\x5a", fs_kip_patches_401 }, - { "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82\x71\xf3\x91\x69\x95\x41\x3b\x0b", fs_kip_patches_410 }, - { "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0\x63\x3a\xa0\xdb\xae\xe0\x37\x7e", fs_kip_patches_410 }, - { "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad\x41\x9b\x63\xb2\x3e\x78\x5a\x0c", fs_kip_patches_500 }, - { "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5\x75\xf8\xf3\x60\x84\x2b\x32\xb4", fs_kip_patches_500 }, - { "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f\x0a\x2f\xab\x1b\x45\xce\xbb\x93", fs_kip_patches_510 }, - { "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99\xdf\x22\x42\xcb\x6b\xac\x2d\xf1", fs_kip_patches_510 }, - { NULL, NULL, NULL }, -}; - -int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch) { - if (!patch || !patch->diffs) return -1; - - for (kipdiff_t *diff = patch->diffs; diff->len; ++diff) { - if (!diff->len || diff->offset + diff->len > kipdata_len) - return 1 + (int)(diff - patch->diffs); - u8 *start = kipdata + diff->offset; - if (memcmp(start, diff->orig_bytes, diff->len)) - return 1 + (int)(diff - patch->diffs); - // TODO: maybe start copying after every diff has been verified? - memcpy(start, diff->patch_bytes, diff->len); - } - - return 0; -} - - -int nca_patch(u8 * kipdata, u64 kipdata_len) { - char pattern[8] = {0xE5, 0x07, 0x00, 0x32, 0xE0, 0x03, 0x16, 0xAA}; - char buf[0x10]; - memcpy(buf, kipdata+0x1C450, 0x10); - u32 * addr = memsearch(kipdata, kipdata_len, pattern, sizeof(pattern)); - int ret=0; - int max_dist = 0x10; - for(int i=0; ipatches; p && p->name; ++p) { - int found = 0; - for (char **filtname = filter; filtname && *filtname; ++filtname) { - if (!strcmp(p->name, *filtname)) { - found = 1; - break; - } - } - - if (filter && !found) continue; - - int r = kippatch_apply(kipdata, kipdata_len, p); - if (r) return r; - } - if(!strncmp("FS", patchset->kip_name, 2)) - nca_patch(kipdata, kipdata_len); - return 0; -} - -kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets) { - for (kippatchset_t *ps = patchsets; ps && ps->kip_name; ++ps) { - if (!memcmp(kiphash, ps->kip_hash, 0x10)) return ps; - } - return NULL; -} diff --git a/src/kippatches.h b/src/kippatches.h deleted file mode 100644 index 277f93b..0000000 --- a/src/kippatches.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include "hwinit/types.h" - -typedef struct kipdiff_s { - u64 offset; // offset from start of kip's .text segment - u32 len; // length of below strings, NULL signifies end of patch - const char *orig_bytes; // original byte string (this must match exactly) - const char *patch_bytes; // replacement byte string (same length) -} kipdiff_t; - -// a single patch for a particular kip version -typedef struct kippatch_s { - const char *name; // name/id of the patch, NULL signifies end of patchset - kipdiff_t *diffs; // array of kipdiff_t's to apply -} kippatch_t; - -// a group of patches that patch several different things in a particular kip version -typedef struct kippatchset_s { - const char *kip_name; // name/id of the kip, NULL signifies end of patchset list - const char *kip_hash; // sha256 of the right version of the kip - kippatch_t *patches; // set of patches for this version of the kip -} kippatchset_t; - -// fs - -extern kippatchset_t kip_patches[]; - -int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch); -int kippatch_apply_set(u8 *kipdata, u64 kipdata_len, kippatchset_t *patchset, char **filter); -kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets); diff --git a/src/kippatches/fs.inc b/src/kippatches/fs.inc index af17442..1128c51 100644 --- a/src/kippatches/fs.inc +++ b/src/kippatches/fs.inc @@ -139,12 +139,59 @@ static kipdiff_t fs_diffs_510_nocmac[8] = { { 0, 0, NULL, NULL }, }; +static kipdiff_t fs_diffs_600_exfat_nocmac[8] = { + { 0x10B7F4, 4, "\x20\x0A\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x10BCF8, 4, "\xA0\x03\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x113934, 4, "\x60\x14\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x11429C, 4, "\x60\x06\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x1143DC, 4, "\x20\x07\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x11B128, 4, "\xC0\x05\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x11B254, 4, "\xC0\x06\x00\x36", "\x1F\x20\x03\xD5" }, + { 0, 0, NULL, NULL }, +}; + +//exfat offsets are simply shifted by + 0xB700 +static kipdiff_t fs_diffs_600_nocmac[8] = { + { 0x1000F4, 4, "\x20\x0A\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x1005F8, 4, "\xA0\x03\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x108234, 4, "\x60\x14\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x108B9C, 4, "\x60\x06\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x108CDC, 4, "\x20\x07\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x10FA28, 4, "\xC0\x05\x00\x36", "\x1F\x20\x03\xD5" }, + { 0x10FB54, 4, "\xC0\x06\x00\x36", "\x1F\x20\x03\xD5" }, + { 0, 0, NULL, NULL }, +}; + static kipdiff_t fs_diffs_510_nogc[3] = { { 0xCF794, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, { 0xD7770, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, { 0, 0, NULL, NULL }, }; +static kipdiff_t fs_diffs_600_exfat_nogc[3] = { + { 0x15EFF4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, + { 0x138320, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, + { 0, 0, NULL, NULL }, +}; + +static kipdiff_t fs_diffs_600_nogc[3] = { + { 0x1538F4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, + { 0x12CC20, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, + { 0, 0, NULL, NULL }, +}; + +static kipdiff_t fs_diffs_600_exfat_nosigchk[3] = { + { 0x7C9A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" }, + { 0xF678C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" }, + { 0, 0, NULL, NULL }, +}; + +static kipdiff_t fs_diffs_600_nosigchk[3] = { + { 0x712A8, 4, "\x8E\x3E\x00\x94", "\xE0\x03\x1F\x2A" }, + { 0xEB08C, 4, "\xC0\x03\x00\x36", "\x1F\x20\x03\xD5" }, + { 0, 0, NULL, NULL }, +}; + /* patches */ static kippatch_t fs_kip_patches_100[] = { @@ -204,3 +251,17 @@ static kippatch_t fs_kip_patches_510[] = { { "nogc", fs_diffs_510_nogc }, { NULL, NULL } }; + +static kippatch_t fs_kip_patches_600[] = { + { "nosigchk", fs_diffs_600_nosigchk }, + { "nocmac", fs_diffs_600_nocmac }, + { "nogc", fs_diffs_600_nogc }, + { NULL, NULL } +}; + +static kippatch_t fs_kip_patches_600_exfat[] = { + { "nosigchk", fs_diffs_600_exfat_nosigchk }, + { "nocmac", fs_diffs_600_exfat_nocmac }, + { "nogc", fs_diffs_600_exfat_nogc }, + { NULL, NULL } +}; \ No newline at end of file diff --git a/src/package.c b/src/package.c index 61b4972..02ccd61 100644 --- a/src/package.c +++ b/src/package.c @@ -14,11 +14,48 @@ * along with this program. If not, see . */ -#include "hwinit/gfx.h" -#include "hwinit/list.h" +#include "hwinit.h" #include "error.h" #include "fs.h" #include "package.h" +#include "kippatches/fs.inc" + +u8 *ReadPackage1(sdmmc_storage_t *storage) { + u8 *pk11 = malloc(0x40000); + sdmmc_storage_read(storage, 0x100000 / NX_EMMC_BLOCKSIZE, 0x40000 / NX_EMMC_BLOCKSIZE, pk11); + return pk11; +} + +u8 *ReadPackage2(sdmmc_storage_t *storage) { + // Read GPT partition. + LIST_INIT(gpt); + sdmmc_storage_set_mmc_partition(storage, 0); + print("Parsing GPT...\n"); + nx_emmc_gpt_parse(&gpt, storage); + emmc_part_t *pkg2_part = nx_emmc_part_find(&gpt, "BCPKG2-1-Normal-Main"); + nx_emmc_gpt_free(&gpt); + if (!pkg2_part) { + error("Failed to read GPT!\n"); + return 0; + } + + // Read Package2. + u8 *tmp = (u8 *)malloc(NX_EMMC_BLOCKSIZE); + print("Reading Package2 size...\n"); + nx_emmc_part_read(storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, 1, tmp); + u32 *hdr = (u32 *)(tmp + 0x100); + u32 pkg2_size = hdr[0] ^ hdr[2] ^ hdr[3]; + free(tmp); + u8 *pkg2 = malloc(ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE)); + print("Reading Package2...\n"); + u32 ret = nx_emmc_part_read(storage, pkg2_part, 0x4000 / NX_EMMC_BLOCKSIZE, ALIGN(pkg2_size, NX_EMMC_BLOCKSIZE) / NX_EMMC_BLOCKSIZE, pkg2); + sdmmc_storage_end(storage); + if (!ret) { + error("Failed to read Package2!\n"); + return 0; + } + return pkg2; +} pkg2_hdr_t *unpackFirmwarePackage(u8 *data) { print("Unpacking firmware...\n"); @@ -189,4 +226,99 @@ void loadKip(link_t *info, char *path) { ki->kip1 = ckip; ki->size = calcKipSize(ckip); list_append(info, &ki->link); +} + +// TODO: get full hashes somewhere and not just the first 16 bytes +// every second one is the exfat version +kippatchset_t kip_patches[] = { + { "FS", "\xde\x9f\xdd\xa4\x08\x5d\xd5\xfe\x68\xdc\xb2\x0b\x41\x09\x5b\xb4", fs_kip_patches_100 }, + { "FS", "\xfc\x3e\x80\x99\x1d\xca\x17\x96\x4a\x12\x1f\x04\xb6\x1b\x17\x5e", fs_kip_patches_100 }, + { "FS", "\xcd\x7b\xbe\x18\xd6\x13\x0b\x28\xf6\x2f\x19\xfa\x79\x45\x53\x5b", fs_kip_patches_200 }, + { "FS", "\xe7\x66\x92\xdf\xaa\x04\x20\xe9\xfd\xd6\x8e\x43\x63\x16\x18\x18", fs_kip_patches_200 }, + { "FS", "\x0d\x70\x05\x62\x7b\x07\x76\x7c\x0b\x96\x3f\x9a\xff\xdd\xe5\x66", fs_kip_patches_210 }, + { "FS", "\xdb\xd8\x5f\xca\xcc\x19\x3d\xa8\x30\x51\xc6\x64\xe6\x45\x2d\x32", fs_kip_patches_210 }, + { "FS", "\xa8\x6d\xa5\xe8\x7e\xf1\x09\x7b\x23\xda\xb5\xb4\xdb\xba\xef\xe7", fs_kip_patches_300 }, + { "FS", "\x98\x1c\x57\xe7\xf0\x2f\x70\xf7\xbc\xde\x75\x31\x81\xd9\x01\xa6", fs_kip_patches_300 }, + { "FS", "\x57\x39\x7c\x06\x3f\x10\xb6\x31\x3f\x4d\x83\x76\x53\xcc\xc3\x71", fs_kip_patches_301 }, + { "FS", "\x07\x30\x99\xd7\xc6\xad\x7d\x89\x83\xbc\x7a\xdd\x93\x2b\xe3\xd1", fs_kip_patches_301 }, + { "FS", "\x06\xe9\x07\x19\x59\x5a\x01\x0c\x62\x46\xff\x70\x94\x6f\x10\xfb", fs_kip_patches_401 }, + { "FS", "\x54\x9b\x0f\x8d\x6f\x72\xc4\xe9\xf3\xfd\x1f\x19\xea\xce\x4a\x5a", fs_kip_patches_401 }, + { "FS", "\x80\x96\xaf\x7c\x6a\x35\xaa\x82\x71\xf3\x91\x69\x95\x41\x3b\x0b", fs_kip_patches_410 }, + { "FS", "\x02\xd5\xab\xaa\xfd\x20\xc8\xb0\x63\x3a\xa0\xdb\xae\xe0\x37\x7e", fs_kip_patches_410 }, + { "FS", "\xa6\xf2\x7a\xd9\xac\x7c\x73\xad\x41\x9b\x63\xb2\x3e\x78\x5a\x0c", fs_kip_patches_500 }, + { "FS", "\xce\x3e\xcb\xa2\xf2\xf0\x62\xf5\x75\xf8\xf3\x60\x84\x2b\x32\xb4", fs_kip_patches_500 }, + { "FS", "\x76\xf8\x74\x02\xc9\x38\x7c\x0f\x0a\x2f\xab\x1b\x45\xce\xbb\x93", fs_kip_patches_510 }, + { "FS", "\x10\xb2\xd8\x16\x05\x48\x85\x99\xdf\x22\x42\xcb\x6b\xac\x2d\xf1", fs_kip_patches_510 }, + { "FS", "\x1b\x82\xcb\x22\x18\x67\xcb\x52\xc4\x4a\x86\x9e\xa9\x1a\x1a\xdd", fs_kip_patches_600 }, + { "FS", "\x96\x6a\xdd\x3d\x20\xb6\x27\x13\x2c\x5a\x8d\xa4\x9a\xc9\xd8\xdd", fs_kip_patches_600_exfat }, + { NULL, NULL, NULL }, +}; + +int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch) { + if (!patch || !patch->diffs) return -1; + + for (kipdiff_t *diff = patch->diffs; diff->len; ++diff) { + if (!diff->len || diff->offset + diff->len > kipdata_len) + return 1 + (int)(diff - patch->diffs); + u8 *start = kipdata + diff->offset; + if (memcmp(start, diff->orig_bytes, diff->len)) + continue; + // TODO: maybe start copying after every diff has been verified? + memcpy(start, diff->patch_bytes, diff->len); + } + + return 0; +} + + +int nca_patch(u8 * kipdata, u64 kipdata_len) { + char pattern[8] = {0xE5, 0x07, 0x00, 0x32, 0xE0, 0x03, 0x16, 0xAA}; + char buf[0x10]; + memcpy(buf, kipdata+0x1C450, 0x10); + u32 * addr = memsearch(kipdata, kipdata_len, pattern, sizeof(pattern)); + int ret=0; + int max_dist = 0x10; + for(int i=0; ipatches; p && p->name; ++p) { + int found = 0; + for (char **filtname = patchFilter; filtname && *filtname; ++filtname) { + if (!strcmp(p->name, *filtname)) { + found = 1; + break; + } + } + + if (patchFilter && !found) continue; + + int r = kippatch_apply(kipdata, kipdata_len, p); + if (r) return r; + } + if(!strncmp("FS", patchset->kip_name, 2)) + nca_patch(kipdata, kipdata_len); + return 0; +} + +kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets) { + for (kippatchset_t *ps = patchsets; ps && ps->kip_name; ++ps) { + if (!memcmp(kiphash, ps->kip_hash, 0x10)) return ps; + } + return NULL; } \ No newline at end of file diff --git a/src/package.h b/src/package.h index 22a4ca9..18f3137 100644 --- a/src/package.h +++ b/src/package.h @@ -31,6 +31,7 @@ #define FREE_CODE_OFF_1ST_302 0x494BC #define FREE_CODE_OFF_1ST_400 0x52890 #define FREE_CODE_OFF_1ST_500 0x5C020 +#define FREE_CODE_OFF_1ST_600 0x5EE00 #define ID_SND_OFF_100 0x23CC0 #define ID_SND_OFF_200 0x3F134 @@ -38,6 +39,7 @@ #define ID_SND_OFF_302 0x26080 #define ID_SND_OFF_400 0x2AF64 #define ID_SND_OFF_500 0x2AD34 +#define ID_SND_OFF_600 0x2BB88 #define ID_RCV_OFF_100 0x219F0 #define ID_RCV_OFF_200 0x3D1A8 @@ -45,7 +47,10 @@ #define ID_RCV_OFF_302 0x240F0 #define ID_RCV_OFF_400 0x28F6C #define ID_RCV_OFF_500 0x28DAC +#define ID_RCV_OFF_600 0x29B6C +#define NOP 0xD503201F +#define ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) static u8 customSecmon = 0; static u8 customWarmboot = 0; @@ -225,6 +230,18 @@ static u32 PRC_ID_RCV_500[] = 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA }; +static u32 PRC_ID_SND_600[] = +{ + 0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, + 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA +}; +#define FREE_CODE_OFF_2ND_600 (FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600) + 4) +static u32 PRC_ID_RCV_600[] = +{ + 0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA +}; + static kernel_patch_t kern1[] = { { SVC_VERIFY_DS, 0x3764C, _NOP(), NULL }, // Disable SVC verifications @@ -313,6 +330,21 @@ static kernel_patch_t kern5[] = { {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} }; +static kernel_patch_t kern6[] = { + { SVC_VERIFY_DS, 0x47E98, _NOP(), NULL }, // Disable SVC verifications + { DEBUG_MODE_EN, 0x52D40, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch + // Atmosphère kernel patches. + { ATM_GEN_PATCH, ID_SND_OFF_600, _B(ID_SND_OFF_600, FREE_CODE_OFF_1ST_600), NULL}, // Send process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_600, sizeof(PRC_ID_SND_600) >> 2, PRC_ID_SND_600}, // Send process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), // Branch back and skip 2 instructions. + _B(FREE_CODE_OFF_1ST_600 + sizeof(PRC_ID_SND_600), ID_SND_OFF_600 + 8), NULL}, + { ATM_GEN_PATCH, ID_RCV_OFF_600, _B(ID_RCV_OFF_600, FREE_CODE_OFF_2ND_600), NULL}, // Receive process id branch. + { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_600, sizeof(PRC_ID_RCV_600) >> 2, PRC_ID_RCV_600}, // Receive process id code. + { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), // Branch back and skip 2 instructions. + _B(FREE_CODE_OFF_2ND_600 + sizeof(PRC_ID_RCV_600), ID_RCV_OFF_600 + 8), NULL}, + {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} +}; + static const pkg2_kernel_id_t _pkg2_kernel_ids[] = { { 0x427f2647, kern1 }, //1.0.0 @@ -321,9 +353,37 @@ static const pkg2_kernel_id_t _pkg2_kernel_ids[] = { 0xe0e8cdc4, kern302 }, //3.0.2 { 0x485d0157, kern4 }, //4.0.0 - 4.1.0 { 0xf3c363f2, kern5 }, //5.0.0 - 5.1.0 + { 0x64ce1a44, kern6 }, //6.0.0 { 0, 0 } //End. }; +typedef struct kipdiff_s { + u64 offset; // offset from start of kip's .text segment + u32 len; // length of below strings, NULL signifies end of patch + const char *orig_bytes; // original byte string (this must match exactly) + const char *patch_bytes; // replacement byte string (same length) +} kipdiff_t; + +// a single patch for a particular kip version +typedef struct kippatch_s { + const char *name; // name/id of the patch, NULL signifies end of patchset + kipdiff_t *diffs; // array of kipdiff_t's to apply +} kippatch_t; + +// a group of patches that patch several different things in a particular kip version +typedef struct kippatchset_s { + const char *kip_name; // name/id of the kip, NULL signifies end of patchset list + const char *kip_hash; // sha256 of the right version of the kip + kippatch_t *patches; // set of patches for this version of the kip +} kippatchset_t; + + +extern kippatchset_t kip_patches[]; +u8 *ReadPackage1(sdmmc_storage_t *storage); +u8 *ReadPackage2(sdmmc_storage_t *storage); +int kippatch_apply(u8 *kipdata, u64 kipdata_len, kippatch_t *patch); +int kippatch_apply_set(u8 *kipdata, u64 kipdata_len, kippatchset_t *patchset); +kippatchset_t *kippatch_find_set(u8 *kiphash, kippatchset_t *patchsets); pkg2_hdr_t *unpackFirmwarePackage(u8 *data); void pkg1_unpack(pk11_offs *offs, u8 *pkg1); void buildFirmwarePackage(u8 *kernel, u32 kernel_size, link_t *kips_info); diff --git a/src/start.s b/src/start.s index f04811a..30786b1 100644 --- a/src/start.s +++ b/src/start.s @@ -36,14 +36,14 @@ .type _start, %function _start: ADR R0, _start - LDR R1, =__ipl_start + LDR R1, =payload_start CMP R0, R1 BEQ _real_start /* If we are not in the right location already, copy a relocator to upper IRAM. */ - ADR R2, _reloc_ipl + ADR R2, reloc_payload LDR R3, =0x4003FF00 - MOV R4, #(_real_start - _reloc_ipl) + MOV R4, #(_real_start - reloc_payload) _copy_loop: LDMIA R2!, {R5} STMIA R3!, {R5} @@ -51,17 +51,17 @@ _copy_loop: BNE _copy_loop /* Use the relocator to copy ourselves into the right place. */ - LDR R2, =__ipl_end + LDR R2, =payload_end SUB R2, R2, R1 LDR R3, =_real_start LDR R4, =0x4003FF00 BX R4 -_reloc_ipl: +reloc_payload: LDMIA R0!, {R4-R7} STMIA R1!, {R4-R7} SUBS R2, #0x10 - BNE _reloc_ipl + BNE reloc_payload /* Jump to the relocated entry. */ BX R3