How to memory map the framebuffer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



Hi everybody,
first of all I apologize if this is not the right place for this
question but I couldn't find
any answer in other places and I think this is a good question about
DRI. I also apologize
for the length of the question!

For a security application I'm developing I need direct access to the
framebuffer on the
graphic device under X on both linux and freebsd.
My goal is to memory map the portion of the graphic device memory
where pixel values
are stored just before they are read by the monitor. I need to achieve
this for a couple of
well known architectures that will not change in time (say an ati and
an nvidia specific card).

This would be the best scenario even if it is not really clear to me
if it is really possible at all.

I've spent days trying to figure out how to do that and I've seen that
DRI2 / DRM is probably
what I should use.

By now I've found 3 possible solutions (sorry if two of these
solutions are not DRI related, but maybe
some of you have an answer!). If you are not interested in anything
but DRI you should jump to point 3.

1. Use of the kernel fbdev (/dev/fb0).
    Issues:
    - 1.a What am I really accessing when reading from /dev/fb0? Is
that really the videocard memory
    or some system memory the kernel allocates and keep updated?
    - 1.b Capturing /dev/fb0 is not working under X unless fbdev is
specified as videodriver for X. And that is
      really really slow!


2. Use of X API and shm extension. This is what screenshot grabber are
usually doing. Basically ask X to get
    the pixmap of the screen root drawable and retrieve it by using a
shared memory.
    Issues:
    - This is working fine actually but it is using X. I would like
something of more low level (that is more reliable
      for the security applications). Also I'm not sure of the
pipeline involved in this process.
      I guess it is something like: X gets the backbuffer reading
directly from the graphic device and copies it to the
      shared memory. Or is it possible that X is accessing some buffer
in system memory that it keeps updated?
     (Note that I'm supposing DRI2 and hardware acceleration are
active and runinng).


3. Use of DRI2 infrastructure and DRM. This would be my favourite
solution since I would have the biggest control
    over what is happening.
    I've made some test and I failed but I feel I'm close to the
solution...but sadly it is not working!
    I would really appreciate if you validated this procedure and/or
if you suggested any possible mistake I've made.

    So first, DRM seems to be the key...and more precisely, drmMap
function seems to be exactly what I need!

    int drmMap(int fd, drmHandle handle, drmSize size, drmAddressPtr address)

    I have fd here (I got it by open("/dev/dri/card0")), I need the
handle and the size. After a long search and try
    this is what I've found that should work for getting this information:

   - I setup a DRI connection using xcb_dri2_connect() and
xcb_dri2_authenticate(). This is working.

   - I call xcb_dri2_get_buffers(...) passing as input drawable the
root window of the screen and XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT
    as the attachment.This is half working. I receive an answer, width
and height are correct but, the count attribute is 0!
    If I call   xcb_dri2_create_drawable() with the same drawable,
then the xcb_dri2_get_buffers call returns a good answer, where
    count is 5! I can't really understand this..why 5?..but then I go
on with buffer[0] and

   - I need to convert the buffer name to an handle to be used for the
drmMap call. So I execute this code I've found googling and
    that makes sense to me:

    struct drm_gem_open open;
    int ret;

    open.name = buffer[0].name;
    open.handle = 0;
    open.size = 0;

    do {
	ret = ioctl (drmFD, DRM_IOCTL_GEM_OPEN, &open);
    } while (ret == -1 && errno == EINTR);

   This code is working with no error and at the end I get open.handle
with a (seems) good value.

  - At the end of this I call drmMap(fd, open.handle, open.size,
pointer); but this is returning a negative value :-(

  So, Is this a correct way of doing things? The key could really be
that xcb_dri2_get_buffers() is returning count == 0 when
  called and I need to call xcb_dri2_create_drawable()...but I think
that this is wrong since X should have created that at the beginning
  of the times! Isn't there any other way of retrieving the name of
the root drawable of X?

  Last question: even If I'll manage to read the buffer memory mapping
it...will that memory be the final step before
  monitor, or there will be some other piece of software moving it
around to some other buffer?

 Sorry for the very long post, but I really thing this could be an
instructive thread for a lot of people!

Thanks!

Daniele


[Index of Archives]     [Linux DRI Development]     [Linux Intel Graphics]     [Linux AMD Graphics]     [Video for Linux]     [Linux Audio Users]     [Yosemite Waterfalls]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux Media]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux