Permalink
Comparing changes
Open a pull request
- 19 commits
- 21 files changed
- 0 commit comments
- 5 contributors
Unified
Split
Showing
with
1,108 additions
and 351 deletions.
- +4 −1 Makefile
- +1 −1 NX_Sysmodules
- +2 −0 README.md
- +1 −0 src/error.c
- +178 −70 src/firmware.c
- +1 −0 src/hwinit/gfx.h
- +2 −0 src/hwinit/max77620.h
- +1 −1 src/hwinit/util.c
- +16 −2 src/kippatches/fs.inc
- +149 −0 src/menu/menu.c
- +44 −0 src/menu/menu.h
- +32 −0 src/menu/menu_entry.c
- +36 −0 src/menu/menu_entry.h
- +48 −0 src/menu/menu_pool.c
- +34 −0 src/menu/menu_pool.h
- +168 −0 src/menu/menu_tools.c
- +34 −0 src/menu/menu_tools.h
- +90 −27 src/package.c
- +84 −249 src/package.h
- +156 −0 src/reinx_menu.c
- +27 −0 src/reinx_menu.h
| @@ -4,7 +4,7 @@ ifeq ($(strip $(DEVKITARM)),) | ||
| $(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>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 | ||
| @@ -51,9 +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)/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 $< $@ | ||
Submodule NX_Sysmodules
updated
13 files
| +1 −1 | Makefile | |
| +2 −0 | README.md | |
| +36 −42 | libstratosphere/include/stratosphere/hossynch.hpp | |
| +6 −4 | loader/source/ldr_nso.cpp | |
| +1 −0 | pm/pm.json | |
| +1 −0 | pm/source/pm_boot2.cpp | |
| +1 −0 | pm/source/pm_boot2.hpp | |
| +10 −0 | pm/source/pm_debug_monitor.cpp | |
| +3 −0 | pm/source/pm_debug_monitor.hpp | |
| +8 −8 | pm/source/pm_main.cpp | |
| +10 −0 | pm/source/pm_registration.cpp | |
| +12 −11 | pm/source/pm_registration.hpp | |
| +87 −39 | pm/source/pm_resource_limits.cpp |
| @@ -23,6 +23,8 @@ 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) | ||
| * Kernel patches on the fly (optional debug mode) | ||
| * Exclusive ReiNX sysmodules | ||
| * ES patch in RXP patch format (used with custom loader.kip) | ||
| @@ -30,6 +30,7 @@ void panic() { | ||
| } | ||
| void error(char *errStr) { | ||
| gfx_con.mute = 0; | ||
| gfx_con_setcol(&gfx_con, RED, 0, 0); | ||
| print("Error: %s", errStr); | ||
| gfx_con_setcol(&gfx_con, DEFAULT_TEXT_COL, 0, 0); | ||
| @@ -22,16 +22,18 @@ | ||
| #include "error.h" | ||
| #include "bootloader.h" | ||
| #include "firmware.h" | ||
| #include "reinx_menu.h" | ||
| static pk11_offs *pk11Offs = NULL; | ||
| 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) { | ||
| @@ -41,6 +43,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){ | ||
| @@ -120,69 +175,115 @@ 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]; | ||
| //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"); | ||
| 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; | ||
| 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); | ||
| if (res) error("kippatch_apply_set() failed\n"); | ||
| } | ||
| 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; | ||
| } | ||
| free(ki->kip1); | ||
| ki->size = newSize; | ||
| ki->kip1 = moddedKip; | ||
| 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; | ||
| } | ||
| 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:; | ||
| } | ||
| 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); | ||
| } | ||
| } | ||
| @@ -298,18 +399,18 @@ void launch() { | ||
| void firmware() { | ||
| display_init(); | ||
| gfx_init_ctxt(&gfx_ctxt, display_init_framebuffer(), 720, 1280, 768); | ||
| gfx_clear_color(&gfx_ctxt, 0xFF000000); | ||
| gfx_clear_color(&gfx_ctxt, BLACK); | ||
| gfx_con_init(&gfx_con, &gfx_ctxt); | ||
| gfx_con_setcol(&gfx_con, DEFAULT_TEXT_COL, 0, 0); | ||
| while (!sdMount()) { | ||
| if (!sdMount()) { | ||
| error("Failed to init SD card!\n"); | ||
| print("Press POWER to power off, any other key to retry\n"); | ||
| 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(); | ||
| @@ -321,10 +422,17 @@ void firmware() { | ||
| ((void (*)())PAYLOAD_ADDR)(); | ||
| } | ||
| SYSREG(AHB_AHB_SPARE_REG) = (volatile vu32)0xFFFFFF9F; | ||
| PMC(APBDEV_PMC_SCRATCH49) = 0; | ||
| PMC(APBDEV_PMC_SCRATCH49) = 0; | ||
| if (btn_read() & BTN_VOL_DOWN) { | ||
| print("Running in verbose mode!\n"); | ||
| } else if (btn_read() & BTN_VOL_UP) { | ||
| init_reinx_menu(); | ||
| } else if (drawSplash()) { | ||
| gfx_con.mute = 1; | ||
| } | ||
| print("Welcome to ReiNX %s!\n", VERSION); | ||
| loadFirm(); | ||
| drawSplash(); | ||
| launch(); | ||
| } | ||
| @@ -26,6 +26,7 @@ | ||
| #define YELLOW 0xFF00FFFF | ||
| #define ORANGE 0xFF3891FF | ||
| #define WHITE 0xFFFFFFFF | ||
| #define BLACK 0xFF000000 | ||
| typedef struct _gfx_ctxt_t | ||
| { | ||
| @@ -11,6 +11,8 @@ | ||
| #ifndef _MFD_MAX77620_H_ | ||
| #define _MFD_MAX77620_H_ | ||
| #define MAX77620_I2C_ADDR 0x3C | ||
| /* GLOBAL, PMIC, GPIO, FPS, ONOFFC, CID Registers */ | ||
| #define MAX77620_REG_CNFGGLBL1 0x00 | ||
| #define MAX77620_REG_CNFGGLBL2 0x01 | ||
| @@ -70,7 +70,7 @@ uPtr getFreeSpace(void *start, size_t space, size_t searchSize) { | ||
| if(*(u8*)(start+i) == 0) { | ||
| for(int j=0;j<space;j++) { | ||
| if(*(u8*)(start+i+j) != 0) break; | ||
| if(j==space-1) return (uPtr)(start+i); | ||
| if(j==space-1) return (uPtr)i; | ||
| } | ||
| } | ||
| } | ||
Oops, something went wrong.