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