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>
		
			
				
	
	
		
			193 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			193 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
 | 
						|
  regenerates the ACPI tables.
 | 
						|
 | 
						|
  Copyright (C) 2016, Red Hat, Inc.
 | 
						|
 | 
						|
  SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
**/
 | 
						|
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
 | 
						|
#include "AcpiPlatform.h"
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Collect all PciIo protocol instances in the system. Save their original
 | 
						|
  attributes, and enable IO and MMIO decoding for each.
 | 
						|
 | 
						|
  This is a best effort function; it doesn't return status codes. Its
 | 
						|
  caller is supposed to proceed even if this function fails.
 | 
						|
 | 
						|
  @param[out] OriginalAttributes  On output, a dynamically allocated array of
 | 
						|
                                  ORIGINAL_ATTRIBUTES elements. The array lists
 | 
						|
                                  the PciIo protocol instances found in the
 | 
						|
                                  system at the time of the call, plus the
 | 
						|
                                  original PCI attributes for each.
 | 
						|
 | 
						|
                                  Before returning, the function enables IO and
 | 
						|
                                  MMIO decoding for each PciIo instance it
 | 
						|
                                  finds.
 | 
						|
 | 
						|
                                  On error, or when no such instances are
 | 
						|
                                  found, OriginalAttributes is set to NULL.
 | 
						|
 | 
						|
  @param[out] Count               On output, the number of elements in
 | 
						|
                                  OriginalAttributes. On error it is set to
 | 
						|
                                  zero.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
EnablePciDecoding (
 | 
						|
  OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
 | 
						|
  OUT UINTN               *Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS          Status;
 | 
						|
  UINTN               NoHandles;
 | 
						|
  EFI_HANDLE          *Handles;
 | 
						|
  ORIGINAL_ATTRIBUTES *OrigAttrs;
 | 
						|
  UINTN               Idx;
 | 
						|
 | 
						|
  *OriginalAttributes = NULL;
 | 
						|
  *Count              = 0;
 | 
						|
 | 
						|
  if (PcdGetBool (PcdPciDisableBusEnumeration)) {
 | 
						|
    //
 | 
						|
    // The platform downloads ACPI tables from QEMU in general, but there are
 | 
						|
    // no root bridges in this execution. We're done.
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiPciIoProtocolGuid,
 | 
						|
                  NULL /* SearchKey */, &NoHandles, &Handles);
 | 
						|
  if (Status == EFI_NOT_FOUND) {
 | 
						|
    //
 | 
						|
    // No PCI devices were found on either of the root bridges. We're done.
 | 
						|
    //
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    DEBUG ((EFI_D_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
 | 
						|
      Status));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
 | 
						|
  if (OrigAttrs == NULL) {
 | 
						|
    DEBUG ((EFI_D_WARN, "%a: AllocatePool(): out of resources\n",
 | 
						|
      __FUNCTION__));
 | 
						|
    goto FreeHandles;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Idx = 0; Idx < NoHandles; ++Idx) {
 | 
						|
    EFI_PCI_IO_PROTOCOL *PciIo;
 | 
						|
    UINT64              Attributes;
 | 
						|
 | 
						|
    //
 | 
						|
    // Look up PciIo on the handle and stash it
 | 
						|
    //
 | 
						|
    Status = gBS->HandleProtocol (Handles[Idx], &gEfiPciIoProtocolGuid,
 | 
						|
                    (VOID**)&PciIo);
 | 
						|
    ASSERT_EFI_ERROR (Status);
 | 
						|
    OrigAttrs[Idx].PciIo = PciIo;
 | 
						|
 | 
						|
    //
 | 
						|
    // Stash the current attributes
 | 
						|
    //
 | 
						|
    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationGet, 0,
 | 
						|
                      &OrigAttrs[Idx].PciAttributes);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
 | 
						|
        __FUNCTION__, Status));
 | 
						|
      goto RestoreAttributes;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Retrieve supported attributes
 | 
						|
    //
 | 
						|
    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
 | 
						|
                      &Attributes);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_WARN, "%a: EfiPciIoAttributeOperationSupported: %r\n",
 | 
						|
        __FUNCTION__, Status));
 | 
						|
      goto RestoreAttributes;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Enable IO and MMIO decoding
 | 
						|
    //
 | 
						|
    Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
 | 
						|
    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationEnable,
 | 
						|
                      Attributes, NULL);
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((EFI_D_WARN, "%a: EfiPciIoAttributeOperationEnable: %r\n",
 | 
						|
        __FUNCTION__, Status));
 | 
						|
      goto RestoreAttributes;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Success
 | 
						|
  //
 | 
						|
  FreePool (Handles);
 | 
						|
  *OriginalAttributes = OrigAttrs;
 | 
						|
  *Count              = NoHandles;
 | 
						|
  return;
 | 
						|
 | 
						|
RestoreAttributes:
 | 
						|
  while (Idx > 0) {
 | 
						|
    --Idx;
 | 
						|
    OrigAttrs[Idx].PciIo->Attributes (OrigAttrs[Idx].PciIo,
 | 
						|
                            EfiPciIoAttributeOperationSet,
 | 
						|
                            OrigAttrs[Idx].PciAttributes,
 | 
						|
                            NULL
 | 
						|
                            );
 | 
						|
  }
 | 
						|
  FreePool (OrigAttrs);
 | 
						|
 | 
						|
FreeHandles:
 | 
						|
  FreePool (Handles);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Restore the original PCI attributes saved with EnablePciDecoding().
 | 
						|
 | 
						|
  @param[in] OriginalAttributes  The array allocated and populated by
 | 
						|
                                 EnablePciDecoding(). This parameter may be
 | 
						|
                                 NULL. If OriginalAttributes is NULL, then the
 | 
						|
                                 function is a no-op; otherwise the PciIo
 | 
						|
                                 attributes will be restored, and the
 | 
						|
                                 OriginalAttributes array will be freed.
 | 
						|
 | 
						|
  @param[in] Count               The Count value stored by EnablePciDecoding(),
 | 
						|
                                 the number of elements in OriginalAttributes.
 | 
						|
                                 Count may be zero if and only if
 | 
						|
                                 OriginalAttributes is NULL.
 | 
						|
**/
 | 
						|
VOID
 | 
						|
RestorePciDecoding (
 | 
						|
  IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
 | 
						|
  IN UINTN               Count
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Idx;
 | 
						|
 | 
						|
  ASSERT ((OriginalAttributes == NULL) == (Count == 0));
 | 
						|
  if (OriginalAttributes == NULL) {
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (Idx = 0; Idx < Count; ++Idx) {
 | 
						|
    OriginalAttributes[Idx].PciIo->Attributes (
 | 
						|
                                     OriginalAttributes[Idx].PciIo,
 | 
						|
                                     EfiPciIoAttributeOperationSet,
 | 
						|
                                     OriginalAttributes[Idx].PciAttributes,
 | 
						|
                                     NULL
 | 
						|
                                     );
 | 
						|
  }
 | 
						|
  FreePool (OriginalAttributes);
 | 
						|
}
 |