Home | History | Annotate | Download | only in TcpDxe
      1 /** @file
      2   Interface function of the Socket.
      3 
      4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "SockImpl.h"
     17 
     18 /**
     19   Check whether the Event is in the List.
     20 
     21   @param[in]  List             Pointer to the token list to be searched.
     22   @param[in]  Event            The event to be checked.
     23 
     24   @retval  TRUE                The specific Event exists in the List.
     25   @retval  FALSE               The specific Event is not in the List.
     26 
     27 **/
     28 BOOLEAN
     29 SockTokenExistedInList (
     30   IN LIST_ENTRY     *List,
     31   IN EFI_EVENT      Event
     32   )
     33 {
     34   LIST_ENTRY      *ListEntry;
     35   SOCK_TOKEN      *SockToken;
     36 
     37   NET_LIST_FOR_EACH (ListEntry, List) {
     38     SockToken = NET_LIST_USER_STRUCT (
     39                   ListEntry,
     40                   SOCK_TOKEN,
     41                   TokenList
     42                   );
     43 
     44     if (Event == SockToken->Token->Event) {
     45       return TRUE;
     46     }
     47   }
     48 
     49   return FALSE;
     50 }
     51 
     52 /**
     53   Call SockTokenExistedInList() to check whether the Event is
     54   in the related socket's lists.
     55 
     56   @param[in]  Sock             Pointer to the instance's socket.
     57   @param[in]  Event            The event to be checked.
     58 
     59   @retval  TRUE                The Event exists in related socket's lists.
     60   @retval  FALSE               The Event is not in related socket's lists.
     61 
     62 **/
     63 BOOLEAN
     64 SockTokenExisted (
     65   IN SOCKET    *Sock,
     66   IN EFI_EVENT Event
     67   )
     68 {
     69 
     70   if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||
     71       SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||
     72       SockTokenExistedInList (&Sock->RcvTokenList, Event) ||
     73       SockTokenExistedInList (&Sock->ListenTokenList, Event)
     74         ) {
     75 
     76     return TRUE;
     77   }
     78 
     79   if ((Sock->ConnectionToken != NULL) && (Sock->ConnectionToken->Event == Event)) {
     80 
     81     return TRUE;
     82   }
     83 
     84   if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {
     85     return TRUE;
     86   }
     87 
     88   return FALSE;
     89 }
     90 
     91 /**
     92   Buffer a token into the specific list of the socket Sock.
     93 
     94   @param[in]  Sock             Pointer to the instance's socket.
     95   @param[in]  List             Pointer to the list to store the token.
     96   @param[in]  Token            Pointer to the token to be buffered.
     97   @param[in]  DataLen          The data length of the buffer contained in Token.
     98 
     99   @return Pointer to the token that wraps Token. If NULL, an error condition occurred.
    100 
    101 **/
    102 SOCK_TOKEN *
    103 SockBufferToken (
    104   IN SOCKET         *Sock,
    105   IN LIST_ENTRY     *List,
    106   IN VOID           *Token,
    107   IN UINT32         DataLen
    108   )
    109 {
    110   SOCK_TOKEN  *SockToken;
    111 
    112   SockToken = AllocateZeroPool (sizeof (SOCK_TOKEN));
    113   if (NULL == SockToken) {
    114 
    115     DEBUG (
    116       (EFI_D_ERROR,
    117       "SockBufferIOToken: No Memory to allocate SockToken\n")
    118       );
    119 
    120     return NULL;
    121   }
    122 
    123   SockToken->Sock           = Sock;
    124   SockToken->Token          = (SOCK_COMPLETION_TOKEN *) Token;
    125   SockToken->RemainDataLen  = DataLen;
    126   InsertTailList (List, &SockToken->TokenList);
    127 
    128   return SockToken;
    129 }
    130 
    131 /**
    132   Destroy the socket Sock and its associated protocol control block.
    133 
    134   @param[in, out]  Sock                 The socket to be destroyed.
    135 
    136   @retval EFI_SUCCESS          The socket Sock was destroyed successfully.
    137   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    138 
    139 **/
    140 EFI_STATUS
    141 SockDestroyChild (
    142   IN OUT SOCKET *Sock
    143   )
    144 {
    145   EFI_STATUS  Status;
    146 
    147   ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));
    148 
    149   if (Sock->InDestroy) {
    150     return EFI_SUCCESS;
    151   }
    152 
    153   Sock->InDestroy = TRUE;
    154 
    155   Status            = EfiAcquireLockOrFail (&(Sock->Lock));
    156   if (EFI_ERROR (Status)) {
    157 
    158     DEBUG (
    159       (EFI_D_ERROR,
    160       "SockDestroyChild: Get the lock to access socket failed with %r\n",
    161       Status)
    162       );
    163 
    164     return EFI_ACCESS_DENIED;
    165   }
    166 
    167   //
    168   // force protocol layer to detach the PCB
    169   //
    170   Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);
    171 
    172   if (EFI_ERROR (Status)) {
    173 
    174     DEBUG (
    175       (EFI_D_ERROR,
    176       "SockDestroyChild: Protocol detach socket failed with %r\n",
    177       Status)
    178       );
    179 
    180     Sock->InDestroy = FALSE;
    181   } else if (SOCK_IS_CONFIGURED (Sock)) {
    182 
    183     SockConnFlush (Sock);
    184     SockSetState (Sock, SO_CLOSED);
    185 
    186     Sock->ConfigureState = SO_UNCONFIGURED;
    187   }
    188 
    189   EfiReleaseLock (&(Sock->Lock));
    190 
    191   if (EFI_ERROR (Status)) {
    192     return Status;
    193   }
    194 
    195   SockDestroy (Sock);
    196   return EFI_SUCCESS;
    197 }
    198 
    199 /**
    200   Create a socket and its associated protocol control block
    201   with the intial data SockInitData and protocol specific
    202   data ProtoData.
    203 
    204   @param[in]  SockInitData         Inital data to setting the socket.
    205 
    206   @return Pointer to the newly created socket. If NULL, an error condition occured.
    207 
    208 **/
    209 SOCKET *
    210 SockCreateChild (
    211   IN SOCK_INIT_DATA *SockInitData
    212   )
    213 {
    214   SOCKET      *Sock;
    215   EFI_STATUS  Status;
    216 
    217   //
    218   // create a new socket
    219   //
    220   Sock = SockCreate (SockInitData);
    221   if (NULL == Sock) {
    222 
    223     DEBUG (
    224       (EFI_D_ERROR,
    225       "SockCreateChild: No resource to create a new socket\n")
    226       );
    227 
    228     return NULL;
    229   }
    230 
    231   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    232   if (EFI_ERROR (Status)) {
    233 
    234     DEBUG (
    235       (EFI_D_ERROR,
    236       "SockCreateChild: Get the lock to access socket failed with %r\n",
    237       Status)
    238       );
    239 
    240     SockDestroy (Sock);
    241     return NULL;
    242   }
    243   //
    244   // inform the protocol layer to attach the socket
    245   // with a new protocol control block
    246   //
    247   Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);
    248   EfiReleaseLock (&(Sock->Lock));
    249   if (EFI_ERROR (Status)) {
    250 
    251     DEBUG (
    252       (EFI_D_ERROR,
    253       "SockCreateChild: Protocol failed to attach a socket with %r\n",
    254       Status)
    255       );
    256 
    257     SockDestroy (Sock);
    258     Sock = NULL;
    259   }
    260 
    261   return Sock;
    262 }
    263 
    264 /**
    265   Configure the specific socket Sock using configuration data ConfigData.
    266 
    267   @param[in]  Sock             Pointer to the socket to be configured.
    268   @param[in]  ConfigData       Pointer to the configuration data.
    269 
    270   @retval EFI_SUCCESS          The socket configured successfully.
    271   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    272                                socket is already configured.
    273 
    274 **/
    275 EFI_STATUS
    276 SockConfigure (
    277   IN SOCKET *Sock,
    278   IN VOID   *ConfigData
    279   )
    280 {
    281   EFI_STATUS  Status;
    282 
    283   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    284   if (EFI_ERROR (Status)) {
    285 
    286     DEBUG (
    287       (EFI_D_ERROR,
    288       "SockConfigure: Get the access for socket failed with %r",
    289       Status)
    290       );
    291 
    292     return EFI_ACCESS_DENIED;
    293   }
    294 
    295   if (SOCK_IS_CONFIGURED (Sock)) {
    296     Status = EFI_ACCESS_DENIED;
    297     goto OnExit;
    298   }
    299 
    300   ASSERT (Sock->State == SO_CLOSED);
    301 
    302   Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);
    303 
    304 OnExit:
    305   EfiReleaseLock (&(Sock->Lock));
    306 
    307   return Status;
    308 }
    309 
    310 /**
    311   Initiate a connection establishment process.
    312 
    313   @param[in]  Sock             Pointer to the socket to initiate the initate the
    314                                connection.
    315   @param[in]  Token            Pointer to the token used for the connection
    316                                operation.
    317 
    318   @retval EFI_SUCCESS          The connection initialized successfully.
    319   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    320                                socket is closed, or the socket is not configured to
    321                                be an active one, or the token is already in one of
    322                                this socket's lists.
    323   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    324                                finished.
    325   @retval EFI_NOT_STARTED      The socket is not configured.
    326 
    327 **/
    328 EFI_STATUS
    329 SockConnect (
    330   IN SOCKET *Sock,
    331   IN VOID   *Token
    332   )
    333 {
    334   EFI_STATUS  Status;
    335   EFI_EVENT   Event;
    336 
    337   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    338   if (EFI_ERROR (Status)) {
    339 
    340     DEBUG (
    341       (EFI_D_ERROR,
    342       "SockConnect: Get the access for socket failed with %r",
    343       Status)
    344       );
    345 
    346     return EFI_ACCESS_DENIED;
    347   }
    348 
    349   if (SOCK_IS_NO_MAPPING (Sock)) {
    350     Status = EFI_NO_MAPPING;
    351     goto OnExit;
    352   }
    353 
    354   if (SOCK_IS_UNCONFIGURED (Sock)) {
    355 
    356     Status = EFI_NOT_STARTED;
    357     goto OnExit;
    358   }
    359 
    360   if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {
    361 
    362     Status = EFI_ACCESS_DENIED;
    363     goto OnExit;
    364   }
    365 
    366   Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
    367 
    368   if (SockTokenExisted (Sock, Event)) {
    369 
    370     Status = EFI_ACCESS_DENIED;
    371     goto OnExit;
    372   }
    373 
    374   Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;
    375   SockSetState (Sock, SO_CONNECTING);
    376   Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);
    377 
    378 OnExit:
    379   EfiReleaseLock (&(Sock->Lock));
    380   return Status;
    381 }
    382 
    383 /**
    384   Issue a listen token to get an existed connected network instance
    385   or wait for a connection if there is none.
    386 
    387   @param[in]  Sock             Pointer to the socket to accept connections.
    388   @param[in]  Token            The token to accept a connection.
    389 
    390   @retval EFI_SUCCESS          Either a connection is accpeted or the Token is
    391                                buffered for further acception.
    392   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    393                                socket is closed, or the socket is not configured to
    394                                be a passive one, or the token is already in one of
    395                                this socket's lists.
    396   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    397                                finished.
    398   @retval EFI_NOT_STARTED      The socket is not configured.
    399   @retval EFI_OUT_OF_RESOURCE  Failed to buffer the Token due to memory limits.
    400 
    401 **/
    402 EFI_STATUS
    403 SockAccept (
    404   IN SOCKET *Sock,
    405   IN VOID   *Token
    406   )
    407 {
    408   EFI_TCP4_LISTEN_TOKEN *ListenToken;
    409   LIST_ENTRY            *ListEntry;
    410   EFI_STATUS            Status;
    411   SOCKET                *Socket;
    412   EFI_EVENT             Event;
    413 
    414   ASSERT (SockStream == Sock->Type);
    415 
    416   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    417   if (EFI_ERROR (Status)) {
    418 
    419     DEBUG (
    420       (EFI_D_ERROR,
    421       "SockAccept: Get the access for socket failed with %r",
    422       Status)
    423       );
    424 
    425     return EFI_ACCESS_DENIED;
    426   }
    427 
    428   if (SOCK_IS_NO_MAPPING (Sock)) {
    429     Status = EFI_NO_MAPPING;
    430     goto Exit;
    431   }
    432 
    433   if (SOCK_IS_UNCONFIGURED (Sock)) {
    434 
    435     Status = EFI_NOT_STARTED;
    436     goto Exit;
    437   }
    438 
    439   if (!SOCK_IS_LISTENING (Sock)) {
    440 
    441     Status = EFI_ACCESS_DENIED;
    442     goto Exit;
    443   }
    444 
    445   Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
    446 
    447   if (SockTokenExisted (Sock, Event)) {
    448 
    449     Status = EFI_ACCESS_DENIED;
    450     goto Exit;
    451   }
    452 
    453   ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;
    454 
    455   //
    456   // Check if a connection has already in this Sock->ConnectionList
    457   //
    458   NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {
    459 
    460     Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);
    461 
    462     if (SOCK_IS_CONNECTED (Socket)) {
    463       ListenToken->NewChildHandle = Socket->SockHandle;
    464       SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);
    465 
    466       RemoveEntryList (ListEntry);
    467 
    468       ASSERT (Socket->Parent != NULL);
    469 
    470       Socket->Parent->ConnCnt--;
    471 
    472       DEBUG (
    473         (EFI_D_NET,
    474         "SockAccept: Accept a socket, now conncount is %d",
    475         Socket->Parent->ConnCnt)
    476         );
    477       Socket->Parent = NULL;
    478 
    479       goto Exit;
    480     }
    481   }
    482 
    483   //
    484   // Buffer this token for latter incoming connection request
    485   //
    486   if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {
    487 
    488     Status = EFI_OUT_OF_RESOURCES;
    489   }
    490 
    491 Exit:
    492   EfiReleaseLock (&(Sock->Lock));
    493 
    494   return Status;
    495 }
    496 
    497 /**
    498   Issue a token with data to the socket to send out.
    499 
    500   @param[in]  Sock             Pointer to the socket to process the token with
    501                                data.
    502   @param[in]  Token            The token with data that needs to send out.
    503 
    504   @retval EFI_SUCCESS          The token processed successfully.
    505   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    506                                socket is closed, or the socket is not in a
    507                                synchronized state , or the token is already in one
    508                                of this socket's lists.
    509   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    510                                finished.
    511   @retval EFI_NOT_STARTED      The socket is not configured.
    512   @retval EFI_OUT_OF_RESOURCE  Failed to buffer the token due to memory limits.
    513 
    514 **/
    515 EFI_STATUS
    516 SockSend (
    517   IN SOCKET *Sock,
    518   IN VOID   *Token
    519   )
    520 {
    521   SOCK_IO_TOKEN           *SndToken;
    522   EFI_EVENT               Event;
    523   UINT32                  FreeSpace;
    524   EFI_TCP4_TRANSMIT_DATA  *TxData;
    525   EFI_STATUS              Status;
    526   SOCK_TOKEN              *SockToken;
    527   UINT32                  DataLen;
    528 
    529   ASSERT (SockStream == Sock->Type);
    530 
    531   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    532   if (EFI_ERROR (Status)) {
    533 
    534     DEBUG (
    535       (EFI_D_ERROR,
    536       "SockSend: Get the access for socket failed with %r",
    537       Status)
    538       );
    539 
    540     return EFI_ACCESS_DENIED;
    541   }
    542 
    543   if (SOCK_IS_NO_MAPPING (Sock)) {
    544     Status = EFI_NO_MAPPING;
    545     goto Exit;
    546   }
    547 
    548   SndToken  = (SOCK_IO_TOKEN *) Token;
    549   TxData    = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;
    550 
    551   if (SOCK_IS_UNCONFIGURED (Sock)) {
    552     Status = EFI_NOT_STARTED;
    553     goto Exit;
    554   }
    555 
    556   if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {
    557 
    558     Status = EFI_ACCESS_DENIED;
    559     goto Exit;
    560   }
    561 
    562   //
    563   // check if a token is already in the token buffer
    564   //
    565   Event = SndToken->Token.Event;
    566 
    567   if (SockTokenExisted (Sock, Event)) {
    568     Status = EFI_ACCESS_DENIED;
    569     goto Exit;
    570   }
    571 
    572   DataLen = TxData->DataLength;
    573 
    574   //
    575   // process this sending token now or buffer it only?
    576   //
    577   FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);
    578 
    579   if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {
    580 
    581     SockToken = SockBufferToken (
    582                   Sock,
    583                   &Sock->SndTokenList,
    584                   SndToken,
    585                   DataLen
    586                   );
    587 
    588     if (NULL == SockToken) {
    589       Status = EFI_OUT_OF_RESOURCES;
    590     }
    591   } else {
    592 
    593     SockToken = SockBufferToken (
    594                   Sock,
    595                   &Sock->ProcessingSndTokenList,
    596                   SndToken,
    597                   DataLen
    598                   );
    599 
    600     if (NULL == SockToken) {
    601       DEBUG (
    602         (EFI_D_ERROR,
    603         "SockSend: Failed to buffer IO token into socket processing SndToken List\n",
    604         Status)
    605         );
    606 
    607       Status = EFI_OUT_OF_RESOURCES;
    608       goto Exit;
    609     }
    610 
    611     Status = SockProcessTcpSndData (Sock, TxData);
    612 
    613     if (EFI_ERROR (Status)) {
    614       DEBUG (
    615         (EFI_D_ERROR,
    616         "SockSend: Failed to process Snd Data\n",
    617         Status)
    618         );
    619 
    620       RemoveEntryList (&(SockToken->TokenList));
    621       FreePool (SockToken);
    622     }
    623   }
    624 
    625 Exit:
    626   EfiReleaseLock (&(Sock->Lock));
    627   return Status;
    628 }
    629 
    630 /**
    631   Issue a token to get data from the socket.
    632 
    633   @param[in]  Sock             Pointer to the socket to get data from.
    634   @param[in]  Token            The token to store the received data from the
    635                                socket.
    636 
    637   @retval EFI_SUCCESS          The token processed successfully.
    638   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    639                                socket is closed, or the socket is not in a
    640                                synchronized state , or the token is already in one
    641                                of this socket's lists.
    642   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    643                                finished.
    644   @retval EFI_NOT_STARTED      The socket is not configured.
    645   @retval EFI_CONNECTION_FIN   The connection is closed and there is no more data.
    646   @retval EFI_OUT_OF_RESOURCE  Failed to buffer the token due to memory limit.
    647 
    648 **/
    649 EFI_STATUS
    650 SockRcv (
    651   IN SOCKET *Sock,
    652   IN VOID   *Token
    653   )
    654 {
    655   SOCK_IO_TOKEN *RcvToken;
    656   UINT32        RcvdBytes;
    657   EFI_STATUS    Status;
    658   EFI_EVENT     Event;
    659 
    660   ASSERT (SockStream == Sock->Type);
    661 
    662   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    663   if (EFI_ERROR (Status)) {
    664 
    665     DEBUG (
    666       (EFI_D_ERROR,
    667       "SockRcv: Get the access for socket failed with %r",
    668       Status)
    669       );
    670 
    671     return EFI_ACCESS_DENIED;
    672   }
    673 
    674   if (SOCK_IS_NO_MAPPING (Sock)) {
    675 
    676     Status = EFI_NO_MAPPING;
    677     goto Exit;
    678   }
    679 
    680   if (SOCK_IS_UNCONFIGURED (Sock)) {
    681 
    682     Status = EFI_NOT_STARTED;
    683     goto Exit;
    684   }
    685 
    686   if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {
    687 
    688     Status = EFI_ACCESS_DENIED;
    689     goto Exit;
    690   }
    691 
    692   RcvToken = (SOCK_IO_TOKEN *) Token;
    693 
    694   //
    695   // check if a token is already in the token buffer of this socket
    696   //
    697   Event = RcvToken->Token.Event;
    698   if (SockTokenExisted (Sock, Event)) {
    699     Status = EFI_ACCESS_DENIED;
    700     goto Exit;
    701   }
    702 
    703   RcvToken  = (SOCK_IO_TOKEN *) Token;
    704   RcvdBytes = GET_RCV_DATASIZE (Sock);
    705 
    706   //
    707   // check whether an error has happened before
    708   //
    709   if (EFI_ABORTED != Sock->SockError) {
    710 
    711     SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);
    712     Sock->SockError = EFI_ABORTED;
    713     goto Exit;
    714   }
    715 
    716   //
    717   // check whether can not receive and there is no any
    718   // data buffered in Sock->RcvBuffer
    719   //
    720   if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {
    721 
    722     Status = EFI_CONNECTION_FIN;
    723     goto Exit;
    724   }
    725 
    726   if (RcvdBytes != 0) {
    727     SockProcessRcvToken (Sock, RcvToken);
    728 
    729     Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
    730   } else {
    731 
    732     if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
    733       Status = EFI_OUT_OF_RESOURCES;
    734     }
    735   }
    736 
    737 Exit:
    738   EfiReleaseLock (&(Sock->Lock));
    739   return Status;
    740 }
    741 
    742 /**
    743   Reset the socket and its associated protocol control block.
    744 
    745   @param[in, out]  Sock        Pointer to the socket to be flushed.
    746 
    747   @retval EFI_SUCCESS          The socket is flushed successfully.
    748   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    749 
    750 **/
    751 EFI_STATUS
    752 SockFlush (
    753   IN OUT SOCKET *Sock
    754   )
    755 {
    756   EFI_STATUS  Status;
    757 
    758   ASSERT (SockStream == Sock->Type);
    759 
    760   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    761   if (EFI_ERROR (Status)) {
    762 
    763     DEBUG (
    764       (EFI_D_ERROR,
    765       "SockFlush: Get the access for socket failed with %r",
    766       Status)
    767       );
    768 
    769     return EFI_ACCESS_DENIED;
    770   }
    771 
    772   if (!SOCK_IS_CONFIGURED (Sock)) {
    773 
    774     Status = EFI_ACCESS_DENIED;
    775     goto Exit;
    776   }
    777 
    778   Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
    779   if (EFI_ERROR (Status)) {
    780 
    781     DEBUG (
    782       (EFI_D_ERROR,
    783       "SockFlush: Protocol failed handling SOCK_FLUSH with %r",
    784       Status)
    785       );
    786 
    787     goto Exit;
    788   }
    789 
    790   SOCK_ERROR (Sock, EFI_ABORTED);
    791   SockConnFlush (Sock);
    792   SockSetState (Sock, SO_CLOSED);
    793 
    794   Sock->ConfigureState = SO_UNCONFIGURED;
    795 
    796 Exit:
    797   EfiReleaseLock (&(Sock->Lock));
    798   return Status;
    799 }
    800 
    801 /**
    802   Close or abort the socket associated connection.
    803 
    804   @param[in, out]  Sock        Pointer to the socket of the connection to close
    805                                or abort.
    806   @param[in]  Token            The token for a close operation.
    807   @param[in]  OnAbort          TRUE for aborting the connection; FALSE to close it.
    808 
    809   @retval EFI_SUCCESS          The close or abort operation initialized
    810                                successfully.
    811   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    812                                socket is closed, or the socket is not in a
    813                                synchronized state , or the token is already in one
    814                                of this socket's lists.
    815   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    816                                finished.
    817   @retval EFI_NOT_STARTED      The socket is not configured.
    818 
    819 **/
    820 EFI_STATUS
    821 SockClose (
    822   IN OUT SOCKET  *Sock,
    823   IN     VOID    *Token,
    824   IN     BOOLEAN OnAbort
    825   )
    826 {
    827   EFI_STATUS  Status;
    828   EFI_EVENT   Event;
    829 
    830   ASSERT (SockStream == Sock->Type);
    831 
    832   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    833   if (EFI_ERROR (Status)) {
    834     DEBUG (
    835       (EFI_D_ERROR,
    836       "SockClose: Get the access for socket failed with %r",
    837       Status)
    838       );
    839 
    840     return EFI_ACCESS_DENIED;
    841   }
    842 
    843   if (SOCK_IS_NO_MAPPING (Sock)) {
    844     Status = EFI_NO_MAPPING;
    845     goto Exit;
    846   }
    847 
    848   if (SOCK_IS_UNCONFIGURED (Sock)) {
    849     Status = EFI_NOT_STARTED;
    850     goto Exit;
    851   }
    852 
    853   if (SOCK_IS_DISCONNECTING (Sock)) {
    854     Status = EFI_ACCESS_DENIED;
    855     goto Exit;
    856   }
    857 
    858   Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
    859 
    860   if (SockTokenExisted (Sock, Event)) {
    861     Status = EFI_ACCESS_DENIED;
    862     goto Exit;
    863   }
    864 
    865   Sock->CloseToken = Token;
    866   SockSetState (Sock, SO_DISCONNECTING);
    867 
    868   if (OnAbort) {
    869     Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
    870   } else {
    871     Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
    872   }
    873 
    874 Exit:
    875   EfiReleaseLock (&(Sock->Lock));
    876   return Status;
    877 }
    878 
    879 /**
    880   Abort the socket associated connection, listen, transmission or receive request.
    881 
    882   @param[in, out]  Sock        Pointer to the socket to abort.
    883   @param[in]       Token       Pointer to a token that has been issued by
    884                                Connect(), Accept(), Transmit() or Receive(). If
    885                                NULL, all pending tokens issued by the four
    886                                functions listed above will be aborted.
    887 
    888   @retval EFI_UNSUPPORTED      The operation is not supported in the current
    889                                implementation.
    890 **/
    891 EFI_STATUS
    892 SockCancel (
    893   IN OUT SOCKET  *Sock,
    894   IN     VOID    *Token
    895   )
    896 {
    897   EFI_STATUS     Status;
    898 
    899   Status    = EFI_SUCCESS;
    900 
    901   ASSERT (SockStream == Sock->Type);
    902 
    903   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    904   if (EFI_ERROR (Status)) {
    905     DEBUG (
    906       (EFI_D_ERROR,
    907       "SockCancel: Get the access for socket failed with %r",
    908       Status)
    909       );
    910 
    911     return EFI_ACCESS_DENIED;
    912   }
    913 
    914   if (SOCK_IS_UNCONFIGURED (Sock)) {
    915     Status = EFI_NOT_STARTED;
    916     goto Exit;
    917   }
    918 
    919   //
    920   // 1. Check ConnectionToken.
    921   //
    922   if (Token == NULL || (SOCK_COMPLETION_TOKEN *) Token == Sock->ConnectionToken) {
    923     if (Sock->ConnectionToken != NULL) {
    924       SIGNAL_TOKEN (Sock->ConnectionToken, EFI_ABORTED);
    925       Sock->ConnectionToken = NULL;
    926     }
    927 
    928     if (Token != NULL) {
    929       Status = EFI_SUCCESS;
    930       goto Exit;
    931     }
    932   }
    933 
    934   //
    935   // 2. Check ListenTokenList.
    936   //
    937   Status = SockCancelToken (Token, &Sock->ListenTokenList);
    938   if (Token != NULL && !EFI_ERROR (Status)) {
    939     goto Exit;
    940   }
    941 
    942   //
    943   // 3. Check RcvTokenList.
    944   //
    945   Status = SockCancelToken (Token, &Sock->RcvTokenList);
    946   if (Token != NULL && !EFI_ERROR (Status)) {
    947     goto Exit;
    948   }
    949 
    950   //
    951   // 4. Check SndTokenList.
    952   //
    953   Status = SockCancelToken (Token, &Sock->SndTokenList);
    954   if (Token != NULL && !EFI_ERROR (Status)) {
    955     goto Exit;
    956   }
    957 
    958   //
    959   // 5. Check ProcessingSndTokenList.
    960   //
    961   Status = SockCancelToken (Token, &Sock->ProcessingSndTokenList);
    962 
    963 Exit:
    964   EfiReleaseLock (&(Sock->Lock));
    965   return Status;
    966 }
    967 
    968 
    969 /**
    970   Get the mode data of the low layer protocol.
    971 
    972   @param[in]       Sock        Pointer to the socket to get mode data from.
    973   @param[in, out]  Mode        Pointer to the data to store the low layer mode
    974                                information.
    975 
    976   @retval EFI_SUCCESS          The mode data was obtained successfully.
    977   @retval EFI_NOT_STARTED      The socket is not configured.
    978 
    979 **/
    980 EFI_STATUS
    981 SockGetMode (
    982   IN     SOCKET *Sock,
    983   IN OUT VOID   *Mode
    984   )
    985 {
    986   return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
    987 }
    988 
    989 /**
    990   Configure the low level protocol to join a multicast group for
    991   this socket's connection.
    992 
    993   @param[in]  Sock             Pointer to the socket of the connection to join the
    994                                specific multicast group.
    995   @param[in]  GroupInfo        Pointer to the multicast group info.
    996 
    997   @retval EFI_SUCCESS          The configuration completed successfully.
    998   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    999   @retval EFI_NOT_STARTED      The socket is not configured.
   1000 
   1001 **/
   1002 EFI_STATUS
   1003 SockGroup (
   1004   IN SOCKET *Sock,
   1005   IN VOID   *GroupInfo
   1006   )
   1007 {
   1008   EFI_STATUS  Status;
   1009 
   1010   Status = EfiAcquireLockOrFail (&(Sock->Lock));
   1011 
   1012   if (EFI_ERROR (Status)) {
   1013 
   1014     DEBUG (
   1015       (EFI_D_ERROR,
   1016       "SockGroup: Get the access for socket failed with %r",
   1017       Status)
   1018       );
   1019 
   1020     return EFI_ACCESS_DENIED;
   1021   }
   1022 
   1023   if (SOCK_IS_UNCONFIGURED (Sock)) {
   1024     Status = EFI_NOT_STARTED;
   1025     goto Exit;
   1026   }
   1027 
   1028   Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
   1029 
   1030 Exit:
   1031   EfiReleaseLock (&(Sock->Lock));
   1032   return Status;
   1033 }
   1034 
   1035 /**
   1036   Add or remove route information in IP route table associated
   1037   with this socket.
   1038 
   1039   @param[in]  Sock             Pointer to the socket associated with the IP route
   1040                                table to operate on.
   1041   @param[in]  RouteInfo        Pointer to the route information to be processed.
   1042 
   1043   @retval EFI_SUCCESS          The route table updated successfully.
   1044   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
   1045   @retval EFI_NO_MAPPING       The IP address configuration operation is  not
   1046                                finished.
   1047   @retval EFI_NOT_STARTED      The socket is not configured.
   1048 
   1049 **/
   1050 EFI_STATUS
   1051 SockRoute (
   1052   IN SOCKET    *Sock,
   1053   IN VOID      *RouteInfo
   1054   )
   1055 {
   1056   EFI_STATUS  Status;
   1057 
   1058   Status = EfiAcquireLockOrFail (&(Sock->Lock));
   1059   if (EFI_ERROR (Status)) {
   1060     DEBUG (
   1061       (EFI_D_ERROR,
   1062       "SockRoute: Get the access for socket failed with %r",
   1063       Status)
   1064       );
   1065 
   1066     return EFI_ACCESS_DENIED;
   1067   }
   1068 
   1069   if (SOCK_IS_NO_MAPPING (Sock)) {
   1070     Status = EFI_NO_MAPPING;
   1071     goto Exit;
   1072   }
   1073 
   1074   if (SOCK_IS_UNCONFIGURED (Sock)) {
   1075     Status = EFI_NOT_STARTED;
   1076     goto Exit;
   1077   }
   1078 
   1079   Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
   1080 
   1081 Exit:
   1082   EfiReleaseLock (&(Sock->Lock));
   1083   return Status;
   1084 }
   1085 
   1086