Bhyve supports providing ACPI tables by FwCfg. Therefore, InstallQemuFwCfgTables should be moved to AcpiPlatformLib to reuse the code. As first step, move PciEncoding into AcpiPlatformLib. Signed-off-by: Corvin Köhne <corvink@FreeBSD.org> Acked-by: Peter Grehan <grehan@freebsd.org>
		
			
				
	
	
		
			234 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			6.8 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/AcpiPlatformLib.h>
 | 
						|
#include <Library/DebugLib.h>                  // DEBUG()
 | 
						|
#include <Library/MemoryAllocationLib.h>       // AllocatePool()
 | 
						|
#include <Library/UefiBootServicesTableLib.h>  // gBS
 | 
						|
 | 
						|
/**
 | 
						|
  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 ((
 | 
						|
      DEBUG_WARN,
 | 
						|
      "%a: LocateHandleBuffer(): %r\n",
 | 
						|
      __func__,
 | 
						|
      Status
 | 
						|
      ));
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
 | 
						|
  if (OrigAttrs == NULL) {
 | 
						|
    DEBUG ((
 | 
						|
      DEBUG_WARN,
 | 
						|
      "%a: AllocatePool(): out of resources\n",
 | 
						|
      __func__
 | 
						|
      ));
 | 
						|
    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 ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "%a: EfiPciIoAttributeOperationGet: %r\n",
 | 
						|
        __func__,
 | 
						|
        Status
 | 
						|
        ));
 | 
						|
      goto RestoreAttributes;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Retrieve supported attributes
 | 
						|
    //
 | 
						|
    Status = PciIo->Attributes (
 | 
						|
                      PciIo,
 | 
						|
                      EfiPciIoAttributeOperationSupported,
 | 
						|
                      0,
 | 
						|
                      &Attributes
 | 
						|
                      );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      DEBUG ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "%a: EfiPciIoAttributeOperationSupported: %r\n",
 | 
						|
        __func__,
 | 
						|
        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 ((
 | 
						|
        DEBUG_WARN,
 | 
						|
        "%a: EfiPciIoAttributeOperationEnable: %r\n",
 | 
						|
        __func__,
 | 
						|
        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);
 | 
						|
}
 |