/** @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 ((DEBUG_WARN, "%a: LocateHandleBuffer(): %r\n", __FUNCTION__,
      Status));
    return;
  }

  OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
  if (OrigAttrs == NULL) {
    DEBUG ((DEBUG_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 ((DEBUG_WARN, "%a: EfiPciIoAttributeOperationGet: %r\n",
        __FUNCTION__, Status));
      goto RestoreAttributes;
    }

    //
    // Retrieve supported attributes
    //
    Status = PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSupported, 0,
                      &Attributes);
    if (EFI_ERROR (Status)) {
      DEBUG ((DEBUG_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 ((DEBUG_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);
}
