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 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         froml = from >> 5;
  52         lindex = from & 0x1f;
  53         tnum = lindex + num;
  54         numl = (tnum + 0x1f) >> 5;
  55         rindex = tnum & 0x1f;
  56 
  57         if (!suser())
  58                 return -EPERM;
  59         if (froml * 32 + tnum > sizeof(current->tss.io_bitmap) * 8 - 8)
  60                 return -EINVAL;
  61 
  62 #ifdef IODEBUG
  63         printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
  64 #endif
  65 
  66         if (numl) {
  67                 iop = (unsigned long *)current->tss.io_bitmap + froml;
  68                 if (lindex != 0) {
  69                         mask = (~0 << lindex);
  70                         if (--numl == 0 && rindex)
  71                                 mask &= ~(~0 << rindex);
  72                         if (turn_on)
  73                                 *iop++ &= ~mask;
  74                         else
  75                                 *iop++ |= mask;
  76                 }
  77                 if (numl) {
  78                         if (rindex)
  79                                 --numl;
  80                         mask = (turn_on ? 0 : ~0);
  81                         while (numl--)
  82                                 *iop++ = mask;
  83                         if (numl && rindex) {
  84                                 mask = ~(~0 << rindex);
  85                                 if (turn_on)
  86                                         *iop++ &= ~mask;
  87                                 else
  88                                         *iop++ |= mask;
  89                         }
  90                 }
  91         }
  92         return 0;
  93 }
  94 
  95 unsigned int *stack;
  96 
  97 /*
  98  * sys_iopl has to be used when you want to access the IO ports
  99  * beyond the 0x3ff range: to get the full 65536 ports bitmapped
 100  * you'd need 8kB of bitmaps/process, which is a bit excessive.
 101  *
 102  * Here we just change the eflags value on the stack: we allow
 103  * only the super-user to do it. This depends on the stack-layout
 104  * on system-call entry - see also fork() and the signal handling
 105  * code.
 106  */
 107 int sys_iopl(long ebx,long ecx,long edx,
     /* [previous][next][first][last][top][bottom][index][help] */
 108              long esi, long edi, long ebp, long eax, long ds,
 109              long es, long fs, long gs, long orig_eax,
 110              long eip,long cs,long eflags,long esp,long ss)
 111 {
 112         unsigned int level = ebx;
 113 
 114         if (level > 3)
 115                 return -EINVAL;
 116         if (!suser())
 117                 return -EPERM;
 118         *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
 119         return 0;
 120 }

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