]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/PciHostBridgeUtilityLib/PciHostBridgeUtilityLib.c
ArmVirtPkg/FdtPciHostBridgeLib: Refactor init/uninit of root bridge
[mirror_edk2.git] / OvmfPkg / Library / PciHostBridgeUtilityLib / PciHostBridgeUtilityLib.c
CommitLineData
7a6172f8
JC
1/** @file\r
2 Provide common utility functions to PciHostBridgeLib instances in\r
3 ArmVirtPkg and OvmfPkg.\r
4\r
5 Copyright (C) 2016, Red Hat, Inc.\r
6 Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
7 Copyright (c) 2020, Huawei Corporation. All rights reserved.<BR>\r
8\r
9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
10\r
11**/\r
12\r
13#include <IndustryStandard/Acpi10.h>\r
7ac1f28d 14#include <Library/BaseMemoryLib.h>\r
7a6172f8 15#include <Library/DebugLib.h>\r
7ac1f28d
JC
16#include <Library/DevicePathLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
7a6172f8
JC
18#include <Library/PciHostBridgeUtilityLib.h>\r
19\r
20\r
7ac1f28d
JC
21#pragma pack(1)\r
22typedef struct {\r
23 ACPI_HID_DEVICE_PATH AcpiDevicePath;\r
24 EFI_DEVICE_PATH_PROTOCOL EndDevicePath;\r
25} OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH;\r
26#pragma pack ()\r
27\r
28\r
7a6172f8
JC
29GLOBAL_REMOVE_IF_UNREFERENCED\r
30CHAR16 *mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[] = {\r
31 L"Mem", L"I/O", L"Bus"\r
32};\r
33\r
34\r
7ac1f28d
JC
35STATIC\r
36CONST\r
37OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {\r
38 {\r
39 {\r
40 ACPI_DEVICE_PATH,\r
41 ACPI_DP,\r
42 {\r
43 (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),\r
44 (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)\r
45 }\r
46 },\r
47 EISA_PNP_ID(0x0A03), // HID\r
48 0 // UID\r
49 },\r
50\r
51 {\r
52 END_DEVICE_PATH_TYPE,\r
53 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
54 {\r
55 END_DEVICE_PATH_LENGTH,\r
56 0\r
57 }\r
58 }\r
59};\r
60\r
61\r
62/**\r
63 Utility function to initialize a PCI_ROOT_BRIDGE structure.\r
64\r
e1b259da 65 @param[in] Supports Supported attributes.\r
7ac1f28d 66\r
e1b259da 67 @param[in] Attributes Initial attributes.\r
7ac1f28d 68\r
e1b259da 69 @param[in] AllocAttributes Allocation attributes.\r
7ac1f28d 70\r
e1b259da 71 @param[in] DmaAbove4G DMA above 4GB memory.\r
7ac1f28d 72\r
e1b259da 73 @param[in] NoExtendedConfigSpace No Extended Config Space.\r
7ac1f28d 74\r
e1b259da 75 @param[in] RootBusNumber The bus number to store in RootBus.\r
7ac1f28d 76\r
e1b259da
JC
77 @param[in] MaxSubBusNumber The inclusive maximum bus number that can\r
78 be assigned to any subordinate bus found\r
79 behind any PCI bridge hanging off this\r
80 root bus.\r
7ac1f28d 81\r
e1b259da
JC
82 The caller is repsonsible for ensuring\r
83 that RootBusNumber <= MaxSubBusNumber. If\r
84 RootBusNumber equals MaxSubBusNumber, then\r
85 the root bus has no room for subordinate\r
86 buses.\r
7ac1f28d 87\r
e1b259da 88 @param[in] Io IO aperture.\r
7ac1f28d 89\r
e1b259da 90 @param[in] Mem MMIO aperture.\r
7ac1f28d 91\r
e1b259da 92 @param[in] MemAbove4G MMIO aperture above 4G.\r
7ac1f28d 93\r
e1b259da 94 @param[in] PMem Prefetchable MMIO aperture.\r
7ac1f28d 95\r
e1b259da 96 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
7ac1f28d 97\r
e1b259da
JC
98 @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated\r
99 by the caller) that should be filled in by\r
100 this function.\r
101\r
102 @retval EFI_SUCCESS Initialization successful. A device path\r
103 consisting of an ACPI device path node,\r
104 with UID = RootBusNumber, has been\r
105 allocated and linked into RootBus.\r
106\r
107 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
7ac1f28d
JC
108**/\r
109EFI_STATUS\r
110EFIAPI\r
111PciHostBridgeUtilityInitRootBridge (\r
112 IN UINT64 Supports,\r
113 IN UINT64 Attributes,\r
114 IN UINT64 AllocAttributes,\r
e1b259da
JC
115 IN BOOLEAN DmaAbove4G,\r
116 IN BOOLEAN NoExtendedConfigSpace,\r
7ac1f28d
JC
117 IN UINT8 RootBusNumber,\r
118 IN UINT8 MaxSubBusNumber,\r
119 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
120 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
121 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
122 IN PCI_ROOT_BRIDGE_APERTURE *PMem,\r
123 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,\r
124 OUT PCI_ROOT_BRIDGE *RootBus\r
125 )\r
126{\r
127 OVMF_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;\r
128\r
129 //\r
130 // Be safe if other fields are added to PCI_ROOT_BRIDGE later.\r
131 //\r
132 ZeroMem (RootBus, sizeof *RootBus);\r
133\r
134 RootBus->Segment = 0;\r
135\r
136 RootBus->Supports = Supports;\r
137 RootBus->Attributes = Attributes;\r
138\r
e1b259da 139 RootBus->DmaAbove4G = DmaAbove4G;\r
7ac1f28d
JC
140\r
141 RootBus->AllocationAttributes = AllocAttributes;\r
142 RootBus->Bus.Base = RootBusNumber;\r
143 RootBus->Bus.Limit = MaxSubBusNumber;\r
144 CopyMem (&RootBus->Io, Io, sizeof (*Io));\r
145 CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));\r
146 CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));\r
147 CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));\r
148 CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));\r
149\r
e1b259da 150 RootBus->NoExtendedConfigSpace = NoExtendedConfigSpace;\r
7ac1f28d
JC
151\r
152 DevicePath = AllocateCopyPool (sizeof mRootBridgeDevicePathTemplate,\r
153 &mRootBridgeDevicePathTemplate);\r
154 if (DevicePath == NULL) {\r
155 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
156 return EFI_OUT_OF_RESOURCES;\r
157 }\r
158 DevicePath->AcpiDevicePath.UID = RootBusNumber;\r
159 RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
160\r
161 DEBUG ((DEBUG_INFO,\r
162 "%a: populated root bus %d, with room for %d subordinate bus(es)\n",\r
163 __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));\r
164 return EFI_SUCCESS;\r
165}\r
166\r
167\r
168/**\r
169 Utility function to uninitialize a PCI_ROOT_BRIDGE structure set up with\r
170 PciHostBridgeUtilityInitRootBridge().\r
171\r
172 @param[in] RootBus The PCI_ROOT_BRIDGE structure, allocated by the caller and\r
173 initialized with PciHostBridgeUtilityInitRootBridge(),\r
174 that should be uninitialized. This function doesn't free\r
175 RootBus.\r
176**/\r
177VOID\r
178EFIAPI\r
179PciHostBridgeUtilityUninitRootBridge (\r
180 IN PCI_ROOT_BRIDGE *RootBus\r
181 )\r
182{\r
183 FreePool (RootBus->DevicePath);\r
184}\r
185\r
186\r
7a6172f8
JC
187/**\r
188 Utility function to inform the platform that the resource conflict happens.\r
189\r
190 @param[in] Configuration Pointer to PCI I/O and PCI memory resource\r
191 descriptors. The Configuration contains the\r
192 resources for all the root bridges. The resource\r
193 for each root bridge is terminated with END\r
194 descriptor and an additional END is appended\r
195 indicating the end of the entire resources. The\r
196 resource descriptor field values follow the\r
197 description in\r
198 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
199 .SubmitResources().\r
200**/\r
201VOID\r
202EFIAPI\r
203PciHostBridgeUtilityResourceConflict (\r
204 IN VOID *Configuration\r
205 )\r
206{\r
207 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;\r
208 UINTN RootBridgeIndex;\r
209 DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));\r
210\r
211 RootBridgeIndex = 0;\r
212 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;\r
213 while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {\r
214 DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));\r
215 for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {\r
216 ASSERT (Descriptor->ResType <\r
217 ARRAY_SIZE (mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr)\r
218 );\r
219 DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",\r
220 mPciHostBridgeUtilityLibAcpiAddressSpaceTypeStr[Descriptor->ResType],\r
221 Descriptor->AddrLen, Descriptor->AddrRangeMax\r
222 ));\r
223 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {\r
224 DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",\r
225 Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,\r
226 ((Descriptor->SpecificFlag &\r
227 EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE\r
228 ) != 0) ? L" (Prefetchable)" : L""\r
229 ));\r
230 }\r
231 }\r
232 //\r
233 // Skip the END descriptor for root bridge\r
234 //\r
235 ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);\r
236 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(\r
237 (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1\r
238 );\r
239 }\r
240}\r
241\r