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