root/drivers/pci/syscall.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. SYSCALL_DEFINE5
  2. SYSCALL_DEFINE5

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * For architectures where we want to allow direct access to the PCI config
   4  * stuff - it would probably be preferable on PCs too, but there people
   5  * just do it by hand with the magic northbridge registers.
   6  */
   7 
   8 #include <linux/errno.h>
   9 #include <linux/pci.h>
  10 #include <linux/security.h>
  11 #include <linux/syscalls.h>
  12 #include <linux/uaccess.h>
  13 #include "pci.h"
  14 
  15 SYSCALL_DEFINE5(pciconfig_read, unsigned long, bus, unsigned long, dfn,
  16                 unsigned long, off, unsigned long, len, void __user *, buf)
  17 {
  18         struct pci_dev *dev;
  19         u8 byte;
  20         u16 word;
  21         u32 dword;
  22         long err;
  23         long cfg_ret;
  24 
  25         if (!capable(CAP_SYS_ADMIN))
  26                 return -EPERM;
  27 
  28         err = -ENODEV;
  29         dev = pci_get_domain_bus_and_slot(0, bus, dfn);
  30         if (!dev)
  31                 goto error;
  32 
  33         switch (len) {
  34         case 1:
  35                 cfg_ret = pci_user_read_config_byte(dev, off, &byte);
  36                 break;
  37         case 2:
  38                 cfg_ret = pci_user_read_config_word(dev, off, &word);
  39                 break;
  40         case 4:
  41                 cfg_ret = pci_user_read_config_dword(dev, off, &dword);
  42                 break;
  43         default:
  44                 err = -EINVAL;
  45                 goto error;
  46         }
  47 
  48         err = -EIO;
  49         if (cfg_ret != PCIBIOS_SUCCESSFUL)
  50                 goto error;
  51 
  52         switch (len) {
  53         case 1:
  54                 err = put_user(byte, (unsigned char __user *)buf);
  55                 break;
  56         case 2:
  57                 err = put_user(word, (unsigned short __user *)buf);
  58                 break;
  59         case 4:
  60                 err = put_user(dword, (unsigned int __user *)buf);
  61                 break;
  62         }
  63         pci_dev_put(dev);
  64         return err;
  65 
  66 error:
  67         /* ??? XFree86 doesn't even check the return value.  They
  68            just look for 0xffffffff in the output, since that's what
  69            they get instead of a machine check on x86.  */
  70         switch (len) {
  71         case 1:
  72                 put_user(-1, (unsigned char __user *)buf);
  73                 break;
  74         case 2:
  75                 put_user(-1, (unsigned short __user *)buf);
  76                 break;
  77         case 4:
  78                 put_user(-1, (unsigned int __user *)buf);
  79                 break;
  80         }
  81         pci_dev_put(dev);
  82         return err;
  83 }
  84 
  85 SYSCALL_DEFINE5(pciconfig_write, unsigned long, bus, unsigned long, dfn,
  86                 unsigned long, off, unsigned long, len, void __user *, buf)
  87 {
  88         struct pci_dev *dev;
  89         u8 byte;
  90         u16 word;
  91         u32 dword;
  92         int err = 0;
  93 
  94         if (!capable(CAP_SYS_ADMIN) ||
  95             security_locked_down(LOCKDOWN_PCI_ACCESS))
  96                 return -EPERM;
  97 
  98         dev = pci_get_domain_bus_and_slot(0, bus, dfn);
  99         if (!dev)
 100                 return -ENODEV;
 101 
 102         switch (len) {
 103         case 1:
 104                 err = get_user(byte, (u8 __user *)buf);
 105                 if (err)
 106                         break;
 107                 err = pci_user_write_config_byte(dev, off, byte);
 108                 if (err != PCIBIOS_SUCCESSFUL)
 109                         err = -EIO;
 110                 break;
 111 
 112         case 2:
 113                 err = get_user(word, (u16 __user *)buf);
 114                 if (err)
 115                         break;
 116                 err = pci_user_write_config_word(dev, off, word);
 117                 if (err != PCIBIOS_SUCCESSFUL)
 118                         err = -EIO;
 119                 break;
 120 
 121         case 4:
 122                 err = get_user(dword, (u32 __user *)buf);
 123                 if (err)
 124                         break;
 125                 err = pci_user_write_config_dword(dev, off, dword);
 126                 if (err != PCIBIOS_SUCCESSFUL)
 127                         err = -EIO;
 128                 break;
 129 
 130         default:
 131                 err = -EINVAL;
 132                 break;
 133         }
 134         pci_dev_put(dev);
 135         return err;
 136 }

/* [<][>][^][v][top][bottom][index][help] */