2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2005 - 2010, Intel Corporation.<BR>
5 All rights reserved. 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
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.
16 #include "MnpDriver.h"
20 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding
= {
21 MnpDriverBindingSupported
,
22 MnpDriverBindingStart
,
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.
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.
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.
49 MnpDriverBindingSupported (
50 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
51 IN EFI_HANDLE ControllerHandle
,
52 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
56 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
59 // Test to open the Simple Network protocol BY_DRIVER.
61 Status
= gBS
->OpenProtocol (
63 &gEfiSimpleNetworkProtocolGuid
,
65 This
->DriverBindingHandle
,
67 EFI_OPEN_PROTOCOL_BY_DRIVER
69 if (EFI_ERROR (Status
)) {
74 // Close the openned SNP protocol.
78 &gEfiSimpleNetworkProtocolGuid
,
79 This
->DriverBindingHandle
,
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.
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.
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.
107 MnpDriverBindingStart (
108 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
109 IN EFI_HANDLE ControllerHandle
,
110 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
114 MNP_SERVICE_DATA
*MnpServiceData
;
115 MNP_DEVICE_DATA
*MnpDeviceData
;
117 VLAN_TCI
*VlanVariable
;
124 // Initialize the Mnp Device Data
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"));
130 return EFI_OUT_OF_RESOURCES
;
133 Status
= MnpInitializeDeviceData (MnpDeviceData
, This
->DriverBindingHandle
, ControllerHandle
);
134 if (EFI_ERROR (Status
)) {
135 DEBUG ((EFI_D_ERROR
, "MnpDriverBindingStart: MnpInitializeDeviceData failed, %r.\n", Status
));
137 FreePool (MnpDeviceData
);
142 // Check whether NIC driver has already produced VlanConfig protocol
144 Status
= gBS
->OpenProtocol (
146 &gEfiVlanConfigProtocolGuid
,
148 This
->DriverBindingHandle
,
150 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
152 if (!EFI_ERROR (Status
)) {
154 // NIC hardware already implement VLAN,
155 // no need to provide software VLAN implementation in MNP driver
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
;
165 // Install VLAN Config Protocol
167 Status
= gBS
->InstallMultipleProtocolInterfaces (
169 &gEfiVlanConfigProtocolGuid
,
170 &MnpDeviceData
->VlanConfig
,
173 if (EFI_ERROR (Status
)) {
178 // Get current VLAN configuration from EFI Variable
181 Status
= MnpGetVlanVariable (MnpDeviceData
, &NumberOfVlan
, &VlanVariable
);
182 if (EFI_ERROR (Status
)) {
184 // No VLAN is set, create a default MNP service data for untagged frame
186 MnpDeviceData
->NumberOfVlan
= 0;
187 MnpServiceData
= MnpCreateServiceData (MnpDeviceData
, 0, 0);
188 Status
= (MnpServiceData
!= NULL
) ? EFI_SUCCESS
: EFI_OUT_OF_RESOURCES
;
193 // Create MNP service data for each VLAN
195 MnpDeviceData
->NumberOfVlan
= NumberOfVlan
;
196 for (Index
= 0; Index
< NumberOfVlan
; Index
++) {
197 MnpServiceData
= MnpCreateServiceData (
199 VlanVariable
[Index
].Bits
.Vid
,
200 (UINT8
) VlanVariable
[Index
].Bits
.Priority
203 if (MnpServiceData
== NULL
) {
204 Status
= EFI_OUT_OF_RESOURCES
;
211 if (VlanVariable
!= NULL
) {
212 FreePool (VlanVariable
);
215 if (EFI_ERROR (Status
)) {
217 // Destroy all MNP service data
219 while (!IsListEmpty (&MnpDeviceData
->ServiceList
)) {
220 Entry
= GetFirstNode (&MnpDeviceData
->ServiceList
);
221 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
222 MnpDestroyServiceData (MnpServiceData
);
226 // Uninstall the VLAN Config Protocol if any
228 if (MnpDeviceData
->VlanConfig
.Set
!= NULL
) {
229 gBS
->UninstallMultipleProtocolInterfaces (
230 MnpDeviceData
->ControllerHandle
,
231 &gEfiVlanConfigProtocolGuid
,
232 &MnpDeviceData
->VlanConfig
,
238 // Destroy Mnp Device Data
240 MnpDestroyDeviceData (MnpDeviceData
, This
->DriverBindingHandle
);
241 FreePool (MnpDeviceData
);
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.
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
259 @param[in] ChildHandleBuffer List of Child Handles to Stop.
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.
267 MnpDriverBindingStop (
268 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
269 IN EFI_HANDLE ControllerHandle
,
270 IN UINTN NumberOfChildren
,
271 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
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
;
283 // Try to retrieve MNP service binding protocol from the ControllerHandle
285 Status
= gBS
->OpenProtocol (
287 &gEfiManagedNetworkServiceBindingProtocolGuid
,
288 (VOID
**) &ServiceBinding
,
289 This
->DriverBindingHandle
,
291 EFI_OPEN_PROTOCOL_GET_PROTOCOL
293 if (EFI_ERROR (Status
)) {
295 // Retrieve VLAN Config Protocol from the ControllerHandle
297 Status
= gBS
->OpenProtocol (
299 &gEfiVlanConfigProtocolGuid
,
300 (VOID
**) &VlanConfig
,
301 This
->DriverBindingHandle
,
303 EFI_OPEN_PROTOCOL_GET_PROTOCOL
305 if (EFI_ERROR (Status
)) {
306 DEBUG ((EFI_D_ERROR
, "MnpDriverBindingStop: try to stop unknown Controller.\n"));
307 return EFI_DEVICE_ERROR
;
310 MnpDeviceData
= MNP_DEVICE_DATA_FROM_THIS (VlanConfig
);
312 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (ServiceBinding
);
313 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
316 if (NumberOfChildren
== 0) {
318 // Destroy all MNP service data
320 while (!IsListEmpty (&MnpDeviceData
->ServiceList
)) {
321 Entry
= GetFirstNode (&MnpDeviceData
->ServiceList
);
322 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
323 MnpDestroyServiceData (MnpServiceData
);
327 // Uninstall the VLAN Config Protocol if any
329 if (MnpDeviceData
->VlanConfig
.Set
!= NULL
) {
330 gBS
->UninstallMultipleProtocolInterfaces (
331 MnpDeviceData
->ControllerHandle
,
332 &gEfiVlanConfigProtocolGuid
,
333 &MnpDeviceData
->VlanConfig
,
339 // Destroy Mnp Device Data
341 MnpDestroyDeviceData (MnpDeviceData
, This
->DriverBindingHandle
);
342 FreePool (MnpDeviceData
);
348 // Stop all MNP child
350 AllChildrenStopped
= TRUE
;
351 NET_LIST_FOR_EACH (Entry
, &MnpDeviceData
->ServiceList
) {
352 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
354 Status
= MnpDestroyServiceChild (MnpServiceData
);
355 if (EFI_ERROR (Status
)) {
356 AllChildrenStopped
= FALSE
;
360 if (!AllChildrenStopped
) {
361 return EFI_DEVICE_ERROR
;
369 Creates a child handle with a set of I/O services.
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.
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
381 @retval Others The child handle was not created.
386 MnpServiceBindingCreateChild (
387 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
388 IN OUT EFI_HANDLE
*ChildHandle
392 MNP_SERVICE_DATA
*MnpServiceData
;
393 MNP_INSTANCE_DATA
*Instance
;
397 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
398 return EFI_INVALID_PARAMETER
;
401 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (This
);
404 // Allocate buffer for the new instance.
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"));
410 return EFI_OUT_OF_RESOURCES
;
414 // Init the instance data.
416 MnpInitializeInstanceData (MnpServiceData
, Instance
);
418 Status
= gBS
->InstallMultipleProtocolInterfaces (
420 &gEfiManagedNetworkProtocolGuid
,
421 &Instance
->ManagedNetwork
,
424 if (EFI_ERROR (Status
)) {
427 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
435 // Save the instance's childhandle.
437 Instance
->Handle
= *ChildHandle
;
439 Status
= gBS
->OpenProtocol (
440 MnpServiceData
->ServiceHandle
,
441 &gEfiManagedNetworkServiceBindingProtocolGuid
,
443 gMnpDriverBinding
.DriverBindingHandle
,
445 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
447 if (EFI_ERROR (Status
)) {
452 // Add the child instance into ChildrenList.
454 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
456 InsertTailList (&MnpServiceData
->ChildrenList
, &Instance
->InstEntry
);
457 MnpServiceData
->ChildrenNumber
++;
459 gBS
->RestoreTPL (OldTpl
);
463 if (EFI_ERROR (Status
)) {
465 if (Instance
->Handle
!= NULL
) {
467 gBS
->UninstallMultipleProtocolInterfaces (
468 &gEfiManagedNetworkProtocolGuid
,
469 &Instance
->ManagedNetwork
,
482 Destroys a child handle with a set of I/O services.
484 The DestroyChild() function does the opposite of CreateChild(). It removes a
485 protocol that was installed by CreateChild() from ChildHandle. If the removed
486 protocol is the last protocol on ChildHandle, then ChildHandle is destroyed.
488 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
490 @param[in] ChildHandle Handle of the child to destroy.
492 @retval EFI_SUCCES The protocol was removed from ChildHandle.
493 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that
495 @retval EFI_INVALID_PARAMETER ChildHandle is not a valid UEFI handle.
496 @retval EFI_ACCESS_DENIED The protocol could not be removed from the
497 ChildHandle because its services are being
499 @retval Others The child handle was not destroyed.
504 MnpServiceBindingDestroyChild (
505 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
506 IN EFI_HANDLE ChildHandle
510 MNP_SERVICE_DATA
*MnpServiceData
;
511 EFI_MANAGED_NETWORK_PROTOCOL
*ManagedNetwork
;
512 MNP_INSTANCE_DATA
*Instance
;
515 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
516 return EFI_INVALID_PARAMETER
;
519 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (This
);
522 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
524 Status
= gBS
->OpenProtocol (
526 &gEfiManagedNetworkProtocolGuid
,
527 (VOID
**) &ManagedNetwork
,
528 gMnpDriverBinding
.DriverBindingHandle
,
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL
532 if (EFI_ERROR (Status
)) {
533 return EFI_UNSUPPORTED
;
536 Instance
= MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork
);
539 // MnpServiceBindingDestroyChild may be called twice: first called by
540 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
541 // in this ChildHandle. Use destroyed to make sure the resource clean code
542 // will only excecute once.
544 if (Instance
->Destroyed
) {
548 Instance
->Destroyed
= TRUE
;
551 // Close the Simple Network protocol.
554 MnpServiceData
->ServiceHandle
,
555 &gEfiManagedNetworkServiceBindingProtocolGuid
,
556 MnpServiceData
->MnpDeviceData
->ImageHandle
,
561 // Uninstall the ManagedNetwork protocol.
563 Status
= gBS
->UninstallMultipleProtocolInterfaces (
565 &gEfiManagedNetworkProtocolGuid
,
566 &Instance
->ManagedNetwork
,
569 if (EFI_ERROR (Status
)) {
572 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
576 Instance
->Destroyed
= FALSE
;
580 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
583 // Reset the configuration.
585 ManagedNetwork
->Configure (ManagedNetwork
, NULL
);
588 // Try to flush the RcvdPacketQueue.
590 MnpFlushRcvdDataQueue (Instance
);
593 // Clean the RxTokenMap.
595 NetMapClean (&Instance
->RxTokenMap
);
598 // Remove this instance from the ChildrenList.
600 RemoveEntryList (&Instance
->InstEntry
);
601 MnpServiceData
->ChildrenNumber
--;
603 gBS
->RestoreTPL (OldTpl
);
611 The entry point for Mnp driver which installs the driver binding and component
612 name protocol on its ImageHandle.
614 @param[in] ImageHandle The image handle of the driver.
615 @param[in] SystemTable The system table.
617 @retval EFI_SUCCES The driver binding and component name protocols are
618 successfully installed.
619 @retval Others Other errors as indicated.
624 MnpDriverEntryPoint (
625 IN EFI_HANDLE ImageHandle
,
626 IN EFI_SYSTEM_TABLE
*SystemTable
629 return EfiLibInstallDriverBindingComponentName2 (