]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/AcpiPlatformDxe/PciDecoding.c
nasm_ext_dep.yaml: Remove leading zero in patch version
[mirror_edk2.git] / OvmfPkg / AcpiPlatformDxe / PciDecoding.c
1 /** @file
2 Temporarily enable IO and MMIO decoding for all PCI devices while QEMU
3 regenerates the ACPI tables.
4
5 Copyright (C) 2016, Red Hat, Inc.
6
7 SPDX-License-Identifier: BSD-2-Clause-Patent
8 **/
9
10 #include <Library/DebugLib.h> // DEBUG()
11 #include <Library/MemoryAllocationLib.h> // AllocatePool()
12 #include <Library/UefiBootServicesTableLib.h> // gBS
13
14 #include "AcpiPlatform.h"
15
16 /**
17 Collect all PciIo protocol instances in the system. Save their original
18 attributes, and enable IO and MMIO decoding for each.
19
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.
22
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.
28
29 Before returning, the function enables IO and
30 MMIO decoding for each PciIo instance it
31 finds.
32
33 On error, or when no such instances are
34 found, OriginalAttributes is set to NULL.
35
36 @param[out] Count On output, the number of elements in
37 OriginalAttributes. On error it is set to
38 zero.
39 **/
40 VOID
41 EnablePciDecoding (
42 OUT ORIGINAL_ATTRIBUTES **OriginalAttributes,
43 OUT UINTN *Count
44 )
45 {
46 EFI_STATUS Status;
47 UINTN NoHandles;
48 EFI_HANDLE *Handles;
49 ORIGINAL_ATTRIBUTES *OrigAttrs;
50 UINTN Idx;
51
52 *OriginalAttributes = NULL;
53 *Count = 0;
54
55 if (PcdGetBool (PcdPciDisableBusEnumeration)) {
56 //
57 // The platform downloads ACPI tables from QEMU in general, but there are
58 // no root bridges in this execution. We're done.
59 //
60 return;
61 }
62
63 Status = gBS->LocateHandleBuffer (
64 ByProtocol,
65 &gEfiPciIoProtocolGuid,
66 NULL /* SearchKey */,
67 &NoHandles,
68 &Handles
69 );
70 if (Status == EFI_NOT_FOUND) {
71 //
72 // No PCI devices were found on either of the root bridges. We're done.
73 //
74 return;
75 }
76
77 if (EFI_ERROR (Status)) {
78 DEBUG ((
79 DEBUG_WARN,
80 "%a: LocateHandleBuffer(): %r\n",
81 __FUNCTION__,
82 Status
83 ));
84 return;
85 }
86
87 OrigAttrs = AllocatePool (NoHandles * sizeof *OrigAttrs);
88 if (OrigAttrs == NULL) {
89 DEBUG ((
90 DEBUG_WARN,
91 "%a: AllocatePool(): out of resources\n",
92 __FUNCTION__
93 ));
94 goto FreeHandles;
95 }
96
97 for (Idx = 0; Idx < NoHandles; ++Idx) {
98 EFI_PCI_IO_PROTOCOL *PciIo;
99 UINT64 Attributes;
100
101 //
102 // Look up PciIo on the handle and stash it
103 //
104 Status = gBS->HandleProtocol (
105 Handles[Idx],
106 &gEfiPciIoProtocolGuid,
107 (VOID **)&PciIo
108 );
109 ASSERT_EFI_ERROR (Status);
110 OrigAttrs[Idx].PciIo = PciIo;
111
112 //
113 // Stash the current attributes
114 //
115 Status = PciIo->Attributes (
116 PciIo,
117 EfiPciIoAttributeOperationGet,
118 0,
119 &OrigAttrs[Idx].PciAttributes
120 );
121 if (EFI_ERROR (Status)) {
122 DEBUG ((
123 DEBUG_WARN,
124 "%a: EfiPciIoAttributeOperationGet: %r\n",
125 __FUNCTION__,
126 Status
127 ));
128 goto RestoreAttributes;
129 }
130
131 //
132 // Retrieve supported attributes
133 //
134 Status = PciIo->Attributes (
135 PciIo,
136 EfiPciIoAttributeOperationSupported,
137 0,
138 &Attributes
139 );
140 if (EFI_ERROR (Status)) {
141 DEBUG ((
142 DEBUG_WARN,
143 "%a: EfiPciIoAttributeOperationSupported: %r\n",
144 __FUNCTION__,
145 Status
146 ));
147 goto RestoreAttributes;
148 }
149
150 //
151 // Enable IO and MMIO decoding
152 //
153 Attributes &= EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY;
154 Status = PciIo->Attributes (
155 PciIo,
156 EfiPciIoAttributeOperationEnable,
157 Attributes,
158 NULL
159 );
160 if (EFI_ERROR (Status)) {
161 DEBUG ((
162 DEBUG_WARN,
163 "%a: EfiPciIoAttributeOperationEnable: %r\n",
164 __FUNCTION__,
165 Status
166 ));
167 goto RestoreAttributes;
168 }
169 }
170
171 //
172 // Success
173 //
174 FreePool (Handles);
175 *OriginalAttributes = OrigAttrs;
176 *Count = NoHandles;
177 return;
178
179 RestoreAttributes:
180 while (Idx > 0) {
181 --Idx;
182 OrigAttrs[Idx].PciIo->Attributes (
183 OrigAttrs[Idx].PciIo,
184 EfiPciIoAttributeOperationSet,
185 OrigAttrs[Idx].PciAttributes,
186 NULL
187 );
188 }
189
190 FreePool (OrigAttrs);
191
192 FreeHandles:
193 FreePool (Handles);
194 }
195
196 /**
197 Restore the original PCI attributes saved with EnablePciDecoding().
198
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.
205
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.
210 **/
211 VOID
212 RestorePciDecoding (
213 IN ORIGINAL_ATTRIBUTES *OriginalAttributes,
214 IN UINTN Count
215 )
216 {
217 UINTN Idx;
218
219 ASSERT ((OriginalAttributes == NULL) == (Count == 0));
220 if (OriginalAttributes == NULL) {
221 return;
222 }
223
224 for (Idx = 0; Idx < Count; ++Idx) {
225 OriginalAttributes[Idx].PciIo->Attributes (
226 OriginalAttributes[Idx].PciIo,
227 EfiPciIoAttributeOperationSet,
228 OriginalAttributes[Idx].PciAttributes,
229 NULL
230 );
231 }
232
233 FreePool (OriginalAttributes);
234 }