Galaxy Nexus, camera and PVRSRVExportFDToIONHandle
Denis 'GNUtoo' Carikli
GNUtoo at no-log.org
Mon Dec 3 18:05:07 UTC 2012
Hi,
I've a galaxy Nexus which has a camera that seems to be tied to the OMX
system which itself uses tiler and ion.
I'm trying to make the camera work under Replicant(A 100% free android
distribution (http://replicant.us/) ).
So the free software userspace camera libs do some read/write
operations on the device node of the OMX driver.
At some point write fails(during camera preview) and the following
messages appear in dmesg:
<6>[ 111.117462] PVR_K:(Error): GetHandleStructure: Handle index out
of range (1835561824 >= 0)
[454, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/handle.c]
<6>[ 111.117584] PVR_K:(Error): PVRSRVLookupHandle: Error looking up
handle (149)
[1407, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/handle.c]
<6>[ 111.117706] PVR_K:(Error): PVRSRVExportFDToIONHandle: Failed to
look up MEM_INFO handle
[78, /home/gnutoo/embedded/android/replicant-4.0/kernel/samsung/tuna/drivers/gpu/pvr/ion.c]
which is because:
* the OMX kernel driver (drivers/rpmsg/rpmsg_omx.c at
https://gitorious.org/replicant/kernel_samsung_tuna/blobs/replicant-4.0/drivers/rpmsg/rpmsg_omx.c
) uses PVRSRVExportFDToIONHandle.
* I don't have installed and can't use the proprietary powervr
libraries.
So I've to replace PVRSRVExportFDToIONHandle...
So I tried 2 approaches:
Approach 1)
-----------
in userspace I've done a very simple program that
opens /dev/pvrsrvkm and loops after it(in order to prevent
the .close())
it didn't result in the full initialization but the range changed from
(1835561824 >= 0) to (1835561824 >= 256)
There is a program in android named pvrsrvinit and tracing it gives
somehthing like that:
open("/dev/pvrsrvkm", O_RDWR) = 3
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
ioctl(3, 0xc01c670c, 0xbeff698c) = 0
getpid() = 5094
ioctl(3, 0xc01c6745, 0xbeff69cc) = 0
I must find to what theses ioctl correspond and find their arguments.
I've also found an exploit that might help in understanding how things
works: http://jon.oberheide.org/files/levitator.c
The problem is that I don't understand the pvr driver pass-trough since
it's too much messy.
I also wonder if it can be called source code because the GPLv2 says:
"The source code for a work means the preferred form of the work for
making modifications to it.", and it seems that they stripped the
comments.
Approach 2)
-----------
The approach 2 was to modify the OMX driver in order to make it not use
PVRSRVExportFDToIONHandle. More precisely to replace that line:
handle = PVRSRVExportFDToIONHandle(fd, &pvr_ion_client);
I failed at that too, however it seem easier than understanding the
ioctls of the pass-trough powervr driver by reading it.
So far I've done that:
+struct ion_handle *global_handle;
+struct ion_client *global_pvr_ion_client;
static int rpmsg_omx_open(struct inode *inode, struct file *filp)
{
[...]
+ ion_phys_addr_t phys;
+ size_t size;
+ struct tiler_view_t view;
+ void * memory;
+ int ret;
+ struct omap_ion_tiler_alloc_data sAllocData = {
+ /* TILER will align width to 128-bytes */
+ /* however, SGX must have full page width */
+ .w = 900, //ALIGN(psLINFBInfo->var.xres,
PAGE_SIZE / ( 4 /*psLINFBInfo->var.bits_per
+ .h = 1600, /* psLINFBInfo->var.yres, */
+ .fmt =
TILER_PIXEL_FMT_32BIT, //psLINFBInfo->var.bits_per_pixel == 16 ?
TILER_PIXEL_F
+ .flags = 0,
+ };
[...]
+ global_pvr_ion_client = ion_client_create(omap_ion_device,
+ 1 << ION_HEAP_TYPE_CARVEOUT |1 <<
OMAP_ION_HEAP_TYPE_TILER, "pvr");
+ ret = omap_ion_tiler_alloc(global_pvr_ion_client, &sAllocData);
+ global_handle = sAllocData.handle;
+ if (ret < 0 )
+ printk("[DBG] %s normal alloc failed \n",__func__);
+ else
+ printk("[DBG] %s normal alloc succedded
\n",__func__); //it succeed
+ ion_phys(global_pvr_ion_client, sAllocData.handle, &phys,
&size);
+ tilview_create(&view, phys, 900, 1600);
And then instead of calling PVRSRVExportFDToIONHandle I would do that:
[...]
+fd = buffer;
+file = fget(fd);
+if (file){
+ handle = global_handle;
+ if (handle &&
+ !ion_phys(global_pvr_ion_client,handle, &paddr, &unused)) {
}
[...]
However that fails too:
AT some point file is false(like when the pvr libs are in use) and pa
becomes 0 in pa = (phys_addr_t) tiler_virt2phys(buffer); which makes
the whole thing fail.
So I wonder how to make it work: maybe someone knows enough how the
powervr driver works or how ion is supposed to work and what I am doing
wrong...
Denis.
More information about the Replicant
mailing list