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