2 Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
3 regenerates the ACPI tables.
5 Copyright (C) 2016, Red Hat, Inc.
7 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/DebugLib.h> // DEBUG()
11 #include <Library/MemoryAllocationLib.h> // AllocatePool()
12 #include <Library/UefiBootServicesTableLib.h> // gBS
14 #include "AcpiPlatform.h"
17 Collect all PciIo protocol instances in the system. Save their original
18 attributes, and enable IO and MMIO decoding for each.
20 This is a best effort function; it doesn't return status codes. Its
21 caller is supposed to proceed even if this function fails.
23 @param[out] OriginalAttributes On output, a dynamically allocated array of
24 ORIGINAL_ATTRIBUTES elements. The array lists
25 the PciIo protocol instances found in the
26 system at the time of the call, plus the
27 original PCI attributes for each.
29 Before returning, the function enables IO and
30 MMIO decoding for each PciIo instance it
33 On error, or when no such instances are
34 found, OriginalAttributes is set to NULL.
36 @param[out] Count On output, the number of elements in
37 OriginalAttributes. On error it is set to
42 OUT ORIGINAL_ATTRIBUTES
**OriginalAttributes
,
49 ORIGINAL_ATTRIBUTES
*OrigAttrs
;
52 *OriginalAttributes
= NULL
;
55 if (PcdGetBool (PcdPciDisableBusEnumeration
)) {
57 // The platform downloads ACPI tables from QEMU in general, but there are
58 // no root bridges in this execution. We're done.
63 Status
= gBS
->LocateHandleBuffer (
65 &gEfiPciIoProtocolGuid
,
70 if (Status
== EFI_NOT_FOUND
) {
72 // No PCI devices were found on either of the root bridges. We're done.
77 if (EFI_ERROR (Status
)) {
80 "%a: LocateHandleBuffer(): %r\n",
87 OrigAttrs
= AllocatePool (NoHandles
* sizeof *OrigAttrs
);
88 if (OrigAttrs
== NULL
) {
91 "%a: AllocatePool(): out of resources\n",
97 for (Idx
= 0; Idx
< NoHandles
; ++Idx
) {
98 EFI_PCI_IO_PROTOCOL
*PciIo
;
102 // Look up PciIo on the handle and stash it
104 Status
= gBS
->HandleProtocol (
106 &gEfiPciIoProtocolGuid
,
109 ASSERT_EFI_ERROR (Status
);
110 OrigAttrs
[Idx
].PciIo
= PciIo
;
113 // Stash the current attributes
115 Status
= PciIo
->Attributes (
117 EfiPciIoAttributeOperationGet
,
119 &OrigAttrs
[Idx
].PciAttributes
121 if (EFI_ERROR (Status
)) {
124 "%a: EfiPciIoAttributeOperationGet: %r\n",
128 goto RestoreAttributes
;
132 // Retrieve supported attributes
134 Status
= PciIo
->Attributes (
136 EfiPciIoAttributeOperationSupported
,
140 if (EFI_ERROR (Status
)) {
143 "%a: EfiPciIoAttributeOperationSupported: %r\n",
147 goto RestoreAttributes
;
151 // Enable IO and MMIO decoding
153 Attributes
&= EFI_PCI_IO_ATTRIBUTE_IO
| EFI_PCI_IO_ATTRIBUTE_MEMORY
;
154 Status
= PciIo
->Attributes (
156 EfiPciIoAttributeOperationEnable
,
160 if (EFI_ERROR (Status
)) {
163 "%a: EfiPciIoAttributeOperationEnable: %r\n",
167 goto RestoreAttributes
;
175 *OriginalAttributes
= OrigAttrs
;
182 OrigAttrs
[Idx
].PciIo
->Attributes (
183 OrigAttrs
[Idx
].PciIo
,
184 EfiPciIoAttributeOperationSet
,
185 OrigAttrs
[Idx
].PciAttributes
,
190 FreePool (OrigAttrs
);
197 Restore the original PCI attributes saved with EnablePciDecoding().
199 @param[in] OriginalAttributes The array allocated and populated by
200 EnablePciDecoding(). This parameter may be
201 NULL. If OriginalAttributes is NULL, then the
202 function is a no-op; otherwise the PciIo
203 attributes will be restored, and the
204 OriginalAttributes array will be freed.
206 @param[in] Count The Count value stored by EnablePciDecoding(),
207 the number of elements in OriginalAttributes.
208 Count may be zero if and only if
209 OriginalAttributes is NULL.
213 IN ORIGINAL_ATTRIBUTES
*OriginalAttributes
,
219 ASSERT ((OriginalAttributes
== NULL
) == (Count
== 0));
220 if (OriginalAttributes
== NULL
) {
224 for (Idx
= 0; Idx
< Count
; ++Idx
) {
225 OriginalAttributes
[Idx
].PciIo
->Attributes (
226 OriginalAttributes
[Idx
].PciIo
,
227 EfiPciIoAttributeOperationSet
,
228 OriginalAttributes
[Idx
].PciAttributes
,
233 FreePool (OriginalAttributes
);