1 /** @file
2   Implement the entry and unload for the socket driver.
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 by the SocketDxe driver.  An
20   alternative set of values exists in EfiSocketLib\UseEfiSocketLib.c
21   which an application uses when it links against EfiSocketLib.  These
22   two sets of values allow the SocketDxe driver to coexist with socket
23   applications.
24 
25   Tag GUID - IPv4 in use by SocketDxe
26 **/
27 CONST EFI_GUID mEslIp4ServiceGuid = {
28   0x4e3a82e6, 0xe43f, 0x460a, { 0x86, 0x6e, 0x9b, 0x5a, 0xab, 0x80, 0x44, 0x48 }
29 };
30 
31 
32 /**
33   Tag GUID - IPv6 in use by SocketDxe
34 **/
35 CONST EFI_GUID mEslIp6ServiceGuid = {
36   0x2fc3b2d3, 0x6eba, 0x42b0, { 0xa4, 0xa7, 0x14, 0xc7, 0xa8, 0x4b, 0x5d, 0x22 }
37 };
38 
39 
40 /**
41   Tag GUID - TCPv4 in use by SocketDxe
42 **/
43 CONST EFI_GUID mEslTcp4ServiceGuid = {
44   0x4dcaab0a, 0x1990, 0x4352, { 0x8d, 0x2f, 0x2d, 0x8f, 0x13, 0x55, 0x98, 0xa5 }
45 };
46 
47 
48 /**
49   Tag GUID - TCPv6 in use by SocketDxe
50 **/
51 CONST EFI_GUID mEslTcp6ServiceGuid = {
52   0xdd455a69, 0xec75, 0x456c, { 0x84, 0xd2, 0x95, 0xca, 0xe7, 0xd3, 0xc6, 0xd3 }
53 };
54 
55 
56 /**
57   Tag GUID - UDPv4 in use by SocketDxe
58 **/
59 CONST EFI_GUID mEslUdp4ServiceGuid = {
60   0x43a110ce, 0x9ccd, 0x402b, { 0x8c, 0x29, 0x4a, 0x6d, 0x8a, 0xf7, 0x79, 0x90 }
61 };
62 
63 
64 /**
65   Tag GUID - UDPv6 in use by SocketDxe
66 **/
67 CONST EFI_GUID mEslUdp6ServiceGuid = {
68   0x32ff59cd, 0xc33, 0x48d0, { 0xa2, 0x44, 0x4b, 0xb8, 0x11, 0x33, 0x64, 0x3 }
69 };
70 
71 
72 /**
73   Socket driver unload routine.
74 
75   @param [in] ImageHandle       Handle for the image.
76 
77   @retval EFI_SUCCESS           Image may be unloaded
78 
79 **/
80 EFI_STATUS
81 EFIAPI
DriverUnload(IN EFI_HANDLE ImageHandle)82 DriverUnload (
83   IN EFI_HANDLE ImageHandle
84   )
85 {
86   UINTN BufferSize;
87   UINTN Index;
88   UINTN Max;
89   EFI_HANDLE * pHandle;
90   EFI_STATUS Status;
91 
92   //
93   //  Determine which devices are using this driver
94   //
95   BufferSize = 0;
96   pHandle = NULL;
97   Status = gBS->LocateHandle (
98                   ByProtocol,
99                   &gEfiCallerIdGuid,
100                   NULL,
101                   &BufferSize,
102                   NULL );
103   if ( EFI_BUFFER_TOO_SMALL == Status ) {
104     for ( ; ; ) {
105       //
106       //  One or more block IO devices are present
107       //
108       Status = gBS->AllocatePool (
109                       EfiRuntimeServicesData,
110                       BufferSize,
111                       (VOID **) &pHandle
112                       );
113       if ( EFI_ERROR ( Status )) {
114         DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
115                   "Insufficient memory, failed handle buffer allocation\r\n" ));
116         break;
117       }
118 
119       //
120       //  Locate the block IO devices
121       //
122       Status = gBS->LocateHandle (
123                       ByProtocol,
124                       &gEfiCallerIdGuid,
125                       NULL,
126                       &BufferSize,
127                       pHandle );
128       if ( EFI_ERROR ( Status )) {
129         //
130         //  Error getting handles
131         //
132         DEBUG (( DEBUG_ERROR | DEBUG_INIT | DEBUG_INFO,
133                 "Failure getting Telnet handles\r\n" ));
134         break;
135       }
136 
137       //
138       //  Remove any use of the driver
139       //
140       Max = BufferSize / sizeof ( pHandle[ 0 ]);
141       for ( Index = 0; Max > Index; Index++ ) {
142         Status = DriverStop ( &mDriverBinding,
143                               pHandle[ Index ],
144                               0,
145                               NULL );
146         if ( EFI_ERROR ( Status )) {
147           DEBUG (( DEBUG_WARN | DEBUG_INIT | DEBUG_INFO,
148                     "WARNING - Failed to shutdown the driver on handle %08x\r\n", pHandle[ Index ]));
149           break;
150         }
151       }
152       break;
153     }
154   }
155   else {
156     if ( EFI_NOT_FOUND == Status ) {
157       //
158       //  No devices were found
159       //
160       Status = EFI_SUCCESS;
161     }
162   }
163 
164   //
165   //  Free the handle array
166   //
167   if ( NULL != pHandle ) {
168     gBS->FreePool ( pHandle );
169   }
170 
171   //
172   //  Done with the socket layer
173   //
174   if ( !EFI_ERROR ( Status )) {
175     Status = EslDxeUninstall ( ImageHandle );
176     if ( !EFI_ERROR ( Status )) {
177       //
178       //  Remove the protocols installed by the EntryPoint routine.
179       //
180       Status = gBS->UninstallMultipleProtocolInterfaces (
181                   ImageHandle,
182                   &gEfiDriverBindingProtocolGuid,
183                   &mDriverBinding,
184                   &gEfiComponentNameProtocolGuid,
185                   &mComponentName,
186                   &gEfiComponentName2ProtocolGuid,
187                   &mComponentName2,
188                   NULL
189                   );
190       if ( !EFI_ERROR ( Status )) {
191         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
192                 "Removed:   gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
193                 ImageHandle ));
194         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
195                   "Removed:   gEfiComponentNameProtocolGuid from 0x%08x\r\n",
196                   ImageHandle ));
197         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
198                   "Removed:   gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
199                   ImageHandle ));
200       }
201       else {
202         DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
203                     "ERROR - Failed to remove gEfiDriverBindingProtocolGuid from 0x%08x, Status: %r\r\n",
204                     ImageHandle,
205                     Status ));
206       }
207     }
208   }
209 
210   //
211   //  Disconnect the network services
212   //
213   if ( !EFI_ERROR ( Status )) {
214     EslServiceUnload ( );
215   }
216 
217   //
218   //  Return the unload status
219   //
220   return Status;
221 }
222 
223 
224 /**
225 Socket driver entry point.
226 
227 @param [in] ImageHandle       Handle for the image.
228 @param [in] pSystemTable      Address of the system table.
229 
230 @retval EFI_SUCCESS           Image successfully loaded.
231 
232 **/
233 EFI_STATUS
234 EFIAPI
EntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * pSystemTable)235 EntryPoint (
236   IN EFI_HANDLE ImageHandle,
237   IN EFI_SYSTEM_TABLE * pSystemTable
238   )
239 {
240   EFI_LOADED_IMAGE_PROTOCOL * pLoadedImage;
241   EFI_STATUS    Status;
242 
243   DBG_ENTER ( );
244 
245   //
246   //  Display the image handle
247   //
248   DEBUG (( DEBUG_INFO,
249             "ImageHandle: 0x%08x\r\n",
250             ImageHandle ));
251 
252   //
253   //  Enable unload support
254   //
255   Status = gBS->HandleProtocol (
256                   gImageHandle,
257                   &gEfiLoadedImageProtocolGuid,
258                   (VOID **)&pLoadedImage
259                   );
260   if (!EFI_ERROR (Status)) {
261     pLoadedImage->Unload = DriverUnload;
262 
263     //
264     //  Add the driver to the list of drivers
265     //
266     Status = EfiLibInstallDriverBindingComponentName2 (
267                ImageHandle,
268                pSystemTable,
269                &mDriverBinding,
270                ImageHandle,
271                &mComponentName,
272                &mComponentName2
273                );
274     if ( !EFI_ERROR ( Status )) {
275       DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
276                 "Installed: gEfiDriverBindingProtocolGuid on   0x%08x\r\n",
277                 ImageHandle ));
278       DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
279                 "Installed: gEfiComponentNameProtocolGuid on   0x%08x\r\n",
280                 ImageHandle ));
281       DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
282                 "Installed: gEfiComponentName2ProtocolGuid on   0x%08x\r\n",
283                 ImageHandle ));
284 
285       //
286       //  Initialize the service layer
287       //
288       EslServiceLoad ( ImageHandle );
289 
290       //
291       //  Make the socket serivces available to other drivers
292       //  and applications
293       //
294       Status = EslDxeInstall ( &ImageHandle );
295       if ( EFI_ERROR ( Status )) {
296         //
297         //  Disconnect from the network
298         //
299         EslServiceUnload ( );
300 
301         //
302         //  Remove the driver bindings
303         //
304         gBS->UninstallMultipleProtocolInterfaces (
305                 ImageHandle,
306                 &gEfiDriverBindingProtocolGuid,
307                 &mDriverBinding,
308                 &gEfiComponentNameProtocolGuid,
309                 &mComponentName,
310                 &gEfiComponentName2ProtocolGuid,
311                 &mComponentName2,
312                 NULL
313                 );
314         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
315                 "Removed:   gEfiComponentName2ProtocolGuid from 0x%08x\r\n",
316                 ImageHandle ));
317         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
318                   "Removed:   gEfiComponentNameProtocolGuid from 0x%08x\r\n",
319                   ImageHandle ));
320         DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
321                   "Removed:   gEfiDriverBindingProtocolGuid from 0x%08x\r\n",
322                   ImageHandle ));
323       }
324     }
325     else  {
326       DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
327                 "ERROR - EfiLibInstallDriverBindingComponentName2 failed, Status: %r\r\n",
328                 Status ));
329     }
330   }
331   DBG_EXIT_STATUS ( Status );
332   return Status;
333 }
334 
335 
336 /**
337   Socket layer's service binding protocol delcaration.
338 **/
339 CONST EFI_SERVICE_BINDING_PROTOCOL mEfiServiceBinding = {
340   EslDxeCreateChild,
341   EslDxeDestroyChild
342 };
343 
344 
345 /**
346   The following entries disable the constructor and destructor
347   for the SocketDxe driver.  Note that socket applications linking
348   against EfiSocketLib use different redirection.
349 **/
350 PFN_ESL_xSTRUCTOR mpfnEslConstructor = NULL;  ///<  No EfiSocketLib constructor needed for SocketDxe
351 PFN_ESL_xSTRUCTOR mpfnEslDestructor = NULL;   ///<  No EfiSocketLib destructor needed for SocketDxe
352