use of custom kstuff (#58)

* reverted libmprotect.h, couldn't make a viable build with recent ps5 sdk's
* added feature to load kstuff from /data/kstuff.elf before using embedded
* added menu feature to download latest kstuff from echostretch
* made download_file() more generic
This commit is contained in:
Adam Furtenbach
2025-09-22 20:11:47 +02:00
committed by GitHub
parent b41b22d768
commit 0a4bfbe558
8 changed files with 127 additions and 13 deletions

View File

@@ -131,6 +131,8 @@ int ItemzLaunchByUri(const char *uri);
bool enable_toolbox();
void sig_handler(int signo);
uint8_t *get_kstuff_address(bool *need_cleanup);
bool is_elf_header(uint8_t *data);
bool if_exists(const char *path);
void *fifo_and_dumper_thread(void *args);
void *Play_time_thread(void *args) noexcept;
@@ -347,8 +349,10 @@ int main() {
}
if (!dont_load_kstuff && !has_hv_bypass && !is_lite && !toolbox_only) {
notify(true, "Loading kstuff ...");
bool cleanup_kstuff;
uint8_t *kstuff_address = get_kstuff_address(&cleanup_kstuff);
if (elfldr_spawn("/", STDOUT_FILENO, kstuff_start, "kstuff")) {
if (elfldr_spawn("/", STDOUT_FILENO, kstuff_address, "kstuff")) {
int wait = 0;
bool kstuff_not_loaded = false;
sleep(1);
@@ -366,6 +370,10 @@ int main() {
else {
notify(true, "Failed to load kstuff, kstuff will be unavailable");
}
if (cleanup_kstuff) {
free(kstuff_address);
}
}
sleep(10);
@@ -440,3 +448,65 @@ int main() {
puts("main thread ended");
return 0;
}
uint8_t *get_kstuff_address(bool *require_cleanup) {
const char *path = "/data/kstuff.elf";
long offset = 0;
off_t size;
uint8_t *address;
int fd;
if (!if_exists(path)) {
goto embedded_kstuff;
}
fd = open(path, O_RDONLY);
if (fd <= 0) {
goto embedded_kstuff;
}
size = lseek(fd, 0, SEEK_END);
address = (uint8_t*) malloc(size);
if (!address) {
goto close_fd;
}
lseek(fd, 0, SEEK_SET);
while (offset != size) {
int n = read(fd, address + offset, size - offset);
if (n <= 0)
{
goto free_mem;
}
offset += n;
}
if(!is_elf_header(address)) {
notify(true, "Kstuff '%s' doesn't have ELF header.", path);
goto free_mem;
}
*require_cleanup = true;
notify(true, "Loading kstuff from: %s", path);
return address;
free_mem:
free(address);
close_fd:
close(fd);
embedded_kstuff:
*require_cleanup = false;
return kstuff_start;
}
bool is_elf_header(uint8_t *data)
{
uint8_t header[] = {0x7f, 'E', 'L', 'F'};
return !memcmp(data, header, 4);
}

View File

@@ -51,6 +51,7 @@ enum DaemonCommands : int {
BREW_UTIL_TOGGLE_CHEAT,
BREW_UTIL_DOWNLOAD_CHEATS,
BREW_UTIL_RELOAD_CHEATS,
BREW_UTIL_DOWNLOAD_KSTUFF,
// Special command to launch Johns elfldr for lite mode
BREW_UTIL_LAUNCH_ELFLDR = 0xE1F1D8, // not used if already running

View File

@@ -3,7 +3,6 @@
#include "ps5/kernel.h"
#include <ps5/klog.h>
/*
static const unsigned long KERNEL_OFFSET_PROC_P_VMSPACE = 0x200;
static unsigned long KERNEL_OFFSET_VMSPACE_P_ROOT = 0x1c8;
@@ -159,4 +158,3 @@ static int kernel_mprotect(int pid, unsigned long addr, unsigned long len, int p
return -1;
}
*/

View File

@@ -28,6 +28,8 @@
<list_item id="id_pause_kstuff_3" title="PS4 sysentvec Only" value="2"/>
<list_item id="id_pause_kstuff_4" title="Pause Both PS5 and PS4 sysentvecs" value="3"/>
</list>
<button id="id_download_kstuff" title="Download latest Kstuff"/>
<toggle_switch id="id_sistro_ps5debug" title="Enable PS5Debug by Sistr0 and CTN" value="0"/>

View File

@@ -286,6 +286,16 @@ public:
return IPC_Ret::NO_ERROR;
}
IPC_Ret DownloadKstuff() {
std::string ipc_msg;
if (!IPCSendCommand(BREW_UTIL_DOWNLOAD_KSTUFF, ipc_msg)) {
shellui_log("Failed to BREW_UTIL_DOWNLOAD_KSTUFF");
return IPC_Ret::OPERATION_FAILED;
}
return IPC_Ret::NO_ERROR;
}
void KillDaemon() {
std::string ipc_msg;
IPCSendCommand(BREW_KILL_DAEMON, ipc_msg);

View File

@@ -86,6 +86,7 @@ MonoClass* MemoryStream_IO = nullptr;
*/
std::atomic_bool install_thread_in_progress(false);
std::atomic_bool download_kstuff_thread_in_progress(false);
std::atomic_bool cheat_action_in_progress(false);
static std::string current_menu_tid;
int usbpath();
@@ -613,6 +614,20 @@ void* download_cheats_thr(void*){
return nullptr;
}
void* kstuff_download_thread(void* args) {
if(download_kstuff_thread_in_progress){
notify("Download action already in progress, please wait for it to complete...");
pthread_exit(nullptr);
return nullptr;
}
download_kstuff_thread_in_progress = true;
IPC_Client& util_ipc = IPC_Client::getInstance(true);
shellui_log("Ret: 0x%X", util_ipc.DownloadKstuff());
download_kstuff_thread_in_progress = false;
pthread_exit(nullptr);
return nullptr;
}
void* reload_cheats_thr(void*){
if(cheat_action_in_progress){
notify("Cheat action already in progress, please wait for it to complete...");
@@ -673,7 +688,7 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
return oOnPress(Instance, element, e);
}
if(value.empty() && id != "id_download_store" && id != "id_dl_cheats" && id != "id_reload_cheats" && !is_game && id != "id_save_rp_info"){
if(value.empty() && id != "id_download_kstuff" && id != "id_download_store" && id != "id_dl_cheats" && id != "id_reload_cheats" && !is_game && id != "id_save_rp_info"){
#if SHELL_DEBUG==1
shellui_log("[LM HOOK] OnPress_Hook: Id: %s has no value set", id.c_str());
#endif
@@ -901,6 +916,11 @@ int OnPress_Hook(MonoObject* Instance, MonoObject* element, MonoObject* e)
pthread_detach(thr);
}
else if (id == "id_download_kstuff") {
pthread_t thr;
pthread_create(&thr, nullptr, kstuff_download_thread, nullptr);
pthread_detach(thr);
}
else if (id == "id_auto_itemzflow") {
Auto_ItemzFlow = !Auto_ItemzFlow;
//(global_conf.launch_itemzflow ? "ItemzFlow will automatically be opened after" : "ItemzFlow will not be launched on boot");

View File

@@ -182,7 +182,7 @@ bool download_file(const char* url, const char* dst)
const char *filename = strrchr(dst, '/');
filename = filename ? filename + 1 : dst; // Get just the filename without the path
snprintf(notifyMsg, sizeof(notifyMsg), "Downloading the latest cheats repo ...");
snprintf(notifyMsg, sizeof(notifyMsg), "Downloading '%s' ...", filename);
notify(true, notifyMsg);
// Get current time for notification timing
@@ -228,12 +228,12 @@ bool download_file(const char* url, const char* dst)
int progress = (int)(((float)total_read / contentLength) * 100);
snprintf(notifyMsg, sizeof(notifyMsg),
"Downloading the cheats repo:..\n%.1f/%.1f MB (%d%%)",
total_mb, total_size_mb, progress);
"Downloading '%s':..\n%.1f/%.1f MB (%d%%)",
filename, total_mb, total_size_mb, progress);
} else {
snprintf(notifyMsg, sizeof(notifyMsg),
"Downloading the cheats repo...\n%.1f MB Downloaded",
total_mb);
"Downloading '%s'...\n%.1f MB Downloaded",
filename, total_mb);
}
notify(true, notifyMsg);
@@ -243,11 +243,11 @@ bool download_file(const char* url, const char* dst)
// Final notification
snprintf(notifyMsg, sizeof(notifyMsg),
"Successfully downloaded the cheats repo\nTotal Size: %.1f MB",
(float)total_read / (1024 * 1024));
"Successfully downloaded '%s'\nTotal Size: %.1f MB",
filename, (float)total_read / (1024 * 1024));
notify(true, notifyMsg);
etaHEN_log("Download complete: %d bytes", total_read);
etaHEN_log("Download complete '%s': %d bytes", filename, total_read);
sceKernelClose(fd);
success = true;
@@ -269,7 +269,7 @@ error:
if (!success) {
// Notify on error
notify(true, "Failed to download the cheats repo!\n\nCheck your internet connection and try again.");
notify(true, "Failed to download [%s]!\n\nCheck your internet connection and try again.", filename);
}
return success;

View File

@@ -550,6 +550,19 @@ void handleIPC(struct clientArgs *client, std::string &inputStr,
reply(sender_app, false);
break;
}
case BREW_UTIL_DOWNLOAD_KSTUFF: {
notify(true, "Downloading kstuff");
if (!download_file("https://github.com/EchoStretch/kstuff/releases/latest/download/kstuff.elf",
"/data/kstuff.elf")) {
etaHEN_log("Failed to download kstuff");
reply(sender_app, true);
break;
}
notify(true, "Successfully downloaded latest kstuff");
reply(sender_app, false);
break;
}
case BREW_UTIL_RELOAD_CHEATS: {
notify(true, "Reloading cheats cache");
ReloadCheatsCache(NULL);