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