]> git.proxmox.com Git - mirror_edk2.git/blame - UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / UefiPayloadPkg / Library / PciHostBridgeLib / PciHostBridgeLib.c
CommitLineData
04af8bf2
DG
1/** @file\r
2 Library instance of PciHostBridgeLib library class for coreboot.\r
3\r
4 Copyright (C) 2016, Red Hat, Inc.\r
99de2e7e 5 Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r
04af8bf2
DG
6\r
7 SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10#include <PiDxe.h>\r
11\r
12#include <IndustryStandard/Pci.h>\r
13#include <Protocol/PciHostBridgeResourceAllocation.h>\r
14#include <Protocol/PciRootBridgeIo.h>\r
15\r
16#include <Library/BaseMemoryLib.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/DevicePathLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20#include <Library/PciHostBridgeLib.h>\r
21#include <Library/PciLib.h>\r
99de2e7e 22#include <Library/HobLib.h>\r
04af8bf2
DG
23\r
24#include "PciHostBridge.h"\r
25\r
26STATIC\r
27CONST\r
e5efcf8b 28CB_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {\r
04af8bf2
DG
29 {\r
30 {\r
31 ACPI_DEVICE_PATH,\r
32 ACPI_DP,\r
33 {\r
e5efcf8b
MK
34 (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)),\r
35 (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)\r
04af8bf2
DG
36 }\r
37 },\r
e5efcf8b
MK
38 EISA_PNP_ID (0x0A03), // HID\r
39 0 // UID\r
04af8bf2
DG
40 },\r
41\r
42 {\r
43 END_DEVICE_PATH_TYPE,\r
44 END_ENTIRE_DEVICE_PATH_SUBTYPE,\r
45 {\r
46 END_DEVICE_PATH_LENGTH,\r
47 0\r
48 }\r
49 }\r
50};\r
51\r
04af8bf2
DG
52/**\r
53 Initialize a PCI_ROOT_BRIDGE structure.\r
54\r
55 @param[in] Supports Supported attributes.\r
56\r
57 @param[in] Attributes Initial attributes.\r
58\r
59 @param[in] AllocAttributes Allocation attributes.\r
60\r
61 @param[in] RootBusNumber The bus number to store in RootBus.\r
62\r
63 @param[in] MaxSubBusNumber The inclusive maximum bus number that can be\r
64 assigned to any subordinate bus found behind any\r
65 PCI bridge hanging off this root bus.\r
66\r
67 The caller is responsible for ensuring that\r
68 RootBusNumber <= MaxSubBusNumber. If\r
69 RootBusNumber equals MaxSubBusNumber, then the\r
70 root bus has no room for subordinate buses.\r
71\r
72 @param[in] Io IO aperture.\r
73\r
74 @param[in] Mem MMIO aperture.\r
75\r
76 @param[in] MemAbove4G MMIO aperture above 4G.\r
77\r
78 @param[in] PMem Prefetchable MMIO aperture.\r
79\r
80 @param[in] PMemAbove4G Prefetchable MMIO aperture above 4G.\r
81\r
82 @param[out] RootBus The PCI_ROOT_BRIDGE structure (allocated by the\r
83 caller) that should be filled in by this\r
84 function.\r
85\r
86 @retval EFI_SUCCESS Initialization successful. A device path\r
87 consisting of an ACPI device path node, with\r
88 UID = RootBusNumber, has been allocated and\r
89 linked into RootBus.\r
90\r
91 @retval EFI_OUT_OF_RESOURCES Memory allocation failed.\r
92**/\r
93EFI_STATUS\r
94InitRootBridge (\r
e5efcf8b
MK
95 IN UINT64 Supports,\r
96 IN UINT64 Attributes,\r
97 IN UINT64 AllocAttributes,\r
98 IN UINT8 RootBusNumber,\r
99 IN UINT8 MaxSubBusNumber,\r
100 IN PCI_ROOT_BRIDGE_APERTURE *Io,\r
101 IN PCI_ROOT_BRIDGE_APERTURE *Mem,\r
102 IN PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,\r
103 IN PCI_ROOT_BRIDGE_APERTURE *PMem,\r
104 IN PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,\r
105 OUT PCI_ROOT_BRIDGE *RootBus\r
106 )\r
04af8bf2 107{\r
e5efcf8b 108 CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;\r
04af8bf2
DG
109\r
110 //\r
111 // Be safe if other fields are added to PCI_ROOT_BRIDGE later.\r
112 //\r
113 ZeroMem (RootBus, sizeof *RootBus);\r
114\r
115 RootBus->Segment = 0;\r
116\r
117 RootBus->Supports = Supports;\r
118 RootBus->Attributes = Attributes;\r
119\r
120 RootBus->DmaAbove4G = FALSE;\r
121\r
122 RootBus->AllocationAttributes = AllocAttributes;\r
e5efcf8b
MK
123 RootBus->Bus.Base = RootBusNumber;\r
124 RootBus->Bus.Limit = MaxSubBusNumber;\r
04af8bf2
DG
125 CopyMem (&RootBus->Io, Io, sizeof (*Io));\r
126 CopyMem (&RootBus->Mem, Mem, sizeof (*Mem));\r
127 CopyMem (&RootBus->MemAbove4G, MemAbove4G, sizeof (*MemAbove4G));\r
128 CopyMem (&RootBus->PMem, PMem, sizeof (*PMem));\r
129 CopyMem (&RootBus->PMemAbove4G, PMemAbove4G, sizeof (*PMemAbove4G));\r
130\r
131 RootBus->NoExtendedConfigSpace = FALSE;\r
132\r
e5efcf8b
MK
133 DevicePath = AllocateCopyPool (\r
134 sizeof (mRootBridgeDevicePathTemplate),\r
135 &mRootBridgeDevicePathTemplate\r
136 );\r
04af8bf2
DG
137 if (DevicePath == NULL) {\r
138 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));\r
139 return EFI_OUT_OF_RESOURCES;\r
140 }\r
04af8bf2 141\r
e5efcf8b
MK
142 DevicePath->AcpiDevicePath.UID = RootBusNumber;\r
143 RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
144\r
145 DEBUG ((\r
146 DEBUG_INFO,\r
147 "%a: populated root bus %d, with room for %d subordinate bus(es)\n",\r
148 __FUNCTION__,\r
149 RootBusNumber,\r
150 MaxSubBusNumber - RootBusNumber\r
151 ));\r
04af8bf2
DG
152 return EFI_SUCCESS;\r
153}\r
154\r
99de2e7e
ZL
155/**\r
156 Initialize DevicePath for a PCI_ROOT_BRIDGE.\r
157 @param[in] HID HID for device path\r
158 @param[in] UID UID for device path\r
159\r
160 @retval A pointer to the new created device patch.\r
161**/\r
162EFI_DEVICE_PATH_PROTOCOL *\r
163CreateRootBridgeDevicePath (\r
e5efcf8b
MK
164 IN UINT32 HID,\r
165 IN UINT32 UID\r
166 )\r
99de2e7e 167{\r
e5efcf8b
MK
168 CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;\r
169\r
170 DevicePath = AllocateCopyPool (\r
171 sizeof (mRootBridgeDevicePathTemplate),\r
172 &mRootBridgeDevicePathTemplate\r
173 );\r
99de2e7e
ZL
174 ASSERT (DevicePath != NULL);\r
175 DevicePath->AcpiDevicePath.HID = HID;\r
176 DevicePath->AcpiDevicePath.UID = UID;\r
177 return (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;\r
178}\r
04af8bf2
DG
179\r
180/**\r
181 Return all the root bridge instances in an array.\r
182\r
183 @param Count Return the count of root bridge instances.\r
184\r
185 @return All the root bridge instances in an array.\r
186 The array should be passed into PciHostBridgeFreeRootBridges()\r
187 when it's not used.\r
188**/\r
189PCI_ROOT_BRIDGE *\r
190EFIAPI\r
191PciHostBridgeGetRootBridges (\r
e5efcf8b
MK
192 UINTN *Count\r
193 )\r
04af8bf2 194{\r
99de2e7e
ZL
195 UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;\r
196 EFI_HOB_GUID_TYPE *GuidHob;\r
197 UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;\r
e5efcf8b 198\r
99de2e7e
ZL
199 //\r
200 // Find Universal Payload PCI Root Bridge Info hob\r
201 //\r
202 GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid);\r
203 if (GuidHob != NULL) {\r
e5efcf8b
MK
204 GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);\r
205 if ((sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {\r
99de2e7e
ZL
206 if ((GenericHeader->Revision == UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) && (GenericHeader->Length >= sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) {\r
207 //\r
208 // UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION\r
209 //\r
e5efcf8b
MK
210 PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *)GET_GUID_HOB_DATA (GuidHob);\r
211 if (PciRootBridgeInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES)) / sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE)) {\r
99de2e7e
ZL
212 return RetrieveRootBridgeInfoFromHob (PciRootBridgeInfo, Count);\r
213 }\r
214 }\r
215 }\r
216 }\r
e5efcf8b 217\r
04af8bf2
DG
218 return ScanForRootBridges (Count);\r
219}\r
220\r
04af8bf2
DG
221/**\r
222 Free the root bridge instances array returned from\r
223 PciHostBridgeGetRootBridges().\r
224\r
6ef57974
GD
225 @param Bridges The root bridge instances array.\r
226 @param Count The count of the array.\r
04af8bf2
DG
227**/\r
228VOID\r
229EFIAPI\r
230PciHostBridgeFreeRootBridges (\r
e5efcf8b
MK
231 PCI_ROOT_BRIDGE *Bridges,\r
232 UINTN Count\r
233 )\r
04af8bf2 234{\r
dfdba857 235 if ((Bridges == NULL) || (Count == 0)) {\r
04af8bf2
DG
236 return;\r
237 }\r
e5efcf8b 238\r
dfdba857 239 ASSERT (Bridges != NULL || Count > 0);\r
04af8bf2
DG
240\r
241 do {\r
242 --Count;\r
243 FreePool (Bridges[Count].DevicePath);\r
244 } while (Count > 0);\r
245\r
246 FreePool (Bridges);\r
247}\r
248\r
04af8bf2
DG
249/**\r
250 Inform the platform that the resource conflict happens.\r
251\r
252 @param HostBridgeHandle Handle of the Host Bridge.\r
253 @param Configuration Pointer to PCI I/O and PCI memory resource\r
254 descriptors. The Configuration contains the resources\r
255 for all the root bridges. The resource for each root\r
256 bridge is terminated with END descriptor and an\r
257 additional END is appended indicating the end of the\r
258 entire resources. The resource descriptor field\r
259 values follow the description in\r
260 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL\r
261 .SubmitResources().\r
262**/\r
263VOID\r
264EFIAPI\r
265PciHostBridgeResourceConflict (\r
e5efcf8b
MK
266 EFI_HANDLE HostBridgeHandle,\r
267 VOID *Configuration\r
268 )\r
04af8bf2
DG
269{\r
270 //\r
271 // coreboot UEFI Payload does not do PCI enumeration and should not call this\r
272 // library interface.\r
273 //\r
274 ASSERT (FALSE);\r
275}\r