TianoCore EDK2 master
Loading...
Searching...
No Matches
ExtraRootBusMap.c
Go to the documentation of this file.
1
9#include <Library/DebugLib.h>
14#include <Protocol/DevicePath.h>
16
17#include "ExtraRootBusMap.h"
18
19//
20// The BusNumbers field is an array with Count elements. The elements increase
21// strictry monotonically. Zero is not an element (because the zero bus number
22// belongs to the "main" root bus, never to an extra root bus). Offset N in the
23// array maps the extra root bus with position (N+1) to its bus number (because
24// the root bus with position 0 is always the main root bus, therefore we don't
25// store it).
26//
27// If there are no extra root buses in the system, then Count is 0, and
28// BusNumbers is NULL.
29//
31 UINT32 *BusNumbers;
32 UINTN Count;
33};
34
50INTN
51EFIAPI
53 IN CONST VOID *UserStruct1,
54 IN CONST VOID *UserStruct2
55 )
56{
59
60 Acpi1 = UserStruct1;
61 Acpi2 = UserStruct2;
62
63 return Acpi1->UID < Acpi2->UID ? -1 :
64 Acpi1->UID > Acpi2->UID ? 1 :
65 0;
66}
67
84INTN
85EFIAPI
87 IN CONST VOID *StandaloneKey,
88 IN CONST VOID *UserStruct
89 )
90{
91 CONST UINT32 *Uid;
93
94 Uid = StandaloneKey;
95 Acpi = UserStruct;
96
97 return *Uid < Acpi->UID ? -1 :
98 *Uid > Acpi->UID ? 1 :
99 0;
100}
101
129 OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap
130 )
131{
132 EFI_STATUS Status;
133 UINTN NumHandles;
134 EFI_HANDLE *Handles;
135 ORDERED_COLLECTION *Collection;
137 UINTN Idx;
138 ORDERED_COLLECTION_ENTRY *Entry, *Entry2;
139
140 //
141 // Handles and Collection are temporary / helper variables, while in Map we
142 // build the return value.
143 //
144
145 Status = gBS->LocateHandleBuffer (
147 &gEfiPciRootBridgeIoProtocolGuid,
148 NULL /* SearchKey */,
149 &NumHandles,
150 &Handles
151 );
152 if (EFI_ERROR (Status)) {
153 return Status;
154 }
155
156 Collection = OrderedCollectionInit (
159 );
160 if (Collection == NULL) {
161 Status = EFI_OUT_OF_RESOURCES;
162 goto FreeHandles;
163 }
164
165 Map = AllocateZeroPool (sizeof *Map);
166 if (Map == NULL) {
167 Status = EFI_OUT_OF_RESOURCES;
168 goto FreeCollection;
169 }
170
171 //
172 // Collect the ACPI device path protocols of the root bridges.
173 //
174 for (Idx = 0; Idx < NumHandles; ++Idx) {
175 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
176
177 Status = gBS->HandleProtocol (
178 Handles[Idx],
179 &gEfiDevicePathProtocolGuid,
180 (VOID **)&DevicePath
181 );
182 if (EFI_ERROR (Status)) {
183 goto FreeMap;
184 }
185
186 //
187 // Examine if the device path is an ACPI HID one, and if so, if UID is
188 // nonzero (ie. the root bridge that the bus number belongs to is "extra",
189 // not the main one). In that case, link the device path into Collection.
190 //
191 if ((DevicePathType (DevicePath) == ACPI_DEVICE_PATH) &&
192 (DevicePathSubType (DevicePath) == ACPI_DP) &&
193 (((ACPI_HID_DEVICE_PATH *)DevicePath)->HID == EISA_PNP_ID (0x0A03)) &&
194 (((ACPI_HID_DEVICE_PATH *)DevicePath)->UID > 0))
195 {
196 Status = OrderedCollectionInsert (Collection, NULL, DevicePath);
197 if (EFI_ERROR (Status)) {
198 goto FreeMap;
199 }
200
201 ++Map->Count;
202 }
203 }
204
205 if (Map->Count > 0) {
206 //
207 // At least one extra PCI root bus exists.
208 //
209 Map->BusNumbers = AllocatePool (Map->Count * sizeof *Map->BusNumbers);
210 if (Map->BusNumbers == NULL) {
211 Status = EFI_OUT_OF_RESOURCES;
212 goto FreeMap;
213 }
214 }
215
216 //
217 // Now collect the bus numbers of the extra PCI root buses into Map.
218 //
219 Idx = 0;
220 Entry = OrderedCollectionMin (Collection);
221 while (Idx < Map->Count) {
223
224 ASSERT (Entry != NULL);
225 Acpi = OrderedCollectionUserStruct (Entry);
226 Map->BusNumbers[Idx] = Acpi->UID;
227 DEBUG ((
228 DEBUG_VERBOSE,
229 "%a: extra bus position 0x%Lx maps to bus number (UID) 0x%x\n",
230 __func__,
231 (UINT64)(Idx + 1),
232 Acpi->UID
233 ));
234 ++Idx;
235 Entry = OrderedCollectionNext (Entry);
236 }
237
238 ASSERT (Entry == NULL);
239
240 *ExtraRootBusMap = Map;
241 Status = EFI_SUCCESS;
242
243 //
244 // Fall through in order to release temporaries.
245 //
246
247FreeMap:
248 if (EFI_ERROR (Status)) {
249 if (Map->BusNumbers != NULL) {
250 FreePool (Map->BusNumbers);
251 }
252
253 FreePool (Map);
254 }
255
256FreeCollection:
257 for (Entry = OrderedCollectionMin (Collection); Entry != NULL;
258 Entry = Entry2)
259 {
260 Entry2 = OrderedCollectionNext (Entry);
261 OrderedCollectionDelete (Collection, Entry, NULL);
262 }
263
264 OrderedCollectionUninit (Collection);
265
266FreeHandles:
267 FreePool (Handles);
268
269 return Status;
270}
271
277VOID
279 IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap
280 )
281{
282 if (ExtraRootBusMap->BusNumbers != NULL) {
283 FreePool (ExtraRootBusMap->BusNumbers);
284 }
285
286 FreePool (ExtraRootBusMap);
287}
288
310 IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap,
311 IN UINT64 RootBusPos,
312 OUT UINT32 *RootBusNr
313 )
314{
315 if (RootBusPos == 0) {
316 return EFI_INVALID_PARAMETER;
317 }
318
319 if (RootBusPos > ExtraRootBusMap->Count) {
320 return EFI_NOT_FOUND;
321 }
322
323 *RootBusNr = ExtraRootBusMap->BusNumbers[(UINTN)RootBusPos - 1];
324 return EFI_SUCCESS;
325}
UINT64 UINTN
INT64 INTN
#define ACPI_DEVICE_PATH
Definition: DevicePath.h:190
#define ACPI_DP
Definition: DevicePath.h:195
UINT8 EFIAPI DevicePathType(IN CONST VOID *Node)
UINT8 EFIAPI DevicePathSubType(IN CONST VOID *Node)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
STATIC INTN EFIAPI RootBridgePathKeyCompare(IN CONST VOID *StandaloneKey, IN CONST VOID *UserStruct)
VOID DestroyExtraRootBusMap(IN EXTRA_ROOT_BUS_MAP *ExtraRootBusMap)
STATIC INTN EFIAPI RootBridgePathCompare(IN CONST VOID *UserStruct1, IN CONST VOID *UserStruct2)
EFI_STATUS MapRootBusPosToBusNr(IN CONST EXTRA_ROOT_BUS_MAP *ExtraRootBusMap, IN UINT64 RootBusPos, OUT UINT32 *RootBusNr)
EFI_STATUS CreateExtraRootBusMap(OUT EXTRA_ROOT_BUS_MAP **ExtraRootBusMap)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionMin(IN CONST ORDERED_COLLECTION *Collection)
VOID *EFIAPI OrderedCollectionUserStruct(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
RETURN_STATUS EFIAPI OrderedCollectionInsert(IN OUT ORDERED_COLLECTION *Collection, OUT ORDERED_COLLECTION_ENTRY **Entry OPTIONAL, IN VOID *UserStruct)
VOID EFIAPI OrderedCollectionUninit(IN ORDERED_COLLECTION *Collection)
ORDERED_COLLECTION *EFIAPI OrderedCollectionInit(IN ORDERED_COLLECTION_USER_COMPARE UserStructCompare, IN ORDERED_COLLECTION_KEY_COMPARE KeyCompare)
ORDERED_COLLECTION_ENTRY *EFIAPI OrderedCollectionNext(IN CONST ORDERED_COLLECTION_ENTRY *Entry)
VOID EFIAPI OrderedCollectionDelete(IN OUT ORDERED_COLLECTION *Collection, IN ORDERED_COLLECTION_ENTRY *Entry, OUT VOID **UserStruct OPTIONAL)
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
@ ByProtocol
Definition: UefiSpec.h:1518