Home | History | Annotate | Download | only in EfiSocketLib
      1 /** @file
      2   Implement the connection to the EFI socket library
      3 
      4   Copyright (c) 2011, Intel Corporation
      5   All rights reserved. This program and the accompanying materials
      6   are licensed and made available under the terms and conditions of the BSD License
      7   which accompanies this distribution.  The full text of the license may be found at
      8   http://opensource.org/licenses/bsd-license.php
      9 
     10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "Socket.h"
     16 
     17 
     18 /**
     19   The following GUID values are only used when an application links
     20   against EfiSocketLib.  An alternative set of values exists in
     21   SocketDxe\EntryUnload.c which the SocketDxe driver uses to coexist
     22   with socket applications.
     23 
     24   Tag GUID - IPv4 in use by an application using EfiSocketLib
     25 **/
     26 CONST EFI_GUID mEslIp4ServiceGuid __attribute__((weak)) = {
     27   0x9c756011, 0x5d44, 0x4ee0, { 0xbc, 0xe7, 0xc3, 0x82, 0x18, 0xfe, 0x39, 0x8d }
     28 };
     29 
     30 
     31 /**
     32   Tag GUID - IPv6 in use by an application using EfiSocketLib
     33 **/
     34 CONST EFI_GUID mEslIp6ServiceGuid __attribute__((weak)) = {
     35   0xc51b2761, 0xc476, 0x45fe, { 0xbe, 0x61, 0xba, 0x4b, 0xcc, 0x32, 0xf2, 0x34 }
     36 };
     37 
     38 
     39 /**
     40   Tag GUID - TCPv4 in use by an application using EfiSocketLib
     41 **/
     42 CONST EFI_GUID mEslTcp4ServiceGuid __attribute__((weak)) = {
     43   0xffc659c2, 0x4ef2, 0x4532, { 0xb8, 0x75, 0xcd, 0x9a, 0xa4, 0x27, 0x4c, 0xde }
     44 };
     45 
     46 
     47 /**
     48   Tag GUID - TCPv6 in use by an application using EfiSocketLib
     49 **/
     50 CONST EFI_GUID mEslTcp6ServiceGuid __attribute__((weak)) = {
     51   0x279858a4, 0x4e9e, 0x4e53, { 0x93, 0x22, 0xf2, 0x54, 0xe0, 0x7e, 0xef, 0xd4 }
     52 };
     53 
     54 
     55 /**
     56   Tag GUID - UDPv4 in use by an application using EfiSocketLib
     57 **/
     58 CONST EFI_GUID mEslUdp4ServiceGuid __attribute__((weak)) = {
     59   0x44e03a55, 0x8d97, 0x4511, { 0xbf, 0xef, 0xa, 0x8b, 0xc6, 0x2c, 0x25, 0xae }
     60 };
     61 
     62 
     63 /**
     64   Tag GUID - UDPv6 in use by an application using EfiSocketLib
     65 **/
     66 CONST EFI_GUID mEslUdp6ServiceGuid __attribute__((weak)) = {
     67   0xaa4af677, 0x6efe, 0x477c, { 0x96, 0x68, 0xe8, 0x13, 0x9d, 0x2, 0xfd, 0x9b }
     68 };
     69 
     70 
     71 /**
     72   Free the socket resources
     73 
     74   This releases the socket resources allocated by calling
     75   EslServiceGetProtocol.
     76 
     77   This routine is called from the ::close routine in BsdSocketLib
     78   to release the socket resources.
     79 
     80   @param [in] pSocketProtocol   Address of an ::EFI_SOCKET_PROTOCOL
     81                                 structure
     82 
     83   @return       Value for ::errno, zero (0) indicates success.
     84 
     85  **/
     86 int
     87 EslServiceFreeProtocol (
     88   IN EFI_SOCKET_PROTOCOL * pSocketProtocol
     89   )
     90 {
     91   int RetVal;
     92 
     93   //
     94   //  Release the socket resources
     95   //
     96   EslSocketFree ( pSocketProtocol, &RetVal );
     97 
     98   //
     99   //  Return the operation status
    100   //
    101   return RetVal;
    102 }
    103 
    104 
    105 /**
    106   Connect to the EFI socket library
    107 
    108   This routine creates the ::ESL_SOCKET structure and returns
    109   the API (::EFI_SOCKET_PROTOCOL address) to the socket file
    110   system layer in BsdSocketLib.
    111 
    112   This routine is called from the ::socket routine in BsdSocketLib
    113   to create the data structure and initialize the API for a socket.
    114   Note that this implementation is only used by socket applications
    115   that link directly to EslSocketLib.
    116 
    117   @param [in] ppSocketProtocol  Address to receive the ::EFI_SOCKET_PROTOCOL
    118                                 structure address
    119 
    120   @return       Value for ::errno, zero (0) indicates success.
    121 
    122  **/
    123 int
    124 EslServiceGetProtocol (
    125   IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol
    126   )
    127 {
    128   EFI_HANDLE ChildHandle;
    129   ESL_SOCKET * pSocket;
    130   int RetVal;
    131   EFI_STATUS Status;
    132 
    133   DBG_ENTER ( );
    134 
    135   //
    136   //  Assume success
    137   //
    138   RetVal = 0;
    139 
    140   //
    141   //  Locate the socket protocol
    142   //
    143   ChildHandle = NULL;
    144   Status = EslSocketAllocate ( &ChildHandle,
    145                                DEBUG_SOCKET,
    146                                &pSocket );
    147   if ( !EFI_ERROR ( Status )) {
    148     *ppSocketProtocol = &pSocket->SocketProtocol;
    149   }
    150   else {
    151     //
    152     //  No resources
    153     //
    154     RetVal = ENOMEM;
    155   }
    156 
    157   //
    158   //  Return the operation status
    159   //
    160   DBG_EXIT_DEC ( RetVal );
    161   return RetVal;
    162 }
    163 
    164 
    165 /**
    166   Connect to the network layer
    167 
    168   This routine is the constructor for the EfiSocketLib when the
    169   library is linked directly to an application.  This routine
    170   walks the ::cEslSocketBinding table to create ::ESL_SERVICE
    171   structures, associated with the network adapters, which this
    172   routine links to the ::ESL_LAYER structure.
    173 
    174   This routine is called from ::EslConstructor as a result of the
    175   constructor redirection in ::mpfnEslConstructor at the end of this
    176   file.
    177 
    178   @retval EFI_SUCCESS   Successfully connected to the network layer
    179 
    180  **/
    181 EFI_STATUS
    182 EslServiceNetworkConnect (
    183   VOID
    184   )
    185 {
    186   BOOLEAN bSomethingFound;
    187   UINTN HandleCount;
    188   UINTN Index;
    189   CONST ESL_SOCKET_BINDING * pEnd;
    190   EFI_HANDLE * pHandles;
    191   CONST ESL_SOCKET_BINDING * pSocketBinding;
    192   EFI_STATUS Status;
    193 
    194   DBG_ENTER ( );
    195 
    196   //
    197   //  Initialize the socket layer
    198   //
    199   Status = EFI_SUCCESS;
    200   bSomethingFound = FALSE;
    201   EslServiceLoad ( gImageHandle );
    202 
    203   //
    204   //  Connect the network devices
    205   //
    206   pSocketBinding = &cEslSocketBinding[0];
    207   pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
    208   while ( pEnd > pSocketBinding ) {
    209     //
    210     //  Attempt to locate the network adapters
    211     //
    212     HandleCount = 0;
    213     pHandles = NULL;
    214     Status = gBS->LocateHandleBuffer ( ByProtocol,
    215                                        pSocketBinding->pNetworkBinding,
    216                                        NULL,
    217                                        &HandleCount,
    218                                        &pHandles );
    219     if ( EFI_ERROR ( Status )) {
    220       DEBUG (( DEBUG_ERROR,
    221                "ERROR with %s layer, Status: %r\r\n",
    222                pSocketBinding->pName,
    223                Status ));
    224     }
    225     else {
    226       if ( NULL != pHandles ) {
    227         //
    228         //  Attempt to connect to this network adapter
    229         //
    230         for ( Index = 0; HandleCount > Index; Index++ ) {
    231           Status = EslServiceConnect ( gImageHandle,
    232                                        pHandles[ Index ]);
    233           if ( !EFI_ERROR ( Status )) {
    234             bSomethingFound = TRUE;
    235           }
    236           else {
    237             if ( EFI_OUT_OF_RESOURCES == Status ) {
    238               //
    239               //  Pointless to continue without memory
    240               //
    241               break;
    242             }
    243           }
    244         }
    245 
    246         //
    247         //  Done with the handles
    248         //
    249         gBS->FreePool ( pHandles );
    250       }
    251     }
    252 
    253     //
    254     //  Set the next network protocol
    255     //
    256     pSocketBinding += 1;
    257   }
    258 
    259   //
    260   //  Return the network connection status
    261   //
    262   if ( bSomethingFound ) {
    263     Status = EFI_SUCCESS;
    264   }
    265   DBG_EXIT_STATUS ( Status );
    266   return Status;
    267 }
    268 
    269 
    270 /**
    271   Disconnect from the network layer
    272 
    273   Destructor for the EfiSocketLib when the library is linked
    274   directly to an application.  This routine walks the
    275   ::cEslSocketBinding table to remove the ::ESL_SERVICE
    276   structures (network connections) from the ::ESL_LAYER structure.
    277 
    278   This routine is called from ::EslDestructor as a result of the
    279   destructor redirection in ::mpfnEslDestructor at the end of this
    280   file.
    281 
    282   @retval EFI_SUCCESS   Successfully disconnected from the network layer
    283 
    284  **/
    285 EFI_STATUS
    286 EslServiceNetworkDisconnect (
    287   VOID
    288   )
    289 {
    290   UINTN HandleCount;
    291   UINTN Index;
    292   CONST ESL_SOCKET_BINDING * pEnd;
    293   EFI_HANDLE * pHandles;
    294   CONST ESL_SOCKET_BINDING * pSocketBinding;
    295   EFI_STATUS Status;
    296 
    297   DBG_ENTER ( );
    298 
    299   //
    300   //  Assume success
    301   //
    302   Status = EFI_SUCCESS;
    303 
    304   //
    305   //  Disconnect the network devices
    306   //
    307   pSocketBinding = &cEslSocketBinding[0];
    308   pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
    309   while ( pEnd > pSocketBinding ) {
    310     //
    311     //  Attempt to locate the network adapters
    312     //
    313     HandleCount = 0;
    314     pHandles = NULL;
    315     Status = gBS->LocateHandleBuffer ( ByProtocol,
    316                                        pSocketBinding->pNetworkBinding,
    317                                        NULL,
    318                                        &HandleCount,
    319                                        &pHandles );
    320     if (( !EFI_ERROR ( Status ))
    321       && ( NULL != pHandles )) {
    322       //
    323       //  Attempt to disconnect from this network adapter
    324       //
    325       for ( Index = 0; HandleCount > Index; Index++ ) {
    326         Status = EslServiceDisconnect ( gImageHandle,
    327                                         pHandles[ Index ]);
    328         if ( EFI_ERROR ( Status )) {
    329           break;
    330         }
    331       }
    332 
    333       //
    334       //  Done with the handles
    335       //
    336       gBS->FreePool ( pHandles );
    337     }
    338 
    339     //
    340     //  Set the next network protocol
    341     //
    342     pSocketBinding += 1;
    343     Status = EFI_SUCCESS;
    344   }
    345 
    346   //
    347   //  Finish the disconnect operation
    348   //
    349   if ( !EFI_ERROR ( Status )) {
    350     EslServiceUnload ( );
    351   }
    352 
    353   //
    354   //  Return the network connection status
    355   //
    356   DBG_EXIT_STATUS ( Status );
    357   return Status;
    358 }
    359 
    360 
    361 /**
    362   Socket layer's service binding protocol delcaration.
    363 **/
    364 CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding __attribute__((weak)) = {
    365   NULL,
    366   NULL
    367 };
    368 
    369 
    370 /**
    371   The following entries redirect the constructor and destructor
    372   for any socket application that links against the EfiSocketLib.
    373   Note that the SocketDxe driver uses different redirection.
    374 **/
    375 PFN_ESL_xSTRUCTOR mpfnEslConstructor __attribute__((weak)) = EslServiceNetworkConnect;    ///<  Constructor for EfiSocketLib
    376 PFN_ESL_xSTRUCTOR mpfnEslDestructor __attribute__((weak)) = EslServiceNetworkDisconnect;  ///<  Destructor for EfiSocketLib
    377