PciDecoding.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. /** @file
  2. Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
  3. regenerates the ACPI tables.
  4. Copyright (C) 2016, Red Hat, Inc.
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Library/MemoryAllocationLib.h>
  8. #include "AcpiPlatform.h"
  9. /**
  10. Collect all PciIo protocol instances in the system. Save their original
  11. attributes, and enable IO and MMIO decoding for each.
  12. This is a best effort function; it doesn't return status codes. Its
  13. caller is supposed to proceed even if this function fails.
  14. @param[out] OriginalAttributes On output, a dynamically allocated array of
  15. ORIGINAL_ATTRIBUTES elements. The array lists
  16. the PciIo protocol instances found in the
  17. system at the time of the call, plus the
  18. original PCI attributes for each.
  19. Before returning, the function enables IO and
  20. MMIO decoding for each PciIo instance it
  21. finds.
  22. On error, or when no such instances are
  23. found, OriginalAttributes is set to NULL.
  24. @param[out] Count On output, the number of elements in
  25. OriginalAttributes. On error it is set to
  26. zero.
  27. **/
  28. VOID
  29. EnablePciDecoding (
  30. OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
  31. OUT UINTN *Count
  32. )
  33. {
  34. EFI_STATUS Status;
  35. UINTN NoHandles;
  36. EFI_HANDLE *Handles;
  37. ORIGINAL_ATTRIBUTES *OrigAttrs;
  38. UINTN Idx;
  39. *OriginalAttributes = NULL;
  40. *Count = 0;
  41. if (PcdGetBool (PcdPciDisableBusEnumeration)) {
  42. //
  43. // The platform downloads ACPI tables from QEMU in general, but there are
  44. // no root bridges in this execution. We're done.
  45. //
  46. return;
  47. }
  48. Status = gBS->LocateHandleBuffer (
  49. ByProtocol,
  50. &gEfiPciIoProtocolGuid,
  51. NULL /* SearchKey */,
  52. &NoHandles,
  53. &Handles
  54. );
  55. if (Status == EFI_NOT_FOUND) {
  56. //
  57. // No PCI devices were found on either of the root bridges. We're done.
  58. //
  59. return;
  60. }
  61. if (EFI_ERROR (Status)) {
  62. DEBUG ((
  63. DEBUG_WARN,
  64. "%a: LocateHandleBuffer(): %r\n",
  65. __FUNCTION__,
  66. Status
  67. ));
  68. return;
  69. }
  70. OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
  71. if (OrigAttrs == NULL) {
  72. DEBUG ((
  73. DEBUG_WARN,
  74. "%a: AllocatePool(): out of resources\n",
  75. __FUNCTION__
  76. ));
  77. goto FreeHandles;
  78. }
  79. for (Idx = 0; Idx < NoHandles; ++Idx) {
  80. EFI_PCI_IO_PROTOCOL *PciIo;
  81. UINT64 Attributes;
  82. //
  83. // Look up PciIo on the handle and stash it
  84. //
  85. Status = gBS->HandleProtocol (
  86. Handles[Idx],
  87. &gEfiPciIoProtocolGuid,
  88. (VOID **)&PciIo
  89. );
  90. ASSERT_EFI_ERROR (Status);
  91. OrigAttrs[Idx].PciIo = PciIo;
  92. //
  93. // Stash the current attributes
  94. //
  95. Status = PciIo->Attributes (
  96. PciIo,
  97. EfiPciIoAttributeOperationGet,
  98. 0,
  99. &OrigAttrs[Idx].PciAttributes
  100. );
  101. if (EFI_ERROR (Status)) {
  102. DEBUG ((
  103. DEBUG_WARN,
  104. "%a: EfiPciIoAttributeOperationGet: %r\n",
  105. __FUNCTION__,
  106. Status
  107. ));
  108. goto RestoreAttributes;
  109. }
  110. //
  111. // Retrieve supported attributes
  112. //
  113. Status = PciIo->Attributes (
  114. PciIo,
  115. EfiPciIoAttributeOperationSupported,
  116. 0,
  117. &Attributes
  118. );
  119. if (EFI_ERROR (Status)) {
  120. DEBUG ((
  121. DEBUG_WARN,
  122. "%a: EfiPciIoAttributeOperationSupported: %r\n",
  123. __FUNCTION__,
  124. Status
  125. ));
  126. goto RestoreAttributes;
  127. }
  128. //
  129. // Enable IO and MMIO decoding
  130. //
  131. Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
  132. Status = PciIo->Attributes (
  133. PciIo,
  134. EfiPciIoAttributeOperationEnable,
  135. Attributes,
  136. NULL
  137. );
  138. if (EFI_ERROR (Status)) {
  139. DEBUG ((
  140. DEBUG_WARN,
  141. "%a: EfiPciIoAttributeOperationEnable: %r\n",
  142. __FUNCTION__,
  143. Status
  144. ));
  145. goto RestoreAttributes;
  146. }
  147. }
  148. //
  149. // Success
  150. //
  151. FreePool (Handles);
  152. *OriginalAttributes = OrigAttrs;
  153. *Count = NoHandles;
  154. return;
  155. RestoreAttributes:
  156. while (Idx > 0) {
  157. --Idx;
  158. OrigAttrs[Idx].PciIo->Attributes (
  159. OrigAttrs[Idx].PciIo,
  160. EfiPciIoAttributeOperationSet,
  161. OrigAttrs[Idx].PciAttributes,
  162. NULL
  163. );
  164. }
  165. FreePool (OrigAttrs);
  166. FreeHandles:
  167. FreePool (Handles);
  168. }
  169. /**
  170. Restore the original PCI attributes saved with EnablePciDecoding().
  171. @param[in] OriginalAttributes The array allocated and populated by
  172. EnablePciDecoding(). This parameter may be
  173. NULL. If OriginalAttributes is NULL, then the
  174. function is a no-op; otherwise the PciIo
  175. attributes will be restored, and the
  176. OriginalAttributes array will be freed.
  177. @param[in] Count The Count value stored by EnablePciDecoding(),
  178. the number of elements in OriginalAttributes.
  179. Count may be zero if and only if
  180. OriginalAttributes is NULL.
  181. **/
  182. VOID
  183. RestorePciDecoding (
  184. IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
  185. IN UINTN Count
  186. )
  187. {
  188. UINTN Idx;
  189. ASSERT ((OriginalAttributes == NULL) == (Count == 0));
  190. if (OriginalAttributes == NULL) {
  191. return;
  192. }
  193. for (Idx = 0; Idx < Count; ++Idx) {
  194. OriginalAttributes[Idx].PciIo->Attributes (
  195. OriginalAttributes[Idx].PciIo,
  196. EfiPciIoAttributeOperationSet,
  197. OriginalAttributes[Idx].PciAttributes,
  198. NULL
  199. );
  200. }
  201. FreePool (OriginalAttributes);
  202. }