https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
		
			
				
	
	
		
			616 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			616 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   The SioBusDxe driver is used to create child devices on the ISA bus and
 | |
|   installs the Super I/O protocols on them.
 | |
| 
 | |
|   Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
 | |
| 
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "SioBusDxe.h"
 | |
| 
 | |
| //
 | |
| // SioBus Driver Binding Protocol
 | |
| //
 | |
| EFI_DRIVER_BINDING_PROTOCOL gSioBusDriverBinding = {
 | |
|   SioBusDriverBindingSupported,
 | |
|   SioBusDriverBindingStart,
 | |
|   SioBusDriverBindingStop,
 | |
|   0x10,
 | |
|   NULL,
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|   Tests to see if this driver supports a given controller. If a child device is
 | |
|   provided, it further tests to see if this driver supports creating a handle
 | |
|   for the specified child device.
 | |
| 
 | |
|   This function checks to see if the driver specified by This supports the
 | |
|   device specified by ControllerHandle. Drivers will typically use the device
 | |
|   path attached to ControllerHandle and/or the services from the bus I/O
 | |
|   abstraction attached to ControllerHandle to determine if the driver supports
 | |
|   ControllerHandle. This function may be called many times during platform
 | |
|   initialization. In order to reduce boot times, the tests performed by this
 | |
|   function must be very small, and take as little time as possible to execute.
 | |
|   This function must not change the state of any hardware devices, and this
 | |
|   function must be aware that the device specified by ControllerHandle may
 | |
|   already be managed by the same driver or a different driver. This function
 | |
|   must match its calls to AllocatePages() with FreePages(), AllocatePool() with
 | |
|   FreePool(), and OpenProtocol() with CloseProtocol(). Since ControllerHandle
 | |
|   may have been previously started by the same driver, if a protocol is already
 | |
|   in the opened state, then it must not be closed with CloseProtocol(). This is
 | |
|   required to guarantee the state of ControllerHandle is not modified by this
 | |
|   function.
 | |
| 
 | |
|   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL
 | |
|                                    instance.
 | |
|   @param[in]  ControllerHandle     The handle of the controller to test. This
 | |
|                                    handle must support a protocol interface
 | |
|                                    that supplies an I/O abstraction to the
 | |
|                                    driver.
 | |
|   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a
 | |
|                                    device path.  This parameter is ignored by
 | |
|                                    device drivers, and is optional for bus
 | |
|                                    drivers. For bus drivers, if this parameter
 | |
|                                    is not NULL, then the bus driver must
 | |
|                                    determine if the bus controller specified by
 | |
|                                    ControllerHandle and the child controller
 | |
|                                    specified by RemainingDevicePath are both
 | |
|                                    supported by this bus driver.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The device specified by ControllerHandle and
 | |
|                                    RemainingDevicePath is supported by the
 | |
|                                    driver specified by This.
 | |
|   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
 | |
|                                    RemainingDevicePath is already being managed
 | |
|                                    by the driver specified by This.
 | |
|   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
 | |
|                                    RemainingDevicePath is already being managed
 | |
|                                    by a different driver or an application that
 | |
|                                    requires exclusive access.
 | |
|   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
 | |
|                                    RemainingDevicePath is not supported by the
 | |
|                                    driver specified by This.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SioBusDriverBindingSupported (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | |
|   IN EFI_HANDLE                     Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS             Status;
 | |
|   EFI_PCI_IO_PROTOCOL    *PciIo;
 | |
|   PCI_TYPE00             Pci;
 | |
|   UINTN                  SegmentNumber;
 | |
|   UINTN                  BusNumber;
 | |
|   UINTN                  DeviceNumber;
 | |
|   UINTN                  FunctionNumber;
 | |
| 
 | |
|   //
 | |
|   // Get PciIo protocol instance
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   (VOID**)&PciIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR(Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = PciIo->Pci.Read (
 | |
|                     PciIo,
 | |
|                     EfiPciIoWidthUint32,
 | |
|                     0,
 | |
|                     sizeof(Pci) / sizeof(UINT32),
 | |
|                     &Pci);
 | |
| 
 | |
|   if (!EFI_ERROR (Status)) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     if ((Pci.Hdr.Command & 0x03) == 0x03) {
 | |
|       if (Pci.Hdr.ClassCode[2] == PCI_CLASS_BRIDGE) {
 | |
|         //
 | |
|         // See if this is a standard PCI to ISA Bridge from the Base Code and
 | |
|         // Class Code
 | |
|         //
 | |
|         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA) {
 | |
|           Status = EFI_SUCCESS;
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // See if this is an Intel PCI to ISA bridge in Positive Decode Mode
 | |
|         //
 | |
|         if (Pci.Hdr.ClassCode[1] == PCI_CLASS_BRIDGE_ISA_PDECODE &&
 | |
|             Pci.Hdr.VendorId     == 0x8086) {
 | |
|           //
 | |
|           // See if this is on Function #0 to avoid false positives on
 | |
|           // PCI_CLASS_BRIDGE_OTHER that has the same value as
 | |
|           // PCI_CLASS_BRIDGE_ISA_PDECODE
 | |
|           //
 | |
|           Status = PciIo->GetLocation (
 | |
|                             PciIo,
 | |
|                             &SegmentNumber,
 | |
|                             &BusNumber,
 | |
|                             &DeviceNumber,
 | |
|                             &FunctionNumber
 | |
|                             );
 | |
|           if (!EFI_ERROR (Status) && FunctionNumber == 0) {
 | |
|             Status = EFI_SUCCESS;
 | |
|           } else {
 | |
|             Status = EFI_UNSUPPORTED;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   gBS->CloseProtocol (
 | |
|          Controller,
 | |
|          &gEfiPciIoProtocolGuid,
 | |
|          This->DriverBindingHandle,
 | |
|          Controller
 | |
|          );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Starts a device controller or a bus controller.
 | |
| 
 | |
|   The Start() function is designed to be invoked from the EFI boot service
 | |
|   ConnectController(). As a result, much of the error checking on the
 | |
|   parameters to Start() has been moved into this common boot service. It is
 | |
|   legal to call Start() from other locations, but the following calling
 | |
|   restrictions must be followed or the system behavior will not be
 | |
|   deterministic.
 | |
|   1. ControllerHandle must be a valid EFI_HANDLE.
 | |
|   2. If RemainingDevicePath is not NULL, then it must be a pointer to a
 | |
|      naturally aligned EFI_DEVICE_PATH_PROTOCOL.
 | |
|   3. Prior to calling Start(), the Supported() function for the driver
 | |
|      specified by This must have been called with the same calling parameters,
 | |
|      and Supported() must have returned EFI_SUCCESS.
 | |
| 
 | |
|   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL
 | |
|                                    instance.
 | |
|   @param[in]  ControllerHandle     The handle of the controller to start. This
 | |
|                                    handle must support a protocol interface
 | |
|                                    that supplies an I/O abstraction to the
 | |
|                                    driver.
 | |
|   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a
 | |
|                                    device path.  This parameter is ignored by
 | |
|                                    device drivers, and is optional for bus
 | |
|                                    drivers. For a bus driver, if this parameter
 | |
|                                    is NULL, then handles for all the children
 | |
|                                    of Controller are created by this driver. If
 | |
|                                    this parameter is not NULL and the first
 | |
|                                    Device Path Node is not the End of Device
 | |
|                                    Path Node, then only the handle for the
 | |
|                                    child device specified by the first Device
 | |
|                                    Path Node of RemainingDevicePath is created
 | |
|                                    by this driver. If the first Device Path
 | |
|                                    Node of RemainingDevicePath is the End of
 | |
|                                    Device Path Node, no child handle is created
 | |
|                                    by this driver.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The device was started.
 | |
|   @retval EFI_DEVICE_ERROR         The device could not be started due to a
 | |
|                                    device error.
 | |
|   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a
 | |
|                                    lack of resources.
 | |
|   @retval Others                   The driver failded to start the device.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SioBusDriverBindingStart (
 | |
|   IN EFI_DRIVER_BINDING_PROTOCOL    *This,
 | |
|   IN EFI_HANDLE                     Controller,
 | |
|   IN EFI_DEVICE_PATH_PROTOCOL       *RemainingDevicePath
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   EFI_PCI_IO_PROTOCOL            *PciIo;
 | |
|   EFI_DEVICE_PATH_PROTOCOL       *ParentDevicePath;
 | |
|   UINT64                         Supports;
 | |
|   UINT64                         OriginalAttributes;
 | |
|   UINT64                         Attributes;
 | |
|   BOOLEAN                        Enabled;
 | |
|   SIO_BUS_DRIVER_PRIVATE_DATA    *Private;
 | |
|   UINT32                         ChildDeviceNumber;
 | |
| 
 | |
|   Enabled            = FALSE;
 | |
|   Supports           = 0;
 | |
|   OriginalAttributes = 0;
 | |
|   Private            = NULL;
 | |
| 
 | |
|   //
 | |
|   // Open the PCI I/O Protocol Interface
 | |
|   //
 | |
|   PciIo = NULL;
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiPciIoProtocolGuid,
 | |
|                   (VOID**) &PciIo,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Open Device Path Protocol
 | |
|   //
 | |
|   Status = gBS->OpenProtocol (
 | |
|                   Controller,
 | |
|                   &gEfiDevicePathProtocolGuid,
 | |
|                   (VOID **) &ParentDevicePath,
 | |
|                   This->DriverBindingHandle,
 | |
|                   Controller,
 | |
|                   EFI_OPEN_PROTOCOL_BY_DRIVER
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiPciIoProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get supported PCI attributes
 | |
|   //
 | |
|   Status = PciIo->Attributes (
 | |
|                     PciIo,
 | |
|                     EfiPciIoAttributeOperationSupported,
 | |
|                     0,
 | |
|                     &Supports
 | |
|                     );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Supports &= (UINT64) (EFI_PCI_IO_ATTRIBUTE_ISA_IO |
 | |
|                         EFI_PCI_IO_ATTRIBUTE_ISA_IO_16);
 | |
|   if (Supports == 0 ||
 | |
|       Supports == (EFI_PCI_IO_ATTRIBUTE_ISA_IO |
 | |
|                    EFI_PCI_IO_ATTRIBUTE_ISA_IO_16)) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = PciIo->Attributes (
 | |
|                     PciIo,
 | |
|                     EfiPciIoAttributeOperationGet,
 | |
|                     0,
 | |
|                     &OriginalAttributes
 | |
|                     );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Attributes = EFI_PCI_DEVICE_ENABLE |
 | |
|                Supports |
 | |
|                EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO;
 | |
|   Status = PciIo->Attributes (
 | |
|                     PciIo,
 | |
|                     EfiPciIoAttributeOperationEnable,
 | |
|                     Attributes,
 | |
|                     NULL
 | |
|                     );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Enabled = TRUE;
 | |
| 
 | |
|   //
 | |
|   // Store the OriginalAttributes for the restore in BindingStop()
 | |
|   //
 | |
|   Private = AllocateZeroPool (sizeof (SIO_BUS_DRIVER_PRIVATE_DATA));
 | |
|   if (Private == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
|   Private->PciIo              = PciIo;
 | |
|   Private->OriginalAttributes = OriginalAttributes;
 | |
| 
 | |
|   Status = gBS->InstallProtocolInterface (
 | |
|                   &Controller,
 | |
|                   &gEfiCallerIdGuid,
 | |
|                   EFI_NATIVE_INTERFACE,
 | |
|                   Private
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Report status code for the start of general controller initialization
 | |
|   //
 | |
|   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|     EFI_PROGRESS_CODE,
 | |
|     (EFI_IO_BUS_LPC | EFI_IOB_PC_INIT),
 | |
|     ParentDevicePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Report status code for the start of enabling devices on the bus
 | |
|   //
 | |
|   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
 | |
|     EFI_PROGRESS_CODE,
 | |
|     (EFI_IO_BUS_LPC | EFI_IOB_PC_ENABLE),
 | |
|     ParentDevicePath
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Create all the children upon the first entrance
 | |
|   //
 | |
|   ChildDeviceNumber = SioCreateAllChildDevices (
 | |
|                         This,
 | |
|                         Controller,
 | |
|                         PciIo,
 | |
|                         ParentDevicePath
 | |
|                         );
 | |
|   if (ChildDeviceNumber == 0) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (PciIo != NULL && Enabled) {
 | |
|       PciIo->Attributes (
 | |
|                PciIo,
 | |
|                EfiPciIoAttributeOperationSet,
 | |
|                OriginalAttributes,
 | |
|                NULL
 | |
|                );
 | |
|     }
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiDevicePathProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
| 
 | |
|     gBS->CloseProtocol (
 | |
|            Controller,
 | |
|            &gEfiPciIoProtocolGuid,
 | |
|            This->DriverBindingHandle,
 | |
|            Controller
 | |
|            );
 | |
| 
 | |
|     if (Private != NULL) {
 | |
|       gBS->UninstallMultipleProtocolInterfaces (
 | |
|              Controller,
 | |
|              &gEfiCallerIdGuid,
 | |
|              Private,
 | |
|              NULL
 | |
|              );
 | |
|       FreePool (Private);
 | |
|     }
 | |
| 
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Stops a device controller or a bus controller.
 | |
| 
 | |
|   The Stop() function is designed to be invoked from the EFI boot service
 | |
|   DisconnectController(). As a result, much of the error checking on the
 | |
|   parameters to Stop() has been moved into this common boot service. It is
 | |
|   legal to call Stop() from other locations, but the following calling
 | |
|   restrictions must be followed or the system behavior will not be
 | |
|   deterministic.
 | |
|   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous
 | |
|      call to this same driver's Start() function.
 | |
|   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a
 | |
|      valid EFI_HANDLE. In addition, all of these handles must have been created
 | |
|      in this driver's Start() function, and the Start() function must have
 | |
|      called OpenProtocol() on ControllerHandle with an Attribute of
 | |
|      EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
 | |
| 
 | |
|   @param[in]  This               A pointer to the EFI_DRIVER_BINDING_PROTOCOL
 | |
|                                  instance.
 | |
|   @param[in]  ControllerHandle   A handle to the device being stopped. The
 | |
|                                  handle must support a bus specific I/O
 | |
|                                  protocol for the driver to use to stop the
 | |
|                                  device.
 | |
|   @param[in]  NumberOfChildren   The number of child device handles in
 | |
|                                  ChildHandleBuffer.
 | |
|   @param[in]  ChildHandleBuffer  An array of child handles to be freed. May be
 | |
|                                  NULL if NumberOfChildren is 0.
 | |
| 
 | |
|   @retval EFI_SUCCESS            The device was stopped.
 | |
|   @retval EFI_DEVICE_ERROR       The device could not be stopped due to a
 | |
|                                  device error.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SioBusDriverBindingStop (
 | |
|   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
 | |
|   IN  EFI_HANDLE                     Controller,
 | |
|   IN  UINTN                          NumberOfChildren,
 | |
|   IN  EFI_HANDLE                     *ChildHandleBuffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   SIO_BUS_DRIVER_PRIVATE_DATA    *Private;
 | |
|   UINTN                          Index;
 | |
|   BOOLEAN                        AllChildrenStopped;
 | |
|   EFI_SIO_PROTOCOL               *Sio;
 | |
|   SIO_DEV                        *SioDevice;
 | |
|   EFI_PCI_IO_PROTOCOL            *PciIo;
 | |
| 
 | |
|   if (NumberOfChildren == 0) {
 | |
|     //
 | |
|     // Restore PCI attributes
 | |
|     //
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiCallerIdGuid,
 | |
|                     (VOID **) &Private,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller,
 | |
|                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     Status = Private->PciIo->Attributes (
 | |
|                                Private->PciIo,
 | |
|                                EfiPciIoAttributeOperationSet,
 | |
|                                Private->OriginalAttributes,
 | |
|                                NULL
 | |
|                                );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     gBS->UninstallProtocolInterface (
 | |
|           Controller,
 | |
|           &gEfiCallerIdGuid,
 | |
|           Private
 | |
|           );
 | |
|     FreePool (Private);
 | |
| 
 | |
|     //
 | |
|     // Close the bus driver
 | |
|     //
 | |
|     Status = gBS->CloseProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiDevicePathProtocolGuid,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     Status = gBS->CloseProtocol (
 | |
|                     Controller,
 | |
|                     &gEfiPciIoProtocolGuid,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller
 | |
|                     );
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       return Status;
 | |
|     }
 | |
| 
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Stop all the children
 | |
|   //
 | |
|   AllChildrenStopped = TRUE;
 | |
| 
 | |
|   for (Index = 0; Index < NumberOfChildren; Index++) {
 | |
|     Status = gBS->OpenProtocol (
 | |
|                     ChildHandleBuffer[Index],
 | |
|                     &gEfiSioProtocolGuid,
 | |
|                     (VOID **) &Sio,
 | |
|                     This->DriverBindingHandle,
 | |
|                     Controller,
 | |
|                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | |
|                     );
 | |
|     if (!EFI_ERROR (Status)) {
 | |
|       SioDevice = SIO_DEV_FROM_SIO (Sio);
 | |
| 
 | |
|       //
 | |
|       // Close the child handle
 | |
|       //
 | |
|       Status = gBS->CloseProtocol (
 | |
|                       Controller,
 | |
|                       &gEfiPciIoProtocolGuid,
 | |
|                       This->DriverBindingHandle,
 | |
|                       ChildHandleBuffer[Index]
 | |
|                       );
 | |
|       Status = gBS->UninstallMultipleProtocolInterfaces (
 | |
|                       ChildHandleBuffer[Index],
 | |
|                       &gEfiDevicePathProtocolGuid,
 | |
|                       SioDevice->DevicePath,
 | |
|                       &gEfiSioProtocolGuid,
 | |
|                       &SioDevice->Sio,
 | |
|                       NULL
 | |
|                       );
 | |
| 
 | |
|       if (!EFI_ERROR (Status)) {
 | |
|         FreePool (SioDevice->DevicePath);
 | |
|         FreePool (SioDevice);
 | |
|       } else {
 | |
|         //
 | |
|         // Re-open PCI IO Protocol on behalf of the child device
 | |
|         // because of failure of destroying the child device handle
 | |
|         //
 | |
|         gBS->OpenProtocol (
 | |
|                Controller,
 | |
|                &gEfiPciIoProtocolGuid,
 | |
|                (VOID **) &PciIo,
 | |
|                This->DriverBindingHandle,
 | |
|                ChildHandleBuffer[Index],
 | |
|                EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | |
|                );
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       AllChildrenStopped = FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!AllChildrenStopped) {
 | |
|     return EFI_DEVICE_ERROR;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   The entry point for the SioBusDxe driver.
 | |
| 
 | |
|   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
 | |
|   @param[in] SystemTable    A pointer to the EFI System Table.
 | |
| 
 | |
|   @retval EFI_SUCCESS       The entry point is executed successfully.
 | |
|   @retval other             Some error occurs when executing this entry point.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| SioBusDxeDriverEntryPoint (
 | |
|   IN EFI_HANDLE          ImageHandle,
 | |
|   IN EFI_SYSTEM_TABLE    *SystemTable
 | |
|   )
 | |
| {
 | |
|   //
 | |
|   // Install driver model protocol(s).
 | |
|   //
 | |
|   return EfiLibInstallDriverBindingComponentName2 (
 | |
|            ImageHandle,
 | |
|            SystemTable,
 | |
|            &gSioBusDriverBinding,
 | |
|            ImageHandle,
 | |
|            &gSioBusComponentName,
 | |
|            &gSioBusComponentName2
 | |
|            );
 | |
| }
 |