Home | History | Annotate | Download | only in TcpDxe
      1 /** @file
      2   Interface function of the Socket.
      3 
      4   Copyright (c) 2009 - 2012, 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_INFO,
    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     Status = SockProcessRcvToken (Sock, RcvToken);
    728 
    729     if (EFI_ERROR (Status)) {
    730       goto Exit;
    731     }
    732 
    733     Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);
    734   } else {
    735 
    736     if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {
    737       Status = EFI_OUT_OF_RESOURCES;
    738     }
    739   }
    740 
    741 Exit:
    742   EfiReleaseLock (&(Sock->Lock));
    743   return Status;
    744 }
    745 
    746 /**
    747   Reset the socket and its associated protocol control block.
    748 
    749   @param[in, out]  Sock        Pointer to the socket to be flushed.
    750 
    751   @retval EFI_SUCCESS          The socket is flushed successfully.
    752   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    753 
    754 **/
    755 EFI_STATUS
    756 SockFlush (
    757   IN OUT SOCKET *Sock
    758   )
    759 {
    760   EFI_STATUS  Status;
    761 
    762   ASSERT (SockStream == Sock->Type);
    763 
    764   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    765   if (EFI_ERROR (Status)) {
    766 
    767     DEBUG (
    768       (EFI_D_ERROR,
    769       "SockFlush: Get the access for socket failed with %r",
    770       Status)
    771       );
    772 
    773     return EFI_ACCESS_DENIED;
    774   }
    775 
    776   if (!SOCK_IS_CONFIGURED (Sock)) {
    777 
    778     Status = EFI_ACCESS_DENIED;
    779     goto Exit;
    780   }
    781 
    782   Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);
    783   if (EFI_ERROR (Status)) {
    784 
    785     DEBUG (
    786       (EFI_D_ERROR,
    787       "SockFlush: Protocol failed handling SOCK_FLUSH with %r",
    788       Status)
    789       );
    790 
    791     goto Exit;
    792   }
    793 
    794   SOCK_ERROR (Sock, EFI_ABORTED);
    795   SockConnFlush (Sock);
    796   SockSetState (Sock, SO_CLOSED);
    797 
    798   Sock->ConfigureState = SO_UNCONFIGURED;
    799 
    800 Exit:
    801   EfiReleaseLock (&(Sock->Lock));
    802   return Status;
    803 }
    804 
    805 /**
    806   Close or abort the socket associated connection.
    807 
    808   @param[in, out]  Sock        Pointer to the socket of the connection to close
    809                                or abort.
    810   @param[in]  Token            The token for a close operation.
    811   @param[in]  OnAbort          TRUE for aborting the connection; FALSE to close it.
    812 
    813   @retval EFI_SUCCESS          The close or abort operation initialized
    814                                successfully.
    815   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket, or the
    816                                socket is closed, or the socket is not in a
    817                                synchronized state , or the token is already in one
    818                                of this socket's lists.
    819   @retval EFI_NO_MAPPING       The IP address configuration operation is not
    820                                finished.
    821   @retval EFI_NOT_STARTED      The socket is not configured.
    822 
    823 **/
    824 EFI_STATUS
    825 SockClose (
    826   IN OUT SOCKET  *Sock,
    827   IN     VOID    *Token,
    828   IN     BOOLEAN OnAbort
    829   )
    830 {
    831   EFI_STATUS  Status;
    832   EFI_EVENT   Event;
    833 
    834   ASSERT (SockStream == Sock->Type);
    835 
    836   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    837   if (EFI_ERROR (Status)) {
    838     DEBUG (
    839       (EFI_D_ERROR,
    840       "SockClose: Get the access for socket failed with %r",
    841       Status)
    842       );
    843 
    844     return EFI_ACCESS_DENIED;
    845   }
    846 
    847   if (SOCK_IS_NO_MAPPING (Sock)) {
    848     Status = EFI_NO_MAPPING;
    849     goto Exit;
    850   }
    851 
    852   if (SOCK_IS_UNCONFIGURED (Sock)) {
    853     Status = EFI_NOT_STARTED;
    854     goto Exit;
    855   }
    856 
    857   if (SOCK_IS_DISCONNECTING (Sock)) {
    858     Status = EFI_ACCESS_DENIED;
    859     goto Exit;
    860   }
    861 
    862   Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;
    863 
    864   if (SockTokenExisted (Sock, Event)) {
    865     Status = EFI_ACCESS_DENIED;
    866     goto Exit;
    867   }
    868 
    869   Sock->CloseToken = Token;
    870   SockSetState (Sock, SO_DISCONNECTING);
    871 
    872   if (OnAbort) {
    873     Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);
    874   } else {
    875     Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);
    876   }
    877 
    878 Exit:
    879   EfiReleaseLock (&(Sock->Lock));
    880   return Status;
    881 }
    882 
    883 /**
    884   Get the mode data of the low layer protocol.
    885 
    886   @param[in]       Sock        Pointer to the socket to get mode data from.
    887   @param[in, out]  Mode        Pointer to the data to store the low layer mode
    888                                information.
    889 
    890   @retval EFI_SUCCESS          The mode data was obtained successfully.
    891   @retval EFI_NOT_STARTED      The socket is not configured.
    892 
    893 **/
    894 EFI_STATUS
    895 SockGetMode (
    896   IN     SOCKET *Sock,
    897   IN OUT VOID   *Mode
    898   )
    899 {
    900   return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);
    901 }
    902 
    903 /**
    904   Configure the low level protocol to join a multicast group for
    905   this socket's connection.
    906 
    907   @param[in]  Sock             Pointer to the socket of the connection to join the
    908                                specific multicast group.
    909   @param[in]  GroupInfo        Pointer to the multicast group info.
    910 
    911   @retval EFI_SUCCESS          The configuration completed successfully.
    912   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    913   @retval EFI_NOT_STARTED      The socket is not configured.
    914 
    915 **/
    916 EFI_STATUS
    917 SockGroup (
    918   IN SOCKET *Sock,
    919   IN VOID   *GroupInfo
    920   )
    921 {
    922   EFI_STATUS  Status;
    923 
    924   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    925 
    926   if (EFI_ERROR (Status)) {
    927 
    928     DEBUG (
    929       (EFI_D_ERROR,
    930       "SockGroup: Get the access for socket failed with %r",
    931       Status)
    932       );
    933 
    934     return EFI_ACCESS_DENIED;
    935   }
    936 
    937   if (SOCK_IS_UNCONFIGURED (Sock)) {
    938     Status = EFI_NOT_STARTED;
    939     goto Exit;
    940   }
    941 
    942   Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);
    943 
    944 Exit:
    945   EfiReleaseLock (&(Sock->Lock));
    946   return Status;
    947 }
    948 
    949 /**
    950   Add or remove route information in IP route table associated
    951   with this socket.
    952 
    953   @param[in]  Sock             Pointer to the socket associated with the IP route
    954                                table to operate on.
    955   @param[in]  RouteInfo        Pointer to the route information to be processed.
    956 
    957   @retval EFI_SUCCESS          The route table updated successfully.
    958   @retval EFI_ACCESS_DENIED    Failed to get the lock to access the socket.
    959   @retval EFI_NO_MAPPING       The IP address configuration operation is  not
    960                                finished.
    961   @retval EFI_NOT_STARTED      The socket is not configured.
    962 
    963 **/
    964 EFI_STATUS
    965 SockRoute (
    966   IN SOCKET    *Sock,
    967   IN VOID      *RouteInfo
    968   )
    969 {
    970   EFI_STATUS  Status;
    971 
    972   Status = EfiAcquireLockOrFail (&(Sock->Lock));
    973   if (EFI_ERROR (Status)) {
    974     DEBUG (
    975       (EFI_D_ERROR,
    976       "SockRoute: Get the access for socket failed with %r",
    977       Status)
    978       );
    979 
    980     return EFI_ACCESS_DENIED;
    981   }
    982 
    983   if (SOCK_IS_NO_MAPPING (Sock)) {
    984     Status = EFI_NO_MAPPING;
    985     goto Exit;
    986   }
    987 
    988   if (SOCK_IS_UNCONFIGURED (Sock)) {
    989     Status = EFI_NOT_STARTED;
    990     goto Exit;
    991   }
    992 
    993   Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);
    994 
    995 Exit:
    996   EfiReleaseLock (&(Sock->Lock));
    997   return Status;
    998 }
    999 
   1000