]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
Fix the comments to follow UEFI Spec regarding how to check an EFI_HANDLE is valid...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file
2 Implementation of driver entry point and driver binding protocol.
3
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions
7 of the BSD License which accompanies this distribution. The full
8 text of the license may be found at<BR>
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "MnpDriver.h"
17 #include "MnpImpl.h"
18 #include "MnpVlan.h"
19
20 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {
21 MnpDriverBindingSupported,
22 MnpDriverBindingStart,
23 MnpDriverBindingStop,
24 0xa,
25 NULL,
26 NULL
27 };
28
29 /**
30 Test to see if this driver supports ControllerHandle. This service
31 is called by the EFI boot service ConnectController(). In
32 order to make drivers as small as possible, there are a few calling
33 restrictions for this service. ConnectController() must
34 follow these calling restrictions. If any other agent wishes to call
35 Supported() it must also follow these calling restrictions.
36
37 @param[in] This Protocol instance pointer.
38 @param[in] ControllerHandle Handle of device to test.
39 @param[in] RemainingDevicePath Optional parameter use to pick a specific
40 child device to start.
41
42 @retval EFI_SUCCESS This driver supports this device.
43 @retval EFI_ALREADY_STARTED This driver is already running on this device.
44 @retval Others This driver does not support this device.
45
46 **/
47 EFI_STATUS
48 EFIAPI
49 MnpDriverBindingSupported (
50 IN EFI_DRIVER_BINDING_PROTOCOL *This,
51 IN EFI_HANDLE ControllerHandle,
52 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
53 )
54 {
55 EFI_STATUS Status;
56 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
57
58 //
59 // Test to open the Simple Network protocol BY_DRIVER.
60 //
61 Status = gBS->OpenProtocol (
62 ControllerHandle,
63 &gEfiSimpleNetworkProtocolGuid,
64 (VOID **) &Snp,
65 This->DriverBindingHandle,
66 ControllerHandle,
67 EFI_OPEN_PROTOCOL_BY_DRIVER
68 );
69 if (EFI_ERROR (Status)) {
70 return Status;
71 }
72
73 //
74 // Close the openned SNP protocol.
75 //
76 gBS->CloseProtocol (
77 ControllerHandle,
78 &gEfiSimpleNetworkProtocolGuid,
79 This->DriverBindingHandle,
80 ControllerHandle
81 );
82
83 return EFI_SUCCESS;
84 }
85
86
87 /**
88 Start this driver on ControllerHandle. This service is called by the
89 EFI boot service ConnectController(). In order to make drivers as small
90 as possible, there are a few calling restrictions for this service.
91 ConnectController() must follow these calling restrictions. If any other
92 agent wishes to call Start() it must also follow these calling restrictions.
93
94 @param[in] This Protocol instance pointer.
95 @param[in] ControllerHandle Handle of device to bind driver to.
96 @param[in] RemainingDevicePath Optional parameter use to pick a specific
97 child device to start.
98
99 @retval EFI_SUCCESS This driver is added to ControllerHandle.
100 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
101 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Mnp Service Data.
102 @retval Others 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 MNP_DEVICE_DATA *MnpDeviceData;
116 LIST_ENTRY *Entry;
117 VLAN_TCI *VlanVariable;
118 UINTN NumberOfVlan;
119 UINTN Index;
120
121 VlanVariable = NULL;
122
123 //
124 // Initialize the Mnp Device Data
125 //
126 MnpDeviceData = AllocateZeroPool (sizeof (MNP_DEVICE_DATA));
127 if (MnpDeviceData == NULL) {
128 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Device Data.\n"));
129
130 return EFI_OUT_OF_RESOURCES;
131 }
132
133 Status = MnpInitializeDeviceData (MnpDeviceData, This->DriverBindingHandle, ControllerHandle);
134 if (EFI_ERROR (Status)) {
135 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeDeviceData failed, %r.\n", Status));
136
137 FreePool (MnpDeviceData);
138 return Status;
139 }
140
141 //
142 // Check whether NIC driver has already produced VlanConfig protocol
143 //
144 Status = gBS->OpenProtocol (
145 ControllerHandle,
146 &gEfiVlanConfigProtocolGuid,
147 NULL,
148 This->DriverBindingHandle,
149 ControllerHandle,
150 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
151 );
152 if (!EFI_ERROR (Status)) {
153 //
154 // NIC hardware already implement VLAN,
155 // no need to provide software VLAN implementation in MNP driver
156 //
157 MnpDeviceData->NumberOfVlan = 0;
158 ZeroMem (&MnpDeviceData->VlanConfig, sizeof (EFI_VLAN_CONFIG_PROTOCOL));
159 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);
160 Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
161 goto Exit;
162 }
163
164 //
165 // Install VLAN Config Protocol
166 //
167 Status = gBS->InstallMultipleProtocolInterfaces (
168 &ControllerHandle,
169 &gEfiVlanConfigProtocolGuid,
170 &MnpDeviceData->VlanConfig,
171 NULL
172 );
173 if (EFI_ERROR (Status)) {
174 goto Exit;
175 }
176
177 //
178 // Get current VLAN configuration from EFI Variable
179 //
180 NumberOfVlan = 0;
181 Status = MnpGetVlanVariable (MnpDeviceData, &NumberOfVlan, &VlanVariable);
182 if (EFI_ERROR (Status)) {
183 //
184 // No VLAN is set, create a default MNP service data for untagged frame
185 //
186 MnpDeviceData->NumberOfVlan = 0;
187 MnpServiceData = MnpCreateServiceData (MnpDeviceData, 0, 0);
188 Status = (MnpServiceData != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
189 goto Exit;
190 }
191
192 //
193 // Create MNP service data for each VLAN
194 //
195 MnpDeviceData->NumberOfVlan = NumberOfVlan;
196 for (Index = 0; Index < NumberOfVlan; Index++) {
197 MnpServiceData = MnpCreateServiceData (
198 MnpDeviceData,
199 VlanVariable[Index].Bits.Vid,
200 (UINT8) VlanVariable[Index].Bits.Priority
201 );
202
203 if (MnpServiceData == NULL) {
204 Status = EFI_OUT_OF_RESOURCES;
205
206 goto Exit;
207 }
208 }
209
210 Exit:
211 if (VlanVariable != NULL) {
212 FreePool (VlanVariable);
213 }
214
215 if (EFI_ERROR (Status)) {
216 //
217 // Destroy all MNP service data
218 //
219 while (!IsListEmpty (&MnpDeviceData->ServiceList)) {
220 Entry = GetFirstNode (&MnpDeviceData->ServiceList);
221 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
222 MnpDestroyServiceData (MnpServiceData);
223 }
224
225 //
226 // Uninstall the VLAN Config Protocol if any
227 //
228 if (MnpDeviceData->VlanConfig.Set != NULL) {
229 gBS->UninstallMultipleProtocolInterfaces (
230 MnpDeviceData->ControllerHandle,
231 &gEfiVlanConfigProtocolGuid,
232 &MnpDeviceData->VlanConfig,
233 NULL
234 );
235 }
236
237 //
238 // Destroy Mnp Device Data
239 //
240 MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);
241 FreePool (MnpDeviceData);
242 }
243
244 return Status;
245 }
246
247 /**
248 Stop this driver on ControllerHandle. This service is called by the
249 EFI boot service DisconnectController(). In order to make drivers as
250 small as possible, there are a few calling restrictions for this service.
251 DisconnectController() must follow these calling restrictions. If any other
252 agent wishes to call Stop() it must also follow these calling restrictions.
253
254 @param[in] This Protocol instance pointer.
255 @param[in] ControllerHandle Handle of device to stop driver on.
256 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If
257 number of children is zero stop the entire
258 bus driver.
259 @param[in] ChildHandleBuffer List of Child Handles to Stop.
260
261 @retval EFI_SUCCESS This driver is removed ControllerHandle.
262 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
263
264 **/
265 EFI_STATUS
266 EFIAPI
267 MnpDriverBindingStop (
268 IN EFI_DRIVER_BINDING_PROTOCOL *This,
269 IN EFI_HANDLE ControllerHandle,
270 IN UINTN NumberOfChildren,
271 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
272 )
273 {
274 EFI_STATUS Status;
275 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
276 EFI_VLAN_CONFIG_PROTOCOL *VlanConfig;
277 MNP_DEVICE_DATA *MnpDeviceData;
278 MNP_SERVICE_DATA *MnpServiceData;
279 BOOLEAN AllChildrenStopped;
280 LIST_ENTRY *Entry;
281
282 //
283 // Try to retrieve MNP service binding protocol from the ControllerHandle
284 //
285 Status = gBS->OpenProtocol (
286 ControllerHandle,
287 &gEfiManagedNetworkServiceBindingProtocolGuid,
288 (VOID **) &ServiceBinding,
289 This->DriverBindingHandle,
290 ControllerHandle,
291 EFI_OPEN_PROTOCOL_GET_PROTOCOL
292 );
293 if (EFI_ERROR (Status)) {
294 //
295 // Retrieve VLAN Config Protocol from the ControllerHandle
296 //
297 Status = gBS->OpenProtocol (
298 ControllerHandle,
299 &gEfiVlanConfigProtocolGuid,
300 (VOID **) &VlanConfig,
301 This->DriverBindingHandle,
302 ControllerHandle,
303 EFI_OPEN_PROTOCOL_GET_PROTOCOL
304 );
305 if (EFI_ERROR (Status)) {
306 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStop: try to stop unknown Controller.\n"));
307 return EFI_DEVICE_ERROR;
308 }
309
310 MnpDeviceData = MNP_DEVICE_DATA_FROM_THIS (VlanConfig);
311 } else {
312 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);
313 MnpDeviceData = MnpServiceData->MnpDeviceData;
314 }
315
316 if (NumberOfChildren == 0) {
317 //
318 // Destroy all MNP service data
319 //
320 while (!IsListEmpty (&MnpDeviceData->ServiceList)) {
321 Entry = GetFirstNode (&MnpDeviceData->ServiceList);
322 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
323 MnpDestroyServiceData (MnpServiceData);
324 }
325
326 //
327 // Uninstall the VLAN Config Protocol if any
328 //
329 if (MnpDeviceData->VlanConfig.Set != NULL) {
330 gBS->UninstallMultipleProtocolInterfaces (
331 MnpDeviceData->ControllerHandle,
332 &gEfiVlanConfigProtocolGuid,
333 &MnpDeviceData->VlanConfig,
334 NULL
335 );
336 }
337
338 //
339 // Destroy Mnp Device Data
340 //
341 MnpDestroyDeviceData (MnpDeviceData, This->DriverBindingHandle);
342 FreePool (MnpDeviceData);
343
344 return EFI_SUCCESS;
345 }
346
347 //
348 // Stop all MNP child
349 //
350 AllChildrenStopped = TRUE;
351 NET_LIST_FOR_EACH (Entry, &MnpDeviceData->ServiceList) {
352 MnpServiceData = MNP_SERVICE_DATA_FROM_LINK (Entry);
353
354 Status = MnpDestroyServiceChild (MnpServiceData);
355 if (EFI_ERROR (Status)) {
356 AllChildrenStopped = FALSE;
357 }
358 }
359
360 if (!AllChildrenStopped) {
361 return EFI_DEVICE_ERROR;
362 }
363
364 return EFI_SUCCESS;
365 }
366
367
368 /**
369 Creates a child handle with a set of I/O services.
370
371 @param[in] This Protocol instance pointer.
372 @param[in, out] ChildHandle Pointer to the handle of the child to create. If
373 it is NULL, then a new handle is created. If
374 it is not NULL, then the I/O services are added
375 to the existing child handle.
376
377 @retval EFI_SUCCES The protocol was added to ChildHandle.
378 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
379 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to
380 create the child.
381 @retval Others The child handle was not created.
382
383 **/
384 EFI_STATUS
385 EFIAPI
386 MnpServiceBindingCreateChild (
387 IN EFI_SERVICE_BINDING_PROTOCOL *This,
388 IN OUT EFI_HANDLE *ChildHandle
389 )
390 {
391 EFI_STATUS Status;
392 MNP_SERVICE_DATA *MnpServiceData;
393 MNP_INSTANCE_DATA *Instance;
394 VOID *MnpSb;
395 EFI_TPL OldTpl;
396
397 if ((This == NULL) || (ChildHandle == NULL)) {
398 return EFI_INVALID_PARAMETER;
399 }
400
401 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
402
403 //
404 // Allocate buffer for the new instance.
405 //
406 Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));
407 if (Instance == NULL) {
408 DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
409
410 return EFI_OUT_OF_RESOURCES;
411 }
412
413 //
414 // Init the instance data.
415 //
416 MnpInitializeInstanceData (MnpServiceData, Instance);
417
418 Status = gBS->InstallMultipleProtocolInterfaces (
419 ChildHandle,
420 &gEfiManagedNetworkProtocolGuid,
421 &Instance->ManagedNetwork,
422 NULL
423 );
424 if (EFI_ERROR (Status)) {
425 DEBUG (
426 (EFI_D_ERROR,
427 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
428 Status)
429 );
430
431 goto ErrorExit;
432 }
433
434 //
435 // Save the instance's childhandle.
436 //
437 Instance->Handle = *ChildHandle;
438
439 Status = gBS->OpenProtocol (
440 MnpServiceData->ServiceHandle,
441 &gEfiManagedNetworkServiceBindingProtocolGuid,
442 (VOID **) &MnpSb,
443 gMnpDriverBinding.DriverBindingHandle,
444 Instance->Handle,
445 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
446 );
447 if (EFI_ERROR (Status)) {
448 goto ErrorExit;
449 }
450
451 //
452 // Add the child instance into ChildrenList.
453 //
454 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
455
456 InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);
457 MnpServiceData->ChildrenNumber++;
458
459 gBS->RestoreTPL (OldTpl);
460
461 ErrorExit:
462
463 if (EFI_ERROR (Status)) {
464
465 if (Instance->Handle != NULL) {
466
467 gBS->UninstallMultipleProtocolInterfaces (
468 Instance->Handle,
469 &gEfiManagedNetworkProtocolGuid,
470 &Instance->ManagedNetwork,
471 NULL
472 );
473 }
474
475 FreePool (Instance);
476 }
477
478 return Status;
479 }
480
481
482 /**
483 Destroys a child handle with a set of I/O services.
484
485 The DestroyChild() function does the opposite of CreateChild(). It removes a
486 protocol that was installed by CreateChild() from ChildHandle. If the removed
487 protocol is the last protocol on ChildHandle, then ChildHandle is destroyed.
488
489 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
490 instance.
491 @param[in] ChildHandle Handle of the child to destroy.
492
493 @retval EFI_SUCCES The protocol was removed from ChildHandle.
494 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that
495 is being removed.
496 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
497 @retval EFI_ACCESS_DENIED The protocol could not be removed from the
498 ChildHandle because its services are being
499 used.
500 @retval Others The child handle was not destroyed.
501
502 **/
503 EFI_STATUS
504 EFIAPI
505 MnpServiceBindingDestroyChild (
506 IN EFI_SERVICE_BINDING_PROTOCOL *This,
507 IN EFI_HANDLE ChildHandle
508 )
509 {
510 EFI_STATUS Status;
511 MNP_SERVICE_DATA *MnpServiceData;
512 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;
513 MNP_INSTANCE_DATA *Instance;
514 EFI_TPL OldTpl;
515
516 if ((This == NULL) || (ChildHandle == NULL)) {
517 return EFI_INVALID_PARAMETER;
518 }
519
520 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
521
522 //
523 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
524 //
525 Status = gBS->OpenProtocol (
526 ChildHandle,
527 &gEfiManagedNetworkProtocolGuid,
528 (VOID **) &ManagedNetwork,
529 gMnpDriverBinding.DriverBindingHandle,
530 ChildHandle,
531 EFI_OPEN_PROTOCOL_GET_PROTOCOL
532 );
533 if (EFI_ERROR (Status)) {
534 return EFI_UNSUPPORTED;
535 }
536
537 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);
538
539 //
540 // MnpServiceBindingDestroyChild may be called twice: first called by
541 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
542 // in this ChildHandle. Use destroyed to make sure the resource clean code
543 // will only excecute once.
544 //
545 if (Instance->Destroyed) {
546 return EFI_SUCCESS;
547 }
548
549 Instance->Destroyed = TRUE;
550
551 //
552 // Close the Simple Network protocol.
553 //
554 gBS->CloseProtocol (
555 MnpServiceData->ServiceHandle,
556 &gEfiManagedNetworkServiceBindingProtocolGuid,
557 MnpServiceData->MnpDeviceData->ImageHandle,
558 ChildHandle
559 );
560
561 //
562 // Uninstall the ManagedNetwork protocol.
563 //
564 Status = gBS->UninstallMultipleProtocolInterfaces (
565 ChildHandle,
566 &gEfiManagedNetworkProtocolGuid,
567 &Instance->ManagedNetwork,
568 NULL
569 );
570 if (EFI_ERROR (Status)) {
571 DEBUG (
572 (EFI_D_ERROR,
573 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
574 Status)
575 );
576
577 Instance->Destroyed = FALSE;
578 return Status;
579 }
580
581 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
582
583 //
584 // Reset the configuration.
585 //
586 ManagedNetwork->Configure (ManagedNetwork, NULL);
587
588 //
589 // Try to flush the RcvdPacketQueue.
590 //
591 MnpFlushRcvdDataQueue (Instance);
592
593 //
594 // Clean the RxTokenMap.
595 //
596 NetMapClean (&Instance->RxTokenMap);
597
598 //
599 // Remove this instance from the ChildrenList.
600 //
601 RemoveEntryList (&Instance->InstEntry);
602 MnpServiceData->ChildrenNumber--;
603
604 gBS->RestoreTPL (OldTpl);
605
606 FreePool (Instance);
607
608 return Status;
609 }
610
611 /**
612 The entry point for Mnp driver which installs the driver binding and component
613 name protocol on its ImageHandle.
614
615 @param[in] ImageHandle The image handle of the driver.
616 @param[in] SystemTable The system table.
617
618 @retval EFI_SUCCES The driver binding and component name protocols are
619 successfully installed.
620 @retval Others Other errors as indicated.
621
622 **/
623 EFI_STATUS
624 EFIAPI
625 MnpDriverEntryPoint (
626 IN EFI_HANDLE ImageHandle,
627 IN EFI_SYSTEM_TABLE *SystemTable
628 )
629 {
630 return EfiLibInstallDriverBindingComponentName2 (
631 ImageHandle,
632 SystemTable,
633 &gMnpDriverBinding,
634 ImageHandle,
635 &gMnpComponentName,
636 &gMnpComponentName2
637 );
638 }