2 Implementation of driver entry point and driver binding protocol.
4 Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) Microsoft Corporation.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
13 One notified function to stop UNDI device when gBS->ExitBootServices() called.
15 @param Event Pointer to this event
16 @param Context Event handler private data
21 SnpNotifyExitBootServices (
28 Snp
= (SNP_DRIVER
*)Context
;
31 // Shutdown and stop UNDI driver
38 Send command to UNDI. It does nothing currently.
40 @param Cdb command to be sent to UNDI.
42 @retval EFI_INVALID_PARAMETER The command is 0.
43 @retval EFI_UNSUPPORTED Default return status because it's not
53 DEBUG ((EFI_D_ERROR
, "\nIssueHwUndiCommand() - This should not be called!"));
56 return EFI_INVALID_PARAMETER
;
60 // %%TBD - For now, nothing is done.
62 return EFI_UNSUPPORTED
;
67 Compute 8-bit checksum of a buffer.
69 @param Buffer Pointer to buffer.
70 @param Length Length of buffer in bytes.
72 @return 8-bit checksum of all bytes in buffer, or zero if ptr is NULL or len
88 if (Ptr
== NULL
|| Length
== 0) {
92 while (Length
-- != 0) {
93 Cksum
= (UINT8
) (Cksum
+ *Ptr
++);
100 Test to see if this driver supports ControllerHandle. This service
101 is called by the EFI boot service ConnectController(). In
102 order to make drivers as small as possible, there are a few calling
103 restrictions for this service. ConnectController() must
104 follow these calling restrictions. If any other agent wishes to call
105 Supported() it must also follow these calling restrictions.
107 @param This Protocol instance pointer.
108 @param ControllerHandle Handle of device to test.
109 @param RemainingDevicePath Optional parameter use to pick a specific child
112 @retval EFI_SUCCESS This driver supports this device.
113 @retval EFI_ALREADY_STARTED This driver is already running on this device.
114 @retval other This driver does not support this device.
119 SimpleNetworkDriverSupported (
120 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
121 IN EFI_HANDLE Controller
,
122 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
126 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*NiiProtocol
;
129 Status
= gBS
->OpenProtocol (
131 &gEfiDevicePathProtocolGuid
,
133 This
->DriverBindingHandle
,
135 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
137 if (EFI_ERROR (Status
)) {
141 Status
= gBS
->OpenProtocol (
143 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
144 (VOID
**) &NiiProtocol
,
145 This
->DriverBindingHandle
,
147 EFI_OPEN_PROTOCOL_BY_DRIVER
150 if (EFI_ERROR (Status
)) {
151 if (Status
== EFI_ALREADY_STARTED
) {
152 DEBUG ((EFI_D_INFO
, "Support(): Already Started. on handle %p\n", Controller
));
157 DEBUG ((EFI_D_INFO
, "Support(): UNDI3.1 found on handle %p\n", Controller
));
160 // check the version, we don't want to connect to the undi16
162 if (NiiProtocol
->Type
!= EfiNetworkInterfaceUndi
) {
163 Status
= EFI_UNSUPPORTED
;
167 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
169 if ((NiiProtocol
->Id
& 0x0F) != 0) {
170 DEBUG ((EFI_D_NET
, "\n!PXE structure is not paragraph aligned.\n"));
171 Status
= EFI_UNSUPPORTED
;
175 Pxe
= (PXE_UNDI
*) (UINTN
) (NiiProtocol
->Id
);
178 // Verify !PXE revisions.
180 if (Pxe
->hw
.Signature
!= PXE_ROMID_SIGNATURE
) {
181 DEBUG ((EFI_D_NET
, "\n!PXE signature is not valid.\n"));
182 Status
= EFI_UNSUPPORTED
;
186 if (Pxe
->hw
.Rev
< PXE_ROMID_REV
) {
187 DEBUG ((EFI_D_NET
, "\n!PXE.Rev is not supported.\n"));
188 Status
= EFI_UNSUPPORTED
;
192 if (Pxe
->hw
.MajorVer
< PXE_ROMID_MAJORVER
) {
194 DEBUG ((EFI_D_NET
, "\n!PXE.MajorVer is not supported.\n"));
195 Status
= EFI_UNSUPPORTED
;
198 } else if (Pxe
->hw
.MajorVer
== PXE_ROMID_MAJORVER
&& Pxe
->hw
.MinorVer
< PXE_ROMID_MINORVER
) {
199 DEBUG ((EFI_D_NET
, "\n!PXE.MinorVer is not supported."));
200 Status
= EFI_UNSUPPORTED
;
204 // Do S/W UNDI specific checks.
206 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) == 0) {
207 if (Pxe
->sw
.EntryPoint
< Pxe
->sw
.Len
) {
208 DEBUG ((EFI_D_NET
, "\n!PXE S/W entry point is not valid."));
209 Status
= EFI_UNSUPPORTED
;
213 if (Pxe
->sw
.BusCnt
== 0) {
214 DEBUG ((EFI_D_NET
, "\n!PXE.BusCnt is zero."));
215 Status
= EFI_UNSUPPORTED
;
220 Status
= EFI_SUCCESS
;
221 DEBUG ((EFI_D_INFO
, "Support(): supported on %p\n", Controller
));
226 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
227 This
->DriverBindingHandle
,
235 Start this driver on ControllerHandle. This service is called by the
236 EFI boot service ConnectController(). In order to make
237 drivers as small as possible, there are a few calling restrictions for
238 this service. ConnectController() must follow these
239 calling restrictions. If any other agent wishes to call Start() it
240 must also follow these calling restrictions.
242 @param This Protocol instance pointer.
243 @param ControllerHandle Handle of device to bind driver to.
244 @param RemainingDevicePath Optional parameter use to pick a specific child
247 @retval EFI_SUCCESS This driver is added to ControllerHandle
248 @retval EFI_DEVICE_ERROR This driver could not be started due to a device error
249 @retval other This driver does not support this device
254 SimpleNetworkDriverStart (
255 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
256 IN EFI_HANDLE Controller
,
257 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
260 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL
*Nii
;
261 EFI_DEVICE_PATH_PROTOCOL
*NiiDevicePath
;
268 PXE_STATFLAGS InitStatFlags
;
269 EFI_PCI_IO_PROTOCOL
*PciIo
;
270 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*BarDesc
;
272 BOOLEAN FoundMemoryBar
;
274 DEBUG ((EFI_D_NET
, "\nSnpNotifyNetworkInterfaceIdentifier() "));
276 Status
= gBS
->OpenProtocol (
278 &gEfiDevicePathProtocolGuid
,
279 (VOID
**) &NiiDevicePath
,
280 This
->DriverBindingHandle
,
282 EFI_OPEN_PROTOCOL_BY_DRIVER
285 if (EFI_ERROR (Status
)) {
289 Status
= gBS
->LocateDevicePath (
290 &gEfiPciIoProtocolGuid
,
295 if (EFI_ERROR (Status
)) {
299 Status
= gBS
->OpenProtocol (
301 &gEfiPciIoProtocolGuid
,
303 This
->DriverBindingHandle
,
305 EFI_OPEN_PROTOCOL_GET_PROTOCOL
307 if (EFI_ERROR (Status
)) {
311 // Get the NII interface.
313 Status
= gBS
->OpenProtocol (
315 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
317 This
->DriverBindingHandle
,
319 EFI_OPEN_PROTOCOL_BY_DRIVER
321 if (EFI_ERROR (Status
)) {
324 &gEfiDevicePathProtocolGuid
,
325 This
->DriverBindingHandle
,
331 DEBUG ((EFI_D_INFO
, "Start(): UNDI3.1 found\n"));
333 Pxe
= (PXE_UNDI
*) (UINTN
) (Nii
->Id
);
335 if (Calc8BitCksum (Pxe
, Pxe
->hw
.Len
) != 0) {
336 DEBUG ((EFI_D_NET
, "\n!PXE checksum is not correct.\n"));
340 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
342 // We can get any packets.
344 } else if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
346 // We need to be able to get broadcast packets for DHCP.
347 // If we do not have promiscuous support, we must at least have
348 // broadcast support or we cannot do DHCP!
351 DEBUG ((EFI_D_NET
, "\nUNDI does not have promiscuous or broadcast support."));
355 // OK, we like this UNDI, and we know snp is not already there on this handle
356 // Allocate and initialize a new simple network protocol structure.
358 Status
= PciIo
->AllocateBuffer (
362 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
367 if (Status
!= EFI_SUCCESS
) {
368 DEBUG ((EFI_D_NET
, "\nCould not allocate SNP_DRIVER structure.\n"));
372 Snp
= (SNP_DRIVER
*) (UINTN
) Address
;
374 ZeroMem (Snp
, sizeof (SNP_DRIVER
));
377 Snp
->Signature
= SNP_DRIVER_SIGNATURE
;
379 EfiInitializeLock (&Snp
->Lock
, TPL_NOTIFY
);
381 Snp
->Snp
.Revision
= EFI_SIMPLE_NETWORK_PROTOCOL_REVISION
;
382 Snp
->Snp
.Start
= SnpUndi32Start
;
383 Snp
->Snp
.Stop
= SnpUndi32Stop
;
384 Snp
->Snp
.Initialize
= SnpUndi32Initialize
;
385 Snp
->Snp
.Reset
= SnpUndi32Reset
;
386 Snp
->Snp
.Shutdown
= SnpUndi32Shutdown
;
387 Snp
->Snp
.ReceiveFilters
= SnpUndi32ReceiveFilters
;
388 Snp
->Snp
.StationAddress
= SnpUndi32StationAddress
;
389 Snp
->Snp
.Statistics
= SnpUndi32Statistics
;
390 Snp
->Snp
.MCastIpToMac
= SnpUndi32McastIpToMac
;
391 Snp
->Snp
.NvData
= SnpUndi32NvData
;
392 Snp
->Snp
.GetStatus
= SnpUndi32GetStatus
;
393 Snp
->Snp
.Transmit
= SnpUndi32Transmit
;
394 Snp
->Snp
.Receive
= SnpUndi32Receive
;
395 Snp
->Snp
.WaitForPacket
= NULL
;
397 Snp
->Snp
.Mode
= &Snp
->Mode
;
399 Snp
->TxRxBufferSize
= 0;
400 Snp
->TxRxBuffer
= NULL
;
402 Snp
->RecycledTxBuf
= AllocatePool (sizeof (UINT64
) * SNP_TX_BUFFER_INCREASEMENT
);
403 if (Snp
->RecycledTxBuf
== NULL
) {
404 Status
= EFI_OUT_OF_RESOURCES
;
405 goto Error_DeleteSNP
;
407 Snp
->MaxRecycledTxBuf
= SNP_TX_BUFFER_INCREASEMENT
;
408 Snp
->RecycledTxBufCount
= 0;
410 if (Nii
->Revision
>= EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION
) {
411 Snp
->IfNum
= Nii
->IfNum
;
414 Snp
->IfNum
= (UINT8
) (Nii
->IfNum
& 0xFF);
417 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_HW_UNDI
) != 0) {
418 Snp
->IsSwUndi
= FALSE
;
419 Snp
->IssueUndi32Command
= &IssueHwUndiCommand
;
421 Snp
->IsSwUndi
= TRUE
;
423 if ((Pxe
->sw
.Implementation
& PXE_ROMID_IMP_SW_VIRT_ADDR
) != 0) {
424 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) Pxe
->sw
.EntryPoint
;
426 Snp
->IssueUndi32Command
= (ISSUE_UNDI32_COMMAND
) (UINTN
) ((UINT8
) (UINTN
) Pxe
+ Pxe
->sw
.EntryPoint
);
430 // Allocate a global CPB and DB buffer for this UNDI interface.
431 // we do this because:
433 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
434 // within 2GB limit, create them here and map them so that when undi calls
435 // v2p callback to check if the physical address is < 2gb, we will pass.
437 // -This is not a requirement for 3.1 or later UNDIs but the code looks
438 // simpler if we use the same cpb, db variables for both old and new undi
439 // interfaces from all the SNP interface calls (we don't map the buffers
440 // for the newer undi interfaces though)
442 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
443 // interface as EFI does not multi-task and so SNP will not be re-entered!
445 Status
= PciIo
->AllocateBuffer (
449 SNP_MEM_PAGES (4096),
454 if (Status
!= EFI_SUCCESS
) {
455 DEBUG ((EFI_D_NET
, "\nCould not allocate CPB and DB structures.\n"));
456 goto Error_DeleteSNP
;
459 Snp
->Cpb
= (VOID
*) (UINTN
) Address
;
460 Snp
->Db
= (VOID
*) ((UINTN
) Address
+ 2048);
463 // Find the correct BAR to do IO.
465 // Enumerate through the PCI BARs for the device to determine which one is
466 // the IO BAR. Save the index of the BAR into the adapter info structure.
467 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
469 Snp
->MemoryBarIndex
= PCI_MAX_BAR
;
470 Snp
->IoBarIndex
= PCI_MAX_BAR
;
471 FoundMemoryBar
= FALSE
;
473 for (BarIndex
= 0; BarIndex
< PCI_MAX_BAR
; BarIndex
++) {
474 Status
= PciIo
->GetBarAttributes (
480 if (Status
== EFI_UNSUPPORTED
) {
482 } else if (EFI_ERROR (Status
)) {
483 goto Error_DeleteSNP
;
486 if ((!FoundMemoryBar
) && (BarDesc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
)) {
487 Snp
->MemoryBarIndex
= BarIndex
;
488 FoundMemoryBar
= TRUE
;
489 } else if ((!FoundIoBar
) && (BarDesc
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
)) {
490 Snp
->IoBarIndex
= BarIndex
;
496 if (FoundMemoryBar
&& FoundIoBar
) {
501 Status
= PxeStart (Snp
);
503 if (Status
!= EFI_SUCCESS
) {
504 goto Error_DeleteSNP
;
507 Snp
->Cdb
.OpCode
= PXE_OPCODE_GET_INIT_INFO
;
508 Snp
->Cdb
.OpFlags
= PXE_OPFLAGS_NOT_USED
;
510 Snp
->Cdb
.CPBsize
= PXE_CPBSIZE_NOT_USED
;
511 Snp
->Cdb
.CPBaddr
= PXE_DBADDR_NOT_USED
;
513 Snp
->Cdb
.DBsize
= (UINT16
) sizeof (Snp
->InitInfo
);
514 Snp
->Cdb
.DBaddr
= (UINT64
)(UINTN
) (&Snp
->InitInfo
);
516 Snp
->Cdb
.StatCode
= PXE_STATCODE_INITIALIZE
;
517 Snp
->Cdb
.StatFlags
= PXE_STATFLAGS_INITIALIZE
;
519 Snp
->Cdb
.IFnum
= Snp
->IfNum
;
520 Snp
->Cdb
.Control
= PXE_CONTROL_LAST_CDB_IN_LIST
;
522 DEBUG ((EFI_D_NET
, "\nSnp->undi.get_init_info() "));
524 (*Snp
->IssueUndi32Command
) ((UINT64
)(UINTN
) &Snp
->Cdb
);
527 // Save the INIT Stat Code...
529 InitStatFlags
= Snp
->Cdb
.StatFlags
;
531 if (Snp
->Cdb
.StatCode
!= PXE_STATCODE_SUCCESS
) {
532 DEBUG ((EFI_D_NET
, "\nSnp->undi.init_info() %xh:%xh\n", Snp
->Cdb
.StatFlags
, Snp
->Cdb
.StatCode
));
534 goto Error_DeleteSNP
;
538 // Initialize simple network protocol mode structure
540 Snp
->Mode
.State
= EfiSimpleNetworkStopped
;
541 Snp
->Mode
.HwAddressSize
= Snp
->InitInfo
.HWaddrLen
;
542 Snp
->Mode
.MediaHeaderSize
= Snp
->InitInfo
.MediaHeaderLen
;
543 Snp
->Mode
.MaxPacketSize
= Snp
->InitInfo
.FrameDataLen
;
544 Snp
->Mode
.NvRamAccessSize
= Snp
->InitInfo
.NvWidth
;
545 Snp
->Mode
.NvRamSize
= Snp
->InitInfo
.NvCount
* Snp
->Mode
.NvRamAccessSize
;
546 Snp
->Mode
.IfType
= Snp
->InitInfo
.IFtype
;
547 Snp
->Mode
.MaxMCastFilterCount
= Snp
->InitInfo
.MCastFilterCnt
;
548 Snp
->Mode
.MCastFilterCount
= 0;
550 switch (InitStatFlags
& PXE_STATFLAGS_CABLE_DETECT_MASK
) {
551 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED
:
552 Snp
->CableDetectSupported
= TRUE
;
555 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED
:
557 Snp
->CableDetectSupported
= FALSE
;
560 switch (InitStatFlags
& PXE_STATFLAGS_GET_STATUS_NO_MEDIA_MASK
) {
561 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_SUPPORTED
:
562 Snp
->MediaStatusSupported
= TRUE
;
565 case PXE_STATFLAGS_GET_STATUS_NO_MEDIA_NOT_SUPPORTED
:
567 Snp
->MediaStatusSupported
= FALSE
;
570 if (Snp
->CableDetectSupported
|| Snp
->MediaStatusSupported
) {
571 Snp
->Mode
.MediaPresentSupported
= TRUE
;
574 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_STATION_ADDR_SETTABLE
) != 0) {
575 Snp
->Mode
.MacAddressChangeable
= TRUE
;
577 Snp
->Mode
.MacAddressChangeable
= FALSE
;
580 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED
) != 0) {
581 Snp
->Mode
.MultipleTxSupported
= TRUE
;
583 Snp
->Mode
.MultipleTxSupported
= FALSE
;
586 Snp
->Mode
.ReceiveFilterMask
= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST
;
588 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
589 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
593 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED
) != 0) {
594 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS
;
598 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED
) != 0) {
599 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST
;
603 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED
) != 0) {
604 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST
;
608 if ((Pxe
->hw
.Implementation
& PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED
) != 0) {
609 Snp
->Mode
.ReceiveFilterMask
|= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST
;
613 Snp
->Mode
.ReceiveFilterSetting
= 0;
616 // need to get the station address to save in the mode structure. we need to
617 // initialize the UNDI first for this.
619 Snp
->TxRxBufferSize
= Snp
->InitInfo
.MemoryRequired
;
620 Status
= PxeInit (Snp
, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE
);
622 if (EFI_ERROR (Status
)) {
624 goto Error_DeleteSNP
;
627 Status
= PxeGetStnAddr (Snp
);
629 if (Status
!= EFI_SUCCESS
) {
630 DEBUG ((EFI_D_ERROR
, "\nSnp->undi.get_station_addr() failed.\n"));
633 goto Error_DeleteSNP
;
636 Snp
->Mode
.MediaPresent
= FALSE
;
639 // We should not leave UNDI started and initialized here. this DriverStart()
640 // routine must only find and attach the SNP interface to UNDI layer that it
641 // finds on the given handle!
642 // The UNDI layer will be started when upper layers call Snp->start.
643 // How ever, this DriverStart() must fill up the snp mode structure which
644 // contains the MAC address of the NIC. For this reason we started and
645 // initialized UNDI here, now we are done, do a shutdown and stop of the
651 if (PcdGetBool (PcdSnpCreateExitBootServicesEvent
)) {
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
;
669 // add SNP to the undi handle
671 Status
= gBS
->InstallProtocolInterface (
673 &gEfiSimpleNetworkProtocolGuid
,
674 EFI_NATIVE_INTERFACE
,
678 if (!EFI_ERROR (Status
)) {
684 SNP_MEM_PAGES (4096),
690 if (Snp
->RecycledTxBuf
!= NULL
) {
691 FreePool (Snp
->RecycledTxBuf
);
696 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
702 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
703 This
->DriverBindingHandle
,
709 &gEfiDevicePathProtocolGuid
,
710 This
->DriverBindingHandle
,
715 // If we got here that means we are in error state.
717 if (!EFI_ERROR (Status
)) {
718 Status
= EFI_DEVICE_ERROR
;
725 Stop this driver on ControllerHandle. This service is called by the
726 EFI boot service DisconnectController(). In order to
727 make drivers as small as possible, there are a few calling
728 restrictions for this service. DisconnectController()
729 must follow these calling restrictions. If any other agent wishes
730 to call Stop() it must also follow these calling restrictions.
732 @param This Protocol instance pointer.
733 @param ControllerHandle Handle of device to stop driver on
734 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
735 children is zero stop the entire bus driver.
736 @param ChildHandleBuffer List of Child Handles to Stop.
738 @retval EFI_SUCCESS This driver is removed ControllerHandle
739 @retval other This driver was not removed from this device
744 SimpleNetworkDriverStop (
745 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
746 IN EFI_HANDLE Controller
,
747 IN UINTN NumberOfChildren
,
748 IN EFI_HANDLE
*ChildHandleBuffer
752 EFI_SIMPLE_NETWORK_PROTOCOL
*SnpProtocol
;
754 EFI_PCI_IO_PROTOCOL
*PciIo
;
757 // Get our context back.
759 Status
= gBS
->OpenProtocol (
761 &gEfiSimpleNetworkProtocolGuid
,
762 (VOID
**) &SnpProtocol
,
763 This
->DriverBindingHandle
,
765 EFI_OPEN_PROTOCOL_GET_PROTOCOL
768 if (EFI_ERROR (Status
)) {
769 return EFI_UNSUPPORTED
;
772 Snp
= EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol
);
774 Status
= gBS
->UninstallProtocolInterface (
776 &gEfiSimpleNetworkProtocolGuid
,
780 if (EFI_ERROR (Status
)) {
784 if (PcdGetBool (PcdSnpCreateExitBootServicesEvent
)) {
786 // Close EXIT_BOOT_SERVICES Event
788 gBS
->CloseEvent (Snp
->ExitBootServicesEvent
);
791 Status
= gBS
->CloseProtocol (
793 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
794 This
->DriverBindingHandle
,
798 Status
= gBS
->CloseProtocol (
800 &gEfiDevicePathProtocolGuid
,
801 This
->DriverBindingHandle
,
808 FreePool (Snp
->RecycledTxBuf
);
813 SNP_MEM_PAGES (4096),
819 SNP_MEM_PAGES (sizeof (SNP_DRIVER
)),
827 // Simple Network Protocol Driver Global Variables
829 EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding
= {
830 SimpleNetworkDriverSupported
,
831 SimpleNetworkDriverStart
,
832 SimpleNetworkDriverStop
,
839 The SNP driver entry point.
841 @param ImageHandle The driver image handle.
842 @param SystemTable The system table.
844 @retval EFI_SUCCESS Initialization routine has found UNDI hardware,
845 loaded it's ROM, and installed a notify event for
846 the Network Identifier Interface Protocol
848 @retval Other Return value from HandleProtocol for
849 DeviceIoProtocol or LoadedImageProtocol
854 InitializeSnpNiiDriver (
855 IN EFI_HANDLE ImageHandle
,
856 IN EFI_SYSTEM_TABLE
*SystemTable
859 return EfiLibInstallDriverBindingComponentName2 (
862 &gSimpleNetworkDriverBinding
,
864 &gSimpleNetworkComponentName
,
865 &gSimpleNetworkComponentName2