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