diff --git a/Dockerfile b/Dockerfile index 1304e77..19c003b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,11 @@ -FROM devkitpro/devkitarm:latest -MAINTAINER jski "jski185@gmail.com" +FROM devkitpro/devkita64 +MAINTAINER elelphatp "elephantp@elephantp.blog" -ADD . / +RUN dkp-pacman -Syyu --noconfirm devkitARM && \ + dkp-pacman -Scc --noconfirm -ENTRYPOINT ["make"] \ No newline at end of file +ENV DEVKITARM=${DEVKITPRO}/devkitARM + +WORKDIR /developer + +ENTRYPOINT ["make"] diff --git a/Makefile b/Makefile index c2282d7..6d632a8 100644 --- a/Makefile +++ b/Makefile @@ -4,11 +4,12 @@ ifeq ($(strip $(DEVKITARM)),) $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") endif -CC = $(DEVKITARM)/bin/arm-none-eabi-gcc +include $(DEVKITARM)/base_tools 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, \ @@ -50,10 +51,12 @@ $(dir_out)/sysmodules: $(dir_sysmod) $(dir_out)/$(name).bin: $(dir_build)/$(name).elf @mkdir -p "$(@D)" @mkdir -p "$(dir_out)/ReiNX/sysmodules" + @mkdir -p "$(dir_out)/ReiNX/sysmodules.dis" @mkdir -p "$(dir_out)/ReiNX/patches" @cp $(dir_sysmod)/loader/loader.kip $(dir_out)/ReiNX/sysmodules/ @cp $(dir_sysmod)/sm/sm.kip $(dir_out)/ReiNX/sysmodules/ - @cp $(dir_sysmod)/fs_mitm/fs_mitm.kip $(dir_out)/ReiNX/sysmodules/ + @cp $(dir_sysmod)/pm/pm.kip $(dir_out)/ReiNX/sysmodules.dis/ + @cp $(dir_sysmod)/fs_mitm/fs_mitm.kip $(dir_out)/ReiNX/sysmodules.dis/ @cp -R $(dir_data)/*.bin $(dir_out)/ReiNX/ @cp -R $(dir_data)/*.rxp $(dir_out)/ReiNX/patches $(OBJCOPY) -S -O binary $< $@ diff --git a/NX_Sysmodules b/NX_Sysmodules index 27a2632..3c12add 160000 --- a/NX_Sysmodules +++ b/NX_Sysmodules @@ -1 +1 @@ -Subproject commit 27a263272d3c44e6521046737dce90e29eca00ae +Subproject commit 3c12add04883b893698cfa04451c834e34bcbe66 diff --git a/README.md b/README.md index f51ecc6..cf43cbf 100644 --- a/README.md +++ b/README.md @@ -11,10 +11,11 @@ Put `ReiNX` folder on the root of your switch's SD card and run `ReiNX.bin` with You'll need devkitpro with devkitARM and run `make` -To compile with Docker, `chmod +x docker-build.sh` and run the shell script `./docker-build.sh`. This will compile without requiring installation of DevKit* dependencies. +To compile with Docker, `chmod +x docker-build.sh` and run the shell script `./docker-build.sh`. After that, just check `out` dir. This will compile without requiring installation of DevKit* dependencies. **Features:** +* Modularity (doesn't rely on or require any SD files to run; customize SD files to your liking) * Loads all KIPs from `/ReiNX/sysmodules/` directory @@ -22,18 +23,22 @@ To compile with Docker, `chmod +x docker-build.sh` and run the shell script `./d * FS patches on the fly (NCA verify/cmac and optional nogc) -* Exclusive ReiNX sysmodules with built in ES patches +* Kernel patches on the fly (optional debug mode) + +* Exclusive ReiNX sysmodules + +* ES patch in RXP patch format (used with custom loader.kip) **Official thread:** [HERE](https://gbatemp.net/threads/official-reinx-thread.512203/) **Credits:** - + Naehrwert for hardware init code and generally being helpful! - + CTCaer and st4rk for their contribution to the hardware code aswell! - + SciresM for sysmodules! - + The community for your support! diff --git a/data/es_patch.rxp b/data/es_patch.rxp index 4e23aab..76e540a 100644 Binary files a/data/es_patch.rxp and b/data/es_patch.rxp differ diff --git a/docker-build.sh b/docker-build.sh index baeb3c6..0695d86 100755 --- a/docker-build.sh +++ b/docker-build.sh @@ -1,16 +1,21 @@ #!/usr/bin/env bash -ECHO "" -ECHO "Emptying out /build and /out folders..." -ECHO "" -rm -rf ./build -rm -rf ./out +echo "Checking reinx-builder image..." -ECHO "" -ECHO "Building docker image locally..." -ECHO "" -docker build . -t reinx-builder:latest +IMAGE=`docker image ls|grep reinx-builder -c` +if [[ "$IMAGE" == 1 ]]; then + echo "Reinx-builder image is exist" +else + echo "" + echo "Building docker image locally..." + echo "" + docker build . -t reinx-builder +fi -ECHO "" -ECHO "Running image and generating build..." -ECHO "" -docker run -v $(pwd)/build:/build -v $(pwd)/out:/out reinx-builder:latest \ No newline at end of file +echo "Checking container...." +CONTAINER=`docker ps -a|grep reinx-builder -c` +echo "Building..." +if [[ "$CONTAINER" == 1 ]]; then + docker start -a reinx-builder +else + docker run -a stdout -a stderr --name reinx-builder -v $(pwd):/developer reinx-builder +fi 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 8a16e90..7e4da12 100644 --- a/src/bootloader.c +++ b/src/bootloader.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018 Reisyukaku +* Copyright (c) 2018 Reisyukaku, naehrwert * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -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(); @@ -33,6 +57,68 @@ void check_config_fuses() { panic(); } +int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw) { + u8 tmp[0x10]; + + se_key_acc_ctrl(0x0D, 0x15); + se_key_acc_ctrl(0x0E, 0x15); + + // Get TSEC key. + if (tsec_query(tmp, 1, tsec_fw) < 0) + return 0; + + se_aes_key_set(0x0D, tmp, 0x10); + + // Derive keyblob keys from TSEC+SBK. + se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]); + se_aes_unwrap_key(0x0F, 0x0E, tmp); + se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[fwVer]); + se_aes_unwrap_key(0x0D, 0x0E, tmp); + + // Clear SBK + se_aes_key_clear(0x0E); + + se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed); + se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed); + + // Decrypt keyblob and set keyslots. + se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); + se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // Package1 key + se_aes_key_set(0x0C, keyblob + 0x20, 0x10); + se_aes_key_set(0x0D, keyblob + 0x20, 0x10); + + se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail); + + switch (fwVer) { + case KB_FIRMWARE_VERSION_100_200: + case KB_FIRMWARE_VERSION_300: + case KB_FIRMWARE_VERSION_301: + se_aes_unwrap_key(0x0D, 0x0F, console_keyseed); + se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + break; + + case KB_FIRMWARE_VERSION_400: + se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx); + se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); + se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); + se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + 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); + se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); + se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); + break; + } + + // Package2 key + se_key_acc_ctrl(0x08, 0x15); + se_aes_unwrap_key(0x08, 0x0C, key8_keyseed); +} + void mbist_workaround() { CLOCK(0x410) = (CLOCK(0x410) | 0x8000) & 0xFFFFBFFF; CLOCK(0xD0) |= 0x40800000u; diff --git a/src/bootloader.h b/src/bootloader.h index 7aafd4e..5fc050a 100644 --- a/src/bootloader.h +++ b/src/bootloader.h @@ -16,4 +16,22 @@ #pragma once +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 + { 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 }; +static const u8 master_keyseed_retail[0x10] = { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C }; +static const u8 console_keyseed[0x10] = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 }; +static const u8 key8_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; +static const u8 master_keyseed_4xx[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; +static const u8 console_keyseed_4xx[0x10] = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; + + +int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw); void bootloader(); \ No newline at end of file diff --git a/src/bootrom.c b/src/bootrom.c index 7f6b760..3f7013b 100644 --- a/src/bootrom.c +++ b/src/bootrom.c @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018 Reisyukaku +* Copyright (c) 2018 Reisyukaku, naehrwert * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -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 6debbe8..e790cc6 100644 --- a/src/error.c +++ b/src/error.c @@ -30,7 +30,8 @@ void panic() { } void error(char *errStr) { + gfx_con.mute = 0; gfx_con_setcol(&gfx_con, RED, 0, 0); - print(strcat("Error: ", errStr)); - gfx_con_setcol(&gfx_con, ORANGE, 0, 0); + print("Error: %s", errStr); + 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 7ca3470..fd9daff 100644 --- a/src/firmware.c +++ b/src/firmware.c @@ -17,50 +17,22 @@ #include #include #include "hwinit.h" -#include "hwinit/gfx.h" #include "fs.h" -#include "fuse.h" #include "package.h" #include "error.h" +#include "bootloader.h" #include "firmware.h" -#include "kippatches.h" - -#define VERSION "v0.1" static pk11_offs *pk11Offs = NULL; -// 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 - { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, 0x8000D000, 1 }, //1.0.0 - { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //2.0.0 - 2.3.0 - { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //3.0.0 - { "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 - { NULL, 0, 0, 0, 0 } // End. -}; - -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() { +int drawSplash() { // Draw splashscreen to framebuffer. if(fopen("/ReiNX/splash.bin", "rb") != 0) { fread((void*)0xC0000000, fsize(), 1); fclose(); - usleep(3000000); + return 1; } + return 0; } pk11_offs *pkg11_offsentify(u8 *pkg1) { @@ -70,6 +42,59 @@ pk11_offs *pkg11_offsentify(u8 *pkg1) { return NULL; } +void patchFS(pkg2_kip1_info_t* ki) { + u8 kipHash[0x20]; + + print("Patching FS\n"); + + se_calc_sha256(&kipHash, ki->kip1, ki->size); + se_calc_sha256(&kipHash, ki->kip1, ki->size); + + //Create header + size_t sizeDiff = ki->kip1->sections[0].size_decomp - ki->kip1->sections[0].size_comp; + + size_t newSize = ki->size + sizeDiff; + pkg2_kip1_t *moddedKip = malloc(newSize); + memcpy(moddedKip, ki->kip1, newSize); + + u32 pos = 0; + //Get decomp .text segment + u8 *kipDecompText = blz_decompress(moddedKip->data, moddedKip->sections[0].size_comp); + + kippatchset_t *pset = kippatch_find_set(kipHash, kip_patches); + if (!pset) { + print(" could not find patchset with matching hash\n"); + } else { + int res = kippatch_apply_set(kipDecompText, moddedKip->sections[0].size_decomp, pset); + if (res) error("kippatch_apply_set() failed\n"); + } + + moddedKip->flags &= ~1; + memcpy((void*)moddedKip->data, kipDecompText, moddedKip->sections[0].size_decomp); + free(kipDecompText); + pos += moddedKip->sections[0].size_comp; + moddedKip->sections[0].size_comp = moddedKip->sections[0].size_decomp; + + for(int i = 1; i < KIP1_NUM_SECTIONS; i++) { + if(moddedKip->sections[i].offset != 0) { + memcpy((void*)moddedKip->data + pos + sizeDiff, (void*)ki->kip1->data + pos, moddedKip->sections[i].size_comp); + pos += moddedKip->sections[i].size_comp; + } + } + + free(ki->kip1); + ki->size = newSize; + ki->kip1 = moddedKip; +} + +pkg2_kip1_info_t* find_by_tid(link_t* kip_list, u64 tid) { + LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kip_list, link) { + if(ki->kip1->tid == 0x0100000000000000) + return ki; + } + return NULL; +} + void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { //Patch Secmon if(!customSecmon){ @@ -80,7 +105,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}; @@ -115,7 +139,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}; @@ -123,13 +147,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; }; @@ -141,154 +174,128 @@ void patch(pk11_offs *pk11, pkg2_hdr_t *pkg2, link_t *kips) { //Patch Kernel if(!customKern) { u32 crc = crc32c(pkg2->data, pkg2->sec_size[PKG2_SEC_KERNEL]); - const pkg2_kernel_id_t * id = pkg2_identify(crc); - - kernel_patch_t * kpatch = id->kernel_patchset; - if(kpatch!=NULL) { - for(int i=0; kpatch[i].id!=-1; i++) { - if(kpatch[i].id != ATM_ARR_PATCH) - *(vu32 *)(pkg2->data + kpatch[i].off) = kpatch[i].val; - else { - u32 * temp = (u32 *)kpatch[i].ptr; - for(int j=0; j< kpatch[i].val; j++) { - *(vu32*)(pkg2->data + kpatch[i].off + j*4) = temp[j]; - } - } - } - } - } - - u8 kipHash[0x20]; - char *patchFilter[] = { "nogc", "nosigchk", "nocmac", NULL }; - - //Patch FS module (truly not my proudest code TODO cleanup) - LIST_FOREACH_ENTRY(pkg2_kip1_info_t, ki, kips, link) { - //Patch FS - if(ki->kip1->tid == 0x0100000000000000) { - print("Patching FS\n"); - - // calc hash of source kip - se_calc_sha256(kipHash, ki->kip1, ki->size); - // HACK: for some reason it doesn't always compute correct hash the first time, - // but seems to always do it correctly on the second try. maybe there's some - // init code missing to make this work? I don't even - se_calc_sha256(kipHash, ki->kip1, ki->size); - - //Create header - size_t sizeDiff = ki->kip1->sections[0].size_decomp - ki->kip1->sections[0].size_comp; - size_t newSize = ki->size + sizeDiff; - pkg2_kip1_t *moddedKip = malloc(newSize); - memcpy(moddedKip, ki->kip1, newSize); - u32 pos = 0; - for(int i = 0; i < KIP1_NUM_SECTIONS; i++) { - if(!i) { - //Get decomp .text segment - u8 *kipDecompText = blz_decompress(moddedKip->data, moddedKip->sections[i].size_comp); - - kippatchset_t *pset = kippatch_find_set(kipHash, kip_patches); - 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); - } - } - - moddedKip->flags &= ~1; - memcpy((void*)moddedKip->data, kipDecompText, moddedKip->sections[i].size_decomp); - free(kipDecompText); - pos += moddedKip->sections[i].size_comp; - moddedKip->sections[i].size_comp = moddedKip->sections[i].size_decomp; - } else { - if(moddedKip->sections[i].offset == 0) continue; - memcpy((void*)moddedKip->data + pos + sizeDiff, (void*)ki->kip1->data + pos, moddedKip->sections[i].size_comp); - pos += moddedKip->sections[i].size_comp; - } + uPtr kern = (uPtr)&pkg2->data; + uPtr sendOff, recvOff, codeRcvOff, codeSndOff, svcVerifOff, svcDebugOff, ver; + switch(crc){ + case 0x427f2647:{ //1.0.0 + svcVerifOff = 0x3764C; + svcDebugOff = 0x44074; + sendOff = 0x23CC0; + recvOff = 0x219F0; + codeSndOff = 4; + codeRcvOff = 4; + ver = 0; + break; + } + case 0xae19cf1b:{ //2.0.0 + svcVerifOff = 0x54834; + svcDebugOff = 0x6086C; + sendOff = 0x3F134; + recvOff = 0x3D1A8; + codeSndOff = 4; + codeRcvOff = 4; + ver = 1; + break; + } + case 0x73c9e274:{ //3.0.0 + svcVerifOff = 0x3BD24; + svcDebugOff = 0x483FC; + sendOff = 0x26080; + recvOff = 0x240F0; + codeSndOff = 4; + codeRcvOff = 4; + ver = 2; + break; + } + case 0xe0e8cdc4:{ //3.0.2 + svcVerifOff = 0x3BD24; + svcDebugOff = 0x48414; + sendOff = 0x26080; + recvOff = 0x240F0; + codeSndOff = 4; + codeRcvOff = 4; + ver = 3; + break; + } + case 0x485d0157:{ //4.0.0 + svcVerifOff = 0x41EB4; + svcDebugOff = 0x4EBFC; + sendOff = 0x2AF64; + recvOff = 0x28F6C; + codeSndOff = 8; + codeRcvOff = 4; + ver = 4; + break; } - - free(ki->kip1); - ki->size = newSize; - ki->kip1 = moddedKip; + case 0xf3c363f2:{ //5.0.0 + svcVerifOff = 0x45E6C; + svcDebugOff = 0x5513C; + sendOff = 0x2AD34; + recvOff = 0x28DAC; + codeSndOff = 8; + codeRcvOff = 8; + ver = 5; + break; + } + case 0x64ce1a44:{ //6.0.0 + svcVerifOff = 0x47EA0; + svcDebugOff = 0x57548; + sendOff = 0x2BB8C; + recvOff = 0x29B6C; + codeSndOff = 0x10; + codeRcvOff = 0x10; + ver = 6; + break; + } + default: + error("Kernel not supported"); + goto end; + } + + //ID Send + uPtr freeSpace = getFreeSpace((void*)(kern+0x45000), 0x200, 0x20000) + 0x45000; //Find area to write payload + print("Kernel Freespace: 0x%08X\n", freeSpace); + size_t payloadSize; + u32 *sndPayload = getSndPayload(ver, &payloadSize); + *(vu32*)(kern + sendOff) = _B(sendOff, freeSpace); //write hook to payload + memcpy((void*)(kern + freeSpace), sndPayload, payloadSize); //Copy payload to free space + *(vu32*)(kern + freeSpace + payloadSize) = _B(freeSpace + payloadSize, sendOff + codeSndOff); //Jump back skipping the hook + + //ID Receive + freeSpace += (payloadSize+4); + u32 *rcvPayload = getRcvPayload(ver, &payloadSize); + *(vu32*)(kern + recvOff) = _B(recvOff, freeSpace); + memcpy((void*)(kern + freeSpace), rcvPayload, payloadSize); + *(vu32*)(kern + freeSpace + payloadSize) = _B(freeSpace + payloadSize, recvOff + codeRcvOff); + + //SVC patches + *(vu32*)(kern + svcVerifOff) = NOP; + if (fopen("/ReiNX/debug", "rb")) { + fclose(); + *(vu32*)(kern + svcDebugOff) = _MOVZX(8, 1, 0); } + + end:; } -} - -int keygen(u8 *keyblob, u32 fwVer, void *tsec_fw) { - u8 tmp[0x10]; - - se_key_acc_ctrl(0x0D, 0x15); - se_key_acc_ctrl(0x0E, 0x15); - - // Get TSEC key. - if (tsec_query(tmp, 1, tsec_fw) < 0) - return 0; - - se_aes_key_set(0x0D, tmp, 0x10); - - // Derive keyblob keys from TSEC+SBK. - se_aes_crypt_block_ecb(0x0D, 0x00, tmp, keyblob_keyseeds[0]); - se_aes_unwrap_key(0x0F, 0x0E, tmp); - se_aes_crypt_block_ecb(0xD, 0x00, tmp, keyblob_keyseeds[fwVer]); - se_aes_unwrap_key(0x0D, 0x0E, tmp); - - // Clear SBK - se_aes_key_clear(0x0E); - - se_aes_crypt_block_ecb(0x0D, 0, tmp, cmac_keyseed); - se_aes_unwrap_key(0x0B, 0x0D, cmac_keyseed); - - // Decrypt keyblob and set keyslots. - se_aes_crypt_ctr(0x0D, keyblob + 0x20, 0x90, keyblob + 0x20, 0x90, keyblob + 0x10); - se_aes_key_set(0x0B, keyblob + 0x20 + 0x80, 0x10); // Package1 key - se_aes_key_set(0x0C, keyblob + 0x20, 0x10); - se_aes_key_set(0x0D, keyblob + 0x20, 0x10); - - se_aes_crypt_block_ecb(0x0C, 0, tmp, master_keyseed_retail); - - switch (fwVer) { - case KB_FIRMWARE_VERSION_100_200: - case KB_FIRMWARE_VERSION_300: - case KB_FIRMWARE_VERSION_301: - se_aes_unwrap_key(0x0D, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); - break; - - case KB_FIRMWARE_VERSION_400: - se_aes_unwrap_key(0x0D, 0x0F, console_keyseed_4xx); - se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); - break; - - case KB_FIRMWARE_VERSION_500: - default: - se_aes_unwrap_key(0x0A, 0x0F, console_keyseed_4xx); - se_aes_unwrap_key(0x0F, 0x0F, console_keyseed); - se_aes_unwrap_key(0x0E, 0x0C, master_keyseed_4xx); - se_aes_unwrap_key(0x0C, 0x0C, master_keyseed_retail); - break; + + pkg2_kip1_info_t* FS_module = find_by_tid(kips, 0x0100000000000000); + if(FS_module == NULL) { + error("Could not find FS Module.\n"); + } else { + patchFS(FS_module); } - - // Package2 key - se_key_acc_ctrl(0x08, 0x15); - se_aes_unwrap_key(0x08, 0x0C, key8_keyseed); } 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); @@ -306,33 +313,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"); @@ -348,7 +330,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]); } @@ -358,6 +340,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; @@ -405,15 +400,36 @@ 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); - if (!sd_mount()) { + if (!sdMount()) { error("Failed to init SD card!\n"); - return; + print("Press POWER to power off, or any other key to continue without SD.\n"); + if (btn_wait() & BTN_POWER) + i2c_send_byte(I2C_5, 0x3C, MAX77620_REG_ONOFFCNFG1, MAX77620_ONOFFCNFG1_PWR_OFF); + btn_wait(); + } + + 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) = 69; + ((void (*)())PAYLOAD_ADDR)(); + } + SYSREG(AHB_AHB_SPARE_REG) = (volatile vu32)0xFFFFFF9F; + PMC(APBDEV_PMC_SCRATCH49) = 0; + + if (btn_read() & BTN_VOL_DOWN) { + print("Booting verbosely\n"); + } else if (drawSplash()) { + gfx_con.mute = 1; } print("Welcome to ReiNX %s!\n", VERSION); loadFirm(); - drawSplash(); launch(); } diff --git a/src/firmware.h b/src/firmware.h index 8535f38..ab2d2ee 100644 --- a/src/firmware.h +++ b/src/firmware.h @@ -1,3 +1,18 @@ +/* +* Copyright (c) 2018 Reisyukaku, naehrwert +* +* 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 #include "hwinit/types.h" @@ -11,8 +26,20 @@ #define BOOT_PKG2_LOADED_4X 3 #define BOOT_DONE_4X 4 -//Instructions -#define NOP 0xD503201F -#define ADRP(r, o) 0x90000000 | ((((o) >> 12) & 0x3) << 29) | ((((o) >> 12) & 0x1FFFFC) << 3) | ((r) & 0x1F) +#define PAYLOAD_ADDR 0xCFF00000 -void firmware(); +// 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 + { "20161121183008", 0, 0x1900, 0x3FE0, { 2, 1, 0 }, 0x40014020, 0x8000D000, 1 }, //1.0.0 + { "20170210155124", 0, 0x1900, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //2.0.0 - 2.3.0 + { "20170519101410", 1, 0x1A00, 0x3FE0, { 0, 1, 2 }, 0x4002D000, 0x8000D000, 1 }, //3.0.0 + { "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. +}; + + +void firmware(); \ No newline at end of file diff --git a/src/fs.c b/src/fs.c index 9abacf9..112e2ec 100644 --- a/src/fs.c +++ b/src/fs.c @@ -1,5 +1,4 @@ /* -* Copyright (c) 2018 naehrwert * Copyright (c) 2018 Reisyukaku * * This program is free software; you can redistribute it and/or modify it @@ -18,7 +17,6 @@ #include #include #include "hwinit.h" -#include "hwinit/gfx.h" #include "hwinit/ff.h" #include "error.h" #include "fs.h" @@ -29,7 +27,7 @@ FATFS sd_fs; int sd_mounted; FIL fp; -u32 sd_mount() { +u32 sdMount() { if (sd_mounted) return 1; if (sdmmc_storage_init_sd(&sd_storage, &sd_sdmmc, SDMMC_1, SDMMC_BUS_WIDTH_4, 11) && f_mount(&sd_fs, "", 1) == FR_OK) { @@ -40,6 +38,13 @@ u32 sd_mount() { return 0; } +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) { u32 m = (mode[0] == 0x77 ? (FA_WRITE|FA_CREATE_NEW) : FA_READ); if (f_open(&fp, path, m) != FR_OK) diff --git a/src/fs.h b/src/fs.h index d3f9681..9135c76 100644 --- a/src/fs.h +++ b/src/fs.h @@ -1,6 +1,23 @@ +/* +* 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 sd_mount(); +u32 sdMount(); +void sdUnmount(); u32 fopen(const char *path, const char *mode); u32 fread(void *buf, size_t size, size_t ntimes); u32 fwrite(void *buf, size_t size, size_t ntimes); 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 f30cf30..b4d1ef7 100644 --- a/src/hwinit.h +++ b/src/hwinit.h @@ -42,19 +42,6 @@ #include "hwinit/se.h" #include "hwinit/se_t210.h" #include "hwinit/mmc.h" +#include "hwinit/gfx.h" -#define NUM_KEYBLOB_KEYS 5 -static const u8 keyblob_keyseeds[NUM_KEYBLOB_KEYS][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 -}; - -static const u8 cmac_keyseed[0x10] = { 0x59, 0xC7, 0xFB, 0x6F, 0xBE, 0x9B, 0xBE, 0x87, 0x65, 0x6B, 0x15, 0xC0, 0x53, 0x73, 0x36, 0xA5 }; -static const u8 master_keyseed_retail[0x10] = { 0xD8, 0xA2, 0x41, 0x0A, 0xC6, 0xC5, 0x90, 0x01, 0xC6, 0x1D, 0x6A, 0x26, 0x7C, 0x51, 0x3F, 0x3C }; -static const u8 console_keyseed[0x10] = { 0x4F, 0x02, 0x5F, 0x0E, 0xB6, 0x6D, 0x11, 0x0E, 0xDC, 0x32, 0x7D, 0x41, 0x86, 0xC2, 0xF4, 0x78 }; -static const u8 key8_keyseed[] = { 0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7 }; -static const u8 master_keyseed_4xx[0x10] = { 0x2D, 0xC1, 0xF4, 0x8D, 0xF3, 0x5B, 0x69, 0x33, 0x42, 0x10, 0xAC, 0x65, 0xDA, 0x90, 0x46, 0x66 }; -static const u8 console_keyseed_4xx[0x10] = { 0x0C, 0x91, 0x09, 0xDB, 0x93, 0x93, 0x07, 0x81, 0x07, 0x3C, 0xC4, 0x16, 0x22, 0x7C, 0x6C, 0x28 }; \ No newline at end of file +#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..375f6e2 100644 --- a/src/hwinit/util.c +++ b/src/hwinit/util.c @@ -56,14 +56,27 @@ void exec_cfg(u32 *base, const cfg_op_t *ops, u32 num_ops) base[ops[i].off] = ops[i].val; } -uPtr memsearch(const u8 *startPos, u32 searchSize, const void *pattern, u32 patternSize) { +uPtr memsearch(void *startPos, size_t searchSize, void *pattern, size_t patternSize) { if(!searchSize) return 0; - for (u8 *pos = (u8 *)startPos; pos <= startPos + searchSize - patternSize; pos++) { + for (u8 *pos = (u8*)startPos; pos <= (u8*)startPos + searchSize - patternSize; pos++) { if (memcmp(pos, pattern, patternSize) == 0) return (uPtr)pos; } 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 "kippatches.h" -#include "fs.h" -#include "kippatches/fs.inc" - -// 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 kippatch_apply_set(u8 *kipdata, u64 kipdata_len, kippatchset_t *patchset, char **filter) { - for (kippatch_t *p = patchset->patches; p && p->name; ++p) { - int found = 0; - for (char **filtname = filter; filtname && *filtname; ++filtname) { - if (!strcmp(p->name, *filtname)) { - found = 1; - break; - } - } - if (!strcmp(p->name, "nogc")){ - if(!fopen("/ReiNX/nogc", "rb")) { - fclose(); - continue; - } - } - if (filter && !found) continue; - - int r = kippatch_apply(kipdata, kipdata_len, p); - if (r) return r; - } - - 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 db34fc5..7a41e55 100644 --- a/src/kippatches/fs.inc +++ b/src/kippatches/fs.inc @@ -89,13 +89,13 @@ static kipdiff_t fs_diffs_401_nocmac[6] = { static kipdiff_t fs_diffs_401_nogc[3] = { { 0xA3458, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" }, - { 0xAAC98, 8, "\x80\x02\xA0\x52\x40\x40\x91\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" }, + { 0xAAB44, 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_410_nogc[3] = { { 0xA34BC, 4, "\x14\x40\x80\x72", "\x14\x80\x80\x72" }, - { 0xAACFC, 8, "\x80\x02\xA0\x52\x40\x40\x91\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" }, + { 0xAABA8, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, { 0, 0, NULL, NULL }, }; @@ -118,7 +118,7 @@ static kipdiff_t fs_diffs_500_nocmac[8] = { static kipdiff_t fs_diffs_500_nogc[3] = { { 0xCF3C4, 4, "\x14\x40\x80\x52", "\x14\x80\x80\x52" }, - { 0xD74FC, 8, "\x40\x40\x91\x52\x80\x02\xA0\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" }, + { 0xD73A0, 8, "\xF4\x4F\xBE\xA9\xFD\x7B\x01\xA9", "\xE0\x03\x1F\x2A\xC0\x03\x5F\xD6" }, { 0, 0, NULL, NULL }, }; @@ -139,9 +139,56 @@ 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" }, - { 0xD78CC, 8, "\x40\x40\x91\x52\x80\x02\xA0\x72", "\xE0\x03\x1F\x2A\x1F\x20\x03\xD5" }, + { 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 }, }; @@ -204,3 +251,31 @@ static kippatch_t fs_kip_patches_510[] = { { "nogc", fs_diffs_510_nogc }, { NULL, NULL } }; + +static kippatch_t fs_kip_patches_600_40[] = { + { "nosigchk", fs_diffs_600_nosigchk }, + { "nocmac", fs_diffs_600_nocmac }, + { "nogc", fs_diffs_600_nogc }, + { NULL, NULL } +}; + +static kippatch_t fs_kip_patches_600_40_exfat[] = { + { "nosigchk", fs_diffs_600_exfat_nosigchk }, + { "nocmac", fs_diffs_600_exfat_nocmac }, + { "nogc", fs_diffs_600_exfat_nogc }, + { NULL, NULL } +}; + +static kippatch_t fs_kip_patches_600_50[] = { + { "nosigchk", fs_diffs_600_nosigchk }, + { "nocmac", fs_diffs_600_nocmac }, + { "nogc", fs_diffs_600_nogc }, + { NULL, NULL } +}; + +static kippatch_t fs_kip_patches_600_50_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..7a1284e 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"); @@ -87,14 +124,6 @@ void pkg1_unpack(pk11_offs *offs, u8 *pkg1) { } } -const pkg2_kernel_id_t *pkg2_identify(u32 id) -{ - for (u32 i = 0; _pkg2_kernel_ids[i].crc32c_id; i++) - if (id == _pkg2_kernel_ids[i].crc32c_id) - return &_pkg2_kernel_ids[i]; - return NULL; -} - void buildFirmwarePackage(u8 *kernel, u32 kernel_size, link_t *kips_info) { u8 *pdst = (u8 *)0xA9800000; @@ -189,4 +218,170 @@ 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_40 }, + { "FS", "\x96\x6a\xdd\x3d\x20\xb6\x27\x13\x2c\x5a\x8d\xa4\x9a\xc9\xd8\xdd", fs_kip_patches_600_40_exfat }, + { "FS", "\x3a\x57\x4d\x43\x61\x86\x19\x1d\x17\x88\xeb\x2c\x0f\x07\x6b\x11", fs_kip_patches_600_50 }, + { "FS", "\x33\x05\x53\xf6\xb5\xfb\x55\xc4\xc2\xd7\xb7\x36\x24\x02\x76\xb3", fs_kip_patches_600_50_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; +} + +u32 *getSndPayload(u32 id, size_t *size) { + u32 *ret; + switch(id){ + case 0: + *size = sizeof(PRC_ID_SND_100); + ret = PRC_ID_SND_100; + break; + case 1: + *size = sizeof(PRC_ID_SND_200); + ret = PRC_ID_SND_200; + break; + case 2: + *size = sizeof(PRC_ID_SND_300); + ret = PRC_ID_SND_300; + break; + case 3: + *size = sizeof(PRC_ID_SND_302); + ret = PRC_ID_SND_302; + break; + case 4: + *size = sizeof(PRC_ID_SND_400); + ret = PRC_ID_SND_400; + break; + case 5: + *size = sizeof(PRC_ID_SND_500); + ret = PRC_ID_SND_500; + break; + case 6: + *size = sizeof(PRC_ID_SND_600); + ret = PRC_ID_SND_600; + break; + } + return ret; +} + +u32 *getRcvPayload(u32 id, size_t *size) { + u32 *ret; + switch(id){ + case 0: + *size = sizeof(PRC_ID_RCV_100); + ret = PRC_ID_RCV_100; + break; + case 1: + *size = sizeof(PRC_ID_RCV_200); + ret = PRC_ID_RCV_200; + break; + case 2: + *size = sizeof(PRC_ID_RCV_300); + ret = PRC_ID_RCV_300; + break; + case 3: + *size = sizeof(PRC_ID_RCV_302); + ret = PRC_ID_RCV_302; + break; + case 4: + *size = sizeof(PRC_ID_RCV_400); + ret = PRC_ID_RCV_400; + break; + case 5: + *size = sizeof(PRC_ID_RCV_500); + ret = PRC_ID_RCV_500; + break; + case 6: + *size = sizeof(PRC_ID_RCV_600); + ret = PRC_ID_RCV_600; + break; + } + return ret; +} + +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 211f3e3..c6f3bd0 100644 --- a/src/package.h +++ b/src/package.h @@ -1,3 +1,19 @@ +/* +* Copyright (c) 2018 naehrwert, CTCaer, 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 #include "hwinit.h" #include "hwinit/arm64.h" @@ -9,27 +25,8 @@ #define INI1_MAGIC 0x31494E49 -#define FREE_CODE_OFF_1ST_100 0x4797C -#define FREE_CODE_OFF_1ST_200 0x6486C -#define FREE_CODE_OFF_1ST_300 0x494A4 -#define FREE_CODE_OFF_1ST_302 0x494BC -#define FREE_CODE_OFF_1ST_400 0x52890 -#define FREE_CODE_OFF_1ST_500 0x5C020 - -#define ID_SND_OFF_100 0x23CC0 -#define ID_SND_OFF_200 0x3F134 -#define ID_SND_OFF_300 0x26080 -#define ID_SND_OFF_302 0x26080 -#define ID_SND_OFF_400 0x2AF64 -#define ID_SND_OFF_500 0x2AD34 - -#define ID_RCV_OFF_100 0x219F0 -#define ID_RCV_OFF_200 0x3D1A8 -#define ID_RCV_OFF_300 0x240F0 -#define ID_RCV_OFF_302 0x240F0 -#define ID_RCV_OFF_400 0x28F6C -#define ID_RCV_OFF_500 0x28DAC - +#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; @@ -37,281 +34,195 @@ static u8 customKern = 0; typedef struct _pkg2_hdr_t { - u8 ctr[0x10]; - u8 sec_ctr[0x40]; - u32 magic; - u32 base; - u32 pad0; - u16 version; - u16 pad1; - u32 sec_size[4]; - u32 sec_off[4]; - u8 sec_sha256[0x80]; - u8 data[]; + u8 ctr[0x10]; + u8 sec_ctr[0x40]; + u32 magic; + u32 base; + u32 pad0; + u16 version; + u16 pad1; + u32 sec_size[4]; + u32 sec_off[4]; + u8 sec_sha256[0x80]; + u8 data[]; } pkg2_hdr_t; typedef struct _pkg2_ini1_t { - u32 magic; - u32 size; - u32 num_procs; - u32 pad; + u32 magic; + u32 size; + u32 num_procs; + u32 pad; } pkg2_ini1_t; typedef struct _pkg2_kip1_sec_t { - u32 offset; - u32 size_decomp; - u32 size_comp; - u32 attrib; + u32 offset; + u32 size_decomp; + u32 size_comp; + u32 attrib; } pkg2_kip1_sec_t; #define KIP1_NUM_SECTIONS 6 typedef struct _pkg2_kip1_t { - u32 magic; - char name[12]; - u64 tid; - u32 proc_cat; - u8 main_thrd_prio; - u8 def_cpu_core; - u8 res; - u8 flags; - pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; - u32 caps[0x20]; - u8 data[]; + u32 magic; + char name[12]; + u64 tid; + u32 proc_cat; + u8 main_thrd_prio; + u8 def_cpu_core; + u8 res; + u8 flags; + pkg2_kip1_sec_t sections[KIP1_NUM_SECTIONS]; + u32 caps[0x20]; + u8 data[]; } pkg2_kip1_t; typedef struct _pkg2_kip1_info_t { - pkg2_kip1_t *kip1; - u32 size; - link_t link; + pkg2_kip1_t *kip1; + u32 size; + link_t link; } pkg2_kip1_info_t; typedef struct { - const char *id; - u32 kb; - u32 tsec_off; - u32 pkg11_off; - u32 sec_map[3]; - u32 secmon_base; - u32 warmboot_base; - int set_warmboot; + const char *id; + u32 kb; + u32 tsec_off; + u32 pkg11_off; + u32 sec_map[3]; + u32 secmon_base; + u32 warmboot_base; + int set_warmboot; } pk11_offs; typedef struct { - u32 magic; - u32 wb_size; - u32 wb_off; - u32 pad; - u32 ldr_size; - u32 ldr_off; - u32 sm_size; - u32 sm_off; + u32 magic; + u32 wb_size; + u32 wb_off; + u32 pad; + u32 ldr_size; + u32 ldr_off; + u32 sm_size; + u32 sm_off; } pk11_header; -enum -{ - // Generic instruction patches - SVC_VERIFY_DS = 0x10, // 0x0-0xF are RESERVED. - DEBUG_MODE_EN, - ATM_GEN_PATCH, - // >4 bytes patches. Value is a pointer of a u32 array. - ATM_ARR_PATCH, -}; - -typedef struct _kernel_patch_t -{ - u32 id; - u32 off; - u32 val; - u32 *ptr; -} kernel_patch_t; - -typedef struct _pkg2_kernel_id_t -{ - u32 crc32c_id; - kernel_patch_t *kernel_patchset; -} pkg2_kernel_id_t; - - static u32 PRC_ID_SND_100[] = { - 0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA + 0xA9BF2FEA, 0x2A0E03EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9412948, 0xA8C12FEA }; -#define FREE_CODE_OFF_2ND_100 (FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100) + 4) + static u32 PRC_ID_RCV_100[] = { - 0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA + 0xA9BF2FEA, 0x2A1C03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9412968, 0xA8C12FEA }; static u32 PRC_ID_SND_200[] = { - 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9413148, 0xA8C12FEA }; -#define FREE_CODE_OFF_2ND_200 (FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200) + 4) + static u32 PRC_ID_RCV_200[] = { - 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, - 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9413168, 0xA8C12FEA }; static u32 PRC_ID_SND_300[] = { - 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA }; -#define FREE_CODE_OFF_2ND_300 (FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300) + 4) + static u32 PRC_ID_RCV_300[] = { - 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, - 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA }; static u32 PRC_ID_SND_302[] = { - 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, - 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA + 0xA9BF2FEA, 0x2A1803EB, 0xD37EF56B, 0xF86B6B8B, 0x92FFFFE9, 0x8A090168, 0xD2FFFFE9, 0x8A09016B, + 0xD2FFFFC9, 0xEB09017F, 0x54000040, 0xF9415548, 0xA8C12FEA }; -#define FREE_CODE_OFF_2ND_302 (FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302) + 4) + static u32 PRC_ID_RCV_302[] = { - 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, - 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA + 0xA9BF2FEA, 0x2A0F03EA, 0xD37EF54A, 0xF9405FEB, 0xF86A696A, 0xF9407BEB, 0x92FFFFE9, 0x8A090148, + 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415568, 0xA8C12FEA }; static u32 PRC_ID_SND_400[] = { - 0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, - 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA + 0x2A1703EA, 0xD37EF54A, 0xF86A6B8A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, + 0xEB09015F, 0x54000060, 0xF94053EA, 0xF9415948, 0xF94053EA }; -#define FREE_CODE_OFF_2ND_400 (FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400) + 4) + static u32 PRC_ID_RCV_400[] = { - 0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F + 0xF9403BED, 0x2A0E03EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, + 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B28, 0xD503201F }; static u32 PRC_ID_SND_500[] = { - 0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, - 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA + 0x2A1703EA, 0xD37EF54A, 0xF86A6B6A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, + 0xEB09015F, 0x54000060, 0xF94043EA, 0xF9415948, 0xF94043EA }; -#define FREE_CODE_OFF_2ND_500 (FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500) + 4) + static u32 PRC_ID_RCV_500[] = { - 0xF9403BED, 0x2A1503EA, 0xD37EF54A, 0xF86A69AA, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, - 0xD2FFFFC9, 0xEB09015F, 0x54000040, 0xF9415B08, 0xF9406FEA + 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 - { DEBUG_MODE_EN, 0x44074, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_100, _B(ID_SND_OFF_100, FREE_CODE_OFF_1ST_100), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_100, sizeof(PRC_ID_SND_100) >> 2, PRC_ID_SND_100}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_100 + sizeof(PRC_ID_SND_100), ID_SND_OFF_100 + 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_100, _B(ID_RCV_OFF_100, FREE_CODE_OFF_2ND_100), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_100, sizeof(PRC_ID_RCV_100) >> 2, PRC_ID_RCV_100}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_100 + sizeof(PRC_ID_RCV_100), ID_RCV_OFF_100 + 4), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} +static u32 PRC_ID_SND_600[] = +{ + 0xA9BF2FEA, 0xF94037EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 }; -static kernel_patch_t kern2[] = { - { SVC_VERIFY_DS, 0x54834, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x6086C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_200, _B(ID_SND_OFF_200, FREE_CODE_OFF_1ST_200), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_200, sizeof(PRC_ID_SND_200) >> 2, PRC_ID_SND_200}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_200 + sizeof(PRC_ID_SND_200), ID_SND_OFF_200 + 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_200, _B(ID_RCV_OFF_200, FREE_CODE_OFF_2ND_200), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_200, sizeof(PRC_ID_RCV_200) >> 2, PRC_ID_RCV_200}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_200 + sizeof(PRC_ID_RCV_200), ID_RCV_OFF_200 + 4), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} -}; -static kernel_patch_t kern3[] = { - { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x483FC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_300, _B(ID_SND_OFF_300, FREE_CODE_OFF_1ST_300), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_300, sizeof(PRC_ID_SND_300) >> 2, PRC_ID_SND_300}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_300 + sizeof(PRC_ID_SND_300), ID_SND_OFF_300 + 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_300, _B(ID_RCV_OFF_300, FREE_CODE_OFF_2ND_300), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_300, sizeof(PRC_ID_RCV_300) >> 2, PRC_ID_RCV_300}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_300 + sizeof(PRC_ID_RCV_300), ID_RCV_OFF_300 + 4), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} -}; -static kernel_patch_t kern302[] = { - { SVC_VERIFY_DS, 0x3BD24, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x48414, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_302, _B(ID_SND_OFF_302, FREE_CODE_OFF_1ST_302), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_302, sizeof(PRC_ID_SND_302) >> 2, PRC_ID_SND_302}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_1ST_302 + sizeof(PRC_ID_SND_302), ID_SND_OFF_302 + 4), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_302, _B(ID_RCV_OFF_302, FREE_CODE_OFF_2ND_302), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_302, sizeof(PRC_ID_RCV_302) >> 2, PRC_ID_RCV_302}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_302 + sizeof(PRC_ID_RCV_302), ID_RCV_OFF_302 + 4), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} -}; -static kernel_patch_t kern4[] = { - { SVC_VERIFY_DS, 0x41EB4, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x4EBFC, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_400, _B(ID_SND_OFF_400, FREE_CODE_OFF_1ST_400), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_400, sizeof(PRC_ID_SND_400) >> 2, PRC_ID_SND_400}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_1ST_400 + sizeof(PRC_ID_SND_400), ID_SND_OFF_400 + 8), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_400, _B(ID_RCV_OFF_400, FREE_CODE_OFF_2ND_400), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_400, sizeof(PRC_ID_RCV_400) >> 2, PRC_ID_RCV_400}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), // Branch back and skip 1 instruction. - _B(FREE_CODE_OFF_2ND_400 + sizeof(PRC_ID_RCV_400), ID_RCV_OFF_400 + 4), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} +static u32 PRC_ID_RCV_600[] = +{ + 0xA9BF2FEA, 0xF94043EB, 0x2A1503EA, 0xD37EF54A, 0xF86A696A, 0x92FFFFE9, 0x8A090148, 0xD2FFFFE9, 0x8A09014A, 0xD2FFFFC9, 0xEB09015F, 0x54000100, 0xA9BF27E8, 0xF9400308, 0xF9401D08, 0xAA1803E0, 0xD63F0100, 0xA8C127E8, 0xAA0003E8, 0xA8C12FEA, 0xAA0803E0 }; -static kernel_patch_t kern5[] = { - { SVC_VERIFY_DS, 0x45E6C, _NOP(), NULL }, // Disable SVC verifications - { DEBUG_MODE_EN, 0x5513C, _MOVZX(8, 1, 0), NULL }, // Enable Debug Patch - // Atmosphère kernel patches. - { ATM_GEN_PATCH, ID_SND_OFF_500, _B(ID_SND_OFF_500, FREE_CODE_OFF_1ST_500), NULL}, // Send process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_1ST_500, sizeof(PRC_ID_SND_500) >> 2, PRC_ID_SND_500}, // Send process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_1ST_500 + sizeof(PRC_ID_SND_500), ID_SND_OFF_500 + 8), NULL}, - { ATM_GEN_PATCH, ID_RCV_OFF_500, _B(ID_RCV_OFF_500, FREE_CODE_OFF_2ND_500), NULL}, // Receive process id branch. - { ATM_ARR_PATCH, FREE_CODE_OFF_2ND_500, sizeof(PRC_ID_RCV_500) >> 2, PRC_ID_RCV_500}, // Receive process id code. - { ATM_GEN_PATCH, FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), // Branch back and skip 2 instructions. - _B(FREE_CODE_OFF_2ND_500 + sizeof(PRC_ID_RCV_500), ID_RCV_OFF_500 + 8), NULL}, - {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, (u32*)0xFFFFFFFF} -}; +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; -static const pkg2_kernel_id_t _pkg2_kernel_ids[] = -{ - { 0x427f2647, kern1 }, //1.0.0 - { 0xae19cf1b, kern2 }, //2.0.0 - 2.3.0 - { 0x73c9e274, kern3 }, //3.0.0 - 3.0.1 - { 0xe0e8cdc4, kern302 }, //3.0.2 - { 0x485d0157, kern4 }, //4.0.0 - 4.1.0 - { 0xf3c363f2, kern5 }, //5.0.0 - 5.1.0 - { 0, 0 } //End. -}; +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); size_t calcKipSize(pkg2_kip1_t *kip1); void pkg2_parse_kips(link_t *info, pkg2_hdr_t *pkg2); void loadKip(link_t *info, char *path); -const pkg2_kernel_id_t *pkg2_identify(u32 id); \ No newline at end of file +u32 *getSndPayload(u32 id, size_t *size); +u32 *getRcvPayload(u32 id, size_t *size); \ No newline at end of file diff --git a/src/reloc.s b/src/reloc.s deleted file mode 100644 index d89a414..0000000 --- a/src/reloc.s +++ /dev/null @@ -1,34 +0,0 @@ -/* -* Copyright (c) 2018 naehrwert -* -* 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 . -*/ - -/* -* TODO: the placement of the relocator is a bit fragile atm, maybe we -* should include it in start.S and copy it to some known good -* place in IRAM instead. Basically we want it as far back atm -* as it might be overwritten during relocation. -*/ - -.section .text.reloc -.arm - -.globl _reloc_ipl -.type _reloc_ipl, %function -_reloc_ipl: - LDMIA R0!, {R4-R7} - STMIA R1!, {R4-R7} - SUBS R2, #0x10 - BNE _reloc_ipl - BX R3 diff --git a/src/start.s b/src/start.s index 006f818..30786b1 100644 --- a/src/start.s +++ b/src/start.s @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018 naehrwert +* Copyright (c) 2018 naehrwert, 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, @@ -17,27 +17,33 @@ .section .text.start .arm -.extern _reloc_ipl -.type _reloc_ipl, %function - .extern memset .type memset, %function -.extern ipl_main -.type ipl_main, %function +.extern heap_init +.type heap_init, %function + +.extern bootrom +.type bootrom, %function + +.extern bootloader +.type bootloader, %function + +.extern firmware +.type firmware, %function .globl _start .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} @@ -45,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 @@ -73,18 +79,3 @@ _real_start: BL bootloader BL firmware B . - -.globl rebootRCM -.type rebootRCM, %function -rebootRCM: - MOVS R3, #2 - LDR R2, =0x7000E450 - LDR R1, [R2] - ORRS R3, R1 - STR R3, [R2] - MOVS R3, #0x10 - LDR R2, =0x7000E400 - LDR R1, [R2] - ORRS R3, R1 - MOVS R0, #0 - STR R3, [R2]