From 499cc60e728ff7225fd7cac158ff772435c27b62 Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Tue, 6 Aug 2024 22:27:40 +0100 Subject: drv: Attempt to add mapping support Map allocated buffers so we can clear them and then write copied dumps from proprietary driver to them. Currently memory allocations fail with `MAP_FAILED` in mmap. --- src/drv.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++------------- src/pprint.c | 39 +++++++++++++++++++++++++++++++++-- src/wrap.c | 16 +++++++++++---- 3 files changed, 101 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/drv.c b/src/drv.c index e4d74f5..9733ac3 100644 --- a/src/drv.c +++ b/src/drv.c @@ -33,6 +33,11 @@ #define UNUSED(x) (void)x +struct mem_alloc { + PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM dev_mem; + void *data; +}; + struct driver_state { int fd; IMG_HANDLE kernel_services; @@ -44,11 +49,11 @@ struct driver_state { PVRSRV_HEAP_INFO kernel_heap; PVRSRV_HEAP_INFO perctx_3d_heap; PVRSRV_HEAP_INFO ta_data_heap; - PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM ccb_buffer; - PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM kernel_buffer_2; - PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM kernel_buffer_3; - PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM perctx_3d_buffer; - PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM ta_data_buffer; + struct mem_alloc ccb_buffer; + struct mem_alloc kernel_buffer_2; + struct mem_alloc kernel_buffer_3; + struct mem_alloc perctx_3d_buffer; + struct mem_alloc ta_data_buffer; IMG_HANDLE hw_render_ctx; IMG_DEV_VIRTADDR hw_render_ctx_addr; @@ -295,7 +300,8 @@ static void get_dev_mem_heapinfo(struct driver_state *state) { assert(state->perctx_3d_heap.ui32HeapID != 0); } -static PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM allocate_memobj(struct driver_state *state, PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *alloc) { +static struct mem_alloc allocate_memobj(struct driver_state *state, PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *alloc) { + struct mem_alloc mem; PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM out; PVRSRV_BRIDGE_PACKAGE data = { .ui32BridgeID = PVRSRV_BRIDGE_ALLOC_DEVICEMEM, @@ -309,9 +315,41 @@ static PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM allocate_memobj(struct driver_state *sta printf("Allocating from %p %p 0x%x\n", alloc->hDevCookie, alloc->hDevMemHeap, alloc->uSize); check_ioctl(state->fd, DRM_IOCTL_PVR_SRVKM, &data); - check_pvr_error(out.eError); - return out; + + { + PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA in = { + .hMHandle = out.sClientMemInfo.hKernelMemInfo, + }; + PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA out2; + PVRSRV_BRIDGE_PACKAGE data = { + .ui32BridgeID = PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA, + .ui32Size = sizeof(data), + .pvParamIn = &in, + .ui32InBufferSize = sizeof(in), + .pvParamOut = &out2, + .ui32OutBufferSize = sizeof(out2), + .hKernelServices = state->kernel_services + }; + + check_ioctl(state->fd, DRM_IOCTL_PVR_SRVKM, &data); + check_pvr_error(out2.eError); + + PPRINT(stdout, &out2, PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA); + + printf("Attempting map 0x%x, 0x%x\n", out2.uiRealByteSize, out2.uiMMapOffset); + //mem.data = mmap2(NULL, out2.uiRealByteSize, PROT_READ|PROT_WRITE, + // MAP_SHARED, state->fd, out2.uiMMapOffset); + mem.data = syscall(SYS_mmap2, NULL, out2.uiRealByteSize, + PROT_READ | PROT_WRITE, MAP_SHARED, + state->fd, out2.uiRealByteSize); + + assert(mem.data != MAP_FAILED); + memset(mem.data, 0x00, out.sClientMemInfo.uAllocSize); + } + + mem.dev_mem = out; + return mem; } static void allocate_memory(struct driver_state *state) { @@ -370,12 +408,12 @@ static void register_hw_render_ctx(struct driver_state *state) { 0x21, 0x1, 0x0, - state->ccb_buffer.sClientMemInfo.sDevVAddr.uiAddr, // Not all zeros - state->kernel_buffer_2.sClientMemInfo.sDevVAddr.uiAddr, // All zeros + state->ccb_buffer.dev_mem.sClientMemInfo.sDevVAddr.uiAddr, // Needs to be patched + state->kernel_buffer_2.dev_mem.sClientMemInfo.sDevVAddr.uiAddr, // All zeros 0x0, - state->kernel_buffer_3.sClientMemInfo.sDevVAddr.uiAddr, // All zeros - state->perctx_3d_buffer.sClientMemInfo.sDevVAddr.uiAddr, // All zeros - state->ta_data_buffer.sClientMemInfo.sDevVAddr.uiAddr, // All zeros + state->kernel_buffer_3.dev_mem.sClientMemInfo.sDevVAddr.uiAddr, // All zeros + state->perctx_3d_buffer.dev_mem.sClientMemInfo.sDevVAddr.uiAddr, // All zeros + state->ta_data_buffer.dev_mem.sClientMemInfo.sDevVAddr.uiAddr, // All zeros 0x0, 0x0, 0x0, @@ -384,7 +422,7 @@ static void register_hw_render_ctx(struct driver_state *state) { 0x0, 0x0, 0x0, - 0x50f, // This value seems to change but I'm not sure why + 0x0, // This value seems to change when dumping, but overriding to zero doesn't break anything }; PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT in = { .hDevCookie = state->dev_cookie, diff --git a/src/pprint.c b/src/pprint.c index 1a72fb4..8043ddc 100644 --- a/src/pprint.c +++ b/src/pprint.c @@ -371,7 +371,8 @@ static void pprint_PVRSRV_SGX_MISCINFO_FEATURES(FILE *fp, PVRSRV_SGX_MISCINFO_FE } static void pprint_PVRSRV_HEAP_INFO(FILE *fp, PVRSRV_HEAP_INFO *data) { - fprintf(fp, "{\n.ui32HeapID = 0x%x,\n.hDevMemHeap = %p,\n.sDevVAddrBase = 0x%x,\n.ui32HeapByteSize = 0x%x,\n.ui32Attribs = 0x%x,\n.ui32XTileStride = 0x%x\n}", + fprintf(fp, "{\n.ui32HeapID = 0x%x,\n.hDevMemHeap = %p,\n.sDevVAddrBase = 0x%x,\n.ui32HeapByteSize = 0x%x,\n" + ".ui32Attribs = 0x%x,\n.ui32XTileStride = 0x%x\n}", data->ui32HeapID, data->hDevMemHeap, data->sDevVAddrBase.uiAddr, data->ui32HeapByteSize, data->ui32Attribs, data->ui32XTileStride); } @@ -383,7 +384,7 @@ static void pprint_PVRSRV_BRIDGE_OUT_CREATE_DEVMEMCONTEXT(FILE *fp, PVRSRV_BRIDG PPRINT(fp, &data->sHeapInfo[i], PVRSRV_HEAP_INFO); fprintf(fp, ",\n"); } - fprintf(fp, "}"); + fprintf(fp, "}\n"); } static void pprint_mem_alloc_flags(FILE *fp, uint32_t ui32Attribs) { @@ -450,3 +451,37 @@ static void pprint_SGXMKIF_COMMAND(FILE *fp, SGXMKIF_COMMAND *in) { static void pprint_PVRSRV_EVENTOBJECT(FILE *fp, PVRSRV_EVENTOBJECT *in) { fprintf(fp, "{\n.szName = \"%s\",\n.hOSEventKM = %p\n}\n", in->szName, in->hOSEventKM); } + +static void pprint_PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO(FILE *fp, PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO *out) { + fprintf(fp, "{\n.sSGXInternalDevInfo = {\n" + "\t.hHostCtlKernelMemInfoHandle = %p,\n" + "\t.bForcePTOff = %d,\n" + "},\n" + ".eError = %s,\n" + "}\n", + out->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle, + out->sSGXInternalDevInfo.bForcePTOff, + PPRINT(fp, out->eError, PVRSRV_ERROR)); +} + +static void pprint_PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA(FILE *fp, PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *out) { + fprintf(fp, "{\n.eError = %s,\n" + ".uiMMapOffset = 0x%x,\n" + ".uiByteOffset = 0x%x,\n" + ".uiRealByteSize = 0x%x,\n" + ".uiUserVAddr = 0x%x\n" + "}\n", + PPRINT(fp, out->eError, PVRSRV_ERROR), + out->uiMMapOffset, + out->uiByteOffset, + out->uiRealByteSize, + out->uiUserVAddr); +} + +static void pprint_PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA(FILE *fp, PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *out) { + fprintf(fp, "{\n.ui32BridgeFlags = 0x%x,\n" + ".hMHandle = %p,\n" + "}\n", + out->ui32BridgeFlags, + out->hMHandle); +} diff --git a/src/wrap.c b/src/wrap.c index 01ae2a3..7115b53 100644 --- a/src/wrap.c +++ b/src/wrap.c @@ -215,9 +215,10 @@ static void clear_mem(struct mem_entry *mem) { || heap == PVR_HEAP_SYNC_INFO || heap == PVR_HEAP_TA_DATA; IMG_HANDLE handle = mem->mem_info.hKernelMemInfo; - bool is_special_heap = (uintptr_t)handle == 0x14 || - (uintptr_t)handle == 0x15 || - (uintptr_t)handle == 0x10; + bool is_special_heap = (uintptr_t)handle == 0x14 + //|| (uintptr_t)handle == 0x15 + //|| (uintptr_t)handle == 0x10 + ; if(mem->type == MEM_TYPE_NORMAL && (valid_heap || is_special_heap)) { printf("Clearing heap\n"); for (int i = 0; i < 2; i++) @@ -242,6 +243,7 @@ static void clear_mem(struct mem_entry *mem) { static struct mem_entry *add_mmap_pointer(void* data, int prot, size_t length, uintptr_t pgoffset) { int track_arr_size = sizeof(mem_trackings)/sizeof(mem_trackings[0]); + printf("Tracking %p with length 0x%x and prot %d\n", data, length, prot); for(int i = 0; i < track_arr_size; i++) { struct mem_entry *mem = &mem_trackings[i]; @@ -640,6 +642,7 @@ static void pvrsrv_ioctl_post(int fd, PVRSRV_BRIDGE_PACKAGE *bridge_package, int { PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA *in_data = bridge_package->pvParamIn; PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA *out_data = bridge_package->pvParamOut; + PPRINT(stdout, out_data, PVRSRV_BRIDGE_OUT_MHANDLE_TO_MMAP_DATA); add_mmap_data(fd, in_data->hMHandle, out_data); printf("MHANDLE to MMAP data %p\n", in_data->hMHandle); } @@ -714,6 +717,7 @@ static bool pvrsrv_ioctl(int fd, PVRSRV_BRIDGE_PACKAGE *bridge_package) { switch(ioctl_nr) { case _IOC_NR(PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA): /* TODO track memory */ + PPRINT(stdout, bridge_package->pvParamIn, PVRSRV_BRIDGE_IN_MHANDLE_TO_MMAP_DATA); break; case _IOC_NR(PVRSRV_BRIDGE_ALLOC_DEVICEMEM): { @@ -751,6 +755,7 @@ static bool pvrsrv_ioctl(int fd, PVRSRV_BRIDGE_PACKAGE *bridge_package) { PVRSRV_BRIDGE_IN_SGX_REGISTER_HW_RENDER_CONTEXT *data = bridge_package->pvParamIn; printf("HW Render Context %p\n", data); #if 1 + ((IMG_UINT32*)(data->pHWRenderContextCpuVAddr))[17] = 0x0; for (IMG_UINT32 i = 0; i < data->ui32HWRenderContextSize; i += sizeof(IMG_UINT32)) { IMG_UINT32 *t = (IMG_UINT32*)(data->pHWRenderContextCpuVAddr+i); printf("\t0x%x\n", *t); @@ -918,7 +923,9 @@ static bool pvrsrv_ioctl(int fd, PVRSRV_BRIDGE_PACKAGE *bridge_package) { case _IOC_NR(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS): case _IOC_NR(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER): case _IOC_NR(PVRSRV_BRIDGE_ENUM_CLASS): + break; case _IOC_NR(PVRSRV_BRIDGE_SGX_GETINTERNALDEVINFO): + PPRINT(stdout, bridge_package->pvParamOut, PVRSRV_BRIDGE_OUT_GETINTERNALDEVINFO); break; case _IOC_NR(PVRSRV_BRIDGE_CONNECT_SERVICES): PPRINT(stdout, bridge_package->pvParamIn, PVRSRV_BRIDGE_IN_CONNECT_SERVICES); @@ -1093,9 +1100,10 @@ long syscall(long number, ...) { unsigned long flags = va_arg(args, unsigned long); unsigned long fd = va_arg(args, unsigned long); unsigned long pgoffset = va_arg(args, unsigned long); + va_end(args); long ret = orig_syscall(number, addr, length, prot, flags, fd, pgoffset); if (is_pvr(fd)) { - printf("mmap2 called with 0x%lx\n", ret); + printf("mmap2 called with 0x%lx 0x%x 0x%x %x\n", ret, flags, addr, pgoffset); last_mem_entry = add_mmap_pointer((void*)ret, prot, length, pgoffset); clear_mem(last_mem_entry); } -- cgit