]> git.proxmox.com Git - mirror_edk2.git/blob - StdLib/EfiSocketLib/Service.c
Add Socket Libraries.
[mirror_edk2.git] / StdLib / EfiSocketLib / Service.c
1 /** @file
2 Connect to and disconnect from the various network layers
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 EFI_TCP4_PROTOCOL * mpEfiTcpClose4 [ 1024 ];
18
19
20 /**
21 Connect to the network service bindings
22
23 Walk the network service protocols on the controller handle and
24 locate any that are not in use. Create service structures to
25 manage the service binding for the socket driver.
26
27 @param [in] BindingHandle Handle for protocol binding.
28 @param [in] Controller Handle of device to work with.
29
30 @retval EFI_SUCCESS This driver is added to Controller.
31 @retval other This driver does not support this device.
32
33 **/
34 EFI_STATUS
35 EFIAPI
36 EslServiceConnect (
37 IN EFI_HANDLE BindingHandle,
38 IN EFI_HANDLE Controller
39 )
40 {
41 BOOLEAN bInUse;
42 UINTN LengthInBytes;
43 CONST DT_SOCKET_BINDING * pEnd;
44 VOID * pJunk;
45 VOID * pInterface;
46 DT_SERVICE * pService;
47 CONST DT_SOCKET_BINDING * pSocketBinding;
48 EFI_STATUS Status;
49 EFI_TPL TplPrevious;
50
51 DBG_ENTER ( );
52
53 //
54 // Assume the list is empty
55 //
56 Status = EFI_UNSUPPORTED;
57 bInUse = FALSE;
58
59 //
60 // Walk the list of network connection points
61 //
62 pSocketBinding = &cEslSocketBinding[0];
63 pEnd = &pSocketBinding[ cEslSocketBindingEntries ];
64 while ( pEnd > pSocketBinding ) {
65 //
66 // Determine if the controller supports the network protocol
67 //
68 Status = gBS->OpenProtocol (
69 Controller,
70 pSocketBinding->pNetworkBinding,
71 &pInterface,
72 BindingHandle,
73 Controller,
74 EFI_OPEN_PROTOCOL_GET_PROTOCOL
75 );
76 if ( !EFI_ERROR ( Status )) {
77 //
78 // Determine if the socket layer is already connected
79 //
80 Status = gBS->OpenProtocol (
81 Controller,
82 (EFI_GUID *)pSocketBinding->pTagGuid,
83 &pJunk,
84 BindingHandle,
85 Controller,
86 EFI_OPEN_PROTOCOL_GET_PROTOCOL
87 );
88 if ( EFI_UNSUPPORTED == Status ) {
89 //
90 // Allocate a service structure since the tag is not present
91 //
92 LengthInBytes = sizeof ( *pService );
93 Status = gBS->AllocatePool (
94 EfiRuntimeServicesData,
95 LengthInBytes,
96 (VOID **) &pService
97 );
98 if ( !EFI_ERROR ( Status )) {
99 DEBUG (( DEBUG_POOL | DEBUG_INIT,
100 "0x%08x: Allocate pService, %d bytes\r\n",
101 pService,
102 LengthInBytes ));
103
104 //
105 // Set the structure signature and service binding
106 //
107 ZeroMem ( pService, LengthInBytes );
108 pService->Signature = SERVICE_SIGNATURE;
109 pService->pSocketBinding = pSocketBinding;
110 pService->Controller = Controller;
111 pService->pInterface = pInterface;
112
113 //
114 // Mark the controller in use
115 //
116 if ( !bInUse ) {
117 Status = gBS->InstallMultipleProtocolInterfaces (
118 &Controller,
119 &gEfiCallerIdGuid,
120 NULL,
121 NULL
122 );
123 if ( !EFI_ERROR ( Status )) {
124 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
125 "Installed: gEfiCallerIdGuid on 0x%08x\r\n",
126 Controller ));
127 bInUse = TRUE;
128 }
129 else {
130 if ( EFI_INVALID_PARAMETER == Status ) {
131 Status = EFI_SUCCESS;
132 }
133 }
134 }
135 if ( !EFI_ERROR ( Status )) {
136 //
137 // Mark the network service protocol in use
138 //
139 Status = gBS->InstallMultipleProtocolInterfaces (
140 &Controller,
141 pSocketBinding->pTagGuid,
142 pService,
143 NULL
144 );
145 if ( !EFI_ERROR ( Status )) {
146 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
147 "Installed: %s TagGuid on 0x%08x\r\n",
148 pSocketBinding->pName,
149 Controller ));
150
151 //
152 // Synchronize with the socket layer
153 //
154 RAISE_TPL ( TplPrevious, TPL_SOCKETS );
155
156 //
157 // Initialize the service
158 //
159 Status = pSocketBinding->pfnInitialize ( pService );
160
161 //
162 // Release the socket layer synchronization
163 //
164 RESTORE_TPL ( TplPrevious );
165
166 //
167 // Determine if the initialization was successful
168 //
169 if ( EFI_ERROR ( Status )) {
170 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
171 "ERROR - Failed to initialize service %s on 0x%08x, Status: %r\r\n",
172 pSocketBinding->pName,
173 Controller,
174 Status ));
175
176 //
177 // Free the network service binding if necessary
178 //
179 gBS->UninstallMultipleProtocolInterfaces (
180 Controller,
181 pSocketBinding->pTagGuid,
182 pService,
183 NULL );
184 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
185 "Removed: %s TagGuid from 0x%08x\r\n",
186 pSocketBinding->pName,
187 Controller ));
188 }
189 }
190 else {
191 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
192 "ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n",
193 pSocketBinding->pName,
194 Controller,
195 Status ));
196 }
197
198 if ( EFI_ERROR ( Status )) {
199 //
200 // The controller is no longer in use
201 //
202 if ( bInUse ) {
203 gBS->UninstallMultipleProtocolInterfaces (
204 Controller,
205 &gEfiCallerIdGuid,
206 NULL,
207 NULL );
208 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
209 "Removed: gEfiCallerIdGuid from 0x%08x\r\n",
210 Controller ));
211 }
212 }
213 }
214 else {
215 DEBUG (( DEBUG_ERROR | DEBUG_INIT,
216 "ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n",
217 Controller,
218 Status ));
219 }
220
221 //
222 // Release the service if necessary
223 //
224 if ( EFI_ERROR ( Status )) {
225 gBS->FreePool ( pService );
226 DEBUG (( DEBUG_POOL | DEBUG_INIT,
227 "0x%08x: Free pService, %d bytes\r\n",
228 pService,
229 sizeof ( *pService )));
230 pService = NULL;
231 }
232 }
233 else {
234 DEBUG (( DEBUG_ERROR | DEBUG_INIT,
235 "ERROR - Failed service allocation, Status: %r\r\n",
236 Status ));
237 }
238 }
239 }
240
241 //
242 // Set the next network protocol
243 //
244 pSocketBinding += 1;
245 }
246
247 //
248 // Display the driver start status
249 //
250 DBG_EXIT_STATUS ( Status );
251 return Status;
252 }
253
254
255 /**
256 Shutdown the network connections to this controller by removing
257 NetworkInterfaceIdentifier protocol and closing the DevicePath
258 and PciIo protocols on Controller.
259
260 @param [in] BindingHandle Handle for protocol binding.
261 @param [in] Controller Handle of device to stop driver on.
262
263 @retval EFI_SUCCESS This driver is removed Controller.
264 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
265 @retval other This driver was not removed from this device.
266
267 **/
268 EFI_STATUS
269 EFIAPI
270 EslServiceDisconnect (
271 IN EFI_HANDLE BindingHandle,
272 IN EFI_HANDLE Controller
273 )
274 {
275 CONST DT_SOCKET_BINDING * pEnd;
276 DT_SERVICE * pService;
277 CONST DT_SOCKET_BINDING * pSocketBinding;
278 EFI_STATUS Status;
279 EFI_TPL TplPrevious;
280
281 DBG_ENTER ( );
282
283 //
284 // Walk the list of network connection points in reverse order
285 //
286 pEnd = &cEslSocketBinding[0];
287 pSocketBinding = &pEnd[ cEslSocketBindingEntries ];
288 while ( pEnd < pSocketBinding ) {
289 //
290 // Set the next network protocol
291 //
292 pSocketBinding -= 1;
293
294 //
295 // Determine if the driver connected
296 //
297 Status = gBS->OpenProtocol (
298 Controller,
299 (EFI_GUID *)pSocketBinding->pTagGuid,
300 (VOID **)&pService,
301 BindingHandle,
302 Controller,
303 EFI_OPEN_PROTOCOL_GET_PROTOCOL
304 );
305 if ( !EFI_ERROR ( Status )) {
306
307 //
308 // Synchronize with the socket layer
309 //
310 RAISE_TPL ( TplPrevious, TPL_SOCKETS );
311
312 //
313 // Shutdown the service
314 //
315 pSocketBinding->pfnShutdown ( pService );
316
317 //
318 // Release the socket layer synchronization
319 //
320 RESTORE_TPL ( TplPrevious );
321
322 //
323 // Break the driver connection
324 //
325 Status = gBS->UninstallMultipleProtocolInterfaces (
326 Controller,
327 pSocketBinding->pTagGuid,
328 pService,
329 NULL );
330 if ( !EFI_ERROR ( Status )) {
331 DEBUG (( DEBUG_POOL | DEBUG_INIT,
332 "Removed: %s TagGuid from 0x%08x\r\n",
333 pSocketBinding->pName,
334 Controller ));
335 }
336 else {
337 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
338 "ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n",
339 pSocketBinding->pName,
340 Controller,
341 Status ));
342 }
343
344 //
345 // Free the service structure
346 //
347 Status = gBS->FreePool ( pService );
348 if ( !EFI_ERROR ( Status )) {
349 DEBUG (( DEBUG_POOL | DEBUG_INIT,
350 "0x%08x: Free pService, %d bytes\r\n",
351 pService,
352 sizeof ( *pService )));
353 }
354 else {
355 DEBUG (( DEBUG_POOL | DEBUG_INIT,
356 "ERROR - Failed to free pService 0x%08x, Status: %r\r\n",
357 pService,
358 Status ));
359 }
360 pService = NULL;
361 }
362 }
363
364 //
365 // The controller is no longer in use
366 //
367 gBS->UninstallMultipleProtocolInterfaces (
368 Controller,
369 &gEfiCallerIdGuid,
370 NULL,
371 NULL );
372 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
373 "Removed: gEfiCallerIdGuid from 0x%08x\r\n",
374 Controller ));
375
376 //
377 // The driver is disconnected from the network controller
378 //
379 Status = EFI_SUCCESS;
380
381 //
382 // Display the driver start status
383 //
384 DBG_EXIT_STATUS ( Status );
385 return Status;
386 }
387
388
389
390 /**
391 Install the socket service
392
393 @param [in] pImageHandle Address of the image handle
394
395 @retval EFI_SUCCESS Service installed successfully
396 **/
397 EFI_STATUS
398 EFIAPI
399 EslServiceInstall (
400 IN EFI_HANDLE * pImageHandle
401 )
402 {
403 EFI_STATUS Status;
404
405 //
406 // Install the socket service binding protocol
407 //
408 Status = gBS->InstallMultipleProtocolInterfaces (
409 pImageHandle,
410 &gEfiSocketServiceBindingProtocolGuid,
411 &mEslLayer.ServiceBinding,
412 NULL
413 );
414 if ( !EFI_ERROR ( Status )) {
415 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,
416 "Installed: gEfiSocketServiceBindingProtocolGuid on 0x%08x\r\n",
417 *pImageHandle ));
418 }
419 else {
420 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
421 "ERROR - InstallMultipleProtocolInterfaces failed, Status: %r\r\n",
422 Status ));
423 }
424
425 //
426 // Return the operation status
427 //
428 return Status;
429 }
430
431
432 /**
433 Initialize the service layer
434
435 @param [in] ImageHandle Handle for the image.
436
437 **/
438 VOID
439 EFIAPI
440 EslServiceLoad (
441 IN EFI_HANDLE ImageHandle
442 )
443 {
444 DT_LAYER * pLayer;
445
446 //
447 // Save the image handle
448 //
449 pLayer = &mEslLayer;
450 pLayer->Signature = LAYER_SIGNATURE;
451 pLayer->ImageHandle = ImageHandle;
452
453 //
454 // Initialize the TCP4 close
455 //
456 pLayer->TcpCloseMax4 = DIM ( mpEfiTcpClose4 );
457 pLayer->ppTcpClose4 = mpEfiTcpClose4;
458
459 //
460 // Connect the service binding protocol to the image handle
461 //
462 pLayer->ServiceBinding.CreateChild = EslSocketCreateChild;
463 pLayer->ServiceBinding.DestroyChild = EslSocketDestroyChild;
464 }
465
466
467 /**
468 Uninstall the socket service
469
470 @param [in] ImageHandle Handle for the image.
471
472 @retval EFI_SUCCESS Service installed successfully
473 **/
474 EFI_STATUS
475 EFIAPI
476 EslServiceUninstall (
477 IN EFI_HANDLE ImageHandle
478 )
479 {
480 EFI_STATUS Status;
481
482 //
483 // Install the socket service binding protocol
484 //
485 Status = gBS->UninstallMultipleProtocolInterfaces (
486 ImageHandle,
487 &gEfiSocketServiceBindingProtocolGuid,
488 &mEslLayer.ServiceBinding,
489 NULL
490 );
491 if ( !EFI_ERROR ( Status )) {
492 DEBUG (( DEBUG_POOL | DEBUG_INIT,
493 "Removed: gEfiSocketServiceBindingProtocolGuid from 0x%08x\r\n",
494 ImageHandle ));
495 }
496 else {
497 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,
498 "ERROR - Failed to remove gEfiSocketServiceBindingProtocolGuid from 0x%08x, Status: %r\r\n",
499 ImageHandle,
500 Status ));
501 }
502
503 //
504 // Return the operation status
505 //
506 return Status;
507 }
508
509
510 /**
511 Shutdown the service layer
512
513 **/
514 VOID
515 EFIAPI
516 EslServiceUnload (
517 VOID
518 )
519 {
520 DT_LAYER * pLayer;
521
522 //
523 // Undo the work by ServiceLoad
524 //
525 pLayer = &mEslLayer;
526 pLayer->ImageHandle = NULL;
527 pLayer->ServiceBinding.CreateChild = NULL;
528 pLayer->ServiceBinding.DestroyChild = NULL;
529 }