2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2005 - 2018, 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
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 Callback function which provided by user to remove one node in NetDestroyLinkList process.
32 @param[in] Entry The entry to be removed.
33 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
35 @retval EFI_SUCCESS The entry has been removed successfully.
36 @retval Others Fail to remove the entry.
41 MnpDestroyServiceDataEntry (
46 MNP_SERVICE_DATA
*MnpServiceData
;
48 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
49 return MnpDestroyServiceData (MnpServiceData
);
53 Callback function which provided by user to remove one node in NetDestroyLinkList process.
55 @param[in] Entry The entry to be removed.
56 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
58 @retval EFI_SUCCESS The entry has been removed successfully.
59 @retval Others Fail to remove the entry.
64 MnpDestroyServiceChildEntry (
69 MNP_SERVICE_DATA
*MnpServiceData
;
71 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
72 return MnpDestroyServiceChild (MnpServiceData
);
76 Test to see if this driver supports ControllerHandle. This service
77 is called by the EFI boot service ConnectController(). In
78 order to make drivers as small as possible, there are a few calling
79 restrictions for this service. ConnectController() must
80 follow these calling restrictions. If any other agent wishes to call
81 Supported() it must also follow these calling restrictions.
83 @param[in] This Protocol instance pointer.
84 @param[in] ControllerHandle Handle of device to test.
85 @param[in] RemainingDevicePath Optional parameter use to pick a specific
86 child device to start.
88 @retval EFI_SUCCESS This driver supports this device.
89 @retval EFI_ALREADY_STARTED This driver is already running on this device.
90 @retval Others This driver does not support this device.
95 MnpDriverBindingSupported (
96 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
97 IN EFI_HANDLE ControllerHandle
,
98 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
102 EFI_SIMPLE_NETWORK_PROTOCOL
*Snp
;
105 // Test to open the Simple Network protocol BY_DRIVER.
107 Status
= gBS
->OpenProtocol (
109 &gEfiSimpleNetworkProtocolGuid
,
111 This
->DriverBindingHandle
,
113 EFI_OPEN_PROTOCOL_BY_DRIVER
115 if (EFI_ERROR (Status
)) {
120 // Close the openned SNP protocol.
124 &gEfiSimpleNetworkProtocolGuid
,
125 This
->DriverBindingHandle
,
134 Start this driver on ControllerHandle. This service is called by the
135 EFI boot service ConnectController(). In order to make drivers as small
136 as possible, there are a few calling restrictions for this service.
137 ConnectController() must follow these calling restrictions. If any other
138 agent wishes to call Start() it must also follow these calling restrictions.
140 @param[in] This Protocol instance pointer.
141 @param[in] ControllerHandle Handle of device to bind driver to.
142 @param[in] RemainingDevicePath Optional parameter use to pick a specific
143 child device to start.
145 @retval EFI_SUCCESS This driver is added to ControllerHandle.
146 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
147 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory for Mnp Service Data.
148 @retval Others This driver does not support this device.
153 MnpDriverBindingStart (
154 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
155 IN EFI_HANDLE ControllerHandle
,
156 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
160 MNP_SERVICE_DATA
*MnpServiceData
;
161 MNP_DEVICE_DATA
*MnpDeviceData
;
163 VLAN_TCI
*VlanVariable
;
170 // Initialize the Mnp Device Data
172 MnpDeviceData
= AllocateZeroPool (sizeof (MNP_DEVICE_DATA
));
173 if (MnpDeviceData
== NULL
) {
174 DEBUG ((EFI_D_ERROR
, "MnpDriverBindingStart(): Failed to allocate the Mnp Device Data.\n"));
176 return EFI_OUT_OF_RESOURCES
;
179 Status
= MnpInitializeDeviceData (MnpDeviceData
, This
->DriverBindingHandle
, ControllerHandle
);
180 if (EFI_ERROR (Status
)) {
181 DEBUG ((EFI_D_ERROR
, "MnpDriverBindingStart: MnpInitializeDeviceData failed, %r.\n", Status
));
183 FreePool (MnpDeviceData
);
188 // Check whether NIC driver has already produced VlanConfig protocol
190 Status
= gBS
->OpenProtocol (
192 &gEfiVlanConfigProtocolGuid
,
194 This
->DriverBindingHandle
,
196 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
198 if (!EFI_ERROR (Status
)) {
200 // NIC hardware already implement VLAN,
201 // no need to provide software VLAN implementation in MNP driver
203 MnpDeviceData
->NumberOfVlan
= 0;
204 ZeroMem (&MnpDeviceData
->VlanConfig
, sizeof (EFI_VLAN_CONFIG_PROTOCOL
));
205 MnpServiceData
= MnpCreateServiceData (MnpDeviceData
, 0, 0);
206 Status
= (MnpServiceData
!= NULL
) ? EFI_SUCCESS
: EFI_OUT_OF_RESOURCES
;
211 // Install VLAN Config Protocol
213 Status
= gBS
->InstallMultipleProtocolInterfaces (
215 &gEfiVlanConfigProtocolGuid
,
216 &MnpDeviceData
->VlanConfig
,
219 if (EFI_ERROR (Status
)) {
224 // Get current VLAN configuration from EFI Variable
227 Status
= MnpGetVlanVariable (MnpDeviceData
, &NumberOfVlan
, &VlanVariable
);
228 if (EFI_ERROR (Status
)) {
230 // No VLAN is set, create a default MNP service data for untagged frame
232 MnpDeviceData
->NumberOfVlan
= 0;
233 MnpServiceData
= MnpCreateServiceData (MnpDeviceData
, 0, 0);
234 Status
= (MnpServiceData
!= NULL
) ? EFI_SUCCESS
: EFI_OUT_OF_RESOURCES
;
239 // Create MNP service data for each VLAN
241 MnpDeviceData
->NumberOfVlan
= NumberOfVlan
;
242 for (Index
= 0; Index
< NumberOfVlan
; Index
++) {
243 MnpServiceData
= MnpCreateServiceData (
245 VlanVariable
[Index
].Bits
.Vid
,
246 (UINT8
) VlanVariable
[Index
].Bits
.Priority
249 if (MnpServiceData
== NULL
) {
250 Status
= EFI_OUT_OF_RESOURCES
;
257 if (VlanVariable
!= NULL
) {
258 FreePool (VlanVariable
);
261 if (EFI_ERROR (Status
)) {
263 // Destroy all MNP service data
265 while (!IsListEmpty (&MnpDeviceData
->ServiceList
)) {
266 Entry
= GetFirstNode (&MnpDeviceData
->ServiceList
);
267 MnpServiceData
= MNP_SERVICE_DATA_FROM_LINK (Entry
);
268 MnpDestroyServiceData (MnpServiceData
);
272 // Uninstall the VLAN Config Protocol if any
274 if (MnpDeviceData
->VlanConfig
.Set
!= NULL
) {
275 gBS
->UninstallMultipleProtocolInterfaces (
276 MnpDeviceData
->ControllerHandle
,
277 &gEfiVlanConfigProtocolGuid
,
278 &MnpDeviceData
->VlanConfig
,
284 // Destroy Mnp Device Data
286 MnpDestroyDeviceData (MnpDeviceData
, This
->DriverBindingHandle
);
287 FreePool (MnpDeviceData
);
294 Stop this driver on ControllerHandle. This service is called by the
295 EFI boot service DisconnectController(). In order to make drivers as
296 small as possible, there are a few calling restrictions for this service.
297 DisconnectController() must follow these calling restrictions. If any other
298 agent wishes to call Stop() it must also follow these calling restrictions.
300 @param[in] This Protocol instance pointer.
301 @param[in] ControllerHandle Handle of device to stop driver on.
302 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If
303 number of children is zero stop the entire
305 @param[in] ChildHandleBuffer List of Child Handles to Stop.
307 @retval EFI_SUCCESS This driver is removed ControllerHandle.
308 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
313 MnpDriverBindingStop (
314 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
315 IN EFI_HANDLE ControllerHandle
,
316 IN UINTN NumberOfChildren
,
317 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
321 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
322 EFI_VLAN_CONFIG_PROTOCOL
*VlanConfig
;
323 MNP_DEVICE_DATA
*MnpDeviceData
;
324 MNP_SERVICE_DATA
*MnpServiceData
;
329 // Try to retrieve MNP service binding protocol from the ControllerHandle
331 Status
= gBS
->OpenProtocol (
333 &gEfiManagedNetworkServiceBindingProtocolGuid
,
334 (VOID
**) &ServiceBinding
,
335 This
->DriverBindingHandle
,
337 EFI_OPEN_PROTOCOL_GET_PROTOCOL
339 if (EFI_ERROR (Status
)) {
341 // Retrieve VLAN Config Protocol from the ControllerHandle
343 Status
= gBS
->OpenProtocol (
345 &gEfiVlanConfigProtocolGuid
,
346 (VOID
**) &VlanConfig
,
347 This
->DriverBindingHandle
,
349 EFI_OPEN_PROTOCOL_GET_PROTOCOL
351 if (EFI_ERROR (Status
)) {
352 DEBUG ((EFI_D_ERROR
, "MnpDriverBindingStop: try to stop unknown Controller.\n"));
353 return EFI_DEVICE_ERROR
;
356 MnpDeviceData
= MNP_DEVICE_DATA_FROM_THIS (VlanConfig
);
358 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (ServiceBinding
);
359 MnpDeviceData
= MnpServiceData
->MnpDeviceData
;
362 if (NumberOfChildren
== 0) {
364 // Destroy all MNP service data
366 List
= &MnpDeviceData
->ServiceList
;
367 Status
= NetDestroyLinkList (
369 MnpDestroyServiceDataEntry
,
373 if (EFI_ERROR (Status
) || ListLength
!=0) {
374 return EFI_DEVICE_ERROR
;
378 // Uninstall the VLAN Config Protocol if any
380 if (MnpDeviceData
->VlanConfig
.Set
!= NULL
) {
381 gBS
->UninstallMultipleProtocolInterfaces (
382 MnpDeviceData
->ControllerHandle
,
383 &gEfiVlanConfigProtocolGuid
,
384 &MnpDeviceData
->VlanConfig
,
390 // Destroy Mnp Device Data
392 MnpDestroyDeviceData (MnpDeviceData
, This
->DriverBindingHandle
);
393 FreePool (MnpDeviceData
);
395 if (gMnpControllerNameTable
!= NULL
) {
396 FreeUnicodeStringTable (gMnpControllerNameTable
);
397 gMnpControllerNameTable
= NULL
;
403 // Stop all MNP child
405 List
= &MnpDeviceData
->ServiceList
;
406 Status
= NetDestroyLinkList (
408 MnpDestroyServiceChildEntry
,
412 if (EFI_ERROR (Status
)) {
413 return EFI_DEVICE_ERROR
;
421 Creates a child handle with a set of I/O services.
423 @param[in] This Protocol instance pointer.
424 @param[in, out] ChildHandle Pointer to the handle of the child to create. If
425 it is NULL, then a new handle is created. If
426 it is not NULL, then the I/O services are added
427 to the existing child handle.
429 @retval EFI_SUCCES The protocol was added to ChildHandle.
430 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
431 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to
433 @retval Others The child handle was not created.
438 MnpServiceBindingCreateChild (
439 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
440 IN OUT EFI_HANDLE
*ChildHandle
444 MNP_SERVICE_DATA
*MnpServiceData
;
445 MNP_INSTANCE_DATA
*Instance
;
449 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
450 return EFI_INVALID_PARAMETER
;
453 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (This
);
456 // Allocate buffer for the new instance.
458 Instance
= AllocateZeroPool (sizeof (MNP_INSTANCE_DATA
));
459 if (Instance
== NULL
) {
460 DEBUG ((EFI_D_ERROR
, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
462 return EFI_OUT_OF_RESOURCES
;
466 // Init the instance data.
468 MnpInitializeInstanceData (MnpServiceData
, Instance
);
470 Status
= gBS
->InstallMultipleProtocolInterfaces (
472 &gEfiManagedNetworkProtocolGuid
,
473 &Instance
->ManagedNetwork
,
476 if (EFI_ERROR (Status
)) {
479 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
487 // Save the instance's childhandle.
489 Instance
->Handle
= *ChildHandle
;
491 Status
= gBS
->OpenProtocol (
492 MnpServiceData
->ServiceHandle
,
493 &gEfiManagedNetworkServiceBindingProtocolGuid
,
495 gMnpDriverBinding
.DriverBindingHandle
,
497 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
499 if (EFI_ERROR (Status
)) {
504 // Add the child instance into ChildrenList.
506 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
508 InsertTailList (&MnpServiceData
->ChildrenList
, &Instance
->InstEntry
);
509 MnpServiceData
->ChildrenNumber
++;
511 gBS
->RestoreTPL (OldTpl
);
515 if (EFI_ERROR (Status
)) {
517 if (Instance
->Handle
!= NULL
) {
519 gBS
->UninstallMultipleProtocolInterfaces (
521 &gEfiManagedNetworkProtocolGuid
,
522 &Instance
->ManagedNetwork
,
535 Destroys a child handle with a set of I/O services.
537 The DestroyChild() function does the opposite of CreateChild(). It removes a
538 protocol that was installed by CreateChild() from ChildHandle. If the removed
539 protocol is the last protocol on ChildHandle, then ChildHandle is destroyed.
541 @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL
543 @param[in] ChildHandle Handle of the child to destroy.
545 @retval EFI_SUCCES The protocol was removed from ChildHandle.
546 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that
548 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
549 @retval EFI_ACCESS_DENIED The protocol could not be removed from the
550 ChildHandle because its services are being
552 @retval Others The child handle was not destroyed.
557 MnpServiceBindingDestroyChild (
558 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
559 IN EFI_HANDLE ChildHandle
563 MNP_SERVICE_DATA
*MnpServiceData
;
564 EFI_MANAGED_NETWORK_PROTOCOL
*ManagedNetwork
;
565 MNP_INSTANCE_DATA
*Instance
;
568 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
569 return EFI_INVALID_PARAMETER
;
572 MnpServiceData
= MNP_SERVICE_DATA_FROM_THIS (This
);
575 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
577 Status
= gBS
->OpenProtocol (
579 &gEfiManagedNetworkProtocolGuid
,
580 (VOID
**) &ManagedNetwork
,
581 gMnpDriverBinding
.DriverBindingHandle
,
583 EFI_OPEN_PROTOCOL_GET_PROTOCOL
585 if (EFI_ERROR (Status
)) {
586 return EFI_UNSUPPORTED
;
589 Instance
= MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork
);
592 // MnpServiceBindingDestroyChild may be called twice: first called by
593 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
594 // in this ChildHandle. Use destroyed to make sure the resource clean code
595 // will only excecute once.
597 if (Instance
->Destroyed
) {
601 Instance
->Destroyed
= TRUE
;
604 // Close the Simple Network protocol.
607 MnpServiceData
->ServiceHandle
,
608 &gEfiManagedNetworkServiceBindingProtocolGuid
,
609 MnpServiceData
->MnpDeviceData
->ImageHandle
,
614 // Uninstall the ManagedNetwork protocol.
616 Status
= gBS
->UninstallMultipleProtocolInterfaces (
618 &gEfiManagedNetworkProtocolGuid
,
619 &Instance
->ManagedNetwork
,
622 if (EFI_ERROR (Status
)) {
625 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
629 Instance
->Destroyed
= FALSE
;
633 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
636 // Reset the configuration.
638 ManagedNetwork
->Configure (ManagedNetwork
, NULL
);
641 // Try to flush the RcvdPacketQueue.
643 MnpFlushRcvdDataQueue (Instance
);
646 // Clean the RxTokenMap.
648 NetMapClean (&Instance
->RxTokenMap
);
651 // Remove this instance from the ChildrenList.
653 RemoveEntryList (&Instance
->InstEntry
);
654 MnpServiceData
->ChildrenNumber
--;
656 gBS
->RestoreTPL (OldTpl
);
664 The entry point for Mnp driver which installs the driver binding and component
665 name protocol on its ImageHandle.
667 @param[in] ImageHandle The image handle of the driver.
668 @param[in] SystemTable The system table.
670 @retval EFI_SUCCES The driver binding and component name protocols are
671 successfully installed.
672 @retval Others Other errors as indicated.
677 MnpDriverEntryPoint (
678 IN EFI_HANDLE ImageHandle
,
679 IN EFI_SYSTEM_TABLE
*SystemTable
682 return EfiLibInstallDriverBindingComponentName2 (