2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2004 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed
6 and made available under the terms and conditions of the BSD License which
7 accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
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.
18 One notified function to stop UNDI device when gBS->ExitBootServices() called.
20 @param Event Pointer to this event
21 @param Context Event handler private data
26 SnpNotifyExitBootServices (
33 Snp
= (SNP_DRIVER
*)Context
;
36 // Shutdown and stop UNDI driver
43 Send command to UNDI. It does nothing currently.
45 @param Cdb command to be sent to UNDI.
47 @retval EFI_INVALID_PARAMETER The command is 0.
48 @retval EFI_UNSUPPORTED Default return status because it's not
58 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
61 return EFI_INVALID_PARAMETER
;
65 // %%TBD - For now, nothing is done.
67 return EFI_UNSUPPORTED
;
72 Compute 8-bit checksum of a buffer.
74 @param Buffer Pointer to buffer.
75 @param Length Length of buffer in bytes.
77 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
93 if (Ptr
== NULL
|| Length
== 0) {
97 while (Length
-- != 0) {
98 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
105 Test to see if this driver supports ControllerHandle. This service
106 is called by the EFI boot service ConnectController(). In
107 order to make drivers as small as possible, there are a few calling
108 restrictions for this service. ConnectController() must
109 follow these calling restrictions. If any other agent wishes to call
110 Supported() it must also follow these calling restrictions.
112 @param This Protocol instance pointer.
113 @param ControllerHandle Handle of device to test.
114 @param RemainingDevicePath Optional parameter use to pick a specific child
117 @retval EFI_SUCCESS This driver supports this device.
118 @retval EFI_ALREADY_STARTED This driver is already running on this device.
119 @retval other This driver does not support this device.
124 SimpleNetworkDriverSupported (
125 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
126 IN EFI_HANDLE Controller
,
127 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
131 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
134 Status
= gBS
->OpenProtocol (
136 &gEfiDevicePathProtocolGuid
,
138 This
->DriverBindingHandle
,
140 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
142 if (EFI_ERROR (Status
)) {
146 Status
= gBS
->OpenProtocol (
148 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
149 (VOID
**) &NiiProtocol
,
150 This
->DriverBindingHandle
,
152 EFI_OPEN_PROTOCOL_BY_DRIVER
155 if (EFI_ERROR (Status
)) {
156 if (Status
== EFI_ALREADY_STARTED
) {
157 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
162 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
165 // check the version, we don't want to connect to the undi16
167 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
168 Status
= EFI_UNSUPPORTED
;
172 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
174 if ((NiiProtocol
->Id
& 0x0F) != 0) {
175 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
176 Status
= EFI_UNSUPPORTED
;
180 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->Id
);
183 // Verify !PXE revisions.
185 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
186 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
187 Status
= EFI_UNSUPPORTED
;
191 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
192 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
193 Status
= EFI_UNSUPPORTED
;
197 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
199 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
200 Status
= EFI_UNSUPPORTED
;
203 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
204 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
205 Status
= EFI_UNSUPPORTED
;
209 // Do S/W UNDI specific checks.
211 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
212 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
213 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
214 Status
= EFI_UNSUPPORTED
;
218 if (Pxe
->sw
.BusCnt
== 0) {
219 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
220 Status
= EFI_UNSUPPORTED
;
225 Status
= EFI_SUCCESS
;
226 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
231 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
232 This
->DriverBindingHandle
,
240 Start this driver on ControllerHandle. This service is called by the
241 EFI boot service ConnectController(). In order to make
242 drivers as small as possible, there are a few calling restrictions for
243 this service. ConnectController() must follow these
244 calling restrictions. If any other agent wishes to call Start() it
245 must also follow these calling restrictions.
247 @param This Protocol instance pointer.
248 @param ControllerHandle Handle of device to bind driver to.
249 @param RemainingDevicePath Optional parameter use to pick a specific child
252 @retval EFI_SUCCESS This driver is added to ControllerHandle
253 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error
254 @retval other This driver does not support this device
259 SimpleNetworkDriverStart (
260 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
261 IN EFI_HANDLE Controller
,
262 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
265 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
266 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
273 PXE_STATFLAGS InitStatFlags
;
274 EFI_PCI_IO_PROTOCOL
*PciIo
;
275 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
277 BOOLEAN FoundMemoryBar
;
279 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
281 Status
= gBS
->OpenProtocol (
283 &gEfiDevicePathProtocolGuid
,
284 (VOID
**) &NiiDevicePath
,
285 This
->DriverBindingHandle
,
287 EFI_OPEN_PROTOCOL_BY_DRIVER
290 if (EFI_ERROR (Status
)) {
294 Status
= gBS
->LocateDevicePath (
295 &gEfiPciIoProtocolGuid
,
300 if (EFI_ERROR (Status
)) {
304 Status
= gBS
->OpenProtocol (
306 &gEfiPciIoProtocolGuid
,
308 This
->DriverBindingHandle
,
310 EFI_OPEN_PROTOCOL_GET_PROTOCOL
312 if (EFI_ERROR (Status
)) {
316 // Get the NII interface.
318 Status
= gBS
->OpenProtocol (
320 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
322 This
->DriverBindingHandle
,
324 EFI_OPEN_PROTOCOL_BY_DRIVER
326 if (EFI_ERROR (Status
)) {
329 &gEfiDevicePathProtocolGuid
,
330 This
->DriverBindingHandle
,
336 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
338 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->Id
);
340 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
341 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
345 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
347 // We can get any packets.
349 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
351 // We need to be able to get broadcast packets for DHCP.
352 // If we do not have promiscuous support, we must at least have
353 // broadcast support or we cannot do DHCP!
356 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
360 // OK, we like this UNDI, and we know snp is not already there on this handle
361 // Allocate and initialize a new simple network protocol structure.
363 Status
= PciIo
->AllocateBuffer (
367 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
372 if (Status
!= EFI_SUCCESS
) {
373 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
377 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
379 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
382 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
384 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
386 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
387 Snp
->Snp
.Start
= SnpUndi32Start
;
388 Snp
->Snp
.Stop
= SnpUndi32Stop
;
389 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
390 Snp
->Snp
.Reset
= SnpUndi32Reset
;
391 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
392 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
393 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
394 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
395 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
396 Snp
->Snp
.NvData
= SnpUndi32NvData
;
397 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
398 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
399 Snp
->Snp
.Receive
= SnpUndi32Receive
;
400 Snp
->Snp
.WaitForPacket
= NULL
;
402 Snp
->Snp
.Mode
= &Snp
->Mode
;
404 Snp
->TxRxBufferSize
= 0;
405 Snp
->TxRxBuffer
= NULL
;
407 Snp
->RecycledTxBuf
= AllocatePool (sizeof (UINT64
) * SNP_TX_BUFFER_INCREASEMENT
);
408 if (Snp
->RecycledTxBuf
== NULL
) {
409 Status
= EFI_OUT_OF_RESOURCES
;
410 goto Error_DeleteSNP
;
412 Snp
->MaxRecycledTxBuf
= SNP_TX_BUFFER_INCREASEMENT
;
413 Snp
->RecycledTxBufCount
= 0;
415 if (Nii
->Revision
>= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION
) {
416 Snp
->IfNum
= Nii
->IfNum
;
419 Snp
->IfNum
= (UINT8
) (Nii
->IfNum
& 0xFF);
422 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
423 Snp
->IsSwUndi
= FALSE
;
424 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
426 Snp
->IsSwUndi
= TRUE
;
428 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
429 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
431 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
435 // Allocate a global CPB and DB buffer for this UNDI interface.
436 // we do this because:
438 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
439 // within 2GB limit, create them here and map them so that when undi calls
440 // v2p callback to check if the physical address is < 2gb, we will pass.
442 // -This is not a requirement for 3.1 or later UNDIs but the code looks
443 // simpler if we use the same cpb, db variables for both old and new undi
444 // interfaces from all the SNP interface calls (we don't map the buffers
445 // for the newer undi interfaces though)
447 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
448 // interface as EFI does not multi-task and so SNP will not be re-entered!
450 Status
= PciIo
->AllocateBuffer (
454 SNP_MEM_PAGES (4096),
459 if (Status
!= EFI_SUCCESS
) {
460 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
461 goto Error_DeleteSNP
;
464 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
465 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
468 // Find the correct BAR to do IO.
470 // Enumerate through the PCI BARs for the device to determine which one is
471 // the IO BAR. Save the index of the BAR into the adapter info structure.
472 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
474 Snp
->MemoryBarIndex
= 0;
476 FoundMemoryBar
= FALSE
;
478 for (BarIndex
= 0; BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
479 Status
= PciIo
->GetBarAttributes (
485 if (Status
== EFI_UNSUPPORTED
) {
487 } else if (EFI_ERROR (Status
)) {
488 goto Error_DeleteSNP
;
491 if ((!FoundMemoryBar
) && (BarDesc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
)) {
492 Snp
->MemoryBarIndex
= BarIndex
;
493 FoundMemoryBar
= TRUE
;
494 } else if ((!FoundIoBar
) && (BarDesc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
)) {
495 Snp
->IoBarIndex
= BarIndex
;
501 if (FoundMemoryBar
&& FoundIoBar
) {
506 Status
= PxeStart (Snp
);
508 if (Status
!= EFI_SUCCESS
) {
509 goto Error_DeleteSNP
;
512 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
513 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
515 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
516 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
518 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (Snp
->InitInfo
);
519 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) (&Snp
->InitInfo
);
521 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
522 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
524 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
525 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
527 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_init_info() "));
529 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
532 // Save the INIT Stat Code...
534 InitStatFlags
= Snp
->Cdb
.StatFlags
;
536 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
537 DEBUG ((EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
539 goto Error_DeleteSNP
;
543 // Initialize simple network protocol mode structure
545 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
546 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
547 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
548 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
549 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
550 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
551 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
552 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
553 Snp
->Mode
.MCastFilterCount
= 0;
555 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
556 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
557 Snp
->Mode
.MediaPresentSupported
= TRUE
;
560 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
562 Snp
->Mode
.MediaPresentSupported
= FALSE
;
565 switch (InitStatFlags
& PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK
) {
566 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED
:
567 Snp
->MediaStatusSupported
= TRUE
;
570 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED
:
572 Snp
->MediaStatusSupported
= FALSE
;
575 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
576 Snp
->Mode
.MacAddressChangeable
= TRUE
;
578 Snp
->Mode
.MacAddressChangeable
= FALSE
;
581 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
582 Snp
->Mode
.MultipleTxSupported
= TRUE
;
584 Snp
->Mode
.MultipleTxSupported
= FALSE
;
587 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
589 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
590 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
594 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
595 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
599 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
600 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
604 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
605 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
609 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
610 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
614 Snp
->Mode
.ReceiveFilterSetting
= 0;
617 // need to get the station address to save in the mode structure. we need to
618 // initialize the UNDI first for this.
620 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
621 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
623 if (EFI_ERROR (Status
)) {
625 goto Error_DeleteSNP
;
628 Status
= PxeGetStnAddr (Snp
);
630 if (Status
!= EFI_SUCCESS
) {
631 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
634 goto Error_DeleteSNP
;
637 Snp
->Mode
.MediaPresent
= FALSE
;
640 // We should not leave UNDI started and initialized here. this DriverStart()
641 // routine must only find and attach the SNP interface to UNDI layer that it
642 // finds on the given handle!
643 // The UNDI layer will be started when upper layers call Snp->start.
644 // How ever, this DriverStart() must fill up the snp mode structure which
645 // contains the MAC address of the NIC. For this reason we started and
646 // initialized UNDI here, now we are done, do a shutdown and stop of the
653 // Create EXIT_BOOT_SERIVES Event
655 Status
= gBS
->CreateEventEx (
658 SnpNotifyExitBootServices
,
660 &gEfiEventExitBootServicesGuid
,
661 &Snp
->ExitBootServicesEvent
663 if (EFI_ERROR (Status
)) {
664 goto Error_DeleteSNP
;
668 // add SNP to the undi handle
670 Status
= gBS
->InstallProtocolInterface (
672 &gEfiSimpleNetworkProtocolGuid
,
673 EFI_NATIVE_INTERFACE
,
677 if (!EFI_ERROR (Status
)) {
683 SNP_MEM_PAGES (4096),
689 if (Snp
->RecycledTxBuf
!= NULL
) {
690 FreePool (Snp
->RecycledTxBuf
);
695 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
701 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
702 This
->DriverBindingHandle
,
708 &gEfiDevicePathProtocolGuid
,
709 This
->DriverBindingHandle
,
714 // If we got here that means we are in error state.
716 if (!EFI_ERROR (Status
)) {
717 Status
= EFI_DEVICE_ERROR
;
724 Stop this driver on ControllerHandle. This service is called by the
725 EFI boot service DisconnectController(). In order to
726 make drivers as small as possible, there are a few calling
727 restrictions for this service. DisconnectController()
728 must follow these calling restrictions. If any other agent wishes
729 to call Stop() it must also follow these calling restrictions.
731 @param This Protocol instance pointer.
732 @param ControllerHandle Handle of device to stop driver on
733 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
734 children is zero stop the entire bus driver.
735 @param ChildHandleBuffer List of Child Handles to Stop.
737 @retval EFI_SUCCESS This driver is removed ControllerHandle
738 @retval other This driver was not removed from this device
743 SimpleNetworkDriverStop (
744 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
745 IN EFI_HANDLE Controller
,
746 IN UINTN NumberOfChildren
,
747 IN EFI_HANDLE
*ChildHandleBuffer
751 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
753 EFI_PCI_IO_PROTOCOL
*PciIo
;
756 // Get our context back.
758 Status
= gBS
->OpenProtocol (
760 &gEfiSimpleNetworkProtocolGuid
,
761 (VOID
**) &SnpProtocol
,
762 This
->DriverBindingHandle
,
764 EFI_OPEN_PROTOCOL_GET_PROTOCOL
767 if (EFI_ERROR (Status
)) {
768 return EFI_UNSUPPORTED
;
771 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
773 Status
= gBS
->UninstallProtocolInterface (
775 &gEfiSimpleNetworkProtocolGuid
,
779 if (EFI_ERROR (Status
)) {
784 // Close EXIT_BOOT_SERIVES Event
786 gBS
->CloseEvent (Snp
->ExitBootServicesEvent
);
788 Status
= gBS
->CloseProtocol (
790 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
791 This
->DriverBindingHandle
,
795 Status
= gBS
->CloseProtocol (
797 &gEfiDevicePathProtocolGuid
,
798 This
->DriverBindingHandle
,
805 FreePool (Snp
->RecycledTxBuf
);
810 SNP_MEM_PAGES (4096),
816 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
824 // Simple Network Protocol Driver Global Variables
826 EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding
= {
827 SimpleNetworkDriverSupported
,
828 SimpleNetworkDriverStart
,
829 SimpleNetworkDriverStop
,
836 The SNP driver entry point.
838 @param ImageHandle The driver image handle.
839 @param SystemTable The system table.
841 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,
842 loaded it's ROM, and installed a notify event for
843 the Network Indentifier Interface Protocol
845 @retval Other Return value from HandleProtocol for
846 DeviceIoProtocol or LoadedImageProtocol
851 InitializeSnpNiiDriver (
852 IN EFI_HANDLE ImageHandle
,
853 IN EFI_SYSTEM_TABLE
*SystemTable
856 return EfiLibInstallDriverBindingComponentName2 (
859 &gSimpleNetworkDriverBinding
,
861 &gSimpleNetworkComponentName
,
862 &gSimpleNetworkComponentName2