Unified
Split
Showing
with
515 additions
and 472 deletions.
- +9 −4 Dockerfile
- +2 −2 Makefile
- +1 −1 NX_Sysmodules
- +9 −6 README.md
- BIN data/es_patch.rxp
- +18 −13 docker-build.sh
- +3 −3 link.ld
- +87 −1 src/bootloader.c
- +18 −0 src/bootloader.h
- +1 −2 src/bootrom.c
- +2 −2 src/error.c
- +0 −1 src/error.h
- +56 −136 src/firmware.c
- +2 −18 src/firmware.h
- +8 −2 src/fs.c
- +2 −1 src/fs.h
- +0 −47 src/fuse.c
- +0 −21 src/fuse.h
- +4 −1 src/hwinit.h
- +1 −1 src/hwinit/pmc.h
- +1 −0 src/hwinit/types.h
- +15 −2 src/hwinit/util.c
- +3 −2 src/hwinit/util.h
- +0 −112 src/kippatches.c
- +0 −31 src/kippatches.h
- +61 −0 src/kippatches/fs.inc
- +134 −2 src/package.c
- +60 −0 src/package.h
- +0 −34 src/reloc.s
- +18 −27 src/start.s
| @@ -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"] | ||
| ENV DEVKITARM=${DEVKITPRO}/devkitARM | ||
| WORKDIR /developer | ||
| ENTRYPOINT ["make"] |
| @@ -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, \ | ||
| @@ -53,7 +54,6 @@ $(dir_out)/$(name).bin: $(dir_build)/$(name).elf | ||
| @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 -R $(dir_data)/*.bin $(dir_out)/ReiNX/ | ||
| @cp -R $(dir_data)/*.rxp $(dir_out)/ReiNX/patches | ||
| $(OBJCOPY) -S -O binary $< $@ | ||
Submodule NX_Sysmodules
updated
6 files
| +1 −1 | Makefile | |
| +11 −1 | README.md | |
| +8 −1 | fs_mitm/source/fsmitm_service.hpp | |
| +25 −0 | loader/source/ldr_nso.cpp | |
| +10 −1 | loader/source/ldr_process_creation.cpp | |
| +1 −1 | pm/source/pm_boot2.cpp |
| @@ -11,29 +11,32 @@ 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 | ||
| * Optional custom kernel/secmon/warmboot | ||
| * FS patches on the fly (NCA verify/cmac and optional nogc) | ||
| * Exclusive ReiNX sysmodules with built in ES patches | ||
| * 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! | ||
Binary file not shown.
| @@ -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 | ||
| 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 |
| @@ -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 = .; | ||
| @@ -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; | ||
| @@ -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(); | ||
| @@ -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; | ||
| } | ||
| @@ -31,6 +31,6 @@ void panic() { | ||
| void error(char *errStr) { | ||
| 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); | ||
| } | ||
| @@ -17,7 +17,6 @@ | ||
| #pragma once | ||
| #include "hwinit/types.h" | ||
| #include "hwinit/gfx.h" | ||
| void panic(); | ||
| void error(char *errStr); | ||
Oops, something went wrong.