From bcd6ceffe16c10a73e48afcd8cf040a35f01344e Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 11 Jan 2024 18:29:36 -0500 Subject: [PATCH 01/20] GO ms0/ef0 support --- src/Makefile.signed | 7 ++++++- src/downgrade660_ctrl/main.c | 14 ++++++++++++-- src/downgrade_ctrl/main.c | 16 +++++++++++++++- src/kernel_land.c | 27 +++++++++++++++++---------- src/kernel_land.h | 2 ++ src/main.c | 32 +++++++++++++++++++++++++------- 6 files changed, 77 insertions(+), 21 deletions(-) diff --git a/src/Makefile.signed b/src/Makefile.signed index 6cc1a89..7906c3d 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -1,5 +1,10 @@ +UNAME := $(shell uname) release: all +ifeq ($(UNAME), Linux) + WINEPREFIX=$(shell pwd)/prefix wine bin/prxEncrypter $(TARGET).prx +else bin/prxEncrypter $(TARGET).prx +endif pack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL data.psp NULL rm -f data.psp rm -f downgrade_ctrl.h @@ -19,7 +24,7 @@ LIBS = -lpsppower PSP_FW_VERSION = 271 EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.2 +PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.3 BUILD_PRX = 1 diff --git a/src/downgrade660_ctrl/main.c b/src/downgrade660_ctrl/main.c index eb6511e..fe7e4e7 100644 --- a/src/downgrade660_ctrl/main.c +++ b/src/downgrade660_ctrl/main.c @@ -57,8 +57,18 @@ int ApplyFirmware(SceModule2 *mod) SfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader)); /* Lets open the updater */ - char *file = (sceKernelGetModel() == 4) ? ("ef0:/PSP/GAME/UPDATE/EBOOT.pbp") : ("ms0:/PSP/GAME/UPDATE/EBOOT.pbp"); - + char file[] = "ef0:/PSP/GAME/UPDATE/EBOOT.pbp"; + SceIoStat stats; + int status; + + status = sceIoGetstat(file, &stats); + + if(status < 0) { + file[0] = 'm'; + file[1] = 's'; + status = sceIoGetstat(file, &stats); + } + /* set k1 */ u32 k1 = pspSdkSetK1(0); diff --git a/src/downgrade_ctrl/main.c b/src/downgrade_ctrl/main.c index 5b0e85f..ddd0fbf 100644 --- a/src/downgrade_ctrl/main.c +++ b/src/downgrade_ctrl/main.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -57,7 +58,20 @@ int ApplyFirmware(void) SfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader)); /* Lets open the updater */ - char *file = (sceKernelGetModel() == 4) ? ("ef0:/PSP/GAME/UPDATE/EBOOT.pbp") : ("ms0:/PSP/GAME/UPDATE/EBOOT.pbp"); + char file[] = "ef0:/PSP/GAME/UPDATE/EBOOT.pbp"; + SceIoStat stats; + int status; + + status = sceIoGetstat(file, &stats); + + if(status < 0) { + file[0] = 'm'; + file[1] = 's'; + status = sceIoGetstat(file, &stats); + } + + + /* set k1 */ u32 k1 = pspSdkSetK1(0); diff --git a/src/kernel_land.c b/src/kernel_land.c index 9c39778..730d589 100644 --- a/src/kernel_land.c +++ b/src/kernel_land.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,7 @@ #include "utils.h" #include "downgrade_ctrl/patch_table.h" + /* function pointers */ int (* pspKernelGetModel)(void) = NULL; int (* pspSysconGetBaryonVersion)(u32 *baryon) = NULL; @@ -111,7 +113,7 @@ int patch_loadexec_phat(void) KClearCaches(); /* just return 0 */ - return pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param); + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } int patch_loadexec_slim(void) @@ -138,7 +140,7 @@ int patch_loadexec_slim(void) KClearCaches(); /* just return 0 */ - return pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param); + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } int patch_loadexec_3000(void) @@ -165,7 +167,7 @@ int patch_loadexec_3000(void) KClearCaches(); /* just return 0 */ - return pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param); + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } int patch_loadexec_4000(void) @@ -192,7 +194,7 @@ int patch_loadexec_4000(void) KClearCaches(); /* just return 0 */ - return pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param); + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } int patch_loadexec_pspgo(void) @@ -220,8 +222,13 @@ int patch_loadexec_pspgo(void) /* clear the caches */ KClearCaches(); - /* reboot into the updater */ - return pspKernelLoadExecVSHEf1(PSPGO_UPDATER_PATH, &g_exec_param); + if(strcasecmp(eboot_path, "ms0")>=0) { + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); + } + else { + /* reboot into the updater */ + return pspKernelLoadExecVSHEf1(eboot_path, &g_exec_param); + } } int patch_loadexec_street(void) @@ -240,13 +247,13 @@ int patch_loadexec_street(void) KClearCaches(); /* just return 0 */ - return pspKernelLoadExecVSHMs1(OTHER_UPDATER_PATH, &g_exec_param); + return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } -int launch_updater(void) +int launch_updater() { KClearCaches(); - + int res = -1; /* clear our param */ @@ -254,7 +261,7 @@ int launch_updater(void) /* fill the field */ g_exec_param.size = sizeof(struct SceKernelLoadExecVSHParam); - g_exec_param.argp = (pspKernelGetModel() == 4) ? (PSPGO_UPDATER_PATH) : (OTHER_UPDATER_PATH); + g_exec_param.argp = eboot_path; g_exec_param.args = strlen(g_exec_param.argp) + 1; g_exec_param.key = "updater"; g_exec_param.vshmain_args_size = 0; diff --git a/src/kernel_land.h b/src/kernel_land.h index 0c2b50a..3a8f8ef 100644 --- a/src/kernel_land.h +++ b/src/kernel_land.h @@ -15,6 +15,8 @@ u32 getBaryon(void); int launch_updater(void); int delete_resume_game(void); +extern char eboot_path[]; + extern int (* pspKernelGetModel)(void); extern int (* pspSysconGetBaryonVersion)(u32 *baryon); extern SceModule2 *(* pspKernelFindModuleByName)(const char *name); diff --git a/src/main.c b/src/main.c index 7826abc..b769b9b 100644 --- a/src/main.c +++ b/src/main.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -28,7 +29,9 @@ PSP_MODULE_INFO("Chronoswitch", 0, 1, 1); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(3 << 10); -#define DOWNGRADER_VER ("7.2") +#define DOWNGRADER_VER ("7.3") + +char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; typedef struct __attribute__((packed)) { @@ -50,7 +53,7 @@ typedef struct __attribute__((packed)) short unknown; // 16 } SfoEntry; -u32 get_updater_version(u32 is_pspgo) +u32 get_updater_version() { int i; char *fw_data = NULL; @@ -60,10 +63,20 @@ u32 get_updater_version(u32 is_pspgo) SfoEntry *entries = (SfoEntry *)((char *)sfo_buffer + sizeof(SfoHeader)); /* Lets open the updater */ - char *file = (is_pspgo) ? ("ef0:/PSP/GAME/UPDATE/EBOOT.PBP") : ("ms0:/PSP/GAME/UPDATE/EBOOT.PBP"); - + SceIoStat stats; + int status; + + status = sceIoGetstat(eboot_path, &stats); + + if(status < 0) { + eboot_path[0] = 'm'; + eboot_path[1] = 's'; + status = sceIoGetstat(eboot_path, &stats); + } + + /* open file */ - SceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777); + SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); /* check for failure */ if (fd < 0) @@ -139,7 +152,12 @@ int main(int argc, char *argv[]) "Contributions:" "\n" "\t" "6.31/6.35 Support added by Davee" "\n" "\t" "6.38/6.39/6.60 Support added by some1" "\n" - "\t" "6.61 Support added by qwikrazor87" "\n" "\n" + "\t" "6.61 Support added by qwikrazor87" "\n" + "\t" "Removed factory firmware limits (and more) by TheZett" "\n" + "\t" "GO ms0/ef0 UPDATE support added by krazynez" "\n" "\n" + "Testers:" "\n" + "\t" "Peter Lustig" "\n" + "\t" "Nall (nallwolf)" "\n" "\n" "Web:" "\n" "\t" "https://lolhax.org" "\n" "\n" @@ -254,7 +272,7 @@ int main(int argc, char *argv[]) sceKernelDelayThread(4*1000*1000); /* get the updater version */ - u32 upd_ver = get_updater_version(model == 4); + u32 upd_ver = get_updater_version(); /* make sure that we are not attempting to downgrade a PSP below its firmware boundaries */ From 9946d81688b591b2e477c6ed9a48bd16603eedc1 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 13 Jan 2024 18:19:44 -0500 Subject: [PATCH 02/20] reduced some code down --- src/downgrade660_ctrl/main.c | 15 +++++++++------ src/downgrade_ctrl/main.c | 16 +++++++--------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/downgrade660_ctrl/main.c b/src/downgrade660_ctrl/main.c index fe7e4e7..810ba67 100644 --- a/src/downgrade660_ctrl/main.c +++ b/src/downgrade660_ctrl/main.c @@ -20,6 +20,10 @@ PSP_MODULE_INFO("DowngraderCTRL", 0x3007, 1, 0); + +char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; + + /* function pointers */ int (* PrologueModule)(void *modmgr_param, SceModule2 *mod) = NULL; STMOD_HANDLER previous = NULL; @@ -57,23 +61,22 @@ int ApplyFirmware(SceModule2 *mod) SfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader)); /* Lets open the updater */ - char file[] = "ef0:/PSP/GAME/UPDATE/EBOOT.pbp"; SceIoStat stats; int status; - status = sceIoGetstat(file, &stats); + status = sceIoGetstat(eboot_path, &stats); if(status < 0) { - file[0] = 'm'; - file[1] = 's'; - status = sceIoGetstat(file, &stats); + eboot_path[0] = 'm'; + eboot_path[1] = 's'; + status = sceIoGetstat(eboot_path, &stats); } /* set k1 */ u32 k1 = pspSdkSetK1(0); /* lets open the file */ - SceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777); + SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); /* check for failure */ if (fd < 0) diff --git a/src/downgrade_ctrl/main.c b/src/downgrade_ctrl/main.c index ddd0fbf..c8835e7 100644 --- a/src/downgrade_ctrl/main.c +++ b/src/downgrade_ctrl/main.c @@ -21,6 +21,8 @@ PSP_MODULE_INFO("DowngraderCTRL", 0x3007, 1, 0); +char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; + /* function pointers */ int (* PrologueModule)(void *modmgr_param, SceModule *mod) = NULL; STMOD_HANDLER previous = NULL; @@ -58,26 +60,22 @@ int ApplyFirmware(void) SfoEntry *entries = (SfoEntry *)((char *)g_sfo_buffer + sizeof(SfoHeader)); /* Lets open the updater */ - char file[] = "ef0:/PSP/GAME/UPDATE/EBOOT.pbp"; SceIoStat stats; int status; - status = sceIoGetstat(file, &stats); + status = sceIoGetstat(eboot_path, &stats); if(status < 0) { - file[0] = 'm'; - file[1] = 's'; - status = sceIoGetstat(file, &stats); + eboot_path[0] = 'm'; + eboot_path[1] = 's'; + status = sceIoGetstat(eboot_path, &stats); } - - - /* set k1 */ u32 k1 = pspSdkSetK1(0); /* lets open the file */ - SceUID fd = sceIoOpen(file, PSP_O_RDONLY, 0777); + SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); /* check for failure */ if (fd < 0) From 5bd600d4266e7ce76e757c008ae03958130c574a Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 13 Jan 2024 19:12:46 -0500 Subject: [PATCH 03/20] removed duplicate eboot_path definition --- src/Makefile.signed | 2 +- src/downgrade660_ctrl/main.c | 5 ++--- src/downgrade_ctrl/main.c | 4 ++-- src/include/common.h | 4 ++++ src/main.c | 3 ++- 5 files changed, 11 insertions(+), 7 deletions(-) create mode 100644 src/include/common.h diff --git a/src/Makefile.signed b/src/Makefile.signed index 7906c3d..ff75c12 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -13,7 +13,7 @@ endif TARGET = downgrader OBJS = main.o kernel_exploit.o kernel_land.o rebootex.o utils.o extras.o extra_stubs.o libasm/libinfinityUser.o -INCDIR = ../include +INCDIR = include CFLAGS = -Os -G0 -Wall CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS) -c diff --git a/src/downgrade660_ctrl/main.c b/src/downgrade660_ctrl/main.c index 810ba67..3a0dd84 100644 --- a/src/downgrade660_ctrl/main.c +++ b/src/downgrade660_ctrl/main.c @@ -14,6 +14,8 @@ #include #include +#include "common.h" + #include "utils.h" #include "patch_table.h" #include "decrypt.h" @@ -21,9 +23,6 @@ PSP_MODULE_INFO("DowngraderCTRL", 0x3007, 1, 0); -char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; - - /* function pointers */ int (* PrologueModule)(void *modmgr_param, SceModule2 *mod) = NULL; STMOD_HANDLER previous = NULL; diff --git a/src/downgrade_ctrl/main.c b/src/downgrade_ctrl/main.c index c8835e7..e97df15 100644 --- a/src/downgrade_ctrl/main.c +++ b/src/downgrade_ctrl/main.c @@ -15,14 +15,14 @@ #include #include +#include + #include "utils.h" #include "patch_table.h" #include "decrypt.h" PSP_MODULE_INFO("DowngraderCTRL", 0x3007, 1, 0); -char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; - /* function pointers */ int (* PrologueModule)(void *modmgr_param, SceModule *mod) = NULL; STMOD_HANDLER previous = NULL; diff --git a/src/include/common.h b/src/include/common.h new file mode 100644 index 0000000..4d305b5 --- /dev/null +++ b/src/include/common.h @@ -0,0 +1,4 @@ +#ifndef _COMMON_H_ +#define _COMMON_H_ +#endif +char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; diff --git a/src/main.c b/src/main.c index b769b9b..ea0575a 100644 --- a/src/main.c +++ b/src/main.c @@ -20,6 +20,8 @@ #include #include +#include "common.h" + #include "utils.h" #include "kernel_land.h" #include "kernel_exploit.h" @@ -31,7 +33,6 @@ PSP_HEAP_SIZE_KB(3 << 10); #define DOWNGRADER_VER ("7.3") -char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; typedef struct __attribute__((packed)) { From ecfbbbfbfa8672e9a800e11e8ab4e55845f1ee2f Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 13 Jan 2024 19:18:15 -0500 Subject: [PATCH 04/20] cleanup --- src/downgrade_ctrl/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/downgrade_ctrl/main.c b/src/downgrade_ctrl/main.c index e97df15..200b8c9 100644 --- a/src/downgrade_ctrl/main.c +++ b/src/downgrade_ctrl/main.c @@ -15,7 +15,7 @@ #include #include -#include +#include "common.h" #include "utils.h" #include "patch_table.h" From c124cac8fb14abd790b4d3b0fdd2566908b0417f Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Tue, 16 Jan 2024 09:48:00 -0500 Subject: [PATCH 05/20] Windows syntax for prxEncrypter --- src/Makefile.signed | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Makefile.signed b/src/Makefile.signed index ff75c12..78ce26b 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -3,7 +3,7 @@ release: all ifeq ($(UNAME), Linux) WINEPREFIX=$(shell pwd)/prefix wine bin/prxEncrypter $(TARGET).prx else - bin/prxEncrypter $(TARGET).prx + bin\prxEncrypter $(TARGET).prx endif pack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL data.psp NULL rm -f data.psp From 7848157999ff9759820f1968e1ad856f859f1865 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 17:45:35 -0400 Subject: [PATCH 06/20] clean up --- src/utils.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/utils.h b/src/utils.h index c0d4eeb..5704dea 100644 --- a/src/utils.h +++ b/src/utils.h @@ -19,9 +19,6 @@ #define FIRMWARE_VERSION_660 (0x06060010) #define FIRMWARE_VERSION_661 (0x06060110) -#define PSPGO_UPDATER_PATH "ef0:/PSP/GAME/UPDATE/EBOOT.PBP" -#define OTHER_UPDATER_PATH "ms0:/PSP/GAME/UPDATE/EBOOT.PBP" - #define printf pspDebugScreenPrintf /** From 3ed5dcb1afed3464ed9de10724d2a26e64206bd6 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 17:46:27 -0400 Subject: [PATCH 07/20] Cleanup GO detection stuff when CS on ef0 and OFW is on ms0 --- src/main.c | 79 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 28 deletions(-) diff --git a/src/main.c b/src/main.c index ea0575a..b92f432 100644 --- a/src/main.c +++ b/src/main.c @@ -21,17 +21,18 @@ #include #include "common.h" +#include "kubridge.h" #include "utils.h" #include "kernel_land.h" #include "kernel_exploit.h" #include "rebootex.h" -PSP_MODULE_INFO("Chronoswitch", 0, 1, 1); +PSP_MODULE_INFO("Chronoswitch", 0, 7, 4); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(3 << 10); -#define DOWNGRADER_VER ("7.3") +#define DOWNGRADER_VER ("7.4") typedef struct __attribute__((packed)) @@ -54,7 +55,7 @@ typedef struct __attribute__((packed)) short unknown; // 16 } SfoEntry; -u32 get_updater_version() +u32 get_updater_version(char *argv) { int i; char *fw_data = NULL; @@ -72,25 +73,24 @@ u32 get_updater_version() if(status < 0) { eboot_path[0] = 'm'; eboot_path[1] = 's'; - status = sceIoGetstat(eboot_path, &stats); } - - - /* open file */ - SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); /* check for failure */ - if (fd < 0) - { - /* error firmware */ - return 0xFFF; - } - - /* read the PBP header */ - sceIoRead(fd, pbp_header, sizeof(pbp_header)); - - /* seek to the SFO */ - sceIoLseek32(fd, pbp_header[8/4], PSP_SEEK_SET); + int model = execKernelFunction(getModel); + SceUID fd = -1; + if(model == 4 && strcasecmp(argv, "ef0") > 0) { return 0xFA4E; /*FAKE some reason CS on ef0 does not like reading from ms0 */} + if ((fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777) < 0)) + { + printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); + /* error firmware */ + return 0xFFF; + } + + /* read the PBP header */ + sceIoRead(fd, pbp_header, sizeof(pbp_header)); + + /* seek to the SFO */ + sceIoLseek32(fd, pbp_header[8/4], PSP_SEEK_SET); /* calculate the size of the SFO */ u32 sfo_size = pbp_header[12/4] - pbp_header[8/4]; @@ -102,12 +102,12 @@ u32 get_updater_version() sceIoClose(fd); return 0xFFF; } - - /* read the sfo */ - sceIoRead(fd, sfo_buffer, sizeof(sfo_buffer)); - - /* close the file */ - sceIoClose(fd); + + /* read the sfo */ + sceIoRead(fd, sfo_buffer, sizeof(sfo_buffer)); + + /* close the file */ + sceIoClose(fd); /* now parse the SFO */ for (i = 0; i < header->count; i++) @@ -273,7 +273,25 @@ int main(int argc, char *argv[]) sceKernelDelayThread(4*1000*1000); /* get the updater version */ - u32 upd_ver = get_updater_version(); + u32 upd_ver = get_updater_version(argv); + + if (upd_ver == 0xFFF) { + printf("\nPress R to exit...\n"); + while (1) + { + sceCtrlPeekBufferPositive(&pad_data, 1); + + /* filter out previous buttons */ + cur_buttons = pad_data.Buttons & ~prev_buttons; + prev_buttons = pad_data.Buttons; + + /* check for cross */ + if (cur_buttons & PSP_CTRL_RTRIGGER) + { + ErrorExit(5000, "Exiting in 5 seconds.\n"); + } + } + } /* make sure that we are not attempting to downgrade a PSP below its firmware boundaries */ @@ -391,8 +409,13 @@ int main(int argc, char *argv[]) } /* do confirmation stuff */ - printf("\n" "Will attempt to Downgrade: %X.%X -> %X.%X.\n", (g_devkit_version >> 24) & 0xF, ((g_devkit_version >> 12) & 0xF0) | ((g_devkit_version >> 8) & 0xF), (upd_ver >> 8) & 0xF, upd_ver & 0xFF); - printf("X to continue, R to exit.\n"); + if(model == 4 && (strcasecmp(argv, "ef0") > 0)) { + printf("X to continue to Downgrade, R to exit.\n"); + } + else { + printf("\n" "Will attempt to Downgrade: %X.%X -> %X.%X.\n", (g_devkit_version >> 24) & 0xF, ((g_devkit_version >> 12) & 0xF0) | ((g_devkit_version >> 8) & 0xF), (upd_ver >> 8) & 0xF, upd_ver & 0xFF); + printf("X to continue, R to exit.\n"); + } /* get button */ while (1) From 8a57a7e5f458a03b41303133e41552a1380dba5c Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 17:47:11 -0400 Subject: [PATCH 08/20] PSP Go cleanup stuff --- src/Makefile.signed | 12 +++++++----- src/downgrade660_ctrl/main.c | 5 +++-- src/downgrade_ctrl/main.c | 4 ++-- src/include/common.h | 2 +- src/kernel_exploit.c | 3 +++ src/kernel_land.c | 8 +++++++- src/kernel_land.h | 2 ++ 7 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/Makefile.signed b/src/Makefile.signed index 78ce26b..9463527 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -1,14 +1,16 @@ UNAME := $(shell uname) release: all ifeq ($(UNAME), Linux) - WINEPREFIX=$(shell pwd)/prefix wine bin/prxEncrypter $(TARGET).prx + WINEPREFIX=$(shell pwd)/prefix wine bin/prxEncrypter.exe $(TARGET).prx else - bin\prxEncrypter $(TARGET).prx + bin\prxEncrypter.exe $(TARGET).prx endif pack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL data.psp NULL rm -f data.psp rm -f downgrade_ctrl.h rm -f downgrade660_ctrl.h + @mkdir -p PSP/GAME/ChronoSwitch + @cp EBOOT.PBP PSP/GAME/ChronoSwitch/ TARGET = downgrader OBJS = main.o kernel_exploit.o kernel_land.o rebootex.o utils.o extras.o extra_stubs.o libasm/libinfinityUser.o @@ -18,13 +20,13 @@ CFLAGS = -Os -G0 -Wall CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS) -c -LIBDIR = ../lib -LIBS = -lpsppower +LIBDIR = lib +LIBS = -lpsppower -lpspkubridge PSP_FW_VERSION = 271 EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.3 +PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.4 BUILD_PRX = 1 diff --git a/src/downgrade660_ctrl/main.c b/src/downgrade660_ctrl/main.c index 3a0dd84..3f6956a 100644 --- a/src/downgrade660_ctrl/main.c +++ b/src/downgrade660_ctrl/main.c @@ -69,16 +69,17 @@ int ApplyFirmware(SceModule2 *mod) eboot_path[0] = 'm'; eboot_path[1] = 's'; status = sceIoGetstat(eboot_path, &stats); + } /* set k1 */ u32 k1 = pspSdkSetK1(0); /* lets open the file */ - SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); + SceUID fd; /* check for failure */ - if (fd < 0) + if ((fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777)) < 0) { /* rage */ pspSdkSetK1(k1); diff --git a/src/downgrade_ctrl/main.c b/src/downgrade_ctrl/main.c index 200b8c9..854ab21 100644 --- a/src/downgrade_ctrl/main.c +++ b/src/downgrade_ctrl/main.c @@ -75,10 +75,10 @@ int ApplyFirmware(void) u32 k1 = pspSdkSetK1(0); /* lets open the file */ - SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); + SceUID fd; /* check for failure */ - if (fd < 0) + if ((fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777)) < 0) { /* rage */ pspSdkSetK1(k1); diff --git a/src/include/common.h b/src/include/common.h index 4d305b5..4075fb8 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -1,4 +1,4 @@ #ifndef _COMMON_H_ #define _COMMON_H_ -#endif char eboot_path[] = "ef0:/PSP/GAME/UPDATE/EBOOT.PBP"; +#endif diff --git a/src/kernel_exploit.c b/src/kernel_exploit.c index 99f2e1b..f82a943 100644 --- a/src/kernel_exploit.c +++ b/src/kernel_exploit.c @@ -65,6 +65,7 @@ int pre_kernel(int (* kfunc)(void)) /* find our functions */ if((g_devkit_version == FIRMWARE_VERSION_660) || (g_devkit_version == FIRMWARE_VERSION_661)) { + pspKernelGetModel = (void *)FindProc("sceSystemMemoryManager", "SysMemForKernel", 0x07C586A1); //6.60 pspKernelGetModel = (void *)FindProc("sceSystemMemoryManager", "SysMemForKernel", 0x07C586A1); //6.60 pspKernelLoadExecVSHEf1 = (void *)FindProc("sceLoadExec", "LoadExecForKernel", 0x16A68007); //6.60 pspKernelLoadExecVSHMs1 = (void *)FindProc("sceLoadExec", "LoadExecForKernel", 0x4FB44D27); //6.60 @@ -73,6 +74,8 @@ int pre_kernel(int (* kfunc)(void)) pspIoOpen = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x109F50BC); pspIoWrite = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x42EC03AC); pspIoClose = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x810C4BC3); + pspIoRead = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x6A638D83); + pspIoLseek32 = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x68963324); } else { diff --git a/src/kernel_land.c b/src/kernel_land.c index 730d589..0891a33 100644 --- a/src/kernel_land.c +++ b/src/kernel_land.c @@ -29,6 +29,7 @@ SceUID (* pspIoOpen)(char *file, int flags, SceMode mode) = NULL; int (* pspIoWrite)(SceUID fd, void *data, u32 len) = NULL; int (* pspIoClose)(SceUID fd) = NULL; + /* globals */ struct SceKernelLoadExecVSHParam g_exec_param; @@ -221,7 +222,12 @@ int patch_loadexec_pspgo(void) /* clear the caches */ KClearCaches(); - + SceIoStat stats; + int status = sceIoGetstat(eboot_path, &stats); + if(status < 0) { + eboot_path[0] = 'm'; + eboot_path[1] = 's'; + } if(strcasecmp(eboot_path, "ms0")>=0) { return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } diff --git a/src/kernel_land.h b/src/kernel_land.h index 3a8f8ef..77d83a1 100644 --- a/src/kernel_land.h +++ b/src/kernel_land.h @@ -25,5 +25,7 @@ extern int (* pspKernelLoadExecVSHMs1)(const char *path, struct SceKernelLoadExe extern SceUID (* pspIoOpen)(char *file, int flags, SceMode mode); extern int (* pspIoWrite)(SceUID fd, void *data, u32 len); extern int (* pspIoClose)(SceUID fd); +extern int (* pspIoRead)(int fd, void* data, int size); +extern int (* pspIoLseek32)(int fd, int offset, int whence); #endif /* __KERNEL_LAND_H__ */ From 3df79201f399b279f8322162cffc18f4ed7a2188 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 17:50:04 -0400 Subject: [PATCH 09/20] cleanup --- src/kernel_exploit.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/kernel_exploit.c b/src/kernel_exploit.c index f82a943..c0cc653 100644 --- a/src/kernel_exploit.c +++ b/src/kernel_exploit.c @@ -74,8 +74,6 @@ int pre_kernel(int (* kfunc)(void)) pspIoOpen = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x109F50BC); pspIoWrite = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x42EC03AC); pspIoClose = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x810C4BC3); - pspIoRead = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x6A638D83); - pspIoLseek32 = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x68963324); } else { From 33c1153b62fb13bfdd428c1027c3267f06b6e056 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 18:09:43 -0400 Subject: [PATCH 10/20] fixed --- src/Makefile.signed | 2 +- src/main.c | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Makefile.signed b/src/Makefile.signed index 9463527..3c80eb6 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -21,7 +21,7 @@ CXXFLAGS = $(CFLAGS) -fno-exceptions -fno-rtti ASFLAGS = $(CFLAGS) -c LIBDIR = lib -LIBS = -lpsppower -lpspkubridge +LIBS = -lpsppower PSP_FW_VERSION = 271 diff --git a/src/main.c b/src/main.c index b92f432..959612c 100644 --- a/src/main.c +++ b/src/main.c @@ -21,7 +21,6 @@ #include #include "common.h" -#include "kubridge.h" #include "utils.h" #include "kernel_land.h" @@ -74,12 +73,12 @@ u32 get_updater_version(char *argv) eboot_path[0] = 'm'; eboot_path[1] = 's'; } - + /* check for failure */ int model = execKernelFunction(getModel); - SceUID fd = -1; - if(model == 4 && strcasecmp(argv, "ef0") > 0) { return 0xFA4E; /*FAKE some reason CS on ef0 does not like reading from ms0 */} - if ((fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777) < 0)) + if(model == 4 && (strcasecmp(argv, "ef0")) > 0) { return 0xFA4E; /*FAKE some reason CS on ef0 does not like reading from ms0 */} + SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); + if (fd < 0) { printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); /* error firmware */ From 8f5d6d2b6432c69709bf0273f4ec739b3f664c8a Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Thu, 30 May 2024 18:42:32 -0400 Subject: [PATCH 11/20] Updated --- README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a6e17a5..25da486 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,16 @@ Chronoswitch is a downgrader for the Playstation Portable (PSP). ## Installation Download and extract the latest version from the releases on this github page. Copy the `PSP` folder from the extracted output to your memory stick. You will need the firmware update for version you wish to downgrade to. If you want to downgrade to 6.60, you will need the 6.60 official update. If you're downgrading a PSPgo, make sure you download the official firmware appropriate for that device. -Copy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory stick. If you're using a PSPgo, make sure this copied to the internal storage instead. +Copy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory stick. If you're using a PSPgo, you can use internal storage or the memory stick for the official firmware EBOOT The downgrader is "signed", and can be launched without having a custom firmware installed. Once you run the application, follow the on-screen instructions. ## Changelog +### Version 7.4 +* PSP GO cleanup +* Detect if EBOOT.PBP is missing from `PSP/GAME/UPDATE/` +### Version 7.3 +* PSP GO can boot from ms0/ef0 ### Version 7.2 * Replaced 'factory firmware limitation', which prevented certain PSPs from being downgradable at all or limited them from being downgraded to certain firmwares they theoretically support. * This fixes most cases where an IDXFFFFFFFF or CAAFFFFFCF7 error could appear. From 292b8a32bff316f4a01e497a90ef4b46e1cfa138 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 31 Aug 2024 11:43:47 -0400 Subject: [PATCH 12/20] Updated tools to encrypt EBOOT. Also fixed PSP GO bug --- src/Makefile.signed | 11 +- src/bin/prxEncrypter.exe | Bin 143360 -> 0 bytes src/bin/psptools/pack_btcnf.py | 22 ++ src/bin/psptools/pack_kernel_module.py | 22 ++ src/bin/psptools/pack_ms_game.py | 30 ++ src/bin/psptools/pack_updater.py | 28 ++ src/bin/psptools/pack_user_fw_module.py | 22 ++ src/bin/psptools/psptool/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 173 bytes .../psptool/__pycache__/kirk.cpython-312.pyc | Bin 0 -> 12380 bytes .../psptool/__pycache__/pack.cpython-312.pyc | Bin 0 -> 16524 bytes .../psptool/__pycache__/pbp.cpython-312.pyc | Bin 0 -> 3661 bytes .../psptool/__pycache__/prx.cpython-312.pyc | Bin 0 -> 9332 bytes src/bin/psptools/psptool/kirk.py | 289 ++++++++++++++++ src/bin/psptools/psptool/pack.py | 316 ++++++++++++++++++ src/bin/psptools/psptool/pbp.py | 40 +++ src/bin/psptools/psptool/prx.py | 293 ++++++++++++++++ src/bin/psptools/psptool/prxtypes/__init__.py | 0 .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 182 bytes .../__pycache__/common.cpython-312.pyc | Bin 0 -> 2923 bytes .../__pycache__/type2.cpython-312.pyc | Bin 0 -> 9684 bytes .../__pycache__/type6.cpython-312.pyc | Bin 0 -> 11388 bytes .../__pycache__/type8.cpython-312.pyc | Bin 0 -> 7612 bytes .../__pycache__/type9.cpython-312.pyc | Bin 0 -> 6550 bytes src/bin/psptools/psptool/prxtypes/common.py | 45 +++ src/bin/psptools/psptool/prxtypes/type2.py | 151 +++++++++ src/bin/psptools/psptool/prxtypes/type6.py | 174 ++++++++++ src/bin/psptools/psptool/prxtypes/type8.py | 128 +++++++ src/bin/psptools/psptool/prxtypes/type9.py | 112 +++++++ src/bin/psptools/psptool/psar.py | 182 ++++++++++ src/bin/psptools/psptools.txt | 1 + src/bin/psptools/requirements.txt | 2 + src/kernel_exploit.c | 2 + src/kernel_land.c | 23 +- src/kernel_land.h | 5 +- src/main.c | 23 +- 36 files changed, 1900 insertions(+), 21 deletions(-) delete mode 100644 src/bin/prxEncrypter.exe create mode 100755 src/bin/psptools/pack_btcnf.py create mode 100755 src/bin/psptools/pack_kernel_module.py create mode 100755 src/bin/psptools/pack_ms_game.py create mode 100755 src/bin/psptools/pack_updater.py create mode 100755 src/bin/psptools/pack_user_fw_module.py create mode 100644 src/bin/psptools/psptool/__init__.py create mode 100644 src/bin/psptools/psptool/__pycache__/__init__.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/__pycache__/kirk.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/__pycache__/pack.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/__pycache__/pbp.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/kirk.py create mode 100644 src/bin/psptools/psptool/pack.py create mode 100644 src/bin/psptools/psptool/pbp.py create mode 100644 src/bin/psptools/psptool/prx.py create mode 100644 src/bin/psptools/psptool/prxtypes/__init__.py create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/__init__.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/common.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/type2.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/type6.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/type8.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/__pycache__/type9.cpython-312.pyc create mode 100644 src/bin/psptools/psptool/prxtypes/common.py create mode 100644 src/bin/psptools/psptool/prxtypes/type2.py create mode 100644 src/bin/psptools/psptool/prxtypes/type6.py create mode 100644 src/bin/psptools/psptool/prxtypes/type8.py create mode 100644 src/bin/psptools/psptool/prxtypes/type9.py create mode 100644 src/bin/psptools/psptool/psar.py create mode 100644 src/bin/psptools/psptools.txt create mode 100644 src/bin/psptools/requirements.txt diff --git a/src/Makefile.signed b/src/Makefile.signed index 3c80eb6..1130995 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -1,12 +1,13 @@ UNAME := $(shell uname) release: all ifeq ($(UNAME), Linux) - WINEPREFIX=$(shell pwd)/prefix wine bin/prxEncrypter.exe $(TARGET).prx + bin/psptools/pack_ms_game.py --vanity "$(PSP_EBOOT_TITLE)" EBOOT.PBP EBOOT.PBP else - bin\prxEncrypter.exe $(TARGET).prx + bin\\psptools\\pack_ms_game.py --vanity "$(PSP_EBOOT_TITLE)" EBOOT.PBP EBOOT.PBP endif - pack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL data.psp NULL - rm -f data.psp + unpack-pbp EBOOT.PBP + pack-pbp $(EXTRA_TARGETS) PARAM.SFO icon0.png NULL NULL NULL NULL DATA.PSP NULL + rm -f DATA.PSP rm -f downgrade_ctrl.h rm -f downgrade660_ctrl.h @mkdir -p PSP/GAME/ChronoSwitch @@ -26,7 +27,7 @@ LIBS = -lpsppower PSP_FW_VERSION = 271 EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.4 +PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.5 BUILD_PRX = 1 diff --git a/src/bin/prxEncrypter.exe b/src/bin/prxEncrypter.exe deleted file mode 100644 index 3428331b5883fd2afd53e49d33ccd4f4151c15e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143360 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�>H4=D!BQHb1-m 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

