Home | History | Annotate | Download | only in Uefi
      1 /*
      2  * Copyright (c) 1982, 1986, 1989, 1993
      3  *  The Regents of the University of California.  All rights reserved.
      4  * (c) UNIX System Laboratories, Inc.
      5  * All or some portions of this file are derived from material licensed
      6  * to the University of California by American Telephone and Telegraph
      7  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
      8  * the permission of UNIX System Laboratories, Inc.
      9  *
     10  * Portions copyright (c) 1999, 2000
     11  * Intel Corporation.
     12  * All rights reserved.
     13  *
     14  * Redistribution and use in source and binary forms, with or without
     15  * modification, are permitted provided that the following conditions
     16  * are met:
     17  *
     18  * 1. Redistributions of source code must retain the above copyright
     19  *    notice, this list of conditions and the following disclaimer.
     20  *
     21  * 2. Redistributions in binary form must reproduce the above copyright
     22  *    notice, this list of conditions and the following disclaimer in the
     23  *    documentation and/or other materials provided with the distribution.
     24  *
     25  * 3. All advertising materials mentioning features or use of this software
     26  *    must display the following acknowledgement:
     27  *
     28  *    This product includes software developed by the University of
     29  *    California, Berkeley, Intel Corporation, and its contributors.
     30  *
     31  * 4. Neither the name of University, Intel Corporation, or their respective
     32  *    contributors may be used to endorse or promote products derived from
     33  *    this software without specific prior written permission.
     34  *
     35  * THIS SOFTWARE IS PROVIDED BY THE REGENTS, INTEL CORPORATION AND
     36  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
     37  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     38  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS,
     39  * INTEL CORPORATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     40  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     42  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     43  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     44  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     45  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     46  *
     47  *  @(#)sys_generic.c 8.5 (Berkeley) 1/21/94
     48  * $Id: select.c,v 1.1.1.1 2003/11/19 01:50:30 kyu3 Exp $
     49  */
     50 #include <Library/UefiBootServicesTableLib.h>
     51 
     52 #include  <LibConfig.h>
     53 
     54 #include <stdlib.h>
     55 #include <unistd.h>
     56 #include <strings.h>
     57 #include <sys/poll.h>
     58 #include <sys/param.h>
     59 #include <sys/time.h>
     60 #ifndef KERNEL
     61 #define KERNEL
     62 #include <errno.h>
     63 #undef KERNEL
     64 #else
     65 #include <errno.h>
     66 #endif
     67 
     68 #ifdef  EFI_NT_EMULATOR
     69 #define _SELECT_DELAY_  10000
     70 #else
     71 #define _SELECT_DELAY_  1000
     72 #endif
     73 
     74 #define MAX_SLEEP_DELAY 0xfffffffe
     75 
     76 /** Sleep for the specified number of Microseconds.
     77 
     78     Implements the usleep(3) function.
     79 
     80     @param[in]    Microseconds    Number of microseconds to sleep.
     81 
     82     @retval   0   Always returns zero.
     83 **/
     84 int
     85 usleep( useconds_t Microseconds )
     86 {
     87   while ( MAX_SLEEP_DELAY < Microseconds ) {
     88     gBS->Stall ( MAX_SLEEP_DELAY );
     89     Microseconds -= MAX_SLEEP_DELAY;
     90   }
     91   gBS->Stall((UINTN)Microseconds );
     92   return (0);
     93 }
     94 
     95 unsigned int
     96 sleep( unsigned int Seconds )
     97 {
     98   return (usleep( (useconds_t)(Seconds * 1000000) ));
     99 }
    100 
    101 static int
    102 selscan(
    103   fd_mask **ibits,
    104   fd_mask **obits,
    105   int nfd,
    106   int *nselected
    107   )
    108 {
    109   int   msk;
    110   int i;
    111   int j;
    112   int fd;
    113   int n;
    114   struct pollfd pfd;
    115   int FdCount;
    116   fd_mask   bits;
    117   /* Note: backend also returns POLLHUP/POLLERR if appropriate. */
    118   static int16_t  flag[3] = { POLLRDNORM, POLLWRNORM, POLLRDBAND };
    119 
    120   for (msk = 0, n = 0; msk < 3; msk++) {
    121     if (ibits[msk] == NULL)
    122       continue;
    123     for (i = 0; i < nfd; i += NFDBITS) {
    124       bits = ibits[ msk ][ i / NFDBITS ];
    125       while (( 0 != (j = ffs(bits))) && ((fd = i + --j) < nfd)) {
    126         bits &= ~(1 << j);
    127 
    128         pfd.fd = fd;
    129         pfd.events = flag[msk];
    130         pfd.revents = 0;
    131         FdCount = poll ( &pfd, 1, 0 );
    132         if ( -1 == FdCount ) {
    133           return errno;
    134         }
    135         if ( 0 != FdCount ) {
    136           obits[msk][(fd)/NFDBITS] |=
    137             (1 << ((fd) % NFDBITS));
    138           n++;
    139           break;
    140         }
    141       }
    142     }
    143   }
    144   *nselected = n;
    145   return (0);
    146 }
    147 
    148 int
    149 select(
    150   int nd,
    151   fd_set  *in,
    152   fd_set *ou,
    153   fd_set *ex,
    154   struct  timeval *tv
    155   )
    156 {
    157   fd_mask *ibits[3], *obits[3], *selbits, *sbp;
    158   int error, forever, nselected;
    159   u_int nbufbytes, ncpbytes, nfdbits;
    160   int64_t timo;
    161 
    162   if (nd < 0)
    163     return (EINVAL);
    164 
    165   /*
    166    * Allocate just enough bits for the non-null fd_sets.  Use the
    167    * preallocated auto buffer if possible.
    168    */
    169   nfdbits = roundup(nd, NFDBITS);
    170   ncpbytes = nfdbits / NBBY;
    171   nbufbytes = 0;
    172   if (in != NULL)
    173     nbufbytes += 2 * ncpbytes;
    174   if (ou != NULL)
    175     nbufbytes += 2 * ncpbytes;
    176   if (ex != NULL)
    177     nbufbytes += 2 * ncpbytes;
    178   selbits = malloc(nbufbytes);
    179 
    180   /*
    181    * Assign pointers into the bit buffers and fetch the input bits.
    182    * Put the output buffers together so that they can be bzeroed
    183    * together.
    184    */
    185   sbp = selbits;
    186 #define getbits(name, x) \
    187   do {                \
    188     if (name == NULL)         \
    189       ibits[x] = NULL;        \
    190     else {              \
    191       ibits[x] = sbp + nbufbytes / 2 / sizeof *sbp; \
    192       obits[x] = sbp;         \
    193       sbp += ncpbytes / sizeof *sbp;      \
    194       bcopy(name, ibits[x], ncpbytes);    \
    195     }             \
    196   } while (0)
    197   getbits(in, 0);
    198   getbits(ou, 1);
    199   getbits(ex, 2);
    200 #undef  getbits
    201   if (nbufbytes != 0)
    202     memset(selbits, 0, nbufbytes / 2);
    203 
    204   if (tv) {
    205     timo = tv->tv_usec + (tv->tv_sec * 1000000);
    206     forever = 0;
    207   } else {
    208     timo = 0;
    209     forever = 1;
    210   }
    211 
    212   /*
    213    *  Poll for I/O events
    214    */
    215   nselected = 0;
    216   do {
    217     /*
    218      *  Scan for pending I/O
    219      */
    220     error = selscan(ibits, obits, nd, &nselected);
    221     if (error || nselected)
    222       break;
    223 
    224     /*
    225      *  Adjust timeout is needed
    226      */
    227     if (timo)  {
    228       /*
    229        *  Give it a rest
    230        */
    231       usleep( _SELECT_DELAY_ );
    232       timo -= _SELECT_DELAY_;
    233     }
    234 
    235   } while (timo > 0 || forever);
    236 
    237   /* select is not restarted after signals... */
    238   if (error == ERESTART)
    239     error = EINTR;
    240   else if (error == EWOULDBLOCK)
    241     error = 0;
    242 
    243 #define putbits(name, x)  if (name) bcopy(obits[x], name, ncpbytes)
    244   if (error == 0) {
    245     putbits(in, 0);
    246     putbits(ou, 1);
    247     putbits(ex, 2);
    248 #undef putbits
    249   } else {
    250     errno = error;
    251     nselected = -1;
    252   }
    253 
    254   free( selbits );
    255   return ( nselected );
    256 }
    257