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
EslServiceFreeProtocol(IN EFI_SOCKET_PROTOCOL * pSocketProtocol)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
EslServiceGetProtocol(IN EFI_SOCKET_PROTOCOL ** ppSocketProtocol)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
EslServiceNetworkConnect(VOID)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
EslServiceNetworkDisconnect(VOID)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