mirror of
https://github.com/ps5-linux/ps5-linux-loader.git
synced 2026-07-17 23:40:38 +00:00
remove data_cave offset and use page alloc for sc args
This commit is contained in:
@@ -18,9 +18,12 @@
|
||||
#define hv_stack_size 0x1000ULL
|
||||
|
||||
// This is used as transitional storage from ProsperoOS to Kernel shellcode
|
||||
#define kernel_cave_files 0xFFFF800000000000
|
||||
#define kernel_cave 0xFFFF800000000000
|
||||
#define kernel_cave_arguments kernel_cave
|
||||
#define kernel_cave_files kernel_cave_arguments + PAGE_SIZE
|
||||
#define kernel_cave_linux_info kernel_cave_files
|
||||
#define kernel_cave_bzImage kernel_cave_linux_info + PAGE_SIZE
|
||||
|
||||
// #define kernel_cave_initrd // Allocated dynamically after bzImage
|
||||
|
||||
// Linux boot config
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include "utils.h"
|
||||
#include <stdint.h>
|
||||
|
||||
uint64_t alloc_page(void);
|
||||
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
|
||||
void pte_store(uintptr_t ptep, uint64_t pte);
|
||||
int read_file(const char *path, void *buf, size_t bufsize);
|
||||
|
||||
@@ -12,7 +12,6 @@ typedef struct _offset_list {
|
||||
/* Shellcode Kernel */
|
||||
uint64_t HOOK_ACPI_WAKEUP_MACHDEP;
|
||||
uint64_t KERNEL_CODE_CAVE;
|
||||
uint64_t KERNEL_DATA_CAVE;
|
||||
uint64_t FUN_PRINTF;
|
||||
uint64_t FUN_HV_IOMMU_SET_BUFFERS;
|
||||
uint64_t FUN_HV_IOMM_WAIT_COMPLETION;
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
extern struct linux_info linux_i;
|
||||
|
||||
int prepare_resume(void);
|
||||
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data);
|
||||
uint64_t prepare_sck_args(void);
|
||||
int update_sck_args_ptr(uint64_t shellcode, uint64_t args);
|
||||
void hook_call_near(uint64_t hook, uint64_t dst);
|
||||
void prepare_sck_args(uint64_t dest_data);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -167,4 +167,10 @@ enum kit_type { KIT_RETAIL, KIT_TESTKIT, KIT_DEVKIT };
|
||||
|
||||
enum kit_type get_kit_type(void);
|
||||
|
||||
#define MINI_SYSCORE_PID 1
|
||||
|
||||
uint64_t alloc_page(void);
|
||||
void pte_store(uintptr_t ptep, uint64_t pte);
|
||||
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits);
|
||||
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits);
|
||||
#endif
|
||||
|
||||
@@ -19,59 +19,6 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MINI_SYSCORE_PID 1
|
||||
|
||||
uint64_t alloc_page(void) {
|
||||
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
// Fault it to force physical allocation
|
||||
*(uint8_t *)page = 0;
|
||||
|
||||
return vtophys_user((uintptr_t)page);
|
||||
}
|
||||
|
||||
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
|
||||
uint64_t entry;
|
||||
|
||||
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
|
||||
entry = kread64(pml4e);
|
||||
if (!PAGE_P(entry)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pml4e, entry);
|
||||
}
|
||||
|
||||
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
|
||||
entry = kread64(pdpe);
|
||||
if (!(entry & PG_B_P)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pdpe, entry);
|
||||
}
|
||||
|
||||
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
|
||||
entry = kread64(pde);
|
||||
if (!(entry & PG_B_P)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pde, entry);
|
||||
}
|
||||
|
||||
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
|
||||
entry = pa | PG_B_RW | PG_B_P | bits;
|
||||
pte_store(pte, entry);
|
||||
}
|
||||
|
||||
void pte_store(uintptr_t ptep, uint64_t pte) {
|
||||
static_assert((PAGE_SIZE % 0x1000) == 0,
|
||||
"PAGE_SIZE should be a multiple of 0x1000");
|
||||
|
||||
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
|
||||
kwrite64(ptep + i * 8, pte + i * 0x1000);
|
||||
}
|
||||
}
|
||||
|
||||
const char *file_paths[] = {
|
||||
"/mnt/usb0/", "/mnt/usb1/", "/mnt/usb2/",
|
||||
"/mnt/usb3/", "/mnt/usb0/PS5/Linux/", "/mnt/usb1/PS5/Linux/",
|
||||
@@ -179,9 +126,6 @@ void trim_newline(char *s) {
|
||||
}
|
||||
|
||||
int fetch_linux(struct linux_info *info) {
|
||||
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
|
||||
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
|
||||
|
||||
char bzimage_path[256];
|
||||
char initrd_path[256];
|
||||
|
||||
@@ -269,16 +213,16 @@ int fetch_linux(struct linux_info *info) {
|
||||
|
||||
uint64_t page = alloc_page();
|
||||
kwrite(pa_to_dmap(page), info, sizeof(struct linux_info));
|
||||
install_page(syscore_pml4, kernel_cave_linux_info, page, 0);
|
||||
install_page_syscore(kernel_cave_linux_info, page, 0);
|
||||
|
||||
for (int i = 0; i < bzimage_size; i += PAGE_SIZE) {
|
||||
install_page(syscore_pml4, info->bzimage + i,
|
||||
vtophys_user((uintptr_t)bzimage + i), 0);
|
||||
install_page_syscore(info->bzimage + i,
|
||||
vtophys_user((uintptr_t)bzimage + i), 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < initrd_size; i += PAGE_SIZE) {
|
||||
install_page(syscore_pml4, info->initrd + i,
|
||||
vtophys_user((uintptr_t)initrd + i), 0);
|
||||
install_page_syscore(info->initrd + i, vtophys_user((uintptr_t)initrd + i),
|
||||
0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -7,7 +7,6 @@ offset_list off_0300 = {
|
||||
.DATA_BASE_GVMSPACE = 0x06423F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390E73,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x048B9A0,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E20,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D50,
|
||||
@@ -33,7 +32,6 @@ offset_list off_0310 = {
|
||||
.DATA_BASE_GVMSPACE = 0x06423F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x0390EB3,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x048B9E0,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0x0B33E60,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0x0B33D90,
|
||||
@@ -59,7 +57,6 @@ offset_list off_0320 = {
|
||||
.DATA_BASE_GVMSPACE = 0x06423F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x48BD30,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
|
||||
@@ -85,7 +82,6 @@ offset_list off_0321 = {
|
||||
.DATA_BASE_GVMSPACE = 0x06423F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x391203,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x48BD30,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB34320,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB34250,
|
||||
@@ -112,7 +108,6 @@ offset_list off_0400 = {
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
|
||||
.FUN_PRINTF = 0x4A3240,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB638F0,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63830,
|
||||
.FUN_SMP_RENDEZVOUS = 0xA6C920,
|
||||
@@ -137,7 +132,6 @@ offset_list off_0402 = {
|
||||
.DATA_BASE_GVMSPACE = 0x064C3F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x4A3240,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63950,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63890,
|
||||
@@ -163,7 +157,6 @@ offset_list off_0403 = {
|
||||
.DATA_BASE_GVMSPACE = 0x064C3F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A7613,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x4A3240,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB639F0,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63930,
|
||||
@@ -189,7 +182,6 @@ offset_list off_0450 = {
|
||||
.DATA_BASE_GVMSPACE = 0x064C3F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x03A75E3,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x04A3270,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63BB0,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63AF0,
|
||||
@@ -215,7 +207,6 @@ offset_list off_0451 = {
|
||||
.DATA_BASE_GVMSPACE = 0x64C3F80,
|
||||
.HOOK_ACPI_WAKEUP_MACHDEP = 0x3A75E3,
|
||||
.KERNEL_CODE_CAVE = 0x500,
|
||||
.KERNEL_DATA_CAVE = 0xC01300,
|
||||
.FUN_PRINTF = 0x4A3270,
|
||||
.FUN_HV_IOMMU_SET_BUFFERS = 0xB63FE0,
|
||||
.FUN_HV_IOMM_WAIT_COMPLETION = 0xB63F20,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "prepare_resume.h"
|
||||
#include "../shellcode_kernel/shellcode_kernel.h"
|
||||
#include "../shellcode_kernel/shellcode_kernel_args.h"
|
||||
#include "config.h"
|
||||
#include "iommu.h"
|
||||
#include "offsets.h"
|
||||
#include "utils.h"
|
||||
@@ -14,21 +15,14 @@ int prepare_resume(void) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (env_offset.KERNEL_DATA_CAVE == 0) {
|
||||
printf("Error: missing data cave offset\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint64_t dest_text = ktext + env_offset.KERNEL_CODE_CAVE;
|
||||
uint64_t dest_data = ktext + env_offset.KERNEL_DATA_CAVE;
|
||||
|
||||
kwrite_large(dest_text, shellcode_kernel_bin, shellcode_kernel_bin_len);
|
||||
prepare_sck_args(dest_data);
|
||||
|
||||
if (update_sck_data_ptr(shellcode_kernel_bin, dest_text, dest_data))
|
||||
uint64_t args_va = prepare_sck_args();
|
||||
if (update_sck_args_ptr((uint64_t)shellcode_kernel_bin, args_va))
|
||||
return -1;
|
||||
|
||||
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, dest_text);
|
||||
uint64_t sck_va = ktext + env_offset.KERNEL_CODE_CAVE;
|
||||
kwrite_large(sck_va, shellcode_kernel_bin, shellcode_kernel_bin_len);
|
||||
|
||||
hook_call_near(ktext + env_offset.HOOK_ACPI_WAKEUP_MACHDEP, sck_va);
|
||||
|
||||
kwrite8(ktext + env_offset.KERNEL_DEBUG_PATCH, 0xC3);
|
||||
kwrite8(ktext + env_offset.KERNEL_CFI_CHECK, 0xC3);
|
||||
@@ -36,11 +30,11 @@ int prepare_resume(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) {
|
||||
int update_sck_args_ptr(uint64_t shellcode, uint64_t args) {
|
||||
// Find the address 0x11AA11AA11AA11AA used as marker
|
||||
int offset = -1;
|
||||
for (int i = 0; i < 0x40; i++) {
|
||||
if (*(uint64_t *)((uint64_t)sc + i) == 0x11AA11AA11AA11AA) {
|
||||
for (uint64_t i = 0; i < 0x40; i++) {
|
||||
if (*(uint64_t *)(shellcode + i) == 0x11AA11AA11AA11AA) {
|
||||
offset = i;
|
||||
break;
|
||||
}
|
||||
@@ -49,7 +43,7 @@ int update_sck_data_ptr(void *sc, uint64_t dest_text, uint64_t dest_data) {
|
||||
notify("Could not find offset of args_ptr address - Aborting\n");
|
||||
return -1;
|
||||
}
|
||||
kwrite64(dest_text + offset, dest_data);
|
||||
*(uint64_t *)(shellcode + offset) = args;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -62,7 +56,7 @@ void hook_call_near(uint64_t hook, uint64_t dst) {
|
||||
DEBUG_PRINT("Instruction patched\n");
|
||||
}
|
||||
|
||||
void prepare_sck_args(uint64_t dest_data) {
|
||||
uint64_t prepare_sck_args(void) {
|
||||
shellcode_kernel_args args;
|
||||
args.fw_version = fw;
|
||||
args.ktext = ktext;
|
||||
@@ -94,5 +88,9 @@ void prepare_sck_args(uint64_t dest_data) {
|
||||
|
||||
args.linux_info_va = linux_i.linux_info;
|
||||
|
||||
kernel_copyin(&args, dest_data, sizeof(args));
|
||||
uint64_t args_cave = alloc_page();
|
||||
kernel_copyin(&args, pa_to_dmap(args_cave), sizeof(args));
|
||||
install_page_syscore(kernel_cave_arguments, args_cave, 0);
|
||||
|
||||
return kernel_cave_arguments;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <ps5/kernel.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -284,3 +285,60 @@ enum kit_type get_kit_type(void) {
|
||||
notify("Retail console detected\n");
|
||||
return KIT_RETAIL;
|
||||
}
|
||||
|
||||
uint64_t alloc_page(void) {
|
||||
void *page = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||
|
||||
// Fault it to force physical allocation
|
||||
*(uint8_t *)page = 0;
|
||||
|
||||
return vtophys_user((uintptr_t)page);
|
||||
}
|
||||
|
||||
void install_page(uintptr_t pml4, vm_offset_t va, vm_paddr_t pa, int bits) {
|
||||
uint64_t entry;
|
||||
|
||||
uintptr_t pml4e = pml4 + pmap_pml4e_index(va) * 8;
|
||||
entry = kread64(pml4e);
|
||||
if (!PAGE_P(entry)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pml4e, entry);
|
||||
}
|
||||
|
||||
uintptr_t pdpe = pa_to_dmap(PAGE_PA(entry)) + pmap_pdpe_index(va) * 8;
|
||||
entry = kread64(pdpe);
|
||||
if (!(entry & PG_B_P)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pdpe, entry);
|
||||
}
|
||||
|
||||
uintptr_t pde = pa_to_dmap(PAGE_PA(entry)) + pmap_pde_index(va) * 8;
|
||||
entry = kread64(pde);
|
||||
if (!(entry & PG_B_P)) {
|
||||
uint64_t page = alloc_page();
|
||||
entry = page | PG_B_RW | PG_B_P | bits;
|
||||
kwrite64(pde, entry);
|
||||
}
|
||||
|
||||
uintptr_t pte = pa_to_dmap(PAGE_PA(entry)) + pmap_pte_index(va) * 8;
|
||||
entry = pa | PG_B_RW | PG_B_P | bits;
|
||||
pte_store(pte, entry);
|
||||
}
|
||||
|
||||
void pte_store(uintptr_t ptep, uint64_t pte) {
|
||||
static_assert((PAGE_SIZE % 0x1000) == 0,
|
||||
"PAGE_SIZE should be a multiple of 0x1000");
|
||||
|
||||
for (uint64_t i = 0; i < (PAGE_SIZE / 0x1000); i++) {
|
||||
kwrite64(ptep + i * 8, pte + i * 0x1000);
|
||||
}
|
||||
}
|
||||
|
||||
void install_page_syscore(vm_offset_t va, vm_paddr_t pa, int bits) {
|
||||
uintptr_t syscore_pmap = getpmap(kernel_get_proc(MINI_SYSCORE_PID));
|
||||
uintptr_t syscore_pml4 = kread64(syscore_pmap + 0x20);
|
||||
install_page(syscore_pml4, va, pa, bits);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user