VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/UefiPayloadPkg/Library/PciSegmentInfoLibAcpiBoardInfo/PciSegmentInfoLibAcpiBoardInfo.c@ 109019

Last change on this file since 109019 was 108794, checked in by vboxsync, 4 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

  • Property svn:eol-style set to native
File size: 9.3 KB
Line 
1/** @file
2 PCI Segment Information Library that returns one segment whose
3 segment base address is retrieved from AcpiBoardInfo HOB.
4
5 Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
6 Copyright (c) 2024, Rivos Inc. All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10**/
11
12#include <PiDxe.h>
13#include <Guid/AcpiBoardInfoGuid.h>
14
15#include <Library/HobLib.h>
16#include <Library/PciSegmentInfoLib.h>
17#include <Library/DebugLib.h>
18#include <UniversalPayload/PciRootBridges.h>
19#include <Library/PciLib.h>
20#include <Library/MemoryAllocationLib.h>
21#include <Library/PcdLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Guid/PciSegmentInfoGuid.h>
24
25static PCI_SEGMENT_INFO *mPciSegments;
26static UINTN mCount;
27
28/**
29 Find segment info from all root bridges
30
31 @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob
32 @param[in] UplSegmentInfo Pointer of Universal UPL Segment Info
33
34 @param[out] NumberOfRootBridges Number of root bridges detected
35
36**/
37VOID
38RetrieveMultiSegmentInfoFromHob (
39 IN UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo,
40 IN UPL_PCI_SEGMENT_INFO_HOB *UplSegmentInfo,
41 OUT UINTN *NumberOfRootBridges
42 )
43{
44 UINTN Size;
45 UINT8 IndexForExistingSegments;
46 UINT8 NumberOfExistingSegments;
47 UINT8 IndexForRb;
48 PCI_SEGMENT_INFO *pPciSegments;
49
50 if (PciRootBridgeInfo == NULL) {
51 mPciSegments = NULL;
52 return;
53 }
54
55 IndexForExistingSegments = 0;
56 NumberOfExistingSegments = 0;
57 IndexForRb = 0;
58 Size = PciRootBridgeInfo->Count * sizeof (PCI_SEGMENT_INFO);
59
60 *NumberOfRootBridges = PciRootBridgeInfo->Count;
61
62 pPciSegments = (PCI_SEGMENT_INFO *)AllocatePool (Size);
63 if (pPciSegments == NULL) {
64 ASSERT (pPciSegments != NULL);
65 return;
66 }
67
68 ZeroMem (pPciSegments, PciRootBridgeInfo->Count * sizeof (PCI_SEGMENT_INFO));
69
70 //
71 // RBs may share the same Segment number, but mPciSegments should not have duplicate segment data.
72 // 1. if RB Segment is same with existing one, update StartBus and EndBus of existing one
73 // 2. if RB Segment is different from all existing ones, add it to the existing Segments data buffer.
74 // pPciSegments is local temporary data buffer that will be freed later (size depends on numbers of RB)
75 // mPciSegments is global data that will be updated with the pPciSegments for caller to utilize. (size depends on numbers of different PciSegments)
76 //
77 NumberOfExistingSegments = 1;
78 pPciSegments[0].BaseAddress = UplSegmentInfo->SegmentInfo[0].BaseAddress;
79 pPciSegments[0].SegmentNumber = (UINT16)(PciRootBridgeInfo->RootBridge[0].Segment);
80 pPciSegments[0].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[0].Bus.Base;
81 pPciSegments[0].EndBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[0].Bus.Limit;
82 for (IndexForRb = 1; IndexForRb < PciRootBridgeInfo->Count; IndexForRb++) {
83 for (IndexForExistingSegments = 0; IndexForExistingSegments < NumberOfExistingSegments; IndexForExistingSegments++) {
84 if (pPciSegments[IndexForExistingSegments].SegmentNumber == PciRootBridgeInfo->RootBridge[IndexForRb].Segment) {
85 if (pPciSegments[IndexForExistingSegments].StartBusNumber > PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base) {
86 pPciSegments[IndexForExistingSegments].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base;
87 }
88
89 if (pPciSegments[IndexForExistingSegments].EndBusNumber < PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit) {
90 pPciSegments[IndexForExistingSegments].EndBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit;
91 }
92
93 break; // breaking after a match found
94 }
95 }
96
97 if (IndexForExistingSegments >= NumberOfExistingSegments) {
98 //
99 // No match found, add it to segments data buffer
100 //
101 pPciSegments[NumberOfExistingSegments].BaseAddress = UplSegmentInfo->SegmentInfo[IndexForRb].BaseAddress;
102 pPciSegments[NumberOfExistingSegments].SegmentNumber = (UINT16)(PciRootBridgeInfo->RootBridge[IndexForRb].Segment);
103 pPciSegments[NumberOfExistingSegments].StartBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Base;
104 pPciSegments[NumberOfExistingSegments].EndBusNumber = (UINT8)PciRootBridgeInfo->RootBridge[IndexForRb].Bus.Limit;
105 NumberOfExistingSegments++;
106 }
107 }
108
109 //
110 // Prepare data for returning to caller
111 //
112 *NumberOfRootBridges = NumberOfExistingSegments;
113 Size = NumberOfExistingSegments * sizeof (PCI_SEGMENT_INFO);
114 mPciSegments = (PCI_SEGMENT_INFO *)AllocatePool (Size);
115 if (mPciSegments == NULL) {
116 ASSERT (FALSE);
117 return;
118 }
119
120 CopyMem (&mPciSegments[0], &pPciSegments[0], Size);
121 if (pPciSegments != NULL) {
122 FreePool (pPciSegments);
123 }
124
125 return;
126}
127
128/**
129 Find segment info from all root bridges for legacy systems
130
131 @param[in] PciRootBridgeInfo Pointer of Universal Payload PCI Root Bridge Info Hob
132 @param[out] NumberOfRootBridges Number of root bridges detected
133
134**/
135VOID
136RetrieveSegmentInfoFromHob (
137 OUT UINTN *NumberOfRootBridges
138 )
139{
140 EFI_HOB_GUID_TYPE *GuidHob;
141 ACPI_BOARD_INFO *AcpiBoardInfo;
142
143 *NumberOfRootBridges = 1;
144 // old model relies on gUefiAcpiBoardInfoGuid and hardcoded values for single segment only.
145 // This is only for backward compatibility, new platforms should adopt new model even in single segment cases.
146 //
147 mPciSegments = (PCI_SEGMENT_INFO *)AllocatePool (sizeof (PCI_SEGMENT_INFO));
148 ASSERT (mPciSegments != NULL);
149 GuidHob = GetFirstGuidHob (&gUefiAcpiBoardInfoGuid);
150 ASSERT (GuidHob != NULL);
151 if (GuidHob != NULL) {
152 AcpiBoardInfo = (ACPI_BOARD_INFO *)GET_GUID_HOB_DATA (GuidHob);
153 mPciSegments->SegmentNumber = 0;
154 mPciSegments->BaseAddress = AcpiBoardInfo->PcieBaseAddress;
155 mPciSegments->StartBusNumber = 0;
156 mPciSegments->EndBusNumber = 0xFF;
157 }
158}
159
160/**
161 Return info for all root bridges
162
163 @return All the root bridge info instances in an array.
164**/
165UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *
166Get_RBInfo (
167 VOID
168 )
169{
170 UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;
171 EFI_HOB_GUID_TYPE *GuidHob;
172 UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;
173
174 //
175 // Find Universal Payload PCI Root Bridge Info hob
176 //
177 GuidHob = GetFirstGuidHob (&gUniversalPayloadPciRootBridgeInfoGuid);
178 if ((GuidHob == NULL) || (sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob))) {
179 return NULL;
180 }
181
182 GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
183 if (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob)) {
184 return NULL;
185 }
186
187 if ((GenericHeader->Revision != UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) || (GenericHeader->Length < sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES))) {
188 return NULL;
189 }
190
191 //
192 // UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES structure is used when Revision equals to UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION
193 //
194 PciRootBridgeInfo = (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *)GET_GUID_HOB_DATA (GuidHob);
195 if (PciRootBridgeInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES)) / sizeof (UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGE)) {
196 return PciRootBridgeInfo;
197 }
198
199 return NULL;
200}
201
202/**
203 Return info for all root bridge segments
204
205 @return All the segment info instances in an array.
206**/
207UPL_PCI_SEGMENT_INFO_HOB *
208Get_UPLSegInfo (
209 VOID
210 )
211{
212 UPL_PCI_SEGMENT_INFO_HOB *UplSegmentInfo;
213 EFI_HOB_GUID_TYPE *GuidHob;
214 UNIVERSAL_PAYLOAD_GENERIC_HEADER *GenericHeader;
215
216 //
217 // Find Universal Payload Segment Info hob
218 //
219 GuidHob = GetFirstGuidHob (&gUplPciSegmentInfoHobGuid);
220 if ((GuidHob == NULL) || (sizeof (UNIVERSAL_PAYLOAD_GENERIC_HEADER) > GET_GUID_HOB_DATA_SIZE (GuidHob))) {
221 return NULL;
222 }
223
224 GenericHeader = (UNIVERSAL_PAYLOAD_GENERIC_HEADER *)GET_GUID_HOB_DATA (GuidHob);
225 if (GenericHeader->Length > GET_GUID_HOB_DATA_SIZE (GuidHob)) {
226 return NULL;
227 }
228
229 if ((GenericHeader->Revision != UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES_REVISION) || (GenericHeader->Length < sizeof (UPL_PCI_SEGMENT_INFO_HOB))) {
230 return NULL;
231 }
232
233 //
234 // UPL_PCI_SEGMENT_INFO_HOB structure is used when Revision equals to UPL_PCI_SEGMENT_INFO_HOB_REVISION
235 //
236 UplSegmentInfo = (UPL_PCI_SEGMENT_INFO_HOB *)GET_GUID_HOB_DATA (GuidHob);
237 if (UplSegmentInfo->Count <= (GET_GUID_HOB_DATA_SIZE (GuidHob) - sizeof (UPL_PCI_SEGMENT_INFO_HOB)) / sizeof (UPL_SEGMENT_INFO)) {
238 return UplSegmentInfo;
239 }
240
241 return NULL;
242}
243
244/**
245 Return all the root bridge instances in an array.
246
247 @param Count Return the count of root bridge instances.
248
249 @return All the root bridge instances in an array.
250 The array should be passed into PciHostBridgeFreeRootBridges()
251 when it's not used.
252**/
253PCI_SEGMENT_INFO *
254EFIAPI
255GetPciSegmentInfo (
256 UINTN *Count
257 )
258{
259 UNIVERSAL_PAYLOAD_PCI_ROOT_BRIDGES *PciRootBridgeInfo;
260 UPL_PCI_SEGMENT_INFO_HOB *UplSegmentInfo;
261
262 if (mPciSegments != NULL) {
263 *Count = mCount;
264 return mPciSegments;
265 }
266
267 UplSegmentInfo = Get_UPLSegInfo ();
268
269 if (UplSegmentInfo == NULL) {
270 RetrieveSegmentInfoFromHob (Count);
271 } else {
272 PciRootBridgeInfo = Get_RBInfo ();
273 if (PciRootBridgeInfo == NULL) {
274 return 0;
275 }
276
277 RetrieveMultiSegmentInfoFromHob (PciRootBridgeInfo, UplSegmentInfo, Count);
278 }
279
280 mCount = *Count;
281 return mPciSegments;
282}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette