root/kernel/ioport.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ios
  2. dump_io_bitmap
  3. sys_ioperm
  4. sys_iopl

   1 /*
   2  *      linux/kernel/ioport.c
   3  *
   4  * This contains the io-permission bitmap code - written by obz, with changes
   5  * by Linus.
   6  */
   7 
   8 #include <linux/sched.h>
   9 #include <linux/kernel.h>
  10 #include <linux/errno.h>
  11 #include <linux/types.h>
  12 
  13 #define _IODEBUG
  14 
  15 #ifdef IODEBUG
  16 static char * ios(unsigned long l)
     /* [previous][next][first][last][top][bottom][index][help] */
  17 {
  18         static char str[33] = { '\0' };
  19         int i;
  20         unsigned long mask;
  21 
  22         for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1)
  23                 str[i] = (l & mask) ? '1' : '0';
  24         return str;
  25 }
  26 
  27 static void dump_io_bitmap(void)
     /* [previous][next][first][last][top][bottom][index][help] */
  28 {
  29         int i, j;
  30         int numl = sizeof(current->tss.io_bitmap) >> 2;
  31 
  32         for (i = j = 0; j < numl; ++i)
  33         {
  34                 printk("%4d [%3x]: ", 64*i, 64*i);
  35                 printk("%s ", ios(current->tss.io_bitmap[j++]));
  36                 if (j < numl)
  37                         printk("%s", ios(current->tss.io_bitmap[j++]));
  38                 printk("\n");
  39         }
  40 }
  41 #endif
  42 
  43 /*
  44  * this changes the io permissions bitmap in the current task.
  45  */
  46 extern "C" int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
     /* [previous][next][first][last][top][bottom][index][help] */
  47 {
  48         unsigned long froml, lindex, tnum, numl, rindex, mask;
  49         unsigned long *iop;
  50 
  51         if (from + num <= from)
  52                 return -EINVAL;
  53         if (from + num > IO_BITMAP_SIZE*32)
  54                 return -EINVAL;
  55         if (!suser())
  56                 return -EPERM;
  57         froml = from >> 5;
  58         lindex = from & 0x1f;
  59         tnum = lindex + num;
  60         numl = (tnum + 0x1f) >> 5;
  61         rindex = tnum & 0x1f;
  62 
  63 #ifdef IODEBUG
  64         printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
  65 #endif
  66 
  67         if (numl) {
  68                 iop = (unsigned long *)current->tss.io_bitmap + froml;
  69                 if (lindex != 0) {
  70                         mask = (~0 << lindex);
  71                         if (--numl == 0 && rindex)
  72                                 mask &= ~(~0 << rindex);
  73                         if (turn_on)
  74                                 *iop++ &= ~mask;
  75                         else
  76                                 *iop++ |= mask;
  77                 }
  78                 if (numl) {
  79                         if (rindex)
  80                                 --numl;
  81                         mask = (turn_on ? 0 : ~0);
  82                         while (numl--)
  83                                 *iop++ = mask;
  84                         if (numl && rindex) {
  85                                 mask = ~(~0 << rindex);
  86                                 if (turn_on)
  87                                         *iop++ &= ~mask;
  88                                 else
  89                                         *iop++ |= mask;
  90                         }
  91                 }
  92         }
  93         return 0;
  94 }
  95 
  96 unsigned int *stack;
  97 
  98 /*
  99  * sys_iopl has to be used when you want to access the IO ports
 100  * beyond the 0x3ff range: to get the full 65536 ports bitmapped
 101  * you'd need 8kB of bitmaps/process, which is a bit excessive.
 102  *
 103  * Here we just change the eflags value on the stack: we allow
 104  * only the super-user to do it. This depends on the stack-layout
 105  * on system-call entry - see also fork() and the signal handling
 106  * code.
 107  */
 108 extern "C" int sys_iopl(long ebx,long ecx,long edx,
     /* [previous][next][first][last][top][bottom][index][help] */
 109              long esi, long edi, long ebp, long eax, long ds,
 110              long es, long fs, long gs, long orig_eax,
 111              long eip,long cs,long eflags,long esp,long ss)
 112 {
 113         unsigned int level = ebx;
 114 
 115         if (level > 3)
 116                 return -EINVAL;
 117         if (!suser())
 118                 return -EPERM;
 119         *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
 120         return 0;
 121 }

/* [previous][next][first][last][top][bottom][index][help] */