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**/
27CONST 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**/
35CONST 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**/
43CONST 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**/
51CONST 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**/
59CONST 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**/
67CONST 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**/
80EFI_STATUS
81EFIAPI
82DriverUnload (
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/**
225Socket 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**/
233EFI_STATUS
234EFIAPI
235EntryPoint (
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**/
339CONST 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**/
350PFN_ESL_xSTRUCTOR mpfnEslConstructor = NULL;  ///<  No EfiSocketLib constructor needed for SocketDxe
351PFN_ESL_xSTRUCTOR mpfnEslDestructor = NULL;   ///<  No EfiSocketLib destructor needed for SocketDxe
352