how to use the function copyout()

Julian Elischer julian at elischer.org
Mon Jul 25 20:06:39 GMT 2005



Felix-KM wrote:

>>>#define IOCTL_GET_B    _IOWR("F", 127, 0x4)
>>>      
>>>
>>I think the third parameter to _IOWR should directly specify a type,
>>e.g. _IOWR("F", 127, int) or _IOWR("F", 127, struct MyStruct).
>>
>>    
>>
>>>---- driver ----
>>>
>>>struct my_softc {
>>> ...
>>> short unsigned int B;
>>>};
>>>
>>>...
>>>
>>>static int
>>>my_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag,
>>>                                               struct thread *td)
>>>{
>>> struct my_softc *my_sc;
>>> int unit, error;
>>> unit = minor(dev);
>>>      my_sc = (struct my_softc *)devclass_get_softc(my_devclass, unit);
>>> if (my_sc == NULL)
>>>   return (ENXIO);
>>>    switch(cmd)
>>> {
>>>   ...
>>>   case IOCTL_GET_B:
>>>     error = copyout(&my_sc->B, data, sizeof(my_sc->B));
>>>     switch (error)
>>>     {
>>>   case 0:
>>>     printf(" IOCTL_GET_B: %d\n", my_sc->B);
>>>     break;
>>>   case EFAULT:
>>>     printf("EFAULT\n");
>>>     break;
>>>   case EIO:
>>>     printf("EIO\n");
>>>     break;
>>>   case ENOMEM:
>>>     printf("ENOMEM\n");
>>>     break;
>>>       case ENOSPC:
>>>     printf("ENOSPC\n");
>>>     break;
>>>     }
>>>     break;
>>>      default:
>>>     break;
>>> }
>>>    return 0;
>>>}
>>>
>>>---user program ----------------------
>>>
>>>...
>>>
>>>short unsigned int Data[32768];
>>>
>>>int
>>>main(int argc, char *argv[])
>>>{     ...
>>>
>>> if (ioctl(fd0, IOCTL_GET_B, Data) == -1)
>>>   err(1, "IOCTL_GET_B");
>>>
>>> ...
>>>}
>>>
>>>-------
>>>
>>>Here I get EFAULT.
>>>
>>>What have I done wrong? How can I do it correctly?
>>>      
>>>
>>The caddr_t data in your ioctl is already mapped into kernel
>>memory. Look into the source of other device drivers. You'll
>>find a lot of *(int *) data = ...
>>So your copyout() has to fail because it tries to address
>>memory which is not a part of your application's
>>memory.
>>>From errno(2): EFAULT: Bad address...
>>
>>I have no idea if it is possible for ioctls to have mapped more
>>than a few 100 bytes for data exchange.
>>You should use read and uiomove() instead.
>>    
>>
>
>So if I get it right, it's impossible in FreeBSD to gain access to 64KB of user's program memory with ioctl?
>  
>

no you do not get it right.

you should pass in a pointer to your 64k object.
ioccom.h describes the definition of the ioctl name.
this includes:
#define IOCPARM_MASK    0x1fff          /* parameter length, at most 13 
bits */
so the maximum that the system will AUTOMATICALLY COPYIN() is 8k
For larger amounts you can always have the address as teh parameter and 
do the copyin yourself.
in other words the automatically moved data would be only a smal 
structure specifying address and size,
and you would use those parameters to copyin the larger structure.

>My situation is this - I have a device driver for Linux. My task is port it as it is (1:1) into FreeBSD.
>
>In the Linux driver Ioctl is realized with the macroses _put_user _get_user all over it. As I understand in FreeBSD their analogues are functions described in store(9), copy(9) and fetch(9). 
>
>So the problem is that in my user program an array short unsigned int Data[32768] is defined. I need to gain access to the array(to each element of it) from device driver with Ioctl handler.
>
>Is it possible to do? If yes, then how it can be done?
>  
>


>  
>
>>Norbert
>>_______________________________________________
>>freebsd-hackers at freebsd.org mailing list
>>http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
>>To unsubscribe, send any mail to "freebsd-hackers-unsubscribe at freebsd.org"
>>    
>>
>
>
>  
>


More information about the freebsd-hackers mailing list