]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/EfiSocketLib/Service.c
OvmfPkg/AcpiPlatformDxe: Fix VS2010 build issue
[mirror_edk2.git] / StdLib / EfiSocketLib / Service.c
CommitLineData
d7ce7006 1/** @file\r
2 Connect to and disconnect from the various network layers\r
3\r
4 Copyright (c) 2011, Intel Corporation\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "Socket.h"\r
16\r
d7ce7006 17\r
18/**\r
19 Connect to the network service bindings\r
20\r
21 Walk the network service protocols on the controller handle and\r
a88c3163 22 locate any that are not in use. Create ::ESL_SERVICE structures to\r
23 manage the network layer interfaces for the socket driver. Tag\r
24 each of the network interfaces that are being used. Finally, this\r
25 routine calls ESL_SOCKET_BINDING::pfnInitialize to prepare the network\r
26 interface for use by the socket layer.\r
d7ce7006 27\r
28 @param [in] BindingHandle Handle for protocol binding.\r
29 @param [in] Controller Handle of device to work with.\r
30\r
31 @retval EFI_SUCCESS This driver is added to Controller.\r
32 @retval other This driver does not support this device.\r
33\r
34**/\r
35EFI_STATUS\r
36EFIAPI\r
37EslServiceConnect (\r
38 IN EFI_HANDLE BindingHandle,\r
39 IN EFI_HANDLE Controller\r
40 )\r
41{\r
42 BOOLEAN bInUse;\r
43 UINTN LengthInBytes;\r
a88c3163 44 UINT8 * pBuffer;\r
45 CONST ESL_SOCKET_BINDING * pEnd;\r
d7ce7006 46 VOID * pJunk;\r
a88c3163 47 ESL_SERVICE ** ppServiceListHead;\r
48 ESL_SERVICE * pService;\r
49 CONST ESL_SOCKET_BINDING * pSocketBinding;\r
50 EFI_SERVICE_BINDING_PROTOCOL * pServiceBinding;\r
d7ce7006 51 EFI_STATUS Status;\r
52 EFI_TPL TplPrevious;\r
53\r
54 DBG_ENTER ( );\r
55\r
56 //\r
57 // Assume the list is empty\r
58 //\r
59 Status = EFI_UNSUPPORTED;\r
60 bInUse = FALSE;\r
61\r
62 //\r
63 // Walk the list of network connection points\r
64 //\r
65 pSocketBinding = &cEslSocketBinding[0];\r
66 pEnd = &pSocketBinding[ cEslSocketBindingEntries ];\r
67 while ( pEnd > pSocketBinding ) {\r
68 //\r
69 // Determine if the controller supports the network protocol\r
70 //\r
71 Status = gBS->OpenProtocol (\r
72 Controller,\r
73 pSocketBinding->pNetworkBinding,\r
a88c3163 74 (VOID**)&pServiceBinding,\r
d7ce7006 75 BindingHandle,\r
76 Controller,\r
77 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
78 );\r
79 if ( !EFI_ERROR ( Status )) {\r
80 //\r
81 // Determine if the socket layer is already connected\r
82 //\r
83 Status = gBS->OpenProtocol (\r
84 Controller,\r
85 (EFI_GUID *)pSocketBinding->pTagGuid,\r
86 &pJunk,\r
87 BindingHandle,\r
88 Controller,\r
89 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
90 );\r
91 if ( EFI_UNSUPPORTED == Status ) {\r
92 //\r
93 // Allocate a service structure since the tag is not present\r
94 //\r
95 LengthInBytes = sizeof ( *pService );\r
96 Status = gBS->AllocatePool (\r
97 EfiRuntimeServicesData,\r
98 LengthInBytes,\r
99 (VOID **) &pService\r
100 );\r
101 if ( !EFI_ERROR ( Status )) {\r
102 DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
103 "0x%08x: Allocate pService, %d bytes\r\n",\r
104 pService,\r
105 LengthInBytes ));\r
106\r
107 //\r
108 // Set the structure signature and service binding\r
109 //\r
110 ZeroMem ( pService, LengthInBytes );\r
111 pService->Signature = SERVICE_SIGNATURE;\r
112 pService->pSocketBinding = pSocketBinding;\r
113 pService->Controller = Controller;\r
a88c3163 114 pService->pServiceBinding = pServiceBinding;\r
d7ce7006 115\r
116 //\r
117 // Mark the controller in use\r
118 //\r
119 if ( !bInUse ) {\r
120 Status = gBS->InstallMultipleProtocolInterfaces (\r
121 &Controller,\r
122 &gEfiCallerIdGuid,\r
123 NULL,\r
124 NULL\r
125 );\r
126 if ( !EFI_ERROR ( Status )) {\r
127 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
128 "Installed: gEfiCallerIdGuid on 0x%08x\r\n",\r
129 Controller ));\r
130 bInUse = TRUE;\r
131 }\r
132 else {\r
133 if ( EFI_INVALID_PARAMETER == Status ) {\r
134 Status = EFI_SUCCESS;\r
135 }\r
136 }\r
137 }\r
138 if ( !EFI_ERROR ( Status )) {\r
139 //\r
140 // Mark the network service protocol in use\r
141 //\r
142 Status = gBS->InstallMultipleProtocolInterfaces (\r
143 &Controller,\r
144 pSocketBinding->pTagGuid,\r
145 pService,\r
146 NULL\r
147 );\r
148 if ( !EFI_ERROR ( Status )) {\r
149 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
150 "Installed: %s TagGuid on 0x%08x\r\n",\r
151 pSocketBinding->pName,\r
152 Controller ));\r
153\r
154 //\r
155 // Synchronize with the socket layer\r
156 //\r
157 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
158\r
159 //\r
a88c3163 160 // Connect the service to the list\r
d7ce7006 161 //\r
a88c3163 162 pBuffer = (UINT8 *)&mEslLayer;\r
163 pBuffer = &pBuffer[ pSocketBinding->ServiceListOffset ];\r
164 ppServiceListHead = (ESL_SERVICE **)pBuffer;\r
165 pService->pNext = *ppServiceListHead;\r
166 *ppServiceListHead = pService;\r
d7ce7006 167\r
168 //\r
169 // Release the socket layer synchronization\r
170 //\r
171 RESTORE_TPL ( TplPrevious );\r
172\r
173 //\r
174 // Determine if the initialization was successful\r
175 //\r
176 if ( EFI_ERROR ( Status )) {\r
177 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,\r
178 "ERROR - Failed to initialize service %s on 0x%08x, Status: %r\r\n",\r
179 pSocketBinding->pName,\r
180 Controller,\r
181 Status ));\r
182\r
183 //\r
184 // Free the network service binding if necessary\r
185 //\r
186 gBS->UninstallMultipleProtocolInterfaces (\r
187 Controller,\r
188 pSocketBinding->pTagGuid,\r
189 pService,\r
190 NULL );\r
191 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
192 "Removed: %s TagGuid from 0x%08x\r\n",\r
193 pSocketBinding->pName,\r
194 Controller ));\r
195 }\r
196 }\r
197 else {\r
198 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,\r
199 "ERROR - Failed to install %s TagGuid on 0x%08x, Status: %r\r\n",\r
200 pSocketBinding->pName,\r
201 Controller,\r
202 Status ));\r
203 }\r
204\r
205 if ( EFI_ERROR ( Status )) {\r
206 //\r
207 // The controller is no longer in use\r
208 //\r
209 if ( bInUse ) {\r
210 gBS->UninstallMultipleProtocolInterfaces (\r
211 Controller,\r
212 &gEfiCallerIdGuid,\r
213 NULL,\r
214 NULL );\r
215 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
216 "Removed: gEfiCallerIdGuid from 0x%08x\r\n",\r
217 Controller ));\r
218 }\r
219 }\r
220 }\r
221 else {\r
222 DEBUG (( DEBUG_ERROR | DEBUG_INIT,\r
223 "ERROR - Failed to install gEfiCallerIdGuid on 0x%08x, Status: %r\r\n",\r
224 Controller,\r
225 Status ));\r
226 }\r
227\r
228 //\r
229 // Release the service if necessary\r
230 //\r
231 if ( EFI_ERROR ( Status )) {\r
232 gBS->FreePool ( pService );\r
233 DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
234 "0x%08x: Free pService, %d bytes\r\n",\r
235 pService,\r
236 sizeof ( *pService )));\r
237 pService = NULL;\r
238 }\r
239 }\r
240 else {\r
241 DEBUG (( DEBUG_ERROR | DEBUG_INIT,\r
242 "ERROR - Failed service allocation, Status: %r\r\n",\r
243 Status ));\r
244 }\r
245 }\r
246 }\r
247 \r
248 //\r
249 // Set the next network protocol\r
250 //\r
251 pSocketBinding += 1;\r
252 }\r
253 \r
254 //\r
255 // Display the driver start status\r
256 //\r
257 DBG_EXIT_STATUS ( Status );\r
258 return Status;\r
259}\r
260\r
261\r
262/**\r
a88c3163 263 Shutdown the connections to the network layer by locating the\r
264 tags on the network interfaces established by ::EslServiceConnect.\r
265 This routine shutdowns any activity on the network interface and\r
266 then frees the ::ESL_SERVICE structures.\r
d7ce7006 267\r
268 @param [in] BindingHandle Handle for protocol binding.\r
a88c3163 269 @param [in] Controller Handle of device to stop driver on.\r
d7ce7006 270\r
271 @retval EFI_SUCCESS This driver is removed Controller.\r
272 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
273 @retval other This driver was not removed from this device.\r
274\r
275**/\r
276EFI_STATUS\r
277EFIAPI\r
278EslServiceDisconnect (\r
279 IN EFI_HANDLE BindingHandle,\r
280 IN EFI_HANDLE Controller\r
281 )\r
282{\r
a88c3163 283 UINT8 * pBuffer;\r
284 CONST ESL_SOCKET_BINDING * pEnd;\r
285 ESL_PORT * pPort;\r
286 ESL_SERVICE * pPreviousService;\r
287 ESL_SERVICE * pService;\r
288 ESL_SERVICE ** ppServiceListHead;\r
289 CONST ESL_SOCKET_BINDING * pSocketBinding;\r
d7ce7006 290 EFI_STATUS Status;\r
291 EFI_TPL TplPrevious;\r
292 \r
293 DBG_ENTER ( );\r
294\r
295 //\r
296 // Walk the list of network connection points in reverse order\r
297 //\r
298 pEnd = &cEslSocketBinding[0];\r
299 pSocketBinding = &pEnd[ cEslSocketBindingEntries ];\r
300 while ( pEnd < pSocketBinding ) {\r
301 //\r
302 // Set the next network protocol\r
303 //\r
304 pSocketBinding -= 1;\r
305\r
306 //\r
307 // Determine if the driver connected\r
308 //\r
309 Status = gBS->OpenProtocol (\r
310 Controller,\r
311 (EFI_GUID *)pSocketBinding->pTagGuid,\r
312 (VOID **)&pService,\r
313 BindingHandle,\r
314 Controller,\r
315 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
316 );\r
317 if ( !EFI_ERROR ( Status )) {\r
318\r
319 //\r
320 // Synchronize with the socket layer\r
321 //\r
322 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
323\r
324 //\r
a88c3163 325 // Walk the list of ports\r
d7ce7006 326 //\r
a88c3163 327 pPort = pService->pPortList;\r
328 while ( NULL != pPort ) {\r
329 //\r
330 // Remove the port from the port list\r
331 //\r
332 pPort->pService = NULL;\r
333 pService->pPortList = pPort->pLinkService;\r
334 \r
335 //\r
336 // Close the port\r
337 //\r
338 EslSocketPortCloseStart ( pPort,\r
339 TRUE,\r
340 DEBUG_POOL | DEBUG_INIT );\r
341\r
342 //\r
343 // Set the next port\r
344 //\r
345 pPort = pService->pPortList;\r
346 }\r
347 \r
348 //\r
349 // Remove the service from the service list\r
350 //\r
351 pBuffer = (UINT8 *)&mEslLayer;\r
352 pBuffer = &pBuffer[ pService->pSocketBinding->ServiceListOffset ];\r
353 ppServiceListHead = (ESL_SERVICE **)pBuffer;\r
354 pPreviousService = *ppServiceListHead;\r
355 if ( pService == pPreviousService ) {\r
356 //\r
357 // Remove the service from the beginning of the list\r
358 //\r
359 *ppServiceListHead = pService->pNext;\r
360 }\r
361 else {\r
362 //\r
363 // Remove the service from the middle of the list\r
364 //\r
365 while ( NULL != pPreviousService ) {\r
366 if ( pService == pPreviousService->pNext ) {\r
367 pPreviousService->pNext = pService->pNext;\r
368 break;\r
369 }\r
370 pPreviousService = pPreviousService->pNext;\r
371 }\r
372 }\r
d7ce7006 373\r
374 //\r
375 // Release the socket layer synchronization\r
376 //\r
377 RESTORE_TPL ( TplPrevious );\r
378\r
379 //\r
380 // Break the driver connection\r
381 //\r
382 Status = gBS->UninstallMultipleProtocolInterfaces (\r
383 Controller,\r
384 pSocketBinding->pTagGuid,\r
385 pService,\r
386 NULL );\r
387 if ( !EFI_ERROR ( Status )) {\r
388 DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
389 "Removed: %s TagGuid from 0x%08x\r\n",\r
390 pSocketBinding->pName,\r
391 Controller ));\r
392 }\r
393 else {\r
394 DEBUG (( DEBUG_ERROR | DEBUG_POOL | DEBUG_INIT,\r
395 "ERROR - Failed to removed %s TagGuid from 0x%08x, Status: %r\r\n",\r
396 pSocketBinding->pName,\r
397 Controller,\r
398 Status ));\r
399 }\r
400\r
401 //\r
402 // Free the service structure\r
403 //\r
404 Status = gBS->FreePool ( pService );\r
405 if ( !EFI_ERROR ( Status )) {\r
406 DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
407 "0x%08x: Free pService, %d bytes\r\n",\r
408 pService,\r
409 sizeof ( *pService )));\r
410 }\r
411 else {\r
412 DEBUG (( DEBUG_POOL | DEBUG_INIT,\r
413 "ERROR - Failed to free pService 0x%08x, Status: %r\r\n",\r
414 pService,\r
415 Status ));\r
416 }\r
417 pService = NULL;\r
418 }\r
419 }\r
420\r
421 //\r
422 // The controller is no longer in use\r
423 //\r
424 gBS->UninstallMultipleProtocolInterfaces (\r
425 Controller,\r
426 &gEfiCallerIdGuid,\r
427 NULL,\r
428 NULL );\r
429 DEBUG (( DEBUG_POOL | DEBUG_INIT | DEBUG_INFO,\r
430 "Removed: gEfiCallerIdGuid from 0x%08x\r\n",\r
431 Controller ));\r
432\r
433 //\r
434 // The driver is disconnected from the network controller\r
435 //\r
436 Status = EFI_SUCCESS;\r
437\r
438 //\r
439 // Display the driver start status\r
440 //\r
441 DBG_EXIT_STATUS ( Status );\r
442 return Status;\r
443}\r
444\r
445\r
446\r
d7ce7006 447/**\r
448Initialize the service layer\r
449\r
450@param [in] ImageHandle Handle for the image.\r
451\r
452**/\r
453VOID\r
454EFIAPI\r
455EslServiceLoad (\r
456 IN EFI_HANDLE ImageHandle\r
457 )\r
458{\r
a88c3163 459 ESL_LAYER * pLayer;\r
d7ce7006 460\r
461 //\r
462 // Save the image handle\r
463 //\r
464 pLayer = &mEslLayer;\r
a88c3163 465 ZeroMem ( pLayer, sizeof ( *pLayer ));\r
d7ce7006 466 pLayer->Signature = LAYER_SIGNATURE;\r
467 pLayer->ImageHandle = ImageHandle;\r
468\r
d7ce7006 469 //\r
470 // Connect the service binding protocol to the image handle\r
471 //\r
a88c3163 472 pLayer->pServiceBinding = &mEfiServiceBinding;\r
d7ce7006 473}\r
474\r
475\r
476/**\r
477 Shutdown the service layer\r
478\r
479**/\r
480VOID\r
481EFIAPI\r
482EslServiceUnload (\r
483 VOID\r
484 )\r
485{\r
a88c3163 486 ESL_LAYER * pLayer;\r
d7ce7006 487\r
488 //\r
489 // Undo the work by ServiceLoad\r
490 //\r
491 pLayer = &mEslLayer;\r
492 pLayer->ImageHandle = NULL;\r
a88c3163 493 pLayer->pServiceBinding = NULL;\r
d7ce7006 494}\r