]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
Sync the latest version from R8.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file
2
3 Copyright (c) 2005 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 MnpDriver.c
15
16 Abstract:
17
18
19 **/
20
21 #include "MnpDriver.h"
22 #include "MnpDebug.h"
23 #include "MnpImpl.h"
24
25
26 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {
27 MnpDriverBindingSupported,
28 MnpDriverBindingStart,
29 MnpDriverBindingStop,
30 0xa,
31 NULL,
32 NULL
33 };
34
35
36 /**
37 Test to see if this driver supports ControllerHandle.
38
39 @param This Protocol instance pointer.
40 @param ControllerHandle Handle of device to test.
41 @param RemainingDevicePath Optional parameter use to pick a specific child
42 device to start.
43
44 @retval EFI_SUCCES This driver supports this device.
45 @retval EFI_ALREADY_STARTED This driver is already running on this device.
46 @retval other This driver does not support this device.
47
48 **/
49 EFI_STATUS
50 EFIAPI
51 MnpDriverBindingSupported (
52 IN EFI_DRIVER_BINDING_PROTOCOL *This,
53 IN EFI_HANDLE ControllerHandle,
54 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
55 )
56 {
57 EFI_STATUS Status;
58
59 //
60 // Test to see if MNP is already installed.
61 //
62 Status = gBS->OpenProtocol (
63 ControllerHandle,
64 &gEfiManagedNetworkServiceBindingProtocolGuid,
65 NULL,
66 This->DriverBindingHandle,
67 ControllerHandle,
68 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
69 );
70 if (!EFI_ERROR (Status)) {
71
72 return EFI_ALREADY_STARTED;
73 }
74
75 //
76 // Test to see if SNP is installed.
77 //
78 Status = gBS->OpenProtocol (
79 ControllerHandle,
80 &gEfiSimpleNetworkProtocolGuid,
81 NULL,
82 This->DriverBindingHandle,
83 ControllerHandle,
84 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
85 );
86
87 return Status;
88 }
89
90
91 /**
92 Start this driver on ControllerHandle.
93
94 @param This Protocol instance pointer.
95 @param ControllerHandle Handle of device to bind driver to.
96 @param RemainingDevicePath Optional parameter use to pick a specific child
97 device to start.
98
99 @retval EFI_SUCCES This driver is added to ControllerHandle.
100 @retval EFI_ALREADY_STARTED This driver is already running on
101 ControllerHandle.
102 @retval other This driver does not support this device.
103
104 **/
105 EFI_STATUS
106 EFIAPI
107 MnpDriverBindingStart (
108 IN EFI_DRIVER_BINDING_PROTOCOL *This,
109 IN EFI_HANDLE ControllerHandle,
110 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
111 )
112 {
113 EFI_STATUS Status;
114 MNP_SERVICE_DATA *MnpServiceData;
115 BOOLEAN MnpInitialized;
116
117 MnpInitialized = FALSE;
118
119 MnpServiceData = NetAllocateZeroPool (sizeof (MNP_SERVICE_DATA));
120 if (MnpServiceData == NULL) {
121 MNP_DEBUG_ERROR (("MnpDriverBindingStart(): Failed to allocate the "
122 L"Mnp Service Data.\n"));
123
124 return EFI_OUT_OF_RESOURCES;
125 }
126
127 //
128 // Initialize the Mnp Service Data.
129 //
130 Status = MnpInitializeServiceData (MnpServiceData, This->DriverBindingHandle, ControllerHandle);
131 if (EFI_ERROR (Status)) {
132
133 MNP_DEBUG_ERROR (("MnpDriverBindingStart: MnpInitializeServiceData "
134 L"failed, %r.\n",Status));
135 goto ErrorExit;
136 }
137
138 MnpInitialized = TRUE;
139
140 //
141 // Install the MNP Service Binding Protocol.
142 //
143 Status = gBS->InstallMultipleProtocolInterfaces (
144 &ControllerHandle,
145 &gEfiManagedNetworkServiceBindingProtocolGuid,
146 &MnpServiceData->ServiceBinding,
147 NULL
148 );
149
150 ErrorExit:
151
152 if (EFI_ERROR (Status)) {
153
154 if (MnpInitialized) {
155 //
156 // Flush the Mnp Service Data.
157 //
158 MnpFlushServiceData (MnpServiceData);
159 }
160
161 //
162 // Close the Simple Network Protocol.
163 //
164 gBS->CloseProtocol (
165 ControllerHandle,
166 &gEfiSimpleNetworkProtocolGuid,
167 This->DriverBindingHandle,
168 ControllerHandle
169 );
170
171 NetFreePool (MnpServiceData);
172 }
173
174 return Status;
175 }
176
177
178 /**
179 Stop this driver on ControllerHandle.
180
181 @param This Protocol instance pointer.
182 @param ControllerHandle Handle of device to stop driver on.
183 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
184 of children is zero stop the entire bus driver.
185 @param ChildHandleBuffer List of Child Handles to Stop.
186
187 @retval EFI_SUCCES This driver is removed ControllerHandle.
188 @retval other This driver was not removed from this device.
189
190 **/
191 EFI_STATUS
192 EFIAPI
193 MnpDriverBindingStop (
194 IN EFI_DRIVER_BINDING_PROTOCOL *This,
195 IN EFI_HANDLE ControllerHandle,
196 IN UINTN NumberOfChildren,
197 IN EFI_HANDLE *ChildHandleBuffer
198 )
199 {
200 EFI_STATUS Status;
201 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
202 MNP_SERVICE_DATA *MnpServiceData;
203 MNP_INSTANCE_DATA *Instance;
204
205 //
206 // Retrieve the MNP service binding protocol from the ControllerHandle.
207 //
208 Status = gBS->OpenProtocol (
209 ControllerHandle,
210 &gEfiManagedNetworkServiceBindingProtocolGuid,
211 (VOID **) &ServiceBinding,
212 This->DriverBindingHandle,
213 ControllerHandle,
214 EFI_OPEN_PROTOCOL_GET_PROTOCOL
215 );
216 if (EFI_ERROR (Status)) {
217
218 MNP_DEBUG_ERROR (
219 ("MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",
220 Status)
221 );
222 return EFI_DEVICE_ERROR;
223 }
224
225 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);
226
227 if (NumberOfChildren == 0) {
228 //
229 // Uninstall the MNP Service Binding Protocol.
230 //
231 gBS->UninstallMultipleProtocolInterfaces (
232 ControllerHandle,
233 &gEfiManagedNetworkServiceBindingProtocolGuid,
234 ServiceBinding,
235 NULL
236 );
237
238 //
239 // Close the openned Snp protocol.
240 //
241 gBS->CloseProtocol (
242 ControllerHandle,
243 &gEfiSimpleNetworkProtocolGuid,
244 This->DriverBindingHandle,
245 ControllerHandle
246 );
247
248 //
249 // Flush the Mnp service data.
250 //
251 MnpFlushServiceData (MnpServiceData);
252
253 NetFreePool (MnpServiceData);
254 } else {
255 while (!NetListIsEmpty (&MnpServiceData->ChildrenList)) {
256 //
257 // Don't use NetListRemoveHead here, the remove opreration will be done
258 // in ServiceBindingDestroyChild.
259 //
260 Instance = NET_LIST_HEAD (
261 &MnpServiceData->ChildrenList,
262 MNP_INSTANCE_DATA,
263 InstEntry
264 );
265
266 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
267 }
268 }
269
270 return Status;
271 }
272
273
274 /**
275 Creates a child handle with a set of I/O services.
276
277 @param This Protocol instance pointer.
278 @param ChildHandle Pointer to the handle of the child to create. If
279 it is NULL, then a new handle is created. If it is
280 not NULL, then the I/O services are added to the
281 existing child handle.
282
283 @retval EFI_SUCCES The child handle was created with the I/O
284 services.
285 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
286 the child.
287 @retval other The child handle was not created.
288
289 **/
290 EFI_STATUS
291 EFIAPI
292 MnpServiceBindingCreateChild (
293 IN EFI_SERVICE_BINDING_PROTOCOL *This,
294 IN EFI_HANDLE *ChildHandle
295 )
296 {
297 EFI_STATUS Status;
298 MNP_SERVICE_DATA *MnpServiceData;
299 MNP_INSTANCE_DATA *Instance;
300 VOID *Snp;
301 EFI_TPL OldTpl;
302
303 if ((This == NULL) || (ChildHandle == NULL)) {
304
305 return EFI_INVALID_PARAMETER;
306 }
307
308 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
309
310 //
311 // Allocate buffer for the new instance.
312 //
313 Instance = NetAllocateZeroPool (sizeof (MNP_INSTANCE_DATA));
314 if (Instance == NULL) {
315
316 MNP_DEBUG_ERROR (("MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
317 return EFI_OUT_OF_RESOURCES;
318 }
319
320 //
321 // Init the instance data.
322 //
323 MnpInitializeInstanceData (MnpServiceData, Instance);
324
325 Status = gBS->InstallMultipleProtocolInterfaces (
326 ChildHandle,
327 &gEfiManagedNetworkProtocolGuid,
328 &Instance->ManagedNetwork,
329 NULL
330 );
331 if (EFI_ERROR (Status)) {
332
333 MNP_DEBUG_ERROR (
334 ("MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
335 Status)
336 );
337 goto ErrorExit;
338 }
339
340 //
341 // Save the instance's childhandle.
342 //
343 Instance->Handle = *ChildHandle;
344
345 Status = gBS->OpenProtocol (
346 MnpServiceData->ControllerHandle,
347 &gEfiSimpleNetworkProtocolGuid,
348 (VOID **) &Snp,
349 gMnpDriverBinding.DriverBindingHandle,
350 Instance->Handle,
351 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
352 );
353 if (EFI_ERROR (Status)) {
354 goto ErrorExit;
355 }
356
357 //
358 // Add the child instance into ChildrenList.
359 //
360 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
361
362 NetListInsertTail (&MnpServiceData->ChildrenList, &Instance->InstEntry);
363 MnpServiceData->ChildrenNumber++;
364
365 NET_RESTORE_TPL (OldTpl);
366
367 ErrorExit:
368
369 if (EFI_ERROR (Status)) {
370
371 if (Instance->Handle != NULL) {
372
373 gBS->UninstallMultipleProtocolInterfaces (
374 &gEfiManagedNetworkProtocolGuid,
375 &Instance->ManagedNetwork,
376 NULL
377 );
378 }
379
380 NetFreePool (Instance);
381 }
382
383 return Status;
384 }
385
386
387 /**
388 Destroys a child handle with a set of I/O services.
389
390 @param This Protocol instance pointer.
391 @param ChildHandle Handle of the child to destroy.
392
393 @retval EFI_SUCCES The I/O services were removed from the child
394 handle.
395 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
396 that are being removed.
397 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
398 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
399 its I/O services are being used.
400 @retval other The child handle was not destroyed.
401
402 **/
403 EFI_STATUS
404 EFIAPI
405 MnpServiceBindingDestroyChild (
406 IN EFI_SERVICE_BINDING_PROTOCOL *This,
407 IN EFI_HANDLE ChildHandle
408 )
409 {
410 EFI_STATUS Status;
411 MNP_SERVICE_DATA *MnpServiceData;
412 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;
413 MNP_INSTANCE_DATA *Instance;
414 EFI_TPL OldTpl;
415
416 if ((This == NULL) || (ChildHandle == NULL)) {
417
418 return EFI_INVALID_PARAMETER;
419 }
420
421 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
422
423 //
424 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
425 //
426 Status = gBS->OpenProtocol (
427 ChildHandle,
428 &gEfiManagedNetworkProtocolGuid,
429 (VOID **) &ManagedNetwork,
430 gMnpDriverBinding.DriverBindingHandle,
431 ChildHandle,
432 EFI_OPEN_PROTOCOL_GET_PROTOCOL
433 );
434 if (EFI_ERROR (Status)) {
435
436 return EFI_UNSUPPORTED;
437 }
438
439 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);
440
441 //
442 // MnpServiceBindingDestroyChild may be called twice: first called by
443 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
444 // in this ChildHandle. Use destroyed to make sure the resource clean code
445 // will only excecute once.
446 //
447 if (Instance->Destroyed) {
448
449 return EFI_SUCCESS;
450 }
451
452 Instance->Destroyed = TRUE;
453
454 //
455 // Close the Simple Network protocol.
456 //
457 gBS->CloseProtocol (
458 MnpServiceData->ControllerHandle,
459 &gEfiSimpleNetworkProtocolGuid,
460 gMnpDriverBinding.DriverBindingHandle,
461 ChildHandle
462 );
463
464 //
465 // Uninstall the ManagedNetwork protocol.
466 //
467 Status = gBS->UninstallMultipleProtocolInterfaces (
468 ChildHandle,
469 &gEfiManagedNetworkProtocolGuid,
470 &Instance->ManagedNetwork,
471 NULL
472 );
473 if (EFI_ERROR (Status)) {
474
475 MNP_DEBUG_ERROR (
476 ("MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
477 Status)
478 );
479
480 Instance->Destroyed = FALSE;
481 return Status;
482 }
483
484 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
485
486 //
487 // Reset the configuration.
488 //
489 ManagedNetwork->Configure (ManagedNetwork, NULL);
490
491 //
492 // Try to flush the RcvdPacketQueue.
493 //
494 MnpFlushRcvdDataQueue (Instance);
495
496 //
497 // Clean the RxTokenMap.
498 //
499 NetMapClean (&Instance->RxTokenMap);
500
501 //
502 // Remove this instance from the ChildrenList.
503 //
504 NetListRemoveEntry (&Instance->InstEntry);
505 MnpServiceData->ChildrenNumber--;
506
507 NET_RESTORE_TPL (OldTpl);
508
509 NetFreePool (Instance);
510
511 return Status;
512 }
513
514
515 EFI_STATUS
516 EFIAPI
517 MnpDriverEntryPoint (
518 IN EFI_HANDLE ImageHandle,
519 IN EFI_SYSTEM_TABLE *SystemTable
520 )
521 /*++
522
523 Routine Description:
524
525 The entry point for Mnp driver which installs the driver binding and component name
526 protocol on its ImageHandle.
527
528 Arguments:
529
530 ImageHandle - The image handle of the driver.
531 SystemTable - The system table.
532
533 Returns:
534
535 EFI_SUCCESS - If the driver binding and component name protocols are successfully
536 installed, otherwise if failed.
537
538 --*/
539 {
540 return EfiLibInstallDriverBindingComponentName2 (
541 ImageHandle,
542 SystemTable,
543 &gMnpDriverBinding,
544 ImageHandle,
545 &gMnpComponentName,
546 &gMnpComponentName2
547 );
548 }