KKbe%0x7D| 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

&l{g&H7$J8D+GM@3M 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%0D>@rVFWJ#fYUo7ZbuOD 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 wmwRp>D9?U~?E?F(+qt^&~k-80PJI*$p8QV literal 0 HcmV?d00001 diff --git a/src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc b/src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a5446e79a1ef1ff4bbf3813d298db6dce492439 GIT binary patch literal 9332 zcmb_hTa#SXbw1tGGb3rx=xSjTE`z~@Nw8+$FBt6XD>oqo0t|x zoIZQ)eb!##@15$L}AwcKt8zK5+fl;Hn<~xbn(FT zZZ@-?=-J#>Z>=ZSvDpTj?d#a=fX&WzY<9tB_c}J;fX$wp@3p@D;}PuYo3QxSEiLYV z#qZtH;!Z^7u3K8%4U2njX)y(hdv9s+?fSm@{##mn2WvdAPDFkmHV>|2GmR(x!8$fo z{fG5KbK7o)1>7BqBH-`4_1=2s>(8u7O>4G+dAt_2+`v3l>)LE!o~<9Qzqf&TkJOLW z-`~KzAJl(TyA90qb*SS8=A}B__GG)z5I3OVb1IZ=DhN?=iFES z=xfjU@yD&7HD-6$ufAK&exrU3-#hC=^-tby%r=gRcBM##n`Dg4#UY# z(HZU43m5jSgx=<~%1q&b!ExuENG@m6uREn3Pf}{>t#Ubt%v0hq zd#*w<%o)~R{fAtu@BDiidwOnxwUmG^b3GQ*gY!`axL|@d;YnASj_p7@#T`O%-=iN0GB{ul`*z zv&;l1u%41ZN=}hW!MH`1Jf0vla?>=(jTKHI&D!#u65=O=R*&szw%E(wioQWjB z0(=$RX%_=$4khM-!N$13BV2+Ts3VaD5FT0JQ6);bvRuO(5>N)(I*R&46?lB22lCl(`x=ZOLd0&&-rW8Y<}Are1?j-1lOxdJ;O6<(tvsAtl8ml@R-kzkbMh!o0# zb`NTBNi!isxk5RC&!mfy_~dN@e-ae1WkLncC6SqGXL+F9QHPCM?(xHyaE+|wLAV$b zU=KopD8n-gOrkcmO;icvL+}p%!&i_0yaqJ012Z8@nIoSGK079LVG!pvDk~O((~=9J zl#LSX8bMD1J5C5bQ37lcXhM-on}Jj*qNV}_?~PB{dhn}*s|q~AltHMp&Qf^;!gPU3 zq%uV%NFsF&jiWP zVQ?W;M!GV$B5N=^m{ViAF5wzmd14SQz!41!6>ba%HIbAlmX6*BaI9jSdDO4TNDxQI zh$vC%z-1^{;-ri|vuuO_C3}EFNGTk*Je3OIF>%7MHuxvYY%)QdfCgYM21Ecs^FlaT zLatLJaI{~-NF5TUyZvD|5g;fr zpuq@i(MV7<3Nvc-h>$60l#3qkqkSrd+@QxQX3@oh2jqY@L(qL9&(TV7T?Um&szCkd zbZ9?b<53_?pF#8x5R#Gzm=VMd%!QT|5d^Rvz-WyZSdvHsgd*Yri=Y}ZC@MM;v{695 z%5V|Hr>J7^J`*GWp|Wr_b95^NYV*pzLAXi>fKn(qMm+-MgaDXH0VUe{V9_r5NOMQRi%xRqw?7(q*L2GYr*qfp=;_ksflEA3JamKx=Cv?$w5IH=C4 z1SJ7qMa(V{9vR{aFbeELW^@V(ph_7)D^W0s+sJ_`ofwVLGnY#mLM%-bHOz|$AX+B{ zH&TeqClsRxAA0Z?vlP|VivyY{0Fe+vGzVk?#SkIOv=Aau^mQ;UT#1N*EaBR+^7OTE zm0W@5nU0=Y9kCt!FGF9%Y(c;1NCH{`XaQ##G#L~&dNET_L7-QzfhCzeU?>$T0dk8X z(FXDk0wAD?pg$|01R-dJA!EOW0#>N9Oay?csYa#4XMt{uMw~$R+#q`)Qm@g2Agj<< zGx!y70Kdwtoq;^cASmrf(JPFD&4B#~2}95YMABHw2}GD_F0c)B`Gk-oT$X^Az{?Sj zH0TwX0&=JU2q2TdYy}*s@zUH(Y3n6i6D#`%;Ub`US{gj1g;F_+TERo~UMK(tst4gQ z01K%D6sUtJf+B|u1hWu=?gf1SF$#<)sEuGKlqT8?Y9>LSW zQz8nSiCz&)<#G)_fInaz#0dTuP?>m0fZWT4M;zQl^GCg)q6%ATj`Rov@Il{%9E&cI zF?eV&=wQ#KfE)pow6y`<3||@w+XQG7K`rS@*wuGW(kVUA_ zJC}V zaLX6Aht>cA0IiT1Pzl6%oC**Zppp2VE<*~?h9SGr+~ESy9FR@$RYU{i=+QVNfkZO+ zJfM^^nl_Yl_7Hw3TO=9!#S;`HdJ;|{&>zs$3c919YwOB^LAbJn>O`_Y8K4R#Jqsp5 zgyBGwl*RVZOv*6>!Wg|-fvi!mkbziVdI&jG5)=*^5Rz-rijpq13RMN2DxhUEx^+OI zTMKcEUWStciUx9&SjaeJ!fHk`RRo!}LQoB{0S#fnJPcC=m;tPxO|*)DQIZa5(#V(3 z$frk;A!#xd04@$24uJw=Yv}-cP&=5l)LNjzp_Q^otZ`6%8loDoE-D*cRSUE)NIUqK zGl&_AS3phzv@&H;!Zo?_>>ykbOF}V$LLmNt9{j+WOGbgc0(NM02D%cZ2quM~MYZG5 zh@OJR2gwEw#p+5_4P-V61{wg7$KehPi1UE~McV+L%><1N z-A#Hpi(>`Up+WTm@fkV<#q2ZW7a*y%f#5aJYfwH)sA$2p97>RuGbviDvL5{vDA?Z=|jP(C`G96_X3 zw`VefR|6IS2R9LDD`)|n6{5$h0YXB6TmiN8jqmOoW8E3W&Iw>Fq9x+xf_ETw?ntWhg~4%Ab5H-MA$ z#d6feN#20Z(H8~KRvMcuJ1ouHqeb9#$A{(Y7trINqzseA?VCUjFI<#kA*T)+~q zGzee=DIuYA(1=*JI6vbQk21yPpl=`|Ifb?;86(IAdOgYmM{Y<<5H3`s0^A^c;8aGI z6kveEtDbJPSNB}l*IvE7eBD#NwlvKV99^${#&A^<`sKgk>teOJTD~^A+#Fb)slJ8F zpRbLaZ7jD2Bge}Nmf!iDY1EAy?aS{+U~{H%u)42WE^lLcpZlxMosDXFV(`0e9^X2+ zzW(>jwdW3=->BZH-mKmldAWMCF+H-s_j>22JLlU=OYMc%rU}o>5iW2v=^4UV@DS| z^M{tFo81vC)oqojOC=IhQ(rwcb8K;bZsu@jZed|=Vdg+*@%Y@4<)xVe2M^4IW1Yo? z#e;9QmyaBqS?U~_Iow{DIkj|Zd2#XN(%@p|ROhX|r%rcAdmeS3#IidP)uk74ajsfz zj*U)!wr$siCqG*H;F&Ai?myr9?Djh^p8eqLrROg{@Q**bayvWUI{)H(w_V+~>-@z3 zd^WM`i>iqko3?&3`R)Ihoc?rj`tp5OCinhw)6CUPTUSRh_SMp6Ed9=2TK&s++@6u& zN_|O03I3Ny@pbXW#1}yHKF6;mdT^)0zssG$zs1!fcT_)L14!MvG2LgI&FW0E9xeCI z;Oc0zjnw~B<8P4u>9PG^H6M9mD%)J&arDs?R32U)Xc;t`F||X!+8? z%eybvmtMWHL;T{|Pj~1m6XsmJI&sH&@&4xbe(({$)cSN{=JFW6K55N-iP_bWYq-ac zQXjn_E#TrJHgfLH>lJeRMoWyB&#>^IYDW7Or4j~MK0AV7ja&=XNH18;Yr*Q214yUH z>P``h{b-ecLq)WT9O{%N--{dGb(Rj+d8~XrSH60YD)~dC)4QOZ8=OY44Ru`ipx%ofPLs5X$#={q@7cW7au{b*3Bpr}y++ z>W&{fv~=ub`*3$>D6fGR_r9>)KDoF5cDYkB*B!xo=I+GW=;N^N6gRuKtyRn36Yb84 z?)ciT?w-MIz@S&dd&@WLZW{dVj`nZd+)(w0)sS^ef7lEew*6t-16VI~9S2`~A^+#9 zxAh(hzuNT3{9^sa$+_=$<}i-%R!e7)@70k;qw%Y1>#wTGUsn(Py1Mf>)vo`n9{8ks z;QxNFwnA&Nd9^i(^1iyAUETG~i;sTr=-QvpH;?WZTOBDDtJ|y5ZEH3=>)#sR(Hp;e z==eRo@rQ3^jP7(X)8*28;eSJ|Azv{~z{;4-XkW(jQ(JGQ8Ly z{^^k6xBJ7ndEL7kpZ!>~=h|~ah7b0KUmY_1T7MW7KP>hq`W9~uw>aIm$Rk77c&wk` z=hrM&o7Ik`)=hx$`3rr+!|NHY9_bsNTG#N8`-XqIuHm2c4fnPByBO-@>eD?uugvZ;R-lM$aJosk zpY2;cId)5{r^b4Fc> 8) & 0xFF + self.modname = modinfo.modname + self.elf_size = len(executable) + + self.entry = elf.e_entry + self.nsegments = elf.e_phnum if elf.e_phnum < 2 else 2 + self.seg_align = [ + x.p_align for x in elf.phdrs[:self.nsegments]] + [0]*(4-self.nsegments) + self.seg_address = [ + x.p_vaddr for x in elf.phdrs[:self.nsegments]] + [0]*(4-self.nsegments) + self.seg_size = [ + x.p_memsz for x in elf.phdrs[:self.nsegments]] + [0]*(4-self.nsegments) + + bss = next(x for x in elf.shdrs if elf.strtab[x.sh_name:].split( + '\0')[0] == '.bss') + self.bss_size = bss.sh_size + + self.devkitversion = 0 + + if modinfo.is_kernel(): + # self.devkitversion = 0x06060110 if self.attribute & 0x2000 else 0x05070110 + self.decrypt_mode = 1 + + elif is_pbp: + # check if VSH API (updater) + if (self.attribute & 0x800) == 0x800: + self.decrypt_mode = 0xC + + # check if APP API (comics, etc) + elif (self.attribute & 0x600) == 0x600: + self.decrypt_mode = 0xE + + # check if USB WLAN API (skype, etc) + elif (self.attribute & 0x400) == 0x400: + self.decrypt_mode = 0x4 + + # set to MS API + else: + # TODO: could check the SFO for POPS... + # MS games must set attribute to 0x200 for firmware 2.00+ + # On firmware <2.00 it must be set to 0 + self.attribute |= 0x200 + self.decrypt_mode = 0xD + + else: + # standalone user prx + # check for VSH API + if (self.attribute & 0x800) == 0x800: + self.decrypt_mode = 3 + + # standard user prx + else: + self.devkitversion = 0x05070210 + self.decrypt_mode = 4 + + # to be filled in by caller + self.psptag = None + self.oetag = None + self.comp_size = None + self.psp_size = None + + self.reserved = [0]*5 + self.key_data0 = [0xDA]*0x30 + self.reserved2 = [0]*2 + self.key_data1 = [0xDA]*0x10 + self.signcheck = [0]*0x58 + self.key_data2 = 0 + self.key_data3 = [0xDA]*0x1C + + def pack(self): + return struct.pack('cg`rv&&v-k&n!vK&@V1Z)=$dJ(=RA4D9O*yDTXoh3yLaA xDhpDJ_2c6+^D;}~W=x=7TzI!|IWu}R&4 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 Kxr1y{yZjI2UcUwa literal 0 HcmV?d00001 diff --git a/src/bin/psptools/psptool/prxtypes/__pycache__/type6.cpython-312.pyc b/src/bin/psptools/psptool/prxtypes/__pycache__/type6.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..1239b66bc79c0168e41fc4b888a99f5d1b3071c9 GIT binary patch literal 11388 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 Fe**vl21x(_ literal 0 HcmV?d00001 diff --git a/src/bin/psptools/psptool/prxtypes/__pycache__/type8.cpython-312.pyc b/src/bin/psptools/psptool/prxtypes/__pycache__/type8.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..fbed2c6f27caf3c7e8652d99f5e11f966372d7bf GIT binary patch literal 7612 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 literal 0 HcmV?d00001 diff --git a/src/bin/psptools/psptool/prxtypes/common.py b/src/bin/psptools/psptool/prxtypes/common.py new file mode 100644 index 0000000..807d996 --- /dev/null +++ b/src/bin/psptools/psptool/prxtypes/common.py @@ -0,0 +1,45 @@ +import psptool.kirk as kirk + + +class prx_header(object): + def __init__(self, header): + self.header = header + + def btcnf_id(self): + return self.header[0x140:0x150] + + def sha1_hash(self): + return self.header[0x12C:0x140] + + def personalisation(self): + return self.header[0xD0:0x12C] + + def kirk_aes_key(self): + return self.header[0x80:0x90] + + def kirk_cmac_key(self): + return self.header[0x90:0xA0] + + def kirk_cmac_header_hash(self): + return self.header[0xA0:0xB0] + + def kirk_metadata(self): + return self.header[0xB0:0xC0] + + def kirk_cmac_data_hash(self): + return self.header[0xC0:0xD0] + + def elf_info(self): + return self.header[:0x80] + + +def set_kirk_cmd_1(block): + return block[:0x60] + (1).to_bytes(4, 'little') + block[0x64:] + + +def set_kirk_cmd_1_ecdsa(block): + return block[:0x64] + (1).to_bytes(4, 'little') + block[0x68:] + + +def expand_seed(seed, key): + return kirk.kirk7(b''.join([bytes([x])+seed[1:] for x in range(9)]), key) diff --git a/src/bin/psptools/psptool/prxtypes/type2.py b/src/bin/psptools/psptool/prxtypes/type2.py new file mode 100644 index 0000000..9b0521b --- /dev/null +++ b/src/bin/psptools/psptool/prxtypes/type2.py @@ -0,0 +1,151 @@ +import psptool.kirk as kirk + +from .common import expand_seed, prx_header, set_kirk_cmd_1, set_kirk_cmd_1_ecdsa +from Crypto.Util.strxor import strxor as xor +from Crypto.Hash import SHA1 +from Crypto import Random + + +class prx_header_2(object): + def __init__(self, header=None): + if header is None: + self.header = b'\x00'*0x150 + else: + prx = prx_header(header) + self.header = prx.personalisation() + prx.btcnf_id() + prx.sha1_hash() + prx.kirk_aes_key() + prx.kirk_cmac_key() + \ + prx.kirk_cmac_header_hash() + prx.kirk_cmac_data_hash() + \ + prx.kirk_metadata() + prx.elf_info() + + def tag(self): + return self.header[:0x4] + + def set_tag(self, tag): + self.header = tag + self.header[0x4:] + + def btcnf_id(self): + return self.header[0x5C:0x6C] + + def set_btcnf_id(self, id): + self.header = self.header[:0x5C] + id + self.header[0x6C:] + + def sha1_hash(self): + return self.header[0x6C:0x80] + + def set_sha1_hash(self, hash): + self.header = self.header[:0x6C] + hash + self.header[0x80:] + + def personalisation(self): + return self.header[:0x5C] + + def kirk_metadata(self): + return self.header[0xC0:0xD0] + + def set_kirk_metadata(self, metadata): + self.header = self.header[:0xC0] + metadata + self.header[0xD0:] + + def kirk_block(self): + return self.header[0x80:0xC0] + + def set_kirk_block(self, block): + self.header = self.header[:0x80] + block + self.header[0xC0:] + + def elf_info(self): + return self.header[0xD0:] + + def set_elf_info(self, info): + self.header = self.header[:0xD0] + info + + def prx(self): + return self.elf_info() + self.kirk_block()[:0x30] + self.kirk_metadata() + self.kirk_block()[0x30:] + self.personalisation() + self.sha1_hash() + self.btcnf_id() + + def encrypt_header(self, key): + self.header = self.header[:0x5C] + kirk.kirk4( + self.header[0x5C:0x5C+0x60], key) + self.header[0x5C+0x60:] + + def decrypt_header(self, key): + self.header = self.header[:0x5C] + kirk.kirk7( + self.header[0x5C:0x5C+0x60], key) + self.header[0x5C+0x60:] + + +def decrypt(prx, meta): + xorbuf = expand_seed(meta['seed'], meta['key']) + + # check if range contains nonzero + if any(x != 0 for x in prx[0xD4:0xD4+0x58]): + return False + + p = prx_header_2(prx) + + # decrypt the header information + p.decrypt_header(meta['key']) + + # calculate SHA1 of header + h = SHA1.new() + h.update(p.tag()) + h.update(xorbuf[:0x10]) + h.update(b'\x00'*0x58) + h.update(p.btcnf_id()) + h.update(p.kirk_block()) + h.update(p.kirk_metadata()) + h.update(p.elf_info()) + + if h.digest() != p.sha1_hash(): + print("bad SHA1") + return False + + # decrypt the kirk header + header = xor(p.kirk_block(), xorbuf[0x10:0x50]) + header = kirk.kirk7(header, meta['key']) + header = xor(header, xorbuf[0x50:]) + + # prepare the kirk block + block = header + b'\x00'*0x30 + block = set_kirk_cmd_1(block) + block = block + p.kirk_metadata() + b'\x00'*0x10 + \ + p.elf_info() + prx[0x150:] + + # do the decryption + return kirk.kirk1(block) + + +def encrypt(prx, meta, id=None): + xorbuf = expand_seed(meta['seed'], meta['key']) + + # encrypt as kirk1 + encrypted = kirk.kirk1_encrypt_cmac(prx[0x150:], salt=prx[:0x80]) + + header = xor(encrypted[:0x40], xorbuf[0x50:]) + header = kirk.kirk4(header, meta['key']) + header = xor(header, xorbuf[0x10:0x50]) + + # calculate an id + if id == None: + id = Random.get_random_bytes(16) + + elif type(id) is str: + id = '{:16.16}'.format(id).encode() + + id = kirk.kirk7(id, meta['key']) + + # create a prx header + p = prx_header_2() + p.set_elf_info(prx[:0x80]) + p.set_kirk_block(header) + p.set_kirk_metadata(encrypted[0x70:0x80]) + p.set_btcnf_id(id) + p.set_tag(prx[0xD0:0xD4]) + + # calculate SHA1 of header + h = SHA1.new() + h.update(p.tag()) + h.update(xorbuf[:0x10]) + h.update(b'\x00'*0x58) + h.update(p.btcnf_id()) + h.update(p.kirk_block()) + h.update(p.kirk_metadata()) + h.update(p.elf_info()) + p.set_sha1_hash(h.digest()) + + # encrypt the header and return the complete PRX + p.encrypt_header(meta['key']) + return p.prx() + encrypted[0x90+0x80:] diff --git a/src/bin/psptools/psptool/prxtypes/type6.py b/src/bin/psptools/psptool/prxtypes/type6.py new file mode 100644 index 0000000..5d80091 --- /dev/null +++ b/src/bin/psptools/psptool/prxtypes/type6.py @@ -0,0 +1,174 @@ +import psptool.kirk as kirk + +from .common import expand_seed, prx_header, set_kirk_cmd_1, set_kirk_cmd_1_ecdsa +from Crypto.Util.strxor import strxor as xor +from Crypto.Hash import SHA1 +from Crypto import Random + + +class prx_header_6(object): + def __init__(self, header=None): + if header is None: + self.header = b'\x00'*0x150 + else: + prx = prx_header(header) + self.header = prx.personalisation() + prx.btcnf_id() + prx.sha1_hash() + prx.kirk_aes_key() + prx.kirk_cmac_key() + \ + prx.kirk_cmac_header_hash() + prx.kirk_cmac_data_hash() + \ + prx.kirk_metadata() + prx.elf_info() + + def tag(self): + return self.header[:0x4] + + def set_tag(self, tag): + self.header = tag + self.header[0x4:] + + def btcnf_id(self): + return self.header[0x5C:0x6C] + + def set_btcnf_id(self, id): + self.header = self.header[:0x5C] + id + self.header[0x6C:] + + def sha1_hash(self): + return self.header[0x6C:0x80] + + def set_sha1_hash(self, hash): + self.header = self.header[:0x6C] + hash + self.header[0x80:] + + def personalisation(self): + return self.header[:0x5C] + + def kirk_aes_key(self): + return self.header[0x80:0x90] + + def kirk_ecdsa_header_sig(self): + return self.header[0x90:0xB8] + + def kirk_ecdsa_data_sig_begin(self): + return self.header[0xB8:0xC0] + + def kirk_metadata(self): + return self.header[0xC0:0xD0] + + def set_kirk_metadata(self, metadata): + self.header = self.header[:0xC0] + metadata + self.header[0xD0:] + + def kirk_ecdsa_data_sig_end(self): + return self.header[0x3C:0x5C] + + def set_kirk_ecdsa_data_sig_end(self, ecdsa_end): + self.header = self.header[:0x3C] + ecdsa_end + self.header[0x5C:] + + def kirk_block(self): + return self.header[0x80:0xC0] + + def set_kirk_block(self, block): + self.header = self.header[:0x80] + block + self.header[0xC0:] + + def elf_info(self): + return self.header[0xD0:] + + def set_elf_info(self, info): + self.header = self.header[:0xD0] + info + + def prx(self): + return self.elf_info() + self.kirk_block()[:0x30] + self.kirk_metadata() + self.kirk_block()[0x30:] + self.personalisation() + self.sha1_hash() + self.btcnf_id() + + def encrypt_header(self, key): + self.header = self.header[:0x5C] + kirk.kirk4( + self.header[0x5C:0x5C+0x60], key) + self.header[0x5C+0x60:] + + def decrypt_header(self, key): + self.header = self.header[:0x5C] + kirk.kirk7( + self.header[0x5C:0x5C+0x60], key) + self.header[0x5C+0x60:] + + +def decrypt(prx, meta): + xorbuf = expand_seed(meta['seed'], meta['key']) + + # check if range contains nonzero + if any(x != 0 for x in prx[0xD4:0xD4+0x38]): + return False + + p = prx_header_6(prx) + + # decrypt the header information + p.decrypt_header(meta['key']) + + # calculate SHA1 of header + h = SHA1.new() + h.update(p.tag()) + h.update(xorbuf[:0x10]) + h.update(b'\x00'*0x38) + h.update(p.kirk_ecdsa_data_sig_end()) + h.update(p.btcnf_id()) + h.update(p.kirk_aes_key()) + h.update(p.kirk_ecdsa_header_sig()) + h.update(p.kirk_ecdsa_data_sig_begin()) + h.update(p.kirk_metadata()) + h.update(p.elf_info()) + + if h.digest() != p.sha1_hash(): + print("bad SHA1") + return False + + # decrypt the kirk header + header = xor(p.kirk_block(), xorbuf[0x10:0x50]) + header = kirk.kirk7(header, meta['key']) + header = xor(header, xorbuf[0x50:]) + + # prepare the kirk block + block = header + p.kirk_ecdsa_data_sig_end() + b'\x00'*0x10 + block = set_kirk_cmd_1(block) + block = set_kirk_cmd_1_ecdsa(block) + block = block + p.kirk_metadata() + b'\x00'*0x10 + \ + p.elf_info() + prx[0x150:] + + # do the decryption + return kirk.kirk1(block) + + +def encrypt(prx, meta, id=None): + xorbuf = expand_seed(meta['seed'], meta['key']) + + # encrypt as kirk1 + encrypted = kirk.kirk1_encrypt_ecdsa(prx[0x150:], salt=prx[:0x80]) + + header = xor(encrypted[:0x40], xorbuf[0x50:]) + header = kirk.kirk4(header, meta['key']) + header = xor(header, xorbuf[0x10:0x50]) + + # calculate an id + if id == None: + id = Random.get_random_bytes(16) + + elif type(id) is str: + id = '{:16.16}'.format(id).encode() + + id = kirk.kirk7(id, meta['key']) + + # create a prx header + prx_header = prx_header_6() + prx_header.set_elf_info(prx[:0x80]) + prx_header.set_kirk_block(header) + prx_header.set_kirk_ecdsa_data_sig_end(encrypted[0x40:0x60]) + prx_header.set_kirk_metadata(encrypted[0x70:0x80]) + prx_header.set_btcnf_id(id) + prx_header.set_tag(prx[0xD0:0xD4]) + + # calculate SHA1 of header + h = SHA1.new() + h.update(prx_header.tag()) + h.update(xorbuf[:0x10]) + h.update(b'\x00'*0x38) + h.update(prx_header.kirk_ecdsa_data_sig_end()) + h.update(prx_header.btcnf_id()) + h.update(prx_header.kirk_aes_key()) + h.update(prx_header.kirk_ecdsa_header_sig()) + h.update(prx_header.kirk_ecdsa_data_sig_begin()) + h.update(prx_header.kirk_metadata()) + h.update(prx_header.elf_info()) + prx_header.set_sha1_hash(h.digest()) + + # encrypt the header and return the complete PRX + prx_header.encrypt_header(meta['key']) + return prx_header.prx() + encrypted[0x90+0x80:] diff --git a/src/bin/psptools/psptool/prxtypes/type8.py b/src/bin/psptools/psptool/prxtypes/type8.py new file mode 100644 index 0000000..d4f94fe --- /dev/null +++ b/src/bin/psptools/psptool/prxtypes/type8.py @@ -0,0 +1,128 @@ +import psptool.kirk as kirk + +from Crypto.Util.strxor import strxor as xor +from Crypto.Hash import SHA1 +from Crypto import Random + + +class prx_header_8(object): + def __init__(self, header=None): + if header is None: + self.header = b'\x00'*0x150 + else: + self.header = header[0xD0:0x150] + \ + header[0x80:0xD0] + header[:0x80] + + def tag(self): + return self.header[:0x4] + + def set_tag(self, tag): + self.header = tag + self.header[0x4:] + + def sha1_hash(self): + return self.header[0x4:0x18] + + def set_sha1_hash(self, hash): + self.header = self.header[:0x4] + hash + self.header[0x18:] + + def vanity_area(self): + return self.header[0x18:0x40] + + def set_vanity_area(self, vanity): + self.header = self.header[:0x18] + vanity + self.header[0x40:] + + def kirk_block(self): + return self.header[0x40:0xB0] + + def set_kirk_block(self, block): + self.header = self.header[:0x40] + block + self.header[0xB0:] + + def kirk_metadata(self): + return self.header[0xB0:0xD0] + + def set_kirk_metadata(self, metadata): + self.header = self.header[:0xB0] + metadata + self.header[0xD0:] + + def elf_info(self): + return self.header[0xD0:] + + def set_elf_info(self, info): + self.header = self.header[:0xD0] + info + + def kirk_aes_key(self): + return self.header[0x40:0x50] + + def kirk_ecdsa_header_sig(self): + return self.header[0x50:0x78] + + def kirk_ecdsa_data_sig(self): + return self.header[0x78:0xA0] + + def prx(self): + return self.elf_info() + self.header[0x80:0xD0] + self.header[:0x80] + + +def decrypt(prx, meta, **kwargs): + p = prx_header_8(prx) + xorbuf = kirk.kirk7(meta['seed'], meta['key']) + + # calculate SHA1 of header + h = SHA1.new() + h.update(xorbuf[:0x14]) + h.update(p.vanity_area()) + h.update(p.kirk_block()) + h.update(p.kirk_metadata()) + h.update(p.elf_info()) + + if h.digest() != p.sha1_hash(): + print("bad SHA1") + return False + + # decrypt the kirk header + header = xor(p.kirk_block(), xorbuf[0x14:0x84]) + header = kirk.kirk7(header, meta['key']) + header = xor(header, xorbuf[0x20:]) + + # prepare the kirk block + block = header + p.kirk_metadata() + p.elf_info() + prx[0x150:] + + # do the decryption + return kirk.kirk1(block) + + +def encrypt(prx, meta, vanity=None, **kwargs): + xorbuf = kirk.kirk7(meta['seed'], meta['key']) + + # encrypt as kirk1 + encrypted = kirk.kirk1_encrypt_ecdsa(prx[0x150:], salt=prx[:0x80]) + + header = xor(encrypted[:0x70], xorbuf[0x20:]) + header = kirk.kirk4(header, meta['key']) + header = xor(header, xorbuf[0x14:0x84]) + + # calculate some vanity + if vanity == None: + vanity = Random.get_random_bytes(0x28) + + elif type(vanity) is str: + vanity = '{:40.40}'.format(vanity).encode() + + # create a prx header + prx_header = prx_header_8() + prx_header.set_elf_info(prx[:0x80]) + prx_header.set_kirk_block(header) + prx_header.set_kirk_metadata(encrypted[0x70:0x90]) + prx_header.set_vanity_area(vanity) + prx_header.set_tag(prx[0xD0:0xD4]) + + # calculate SHA1 of header + h = SHA1.new() + h.update(xorbuf[:0x14]) + h.update(prx_header.vanity_area()) + h.update(prx_header.kirk_block()) + h.update(prx_header.kirk_metadata()) + h.update(prx_header.elf_info()) + prx_header.set_sha1_hash(h.digest()) + + # encrypt the header and return the complete PRX + return prx_header.prx() + encrypted[0x90+0x80:] diff --git a/src/bin/psptools/psptool/prxtypes/type9.py b/src/bin/psptools/psptool/prxtypes/type9.py new file mode 100644 index 0000000..913b9c1 --- /dev/null +++ b/src/bin/psptools/psptool/prxtypes/type9.py @@ -0,0 +1,112 @@ +from ecdsa.ellipticcurve import CurveFp, Point +import hashlib +from ecdsa.numbertheory import inverse_mod +from ecdsa import SigningKey +from ecdsa.curves import Curve +import psptool.kirk as kirk + +from .common import expand_seed, prx_header, set_kirk_cmd_1 +from Crypto.Util.strxor import strxor as xor +from Crypto.Hash import SHA1 + + +class prx_header_9(object): + def __init__(self, header): + prx = prx_header(header) + self.header = prx.personalisation() + prx.btcnf_id() + prx.sha1_hash() + prx.kirk_aes_key() + prx.kirk_cmac_key() + \ + prx.kirk_cmac_header_hash() + prx.kirk_cmac_data_hash() + \ + prx.kirk_metadata() + prx.elf_info() + + def tag(self): + return self.header[:0x4] + + def btcnf_id(self): + return self.header[0x5C:0x6C] + + def sha1_hash(self): + return self.header[0x6C:0x80] + + def personalisation(self): + return self.header[:0x5C] + + def prx_ecdsa(self): + return self.header[0x34:0x5C] + + def kirk_aes_key(self): + return self.header[0x80:0x90] + + def kirk_cmac_key(self): + return self.header[0x90:0xA0] + + def kirk_cmac_header_hash(self): + return self.header[0xA0:0xB0] + + def kirk_cmac_data_hash(self): + return self.header[0xB0:0xC0] + + def kirk_metadata(self): + return self.header[0xC0:0xD0] + + def kirk_block(self): + return self.header[0x80:0xC0] + + def elf_info(self): + return self.header[0xD0:] + + def decrypt_header(self, key): + self.header = self.header[:0x5C] + kirk.kirk7( + self.header[0x5C:0x5C+0x60], key) + self.header[0x5C+0x60:] + + +def decrypt(prx, meta, **kwargs): + xorbuf = expand_seed(meta['seed'], meta['key']) + + # check if range contains nonzero + if any(x != 0 for x in prx[0xD4:0xD4+0x30]): + return False + + p = prx_header_9(prx) + + print(meta['pubkey']) + print(p.prx_ecdsa().hex()) + + # check ECDSA signature + # kirk.kirk11(bytes.fromhex(meta['pubkey']), p.prx_ecdsa( + # ), prx[4:0x104] + b'\x00'*0x28 + prx[0x12C:]) + + h2 = SHA1.new() + h2.update(prx[4:0x104] + b'\x00'*0x28 + prx[0x12C:]) + print(h2.hexdigest()) + + # decrypt the header information + p.decrypt_header(meta['key']) + + # calculate SHA1 of header + h = SHA1.new() + h.update(p.tag()) + h.update(xorbuf[:0x10]) + h.update(b'\x00'*0x58) + h.update(p.btcnf_id()) + h.update(p.kirk_aes_key()) + h.update(p.kirk_cmac_key()) + h.update(p.kirk_cmac_header_hash()) + h.update(p.kirk_cmac_data_hash()) + h.update(p.kirk_metadata()) + h.update(p.elf_info()) + + # sanity check that our SHA1 actually matches + if h.digest() != p.sha1_hash(): + return False + + # decrypt the kirk block + header = xor(p.kirk_block(), xorbuf[0x10:0x50]) + header = kirk.kirk7(header, meta['key']) + header = xor(header, xorbuf[0x50:]) + + # prepare the kirk block + block = header + b'\x00'*0x30 + block = set_kirk_cmd_1(block) + block = block + p.kirk_metadata() + b'\x00'*0x10 + \ + p.elf_info() + prx[0x150:] + + return kirk.kirk1(block) diff --git a/src/bin/psptools/psptool/psar.py b/src/bin/psptools/psptool/psar.py new file mode 100644 index 0000000..aa96ade --- /dev/null +++ b/src/bin/psptools/psptool/psar.py @@ -0,0 +1,182 @@ +import psptool.prx as prx +import psptool.kirk as kirk +import struct +import zlib +import csv +import io +import math + +import hashlib + +from Crypto.Cipher import DES +from Crypto.Util.strxor import strxor as xor + +_psar_table_keys = [ + { + 'key': '95620B49B730E5C7', + 'iv': '9EA43381860C5285' + }, + { + 'key': '5A7B3D9D45C9DC95', + 'iv': 'B2FED9798A02B187' + }, + { + 'key': '4CCE495B6F20585A', + 'iv': '8108C1F2359869B0' + }, + { + 'key': '73F45262620BF15A', + 'iv': '6D521BA3C236F92B' + }, + { + 'key': 'A664C8F8FD9D4498', + 'iv': 'DB4E7941F59730AD' + }, + { + 'key': 'D7BD74813D6426E7', + 'iv': 'A6830C2F630B9629' + } +] + + +def decrypt_table(f, table, mode): + des = DES.new(bytes.fromhex(_psar_table_keys[mode]['key']), DES.MODE_CBC, iv=bytes.fromhex( + _psar_table_keys[mode]['iv'])) + return prx.decrypt(des.decrypt(table)) + + +def is_table(name, version): + if version == 1 or version == 2: + return name == '01g:00000' or name == '02g:00000' + elif version == 3 or version == 4: + return int(name) < 10 + return False + + +def table_model(name, version): + if version == 1 or version == 2: + if name.startswith('01g'): + return 0 + elif name.startswith('02g'): + return 1 + elif version == 3 or version == 4: + return int(name) + return 0 + + +class psar_file(object): + def __init__(self, data): + self.name = struct.unpack('128s', data[4:0x84])[ + 0].decode().split('\0')[0] + (self.size, self.expanded_size, self.flags) = struct.unpack( + ' 0 else None + return {"name": meta.name, "flags": meta.flags, "file": file} diff --git a/src/bin/psptools/psptools.txt b/src/bin/psptools/psptools.txt new file mode 100644 index 0000000..4fd4781 --- /dev/null +++ b/src/bin/psptools/psptools.txt @@ -0,0 +1 @@ +https://github.com/galaxyhaxz/Infinity/commit/6de980d8fbcaad8bf7a1e7d48a3b476a55752088 diff --git a/src/bin/psptools/requirements.txt b/src/bin/psptools/requirements.txt new file mode 100644 index 0000000..96fed4b --- /dev/null +++ b/src/bin/psptools/requirements.txt @@ -0,0 +1,2 @@ +ecdsa +pycryptodome \ No newline at end of file diff --git a/src/kernel_exploit.c b/src/kernel_exploit.c index c0cc653..4f43aea 100644 --- a/src/kernel_exploit.c +++ b/src/kernel_exploit.c @@ -72,6 +72,8 @@ int pre_kernel(int (* kfunc)(void)) pspSysconGetBaryonVersion = (void *)FindProc("sceSYSCON_Driver", "sceSyscon_driver", 0x7EC5A957); pspIoOpen = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x109F50BC); + pspIoAssign = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0xB2A628C1); + pspIoUnAssign = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x6D08A871); pspIoWrite = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x42EC03AC); pspIoClose = (void *)FindProc("sceIOFileManager", "IoFileMgrForKernel", 0x810C4BC3); } diff --git a/src/kernel_land.c b/src/kernel_land.c index 0891a33..9e9351c 100644 --- a/src/kernel_land.c +++ b/src/kernel_land.c @@ -19,6 +19,9 @@ #include "downgrade_ctrl/patch_table.h" +extern char eboot_path[]; + + /* function pointers */ int (* pspKernelGetModel)(void) = NULL; int (* pspSysconGetBaryonVersion)(u32 *baryon) = NULL; @@ -28,6 +31,8 @@ int (* pspKernelLoadExecVSHMs1)(const char *path, struct SceKernelLoadExecVSHPar SceUID (* pspIoOpen)(char *file, int flags, SceMode mode) = NULL; int (* pspIoWrite)(SceUID fd, void *data, u32 len) = NULL; int (* pspIoClose)(SceUID fd) = NULL; +int (* pspIoAssign)(const char *dev1, const char *dev2, const char *dev3, int mode, void *unk1, long unk2) = NULL; +int (* pspIoUnAssign)(const char *dev) = NULL; /* globals */ @@ -50,6 +55,15 @@ int getModel(void) return pspKernelGetModel(); } + +int reassign() { + u32 ret; + pspIoUnAssign("ms0:"); + pspIoAssign("ms0:","msstor0p1:","fatms0:",IOASSIGN_RDWR,NULL,0); + ret = pspIoOpen(eboot_path, PSP_O_RDONLY, 0777); + return ret; +} + int delete_resume_game(void) { u8 _header[512+64]; @@ -222,13 +236,8 @@ int patch_loadexec_pspgo(void) /* clear the caches */ KClearCaches(); - SceIoStat stats; - int status = sceIoGetstat(eboot_path, &stats); - if(status < 0) { - eboot_path[0] = 'm'; - eboot_path[1] = 's'; - } - if(strcasecmp(eboot_path, "ms0")>=0) { + + if(strstr(eboot_path, "ms0")) { return pspKernelLoadExecVSHMs1(eboot_path, &g_exec_param); } else { diff --git a/src/kernel_land.h b/src/kernel_land.h index 77d83a1..3ce61cd 100644 --- a/src/kernel_land.h +++ b/src/kernel_land.h @@ -13,9 +13,10 @@ int getModel(void); u32 getBaryon(void); int launch_updater(void); +int reassign(void); int delete_resume_game(void); -extern char eboot_path[]; +//extern char eboot_path[]; extern int (* pspKernelGetModel)(void); extern int (* pspSysconGetBaryonVersion)(u32 *baryon); @@ -26,6 +27,8 @@ extern SceUID (* pspIoOpen)(char *file, int flags, SceMode mode); extern int (* pspIoWrite)(SceUID fd, void *data, u32 len); extern int (* pspIoClose)(SceUID fd); extern int (* pspIoRead)(int fd, void* data, int size); +extern int (* pspIoAssign)(const char *dev1, const char *dev2, const char *dev3, int mode, void *unk1, long unk2); +extern int (* pspIoUnAssign)(const char *dev); extern int (* pspIoLseek32)(int fd, int offset, int whence); #endif /* __KERNEL_LAND_H__ */ diff --git a/src/main.c b/src/main.c index 959612c..651bb31 100644 --- a/src/main.c +++ b/src/main.c @@ -27,11 +27,11 @@ #include "kernel_exploit.h" #include "rebootex.h" -PSP_MODULE_INFO("Chronoswitch", 0, 7, 4); +PSP_MODULE_INFO("Chronoswitch", 0, 7, 5); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(3 << 10); -#define DOWNGRADER_VER ("7.4") +#define DOWNGRADER_VER ("7.5") typedef struct __attribute__((packed)) @@ -76,8 +76,14 @@ u32 get_updater_version(char *argv) /* check for failure */ int model = execKernelFunction(getModel); - if(model == 4 && (strcasecmp(argv, "ef0")) > 0) { return 0xFA4E; /*FAKE some reason CS on ef0 does not like reading from ms0 */} + if(model == 4 && strstr(argv, "ef0")) { return 0xFA4E; /* FAKE some reason CS on ef0 does not like reading from ms0 */ } + /*if(model == 4 && strstr(argv, "ef0")) { + fd = execKernelFunction(reassign); + } + else { + */ SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); + //} if (fd < 0) { printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); @@ -157,11 +163,12 @@ int main(int argc, char *argv[]) "\t" "GO ms0/ef0 UPDATE support added by krazynez" "\n" "\n" "Testers:" "\n" "\t" "Peter Lustig" "\n" - "\t" "Nall (nallwolf)" "\n" "\n" + "\t" "Nall (nallwolf)" "\n" + "\t" "Total Kommando" "\n" "\n" "Web:" "\n" - "\t" "https://lolhax.org" "\n" "\n" - , DOWNGRADER_VER, __DATE__, __TIME__); + "\t" "https://lolhax.org" "\n" + , DOWNGRADER_VER, __DATE__, __TIME__ "\n"); #ifdef HBL_SUKKIRI /* Clear html param to 0 */ @@ -272,7 +279,7 @@ int main(int argc, char *argv[]) sceKernelDelayThread(4*1000*1000); /* get the updater version */ - u32 upd_ver = get_updater_version(argv); + u32 upd_ver = get_updater_version(argv[0]); if (upd_ver == 0xFFF) { printf("\nPress R to exit...\n"); @@ -408,7 +415,7 @@ int main(int argc, char *argv[]) } /* do confirmation stuff */ - if(model == 4 && (strcasecmp(argv, "ef0") > 0)) { + if(model == 4 && strstr(argv[0], "ef0")) { printf("X to continue to Downgrade, R to exit.\n"); } else { From e4a138a04da923b6756b12bc9ff47410db1f2e9b Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 31 Aug 2024 11:54:16 -0400 Subject: [PATCH 13/20] Updated Changelog --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 25da486..d803ce5 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Copy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory The downgrader is "signed", and can be launched without having a custom firmware installed. Once you run the application, follow the on-screen instructions. ## Changelog +### Version 7.5 +* Updated Tools to encrypt EBOOT to be OS agnostic ( from Yoti's psp_pspident ) +* Bugfix: GO had issue running with just Infinity/OFW running. ### Version 7.4 * PSP GO cleanup * Detect if EBOOT.PBP is missing from `PSP/GAME/UPDATE/` From dd64dd7a3648afdbb6d8f0abf319b97d7e1d0c55 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 31 Aug 2024 14:30:01 -0400 Subject: [PATCH 14/20] Added check for GO at least if being run from ms0 to detect if UPDATE/EBOOT.PBP exist also some wording changes --- src/main.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/main.c b/src/main.c index 651bb31..1e13dfd 100644 --- a/src/main.c +++ b/src/main.c @@ -74,16 +74,17 @@ u32 get_updater_version(char *argv) eboot_path[1] = 's'; } + status = sceIoGetstat(eboot_path, &stats); + + if(status < 0 && !strstr(argv, "ef0")) { + printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); + return 0xFFF; + } + /* check for failure */ int model = execKernelFunction(getModel); if(model == 4 && strstr(argv, "ef0")) { return 0xFA4E; /* FAKE some reason CS on ef0 does not like reading from ms0 */ } - /*if(model == 4 && strstr(argv, "ef0")) { - fd = execKernelFunction(reassign); - } - else { - */ SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); - //} if (fd < 0) { printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); @@ -416,11 +417,11 @@ int main(int argc, char *argv[]) /* do confirmation stuff */ if(model == 4 && strstr(argv[0], "ef0")) { - printf("X to continue to Downgrade, R to exit.\n"); + printf("\nX to continue, R to exit.\n"); } else { - printf("\n" "Will attempt to Downgrade: %X.%X -> %X.%X.\n", (g_devkit_version >> 24) & 0xF, ((g_devkit_version >> 12) & 0xF0) | ((g_devkit_version >> 8) & 0xF), (upd_ver >> 8) & 0xF, upd_ver & 0xFF); - printf("X to continue, R to exit.\n"); + printf("\n" "Currently Running: %X.%X going to Downgrade/Reinstall: %X.%X.\n", (g_devkit_version >> 24) & 0xF, ((g_devkit_version >> 12) & 0xF0) | ((g_devkit_version >> 8) & 0xF), (upd_ver >> 8) & 0xF, upd_ver & 0xFF); + printf("\nX to continue, R to exit.\n"); } /* get button */ @@ -431,6 +432,7 @@ int main(int argc, char *argv[]) /* filter out previous buttons */ cur_buttons = pad_data.Buttons & ~prev_buttons; prev_buttons = pad_data.Buttons; + /* check for cross */ if (cur_buttons & PSP_CTRL_CROSS) From 922da4382dc0d9ebfd177e681c575fabd48e9504 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 7 Sep 2024 09:15:19 -0400 Subject: [PATCH 15/20] version bump --- src/Makefile.signed | 2 +- src/main.c | 26 ++++++++++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/Makefile.signed b/src/Makefile.signed index 1130995..9fc227d 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -27,7 +27,7 @@ LIBS = -lpsppower PSP_FW_VERSION = 271 EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.5 +PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.6 BUILD_PRX = 1 diff --git a/src/main.c b/src/main.c index 1e13dfd..553e643 100644 --- a/src/main.c +++ b/src/main.c @@ -27,11 +27,11 @@ #include "kernel_exploit.h" #include "rebootex.h" -PSP_MODULE_INFO("Chronoswitch", 0, 7, 5); +PSP_MODULE_INFO("Chronoswitch", 0, 7, 6); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(3 << 10); -#define DOWNGRADER_VER ("7.5") +#define DOWNGRADER_VER ("7.6") typedef struct __attribute__((packed)) @@ -76,6 +76,17 @@ u32 get_updater_version(char *argv) status = sceIoGetstat(eboot_path, &stats); + int go_fw = -1; + + int go_check = sceIoOpen(eboot_path, PSP_O_RDONLY, 0); + sceIoLseek32(go_check, 0x346F, PSP_SEEK_SET); + u8 go_buf[1] = { 0 }; + sceIoRead(go_check, go_buf, 1); + if(go_buf[0] == 0x63) + go_fw = 1; + sceIoLseek32(go_check, 0, PSP_SEEK_SET); + sceIoClose(go_check); + if(status < 0 && !strstr(argv, "ef0")) { printf("\nHmmmm? Are you sure you have EBOOT.PBP in PSP/GAME/UPDATE/ ???\n"); return 0xFFF; @@ -83,7 +94,13 @@ u32 get_updater_version(char *argv) /* check for failure */ int model = execKernelFunction(getModel); - if(model == 4 && strstr(argv, "ef0")) { return 0xFA4E; /* FAKE some reason CS on ef0 does not like reading from ms0 */ } + if(model == 4 && go_fw < 0) { + pspDebugScreenSetTextColor(0xCC0000FF); + printf("\nYour running OFW from a X000 Series, it should be for the GO OFW\n"); + pspDebugScreenSetTextColor(0x00BFFF); + return 0xFFF; + } + else if(model == 4 && strstr(argv, "ef0") && go_fw >= 0) { return 0xFA4E; /* FAKE some reason CS on ef0 does not like reading from ms0 */ } SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); if (fd < 0) { @@ -149,7 +166,8 @@ int main(int argc, char *argv[]) /* initialise the PSP screen */ pspDebugScreenInit(); - pspDebugScreenSetTextColor(0x00D05435); + pspDebugScreenSetTextColor(0x00BFFF); + //pspDebugScreenSetTextColor(0x00D05435); /* display welcome message */ printf( From 3b1272974ddf5b8f6ee2c3a53782bedebbb53ed7 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 7 Sep 2024 09:16:23 -0400 Subject: [PATCH 16/20] Changed default text colors. Check if running the correct FW on X000 series vs GO. --- src/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.c b/src/main.c index 553e643..9c8ce5e 100644 --- a/src/main.c +++ b/src/main.c @@ -100,6 +100,12 @@ u32 get_updater_version(char *argv) pspDebugScreenSetTextColor(0x00BFFF); return 0xFFF; } + else if(model != 4 && go_fw == 1) { + pspDebugScreenSetTextColor(0xCC0000FF); + printf("\nYour running OFW from a GO, it should be for the X000 OFW Series\n"); + pspDebugScreenSetTextColor(0x00BFFF); + return 0xFFF; + } else if(model == 4 && strstr(argv, "ef0") && go_fw >= 0) { return 0xFA4E; /* FAKE some reason CS on ef0 does not like reading from ms0 */ } SceUID fd = sceIoOpen(eboot_path, PSP_O_RDONLY, 0777); if (fd < 0) From 69b37352d27314990062352e2ecf9fd89b605c74 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Sat, 7 Sep 2024 09:17:06 -0400 Subject: [PATCH 17/20] clean up --- src/bin/psptools/psptool/.gitignore | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 173 -> 0 bytes .../psptool/__pycache__/kirk.cpython-312.pyc | Bin 12380 -> 0 bytes .../psptool/__pycache__/pack.cpython-312.pyc | Bin 16524 -> 0 bytes .../psptool/__pycache__/pbp.cpython-312.pyc | Bin 3661 -> 0 bytes .../psptool/__pycache__/prx.cpython-312.pyc | Bin 9332 -> 0 bytes 6 files changed, 1 insertion(+) create mode 100644 src/bin/psptools/psptool/.gitignore delete mode 100644 src/bin/psptools/psptool/__pycache__/__init__.cpython-312.pyc delete mode 100644 src/bin/psptools/psptool/__pycache__/kirk.cpython-312.pyc delete mode 100644 src/bin/psptools/psptool/__pycache__/pack.cpython-312.pyc delete mode 100644 src/bin/psptools/psptool/__pycache__/pbp.cpython-312.pyc delete mode 100644 src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc diff --git a/src/bin/psptools/psptool/.gitignore b/src/bin/psptools/psptool/.gitignore new file mode 100644 index 0000000..bee8a64 --- /dev/null +++ b/src/bin/psptools/psptool/.gitignore @@ -0,0 +1 @@ +__pycache__ diff --git a/src/bin/psptools/psptool/__pycache__/__init__.cpython-312.pyc b/src/bin/psptools/psptool/__pycache__/__init__.cpython-312.pyc deleted file mode 100644 index 2b8285d061afc24d5826ede5b3c35aea5bdeb7a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 173 zcmX@j%ge<81hER2(?IlN5P=Rpvj9b=GgLBYGWxA#C}INgK7-W!^3l)8&rQ`&DoV}E zOU=^{D9X=DO)e?c4+sv>cg`rv&&v-k&n!vK&@V1Z)=$dJ(=RA4D9O*yDTXohXd(jBSjtjrZ*C*|Qsrle6dS!I;4ia7dy+6kGRVOV-0# zT?2Nmf=DwHdzy*mhSqY+q#{Ema_vr?k|s`?H2l#{A8DsjWn$-I2HIrW@l2;fY)V^Z zTKb*6_e#PD3>`Y1>4MJgo;}asv}OY>dZZ z$7A_eK0XlZuH56@alF?J)D0%O6LDRa7)TDLx>M0}av(jJ>CQyYse$^zhVF*JYh<8@n5$=gdIUU~_l#U`uyP^j<&EI@s3ThUbRv_C2wD_M7qUj(qORvF;`LMwCnI zVuj}ZjkN{N-wVt7$^2XGDc^JoE7uqLEjd+rjGb;iRabfJUS3$MKuD$8!}A3~4b!1ER{EzDq1&(Lgx1 zZIi%~!V<($)VFEi*siTtVwl1XoIrSi7nn*3$FfCWo67fX$H6R~XWF)qCUq4hzVLm+ zA)esOaxKGP6tftnNhR~SV+F$ZZ0AV7JUNEv&=j(xO~=Tv)_1 zIAgBxi6^lJYWN1$;o4XZ3PugrwtV6F9uFW7PcVf|Lt;Mli4(}cw7AE7=#?-beQru2 z17SNsxl_1|DCwiOpwd)kU`ocYQmI_iaa|KK0Qkp+}HZAY0jK%F!>r?$Z?!`JiMEC?KB@Ny@Wf)QeQ(jcDY z`ob`ol2Quaa4jZ1i55gkhbjXiwFAuMaIT0+Jc!NnT?MHd(6uET*P+7kd_$?gRnmp2 z+Ll8c4yiK<(LrcjIn41C48Vqd49|sZ{D5ffW7oECnGia54S{gR6)ck2Fly!a@CJiO zi+GOBB}~azmMN)ph_F54OHW}8)I5ZPSOh z;mLJc9a#?!zyX<-l@01AriWoA?+5ZXpBW0TieTg21$?$$j{m;Yeab${53j#vGGat{Er- zBk>7iJaBC+$uKO8AuOhd6}ST1gE89hN*`-A6ztuCgG1`RVy*?5xE_Q_65zMeLNxzM;Jx*68{eOj$B;gkbRLQV`z)yhT%|74NhQ)a8Hj}iZJSOi)+1L2iTkyn4W;u+uV{+ zf*rU9^A(1NR{|P=9v(c53d#V9SRr8$q5*U?ATj1K0j0pCIiVPY>BLonA@!U7I?9yTDbZPfWD z^Bkdl&H@~9X(AT5rUm2jJdA^#NS_%l!ESMbm>nev7NZa`5!+x8rt*9^nTd56Ko&qQ zfw}@Pqiwp$w2EeAfpqnt_Dsuw=)SmcVceAlbn67Z=~#$ul=>!&71}oflQJsdAEu4zHIhKz@NiF2Qy}isAfSeAd5#H_ zHWhba>Xu?AqAdaq!8+g)gxNkoJb>Dz1TircrPPHR+YZ;-m&%5cX<(@cn<44|(v<*H z35o!{0Jjt@9I=cOz^D_LjEg`i&Y5W`g>{gCx`7X=0<#o>un;&wLZA_b0AwIWnQ#QA znL>a#L>Wea?K3nmC~#3?9WV(3w4>ltibDR334|{TcZ3Jaz$`-e@DOkj3f019Ean2K z5VDw*42Xy^qz&4DHNbog@F7SL;3oqP19xqLy%+*pVIGHV+hBQ0G8X|j@Gy*NLR;7^ z2nqopfek2O3RC-lLAVF0IKJm%9X{m4AXX3(kUauM7${&Fpa_o4T=)z42te2)P%pwX zqO3t-mx!MNaV{X*vrPu@Z~>n}K_1fPPz!>g4S0Z?Xd4Ri3Hn$mW(0Tgi~!UD%$Xn*dSGyl0d2zD zVL>)nxZnb~jHoXycmhzy1LFY=W{N^D2J`@{cMX?=hk#B16cO>YwSiL`*b9IV#vT~p zMi5j03ziOo35QfIz!GrGmDq-7C}<5H0O0b$AUNz94hMRGy-*mY<~Pt2*cG4xk(X$B zP(UQeFZMzZ8-RKe{toN1Jg`vAOAJIP;yRkqOAs%@eeigAB}g^*6=n@U_XV+iwD3F+ zKxSz&6oBr6LVyWUx zh)E-!1KnJzpj&V!3wXx4$st5|yS6c3NQU$Y5t?f%1iw~bXQqN7aUbCoD+M9}S707o zxeiL9lP*}TaD7K3B%tCj=DV1?mSNWtyKxp%y8RGF;%Ka4{*C;|Luu zZ2S-WfF~g3B8c@Kg#iV`gglY1Q9}UUwQe0OT7eG&-obn^k#=xExDv=7b#`LHg8+n7 zCt%zJ*{0Nnm;rAtWk3or11VuG4(wOJTR@q74`7Ba;Ht<&Fa`&s0IY$@nbL+Kz`uM4 zI1V|%$uv(UU|!0A*D!<>6C?*>bucLQ6et#87O*~wU19CeJ;E0}0Z}7Bx`u#;q*n7} zB$^aiDKarg3A_Y3nMJ_BASvuquM|ljMnI^tfiqxQ#E}eE37P=O0fUf0U>-P!h13}t zC@|AO42Jex19E^BLgir50{jcH3_C?mrJ0BX)0E249tE!9I>-b-^)!b-$_lrF!@8jM z44H_=Lc$G?m=rq(-9%Oa?g|`1ZVDZ_Sg8#-_hA9h1YjM6DNqu4fEWy72X+v7r4+Wp zl(rq1NPdX21(1dzX;+eCrC=I5;e&t-3lcz>hTS6faRLTL#IO!v5#pfUD2x%zON*Ww z$W3YBA#uYPfK?<%t|uWiL~E?q#9Fu`J?Ia4IcD)05Z*%ofyTkQAWs-8HwY4YV5-h6 zU!4i^pxGcF+>U4kXc;4=l$5ltV=vx&@^`atz48CN(j{ zMgrv50B4TXF)a^RJz+@Ph;I_9!0Zr7If6cX9YIp`E;!bSrSX!$-<1IrIM9lZ;s|Rr zo==R{<&&d{d}=hAPmiXG)kC9LtQ0H7OLeDoA6%p9V)Y4M(xpTxSxTKsR=;J6wd1l_ zK7+5Be0}ZPgR!oL9sis|!?&KS{C5+cU#LF6mALeuZ@u-_fd2j;>$b0XKy6a(Q!Gz`1zP@lDIhneocX~;0D*U>B%IHGx=wu?) z!U}aoSg$MU%kll?_^xt%ce(DaC-8T$91qK>UVVyHZrD>8Dula=!{LZ-+*!Te+_rh| z@L*x{?yxX4R2bTPe>mJ<=q-+HzW>4dH;cXD@X+vskM|XO_ii2udpGay8``{oWPfpZ zcwnUVuvstk_Wd{q>xq`!6U`Ssi%E{*Z{$7{W3gB3%`twVKC27;)L@PIl|sK>Z0s24 zvtk0~EH`?N*Wxrh)ecJfho((T$QlDjOpBebK z-v1K$b%$@*Ug`D9_CNX5LwiL=ucWu?pm>bU1HdX6{_)tn zqxV-&grio~q7*C6^*tT0of(fNOUZui7FS)Rc)l*5SP`q8ILBjX*Kk!MyrNw)pIX@N z!(TF0u1|#D)ouPr7vDoMqSp)s z)I7Q>{-|U4V|@F8ZnPZ*xGq_ zy4{)NvqNVdnz`kU>6KglH4#s3t%!6k&|>U4l>HvWb1mP@$03x8zg2~qPcFwGqw)9l zrl=nR{k#CH{p#LFzjQwHj(&;v(GOJM9sQCZ94Sp9BBiEunQu4*8RV1u81%BFl*(sy z?R&P0e{~7Qheo!;s;k&otEl1EJofcB*S^i)^SRTF^R%dx z?r)p_R(pbmlKCd=ysG8VOsOuP-FGW?*IewFZ>6PB8!H|gYAY_C`G!)FJ$ax*`Ue*RtbK-Ilu} z7rd0mE<$abm-gynzb-URTzUdU_(NU%28t`%bFaRDy>)$$g};ybiYw>J>5*c1ptlHk z9ooOEcVC3Hp$0}E>%n4Sq?~y)93I?Tc%q!?*++UbHCN%^7FfW^&e;yx7=&^xh-)POP0wP3EWU z=}u#|k(^mQ(`bXBy;r}cj-!tpd1S(#Tsm2tlGCfnY?FD0%rwz4b)mUs?5ciBxB+Lur8V;c@-oZLCR;AYBf+b`>vjPIOSJ5e0(nJi50JmZ|J|Hv=1O-I)sSwFsZyf`7pH$P{6 zd&{$1&TK!I{pgsukZV4A$B{e651{`oCq6T^Wa`nAE6?nl>GGzRePlLw$Ju+&?tEeW z4<4S*ZJ$nVe`iS2YKcP9M1-HEy0N9#!lpUTtV0^K06$7|KAVqgObVUi9OKEqN4tDd zdqO@{^JW=)WEl`FSxOY=m{18R)*-ADeuXjj#A|Cf)P$CauP#rSYjY#9o5Q32CAHD#??55o^*rj#%V$B|+)hqa(P=bO zyskDzzYb1UU8T(2{Pm?wHN2-I%x}0x&xX04+4q*#0@Po5)%18RuBz45#`^%W&6RSC z%C@dHR;ga^r4&W6QiFa5LS}bVpzoV_z0`st0>Mj2fZqy#Q@{SHF8&O~n~huUzT165 z{}Jbju9i@XwcNU=Q0xh#e?-w!!M(&lVW^x!)t*B5m%6idf(RMIzt%l6g`o=e{keWi zYVg!qOO+Rm;GbG(Qo3g-{43q>rzpA_%Slk!U8vtRPz;~f_0zg@yf2*9_j(N36SYY1 zE$qq{!g989@4-M7T&>riqt_Yq7}172hnY3lEO%6L+Uf!;D+>P+O)uy^D*M#kuLyh*Pqxr+j863HjRu+j(+CIXC`i(YMbJxN6y%%4*qD( z+58`O%{Iv~b+PTn^KENp+SW{}*|rU1+p)-|j`5v<`E4_eYXR&ntIoHqo@rSX$%VOhMf_Ewv3URu|TlTD?j#j*VDak7f#jao|is4V5GxZbn?*TWa_J;L?y zXZq>wxE`L@b($E5CsB-aqPW)8)f%CHsBtm;xh~4OSOo6Fm-Gh>_2ETbXnY92gQA?y z_w6ZwM9;%~bNGt>`l|k#0kf@;W_{|QpCZT)|6aGypdbE&E`FigCUuiJ$k&GyI-f3A zAYZ>mkgv0*g^*v%uiM`a`q3fBzo6|E{EhTiF~522$&2mRpKtG)Y44i4dA5Di;moU< zmg&s0iyh0)cicA9aodzR+j0Bh`u~+ku>KkAcek9_G6iDF{zs9ZdPuYFbmClYliOxiY@E$)I+LBredO$? zW^%z_G|uF9PJi;@ncTzE$%iW>TAO0+(uuR?4_BT;ajip$1u60zJ+2J|ay6H5m*SfJ z&AH`Vlm0m(J6DC1qSN!gH`JBt`az4YzUJxYgE*+)F;AJgG7HF0FM3Ix=h(9v_=g}mx@V6fWML!YPp|;AUFv=?w4@l}N3Cz>$j&C})>ABpLm_h2+ zPQGh>f6I5aya0Q-Z$6PJ&gNE4Cs+MH5OVk$Hov%V!(VCfX`&hajV>;uSVWL4d;=d= zK#<|{lwr@lutH!s=34r#O zP!~60k0WdG0Ap!bdcI-xOvCEQTfW=$e9O6pkKt#TWcn+2KXv!v-f{cIryJE3w;Nj@|ZZcH>y)a+24z)Q#mXZ%bz5cV1qRjcvN8*=dye@vjz?kOufJFK{>W@LFpv&8XS*J%VVHlzf|4|HX0e22m@ zDrOhM>rOGe-j{VnExn_|La+wF8n38ioR#2AfHPB^jo>VRvr=3(!Px+pO>sE{mjk$5 zipwRqJiz5sTpqy{0IrbY^7*1uOh*A<46u;511#bl0E_t&U!kw4OU;*_Vms`7IbQ}( z#~|x+&f}2XE>)as2^{N-bDhUR{eGsssonoV`~G(S$(Fr4{o}u3n0YPGd8PSDP@XKa zxE{(E7#~^S4wZ`WsjtX%9b8IDlTylp*Q?@|mg7F}u~6sXUf+Si0iWBYjq5y~Kxd!N zI5bE#m z4Jw(sfllwy+JQj6k4#BEWrmPk) zB1wxy@JOr{&%)b!pX9-gU<{$E8TT1hmUQKA3=;F`hNx34#2G z>jo5#)ed-`>*RSM4w(Uxfx0e#uP-=+s6Jnxl<%KPv)A7p5bV%fGGCJ~G-SqA zqdbl59NY$Agn2KESzb%H`rwVK8^>;PH&)CpbKljd^wq%Ej&uAged7mSe>$c&pD8&P zdS!T=f4x^Oyc(97g3HJhY5cGRUMC=M!haA~=@hf5QfnS%C04*HFZ|P_Y^22pv%>y# zRxm}aGAIY*CYhWtP22z_Um%3E4`Lu( zYsx@4vS1qkU?3e+y5!;`V~$rRr0t6l{`vjC2vd0!^ousZE+Py3gJ?d1lp%e$tRvyjct`eL&k=>GA)s@In$6({MfOf1Sg5~j69r{V9r%(C@7+O?m_NNOF;em z?_+h^AfSlf!_M@qyT684E2|7&2F(kS2H{(=BBw*4*p&E}sx`ol-X#;2o=U1DQb%u$|3x>a;+y{l%M*li08 zTezM5`SzV}W!-rGyVeCY1G>lf!96{U_JeyIz#z)fe=e%qS;~EPY2D6B&Ye*wZ3QX; zK^=Y;#hNi|+GU-DRhe}Xn#1XaZIb_Fc!W5NZJ?u56cjabe?{8=F&eobws0ZRQV$i} ziHd~y=%J!Bsg_F;F4X1%`$*#+GHz~dUA-Yl#D}mQ+6avRK4eqvBolbuouQE6KYT3Y ziyNRsMFQl}1&`~x(Y)?G2DTCGc~7W+K+5<6d|Vd{9Xm`=QVwv!6Yv^vB4N+_2OeM| zqdpmABV znli< z&VYHBC7YgL<_>3tvwAA;Zx1G9wJXT#dCwkLz>317i3lY(%9 z5;Zb`pEoKsiKo)9pd&jBqf#UVUJYx6qwv*Hprs{VM?|0Q=yKpv9j}MCB-#x=ppAjF zG01Ig;cZZ+ zYl-_IF&5lw9=g{^2_uChk&;s`kX`Aipe5W{*|>k8J>7$R4q$U-?2;5(jf}0LSftI9 zvDFld{pQP9x{nAqQ1_I)r9h^E?{r+eEX$mEh=XYNH`ULx;7tin0}UDa5LbIR7z9V+Gl;=4g4Z$7>kmPkR8?CqJc$@J zgu7+uVuVDxKh$sT_62;$2ZXId)l~OUlcjcZZ@;&*H@LNyk{yPAg3SPa{qM}LM;I{f zbDfdwi8WU@O>Ua%yzal|pX!-e(HLE^OI)!lX0k1+*_Ao5oLn%vSLVlx%CKDiO2b`j z_W`k%Kfh)xdtJMg^)sNT=27kW@uXlLBNl#Cy?zEh#yo16c~ruFn@X#h$F-Y}BS7IY z4~7aek8_+y?c;J0b0w~)mY;yph`0qzJ`8!$pqOF{TD<*z5H(foMBy2vHUl*t*Z`5I zw?CzL#4mV|MBVEP#C5Q$B(^5BAx=XaP2o|@>jObwcOQC^!T~4?7X~e0*Gg)Hg_6>iW1|L9R|<8(`QFQ}!P5!C4BW zO(Iz1(h(;X9AbJ5CIoR*9D2fWt-SW}EU*p-4iCs23G*Rb;B& zUvbqqX`Jf(8*3!@qT{QM>Bj(VnJcfnI5;*qQ9e<1wRW<0rhFqf$@YiANgi!H+jhF` z9w}|zHogBw#f|2--EXVsplvsIf#emfSX$ z%{ePZn}2F5{e?Mq&X#wh;!<4sSWyX?P_aFtjx>&Gun@DCMGD5bF(kLZSB&IF9vjP-3is6<7(<4$#ER`{ z1TR}YxOajDKEQxN34z5A2hpbdt|@m<5%;}<+&!h-_no51UM>`hMupTP|wc$Cg*sfWgo6BWElG4Dt#YECC8 z2%eg>X?SW@rr|Rs?`b}v_C=&eU`|;mkznS$#h&N0^NT+UdTWf1m6GU~Inn+w{ZR^^$wQcL#+M15H zuH68*)ol&yo7y&z?1m;1@sTXI5$JicTnZVZsT#L|_VBc}G&aM%ibooEwe1j20$TVS zg3lv3g@9=BEMEYlvBHap8Ab5t2)>Nq3kXIKyo}%_1b>0xG=f(Ud=bG}1g|3a5`wQF zxPagsf(U{!1m_Wa6@e2#QY=L}inkNV<7!bJS5QI%;F( zOTj`bS-zmbPC-`J)Lt!_ELqUX#SNRUzi{mZT5M(avTqN+HB1qoVGpv=C%oblUW)2s zd)TP2U-b3MC>>Mcl-{X}23~>3jtgeez{ISqkFMAvuGm5m*dV&CUEJ1AQTy2gtX!~Qd-s@o!Aja& z;DuM+lZoP%Mpmw}DMQO9ls1J@DFWqp_Pn`gK`Q4c{pJ$t9EDmbBK7V!cP}XA-K?Aa zN!bs}?nwwnuYXF4A-e_iu+l?e=xqoH_QHP7`&{UJFZ2AYT_)J;S`#h^2|m4=}#T1nh8aZnAq(t==DN&z@ z=b#SQd{g@jfwV+&Jg4KkMMM?!0qvFK2e zL}oyBC3%ZUrlA1=2(p{qLO0M80W0)EF3t%3h!{jLgx~~%0D>@rVFWJ#fYUo7ZbuOD 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 wmwRp>D9?U~?E?F(+qt^&~k-80PJI*$p8QV diff --git a/src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc b/src/bin/psptools/psptool/__pycache__/prx.cpython-312.pyc deleted file mode 100644 index 0a5446e79a1ef1ff4bbf3813d298db6dce492439..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9332 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 Date: Sat, 7 Sep 2024 09:23:10 -0400 Subject: [PATCH 18/20] Updated for v7.6 --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index d803ce5..adca77d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Copy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory The downgrader is "signed", and can be launched without having a custom firmware installed. Once you run the application, follow the on-screen instructions. ## Changelog +### Version 7.6 +* Changed Default color, makes it a bit easier to read. +* Detect which OFW you have to make sure your flashing the proper model OFW. ( i.e You can only flash GO OFW on GO and vice versa ) ### Version 7.5 * Updated Tools to encrypt EBOOT to be OS agnostic ( from Yoti's psp_pspident ) * Bugfix: GO had issue running with just Infinity/OFW running. From 37a924da525be0433007771ce315c2768e1f0494 Mon Sep 17 00:00:00 2001 From: Brennen Murphy Date: Wed, 20 Nov 2024 07:16:08 -0500 Subject: [PATCH 19/20] Release 7.6.1, added more print statements for other errors that may happen --- README.md | 2 ++ src/Makefile.signed | 2 +- src/main.c | 8 +++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index adca77d..8b5cb20 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ Copy the official firmware update to `PSP/GAME/UPDATE/EBOOT.PBP` on your memory The downgrader is "signed", and can be launched without having a custom firmware installed. Once you run the application, follow the on-screen instructions. ## Changelog +### Version 7.6.1 +* Added more print statements for less common issues with parsing EBOOT.PBP or the buffer ### Version 7.6 * Changed Default color, makes it a bit easier to read. * Detect which OFW you have to make sure your flashing the proper model OFW. ( i.e You can only flash GO OFW on GO and vice versa ) diff --git a/src/Makefile.signed b/src/Makefile.signed index 9fc227d..f2e702a 100644 --- a/src/Makefile.signed +++ b/src/Makefile.signed @@ -27,7 +27,7 @@ LIBS = -lpsppower PSP_FW_VERSION = 271 EXTRA_TARGETS = EBOOT.PBP -PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.6 +PSP_EBOOT_TITLE = Chronoswitch Downgrader v7.6.1 BUILD_PRX = 1 diff --git a/src/main.c b/src/main.c index 9c8ce5e..d0a694f 100644 --- a/src/main.c +++ b/src/main.c @@ -27,11 +27,11 @@ #include "kernel_exploit.h" #include "rebootex.h" -PSP_MODULE_INFO("Chronoswitch", 0, 7, 6); +PSP_MODULE_INFO("Chronoswitch", 0, 7, 61); PSP_MAIN_THREAD_ATTR(PSP_THREAD_ATTR_VFPU); PSP_HEAP_SIZE_KB(3 << 10); -#define DOWNGRADER_VER ("7.6") +#define DOWNGRADER_VER ("7.6.1") typedef struct __attribute__((packed)) @@ -128,6 +128,7 @@ u32 get_updater_version(char *argv) if (sfo_size > sizeof(sfo_buffer)) { /* too much */ + printf("\nTo much deditated wammm ... Perhaps not have all your plugins running right now ...\n"); sceIoClose(fd); return 0xFFF; } @@ -153,6 +154,7 @@ u32 get_updater_version(char *argv) /* see if we went through all the data */ if (i == header->count) { + printf("\nHmmm SFO count is too big ... Looks like the EBOOT.PBP is corrupted somehow.\n"); return 0xFFF; } @@ -178,7 +180,7 @@ int main(int argc, char *argv[]) /* display welcome message */ printf( "Chronoswitch Downgrader" "\n" - "Version %s. Built %s %s" "\n" "\n" + "Version %s Built %s %s" "\n" "\n" "Contributions:" "\n" "\t" "6.31/6.35 Support added by Davee" "\n" From 6e2e7cec54fcf00942e75af36d5c72c278edd103 Mon Sep 17 00:00:00 2001 From: Brennen Murphy <39999447+krazynez@users.noreply.github.com> Date: Wed, 26 Mar 2025 07:48:12 -0400 Subject: [PATCH 20/20] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 8b5cb20..598aad2 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,6 @@ +# Repo moved to [ChronoSwitch](https://github.com/PSP-Archive/Chronoswitch) + + # Chronoswitch Downgrader Chronoswitch is a downgrader for the Playstation Portable (PSP).