PciDecoding.c 6.8 KB

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