mirror of
https://github.com/EchoStretch/kstuff.git
synced 2026-10-22 11:42:27 -05:00
218 lines
6.2 KiB
C
218 lines
6.2 KiB
C
#include <sys/types.h>
|
|
#include <stddef.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/mman.h>
|
|
#include <signal.h>
|
|
#include <sys/thr.h>
|
|
#include <time.h>
|
|
#include <ps4-offsets/kernel.h>
|
|
|
|
#if defined(__9_00__)
|
|
asm("ps4kexec:\n.incbin \"ps4-kexec-900/kexec.bin\"\nps4kexec_end:\n");
|
|
#elif defined(__7_55__)
|
|
asm("ps4kexec:\n.incbin \"ps4-kexec-755/kexec.bin\"\nps4kexec_end:\n");
|
|
#elif defined(__7_02__)
|
|
asm("ps4kexec:\n.incbin \"ps4-kexec-702/kexec.bin\"\nps4kexec_end:\n");
|
|
#elif defined(__6_72__)
|
|
asm("ps4kexec:\n.incbin \"ps4-kexec-672/kexec.bin\"\nps4kexec_end:\n");
|
|
#else
|
|
#error "unsupported firmware"
|
|
#endif
|
|
|
|
extern char ps4kexec[];
|
|
extern char ps4kexec_end[];
|
|
|
|
void kexec(void* f, void* u);
|
|
|
|
unsigned long long get_syscall(void)
|
|
{
|
|
unsigned int eax, ecx, edx;
|
|
ecx = 0xc0000082;
|
|
asm volatile("rdmsr":"=a"(eax),"=d"(edx):"c"(ecx));
|
|
return ((unsigned long long)edx) << 32 | eax;
|
|
}
|
|
|
|
void kernel_main()
|
|
{
|
|
unsigned long long kernel_base = get_syscall() - kernel_offset_xfast_syscall;
|
|
asm volatile("cli\nmov %%cr0, %%rax\nbtc $16, %%rax\nmov %%rax, %%cr0":::"rax");
|
|
*(char*)(kernel_base + kernel_patch_kmem_alloc_1) = 0x07;
|
|
*(char*)(kernel_base + kernel_patch_kmem_alloc_2) = 0x07;
|
|
asm volatile("mov %%cr0, %%rax\nbts $16, %%rax\nmov %%rax, %%cr0\nsti":::"rax");
|
|
unsigned long long early_printf = kernel_base + kernel_offset_printf;
|
|
unsigned long long kmem_alloc = kernel_base + kernel_offset_kmem_alloc;
|
|
unsigned long long kernel_map = kernel_base + kernel_offset_kernel_map;
|
|
char* new_ps4_kexec = ((char*(*)(unsigned long long, unsigned long long))kmem_alloc)(*(unsigned long long*)kernel_map, ps4kexec_end-ps4kexec);
|
|
for(int i = 0; ps4kexec + i != ps4kexec_end; i++)
|
|
new_ps4_kexec[i] = ps4kexec[i];
|
|
((void(*)(void*, void*))new_ps4_kexec)((void*)early_printf, NULL);
|
|
}
|
|
|
|
asm("kexec_load:\nmov %rcx, %r10\nmov $153, %rax\nsyscall\nret");
|
|
|
|
int kexec_load(char* kernel, unsigned long long kernel_size, char* initrd, unsigned long long initrd_size, char* cmdline, int vram_gb);
|
|
|
|
int read_file(char* path, char** ptr, unsigned long long* sz)
|
|
{
|
|
int fd = open(path, O_RDONLY);
|
|
if(fd < 0)
|
|
return -1;
|
|
*sz = lseek(fd, 0, SEEK_END);
|
|
*ptr = mmap(NULL, *sz, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
|
|
char* p = *ptr;
|
|
unsigned long long l = *sz;
|
|
lseek(fd, 0, SEEK_SET);
|
|
while(l)
|
|
{
|
|
unsigned long long chk = read(fd, p, l);
|
|
if(chk <= 0)
|
|
return -1;
|
|
p += chk;
|
|
l -= chk;
|
|
}
|
|
close(fd);
|
|
return 0;
|
|
}
|
|
|
|
int evf_open(char*);
|
|
void evf_cancel(int, unsigned long long, unsigned long long);
|
|
void evf_close(int);
|
|
|
|
void reboot_thread(void* _)
|
|
{
|
|
nanosleep((const struct timespec*)"\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", NULL);
|
|
int evf = evf_open("SceSysCoreReboot");
|
|
evf_cancel(evf, 0x4000, 0);
|
|
evf_close(evf);
|
|
kill(1, SIGUSR1);
|
|
}
|
|
|
|
void* dlopen(const char*, int);
|
|
void* dlsym(void*, const char*);
|
|
|
|
void alert(const char* msg)
|
|
{
|
|
static int(*sceSysUtilSendSystemNotificationWithText)(int, const char*);
|
|
if(!sceSysUtilSendSystemNotificationWithText)
|
|
{
|
|
void* handle = dlopen("/system/common/lib/libSceSysUtil.sprx", 0);
|
|
sceSysUtilSendSystemNotificationWithText = dlsym(handle, "sceSysUtilSendSystemNotificationWithText");
|
|
}
|
|
sceSysUtilSendSystemNotificationWithText(222, msg);
|
|
}
|
|
|
|
int my_atoi(const char *s)
|
|
{
|
|
int ret = 0;
|
|
int neg = 0;
|
|
while(*s == ' ')
|
|
s++;
|
|
neg = (*s == '-') ? 1 : 0;
|
|
for(; *s; s++)
|
|
{
|
|
char c = *s;
|
|
if('0' <= c && c <= '9')
|
|
{
|
|
ret *= 10;
|
|
ret += c-'0';
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
return (neg) ? (-ret) : (ret);
|
|
}
|
|
|
|
#ifndef VRAM_GB_DEFAULT
|
|
#define VRAM_GB_DEFAULT 1
|
|
#endif
|
|
|
|
#ifndef VRAM_GB_MIN
|
|
#define VRAM_GB_MIN 1
|
|
#endif
|
|
|
|
#ifndef VRAM_GB_MAX
|
|
#define VRAM_GB_MAX 5
|
|
#endif
|
|
|
|
#ifndef HDD_BOOT_PATH
|
|
#define HDD_BOOT_PATH "/user/system/boot/"
|
|
#endif
|
|
|
|
int main()
|
|
{
|
|
struct sigaction sa = {
|
|
.sa_handler = SIG_IGN,
|
|
.sa_flags = 0,
|
|
};
|
|
// note: overriding SIGSTOP and SIGKILL requires a kernel patch
|
|
sigaction(SIGSTOP, &sa, NULL);
|
|
sigaction(SIGTERM, &sa, NULL);
|
|
sigaction(SIGKILL, &sa, NULL);
|
|
char* kernel = NULL;
|
|
unsigned long long kernel_size = 0;
|
|
char* initrd = NULL;
|
|
unsigned long long initrd_size = 0;
|
|
char* cmdline = NULL;
|
|
unsigned long long cmdline_size = 0;
|
|
char* vramstr = NULL;
|
|
unsigned long long vramstr_size = 0;
|
|
int vramgb = 0;
|
|
|
|
#define L(name, where, wheresz, is_fatal)\
|
|
if(read_file("/mnt/usb0/" name, where, wheresz)\
|
|
&& read_file("/mnt/usb1/" name, where, wheresz)\
|
|
&& read_file(HDD_BOOT_PATH name, where, wheresz)\
|
|
&& is_fatal)\
|
|
{\
|
|
alert("Failed to load file: " name ".\nPaths checked:\n/mnt/usb0/" name "\n/mnt/usb1/" name "\n" HDD_BOOT_PATH name);\
|
|
return 1;\
|
|
}
|
|
L("bzImage", &kernel, &kernel_size, 1);
|
|
L("initramfs.cpio.gz", &initrd, &initrd_size, 1);
|
|
|
|
L("bootargs.txt", &cmdline, &cmdline_size, 0);
|
|
|
|
if(cmdline && cmdline_size)
|
|
{
|
|
for(int i = 0; i < cmdline_size; i++)
|
|
if(cmdline[i] == '\n')
|
|
{
|
|
cmdline[i] = '\0';
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
cmdline = "panic=0 clocksource=tsc radeon.dpm=0 console=tty0 console=ttyS0,115200n8 "
|
|
"console=uart8250,mmio32,0xd0340000 video=HDMI-A-1:1920x1080-24@60 "
|
|
"consoleblank=0 net.ifnames=0 drm.debug=0";
|
|
|
|
L("vram.txt", &vramstr, &vramstr_size, 0);
|
|
if(vramstr && vramstr_size)
|
|
{
|
|
vramgb = my_atoi(vramstr);
|
|
if(vramgb < VRAM_GB_MIN || vramgb > VRAM_GB_MAX)
|
|
vramgb = VRAM_GB_DEFAULT;
|
|
}
|
|
else
|
|
vramgb = VRAM_GB_DEFAULT;
|
|
|
|
kexec(kernel_main, (void*)0);
|
|
long x, y;
|
|
struct thr_param thr = {
|
|
.start_func = reboot_thread,
|
|
.arg = NULL,
|
|
.stack_base = mmap(NULL, 16384, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0),
|
|
.stack_size = 16384,
|
|
.tls_base = NULL,
|
|
.tls_size = 0,
|
|
.child_tid = &x,
|
|
.parent_tid = &y,
|
|
.flags = 0,
|
|
.rtp = NULL
|
|
};
|
|
thr_new(&thr, sizeof(thr));
|
|
kexec_load(kernel, kernel_size, initrd, initrd_size, cmdline, vramgb);
|
|
for(;;);
|
|
}
|