]> git.proxmox.com Git - mirror_edk2.git/blob - UefiPayloadPkg/Library/PciHostBridgeLib/PciHostBridgeLib.c
UefiPayloadPkg: UefiPayload retrieve PCI root bridge from Guid Hob
[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 (sizeof (mRootBridgeDevicePathTemplate),
134 &mRootBridgeDevicePathTemplate);
135 if (DevicePath == NULL) {
136 DEBUG ((DEBUG_ERROR, "%a: %r\n", __FUNCTION__, EFI_OUT_OF_RESOURCES));
137 return EFI_OUT_OF_RESOURCES;
138 }
139 DevicePath->AcpiDevicePath.UID = RootBusNumber;
140 RootBus->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
141
142 DEBUG ((DEBUG_INFO,
143 "%a: populated root bus %d, with room for %d subordinate bus(es)\n",
144 __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
145 return EFI_SUCCESS;
146 }
147
148 /**
149 Initialize DevicePath for a PCI_ROOT_BRIDGE.
150 @param[in] HID HID for device path
151 @param[in] UID UID for device path
152
153 @retval A pointer to the new created device patch.
154 **/
155 EFI_DEVICE_PATH_PROTOCOL *
156 CreateRootBridgeDevicePath (
157 IN UINT32 HID,
158 IN UINT32 UID
159 )
160 {
161 CB_PCI_ROOT_BRIDGE_DEVICE_PATH *DevicePath;
162 DevicePath = AllocateCopyPool (sizeof (mRootBridgeDevicePathTemplate),
163 &mRootBridgeDevicePathTemplate);
164 ASSERT (DevicePath != NULL);
165 DevicePath->AcpiDevicePath.HID = HID;
166 DevicePath->AcpiDevicePath.UID = UID;
167 return (EFI_DEVICE_PATH_PROTOCOL *)DevicePath;
168 }
169
170 /**
171 Return all the root bridge instances in an array.
172
173 @param Count Return the count of root bridge instances.
174
175 @return All the root bridge instances in an array.
176 The array should be passed into PciHostBridgeFreeRootBridges()
177 when it's not used.
178 **/
179 PCI_ROOT_BRIDGE *
180 EFIAPI
181 PciHostBridgeGetRootBridges (
182 UINTN *Count
183 )
184 {
185 UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;
186 EFI_HOB_GUID_TYPE *GuidHob;
187 UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;
188 //
189 // Find Universal Payload PCI Root Bridge Info hob
190 //
191 GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid);
192 if (GuidHob != NULL) {
193 GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *) GET_GUID_HOB_DATA (GuidHob);
194 if ((sizeof(UNIVERSAL_PAYLOAD_GENERIC_HEADER) <= GET_GUID_HOB_DATA_SIZE (GuidHob)) && (GenericHeader->Length <= GET_GUID_HOB_DATA_SIZE (GuidHob))) {
195 if ((GenericHeader->Revision == UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) && (GenericHeader->Length >= sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) {
196 //
197 // UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION
198 //
199 PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *) GET_GUID_HOB_DATA (GuidHob);
200 if (PciRootBridgeInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES)) / sizeof(UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE)) {
201 return RetrieveRootBridgeInfoFromHob (PciRootBridgeInfo, Count);
202 }
203 }
204 }
205 }
206 return ScanForRootBridges (Count);
207 }
208
209 /**
210 Free the root bridge instances array returned from
211 PciHostBridgeGetRootBridges().
212
213 @param The root bridge instances array.
214 @param The count of the array.
215 **/
216 VOID
217 EFIAPI
218 PciHostBridgeFreeRootBridges (
219 PCI_ROOT_BRIDGE *Bridges,
220 UINTN Count
221 )
222 {
223 if (Bridges == NULL && Count == 0) {
224 return;
225 }
226 ASSERT (Bridges != NULL && Count > 0);
227
228 do {
229 --Count;
230 FreePool (Bridges[Count].DevicePath);
231 } while (Count > 0);
232
233 FreePool (Bridges);
234 }
235
236
237 /**
238 Inform the platform that the resource conflict happens.
239
240 @param HostBridgeHandle Handle of the Host Bridge.
241 @param Configuration Pointer to PCI I/O and PCI memory resource
242 descriptors. The Configuration contains the resources
243 for all the root bridges. The resource for each root
244 bridge is terminated with END descriptor and an
245 additional END is appended indicating the end of the
246 entire resources. The resource descriptor field
247 values follow the description in
248 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
249 .SubmitResources().
250 **/
251 VOID
252 EFIAPI
253 PciHostBridgeResourceConflict (
254 EFI_HANDLE HostBridgeHandle,
255 VOID *Configuration
256 )
257 {
258 //
259 // coreboot UEFI Payload does not do PCI enumeration and should not call this
260 // library interface.
261 //
262 ASSERT (FALSE);
263 }