#include #include #include #include "types.h" #include "netrpc.h" #include "lv1.h" #include "spu.h" #include "mm.h" #include "util.h" #define PS3HOST "192.168.1.2" u8 *_read_file(const char *name, u32 *size) { u8 *buf; u32 len; FILE *fp; if((fp = fopen(name, "rb")) == NULL) { printf("could not open %s\n", name); return NULL; } //Read into buffer. fseek(fp, 0, SEEK_END); len = ftell(fp); fseek(fp, 0, SEEK_SET); buf = (u8 *)malloc(sizeof(u8) * len); fread(buf, sizeof(u8), len, fp); fclose(fp); //Set buffer size. if(size != NULL) *size = len; return buf; } u64 _vas_get_id(netrpc_ctxt_t *ctxt) { u64 id; netrpc_hvcall(ctxt, _N_lv1_get_logical_ppe_id, NULL, 0, &id, 1); netrpc_hvcall(ctxt, _N_lv1_get_virtual_address_space_id_of_ppe, &id, 1, &id, 1); return id; } s64 _get_spe_intr_status(netrpc_ctxt_t *ctxt, u64 spe_id, u64 cls, u64 *stat) { u64 args[] = {spe_id, cls}; return netrpc_hvcall(ctxt, _N_lv1_get_spe_interrupt_status, args, 2, stat, 1); } s64 _clr_spe_intr_status(netrpc_ctxt_t *ctxt, u64 spe_id, u64 cls, u64 stat) { u64 args[] = {spe_id, cls, stat, 0}; return netrpc_hvcall(ctxt, _N_lv1_clear_spe_interrupt_status, args, 4, NULL, 0); } #define LDR_BASE 0x100000 #define LDR_SIZE 0x2300000 #define METLDR_SIZE 0x100000 #define ISOLDR_SIZE 0x100000 #define SPU_SHADOW_SIZE 0x1000 #define SPU_PROBLEM_SIZE 0x20000 #define SPU_PRIV2_SIZE 0x20000 #define SPU_LS_SIZE 0x40000 //static volatile u64 ldr_lpar_addr = 0x700020000000ULL + 0xE900000ULL - LDR_SIZE; static u64 esid = 0x8000000018000000; static u64 vsid = 0x0000000000001400; int main(int argc, char **argv) { netrpc_ctxt_t ctxt; s64 res; //Ohai. printf("connecting..."); if(netrpc_connect(&ctxt, inet_addr(PS3HOST), NETRPC_PORT) < 0) { printf("error\n"); return 1; } printf("ok\n"); printf("ping..."); if(netrpc_ping(&ctxt) < 0) { printf("error\n"); return 1; } printf("ok\n"); //Get vas id. u64 vas_id = _vas_get_id(&ctxt); //File adresses. u64 metldr_addr, isoldr_addr; metldr_addr = LDR_BASE; isoldr_addr = metldr_addr + METLDR_SIZE; //Map region. //res = mm_map_lpar_memory_region(&ctxt, vas_id, MM_EA2VA(metldr_addr), LDR_BASE /*ldr_lpar_addr*/, LDR_SIZE, 0xC, 0, 0); //printf("map_lpar_memory_region : %lld\n", res); netrpc_addmmio(&ctxt, LDR_BASE, LDR_SIZE); printf("copy files out..."); //Read files. u32 metldr_size; u8 *metldr = _read_file("./data/metldr", &metldr_size); u32 isoldr_size; u8 *isoldr = _read_file("./data/isoldr", &isoldr_size); //u8 *isoldr = _read_file("./data/isoldr_patched", &isoldr_size); //Copy files out. netrpc_memcpy_out(&ctxt, metldr_addr, metldr, metldr_size); netrpc_memcpy_out(&ctxt, isoldr_addr, isoldr, isoldr_size); //Cleanup. free(metldr); free(isoldr); printf("done\n"); printf("construct spe..."); //Construct SPE. u64 cspe_args[] = {0xc, 0xc, 0xc, 0xc, 0xc, vas_id, 0}; u64 cspe_res[] = {0, 0, 0, 0, 0, 0}; netrpc_hvcall(&ctxt, _N_lv1_construct_logical_spe, cspe_args, 7, cspe_res, 6); //SPE info. u64 priv2_addr, problem_addr, ls_addr, shadow_addr, spe_id; priv2_addr = cspe_res[0]; problem_addr = cspe_res[1]; ls_addr = cspe_res[2]; shadow_addr = cspe_res[4]; spe_id = cspe_res[5]; netrpc_addmmio(&ctxt, priv2_addr, SPU_PRIV2_SIZE); netrpc_addmmio(&ctxt, problem_addr, SPU_PROBLEM_SIZE); netrpc_addmmio(&ctxt, shadow_addr, SPU_SHADOW_SIZE); netrpc_addmmio(&ctxt, ls_addr, SPU_LS_SIZE); printf("done\n priv2 @ 0x%016llx\n problem @ 0x%016llx\n ls @ 0x%016llx\n shadow @ 0x%016llx\n id : 0x%016llx\n", priv2_addr, problem_addr, ls_addr, shadow_addr, spe_id); printf("setup spe..."); //Setup SPE. u64 setup_spe_args[] = {spe_id, 0, 0}; setup_spe_args[1] = 6; netrpc_hvcall(&ctxt, _N_lv1_enable_logical_spe, setup_spe_args, 2, NULL, 0); setup_spe_args[1] = 0; setup_spe_args[2] = 0x7; netrpc_hvcall(&ctxt, _N_lv1_set_spe_interrupt_mask, setup_spe_args, 3, NULL, 0); setup_spe_args[1] = 1; setup_spe_args[2] = 0xf; netrpc_hvcall(&ctxt, _N_lv1_set_spe_interrupt_mask, setup_spe_args, 3, NULL, 0); setup_spe_args[1] = 2; setup_spe_args[2] = 0xf; netrpc_hvcall(&ctxt, _N_lv1_set_spe_interrupt_mask, setup_spe_args, 3, NULL, 0); printf("done\n"); u64 set_reg_args[] = {spe_id, _OFFSET_MFC_SR1, 0x10}; res = netrpc_hvcall(&ctxt, _N_lv1_set_spe_privilege_state_area_1_register, set_reg_args, 3, NULL, 0); printf("set_spe_privilege_state_area_1_register : %lld\n", res); printf("start spe in isolation mode..."); spu_slb_invalidate_all(&ctxt, priv2_addr); spu_slb_set_entry(&ctxt, priv2_addr, 0, esid, vsid); write_u64(&ctxt, SPU_RADDR(priv2_addr, _OFFSET_SPU_Cfg), 0); netrpc_eieio(&ctxt); spu_in_mbox_write_64(&ctxt, problem_addr, isoldr_addr); spu_sig_notify_1_2_write_64(&ctxt, problem_addr, metldr_addr); spu_isolation_req_enable(&ctxt, priv2_addr); spu_isolation_req(&ctxt, problem_addr); printf("done\n"); FILE *fp = fopen("ls.bin", "wb"); u32 spu_status, size = 0; u64 intr_status; while(1) { res = _get_spe_intr_status(&ctxt, spe_id, 0, &intr_status); if(intr_status) { printf("intr_status (0) : %016llx\n", intr_status); printf("clear_intr_status : %lld\n", _clr_spe_intr_status(&ctxt, spe_id, 0, intr_status)); } res = _get_spe_intr_status(&ctxt, spe_id, 1, &intr_status); if(intr_status) { printf("intr_status (1) : %016llx\n", intr_status); printf("clear_intr_status : %lld\n", _clr_spe_intr_status(&ctxt, spe_id, 1, intr_status)); } res = _get_spe_intr_status(&ctxt, spe_id, 2, &intr_status); if(intr_status & 0x1) { printf("mailbox interrupt\n"); printf("intr_status (2) : %016llx\n", intr_status); printf("clear_intr_status : %lld\n", _clr_spe_intr_status(&ctxt, spe_id, 2, intr_status)); } /* while(size <= 0x40000) { netrpc_eieio(&ctxt); //Wait for mbox value to be written. while(spu_mbox_stat_out_mbox_count(&ctxt, problem_addr) == 0); //Read mbox value. u32 mbox_value; read_u32(&ctxt, SPU_RADDR(problem_addr, _OFFSET_SPU_Out_Mbox), &mbox_value); netrpc_eieio(&ctxt); //Write to file. fwrite(&mbox_value, sizeof(u32), 1, fp); size += 4; printf("\rdumped 0x%08x of 0x40000", size); usleep(10); } */ read_u32(&ctxt, SPU_RADDR(problem_addr, _OFFSET_SPU_Status), &spu_status); if((spu_status & 0x1) == 0) break; usleep(1000); } fclose(fp); printf("\ndone\n"); printf("spu_status: 0x%08x\n", spu_status); //Bye. netrpc_close(&ctxt); return 0; }