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