TianoCore EDK2 master
Loading...
Searching...
No Matches
HardwareInfoPciHostBridgeLib.c
Go to the documentation of this file.
1
10#include <Library/DebugLib.h>
11
13
14#define IS_RANGE_INVALID(Start, Size, MaxValue) (Start >= MaxValue || Size == 0)
15
24UINT64
26 IN UINT64 Start,
27 IN UINT64 Size,
28 IN UINT64 MaxValue
29 )
30{
31 if (IS_RANGE_INVALID (Start, Size, MaxValue)) {
32 return 0;
33 }
34
35 return Start + Size - 1;
36}
37
49VOID
52 OUT UINT64 *LastAddress
53 )
54{
55 if (Mem->Limit > *LastAddress) {
56 *LastAddress = Mem->Limit;
57 }
58}
59
62 IN CONST HOST_BRIDGE_INFO *HostBridge,
63 IN UINTN DataSize,
64 IN BOOLEAN HighMem,
65 OUT UINT64 *LastMmioAddress
66 )
67{
68 EFI_STATUS Status;
70 PCI_ROOT_BRIDGE_APERTURE MemAbove4G;
72 PCI_ROOT_BRIDGE_APERTURE PMemAbove4G;
73
74 if (LastMmioAddress == NULL) {
75 return EFI_INVALID_PARAMETER;
76 }
77
78 //
79 // Set the output to the lowest possible value so that if some step fails
80 // the overall outcome reflects no information found
81 //
82 *LastMmioAddress = 0;
83
85 HostBridge,
86 DataSize,
87 NULL,
88 &Mem,
89 &MemAbove4G,
90 &PMem,
91 &PMemAbove4G,
92 NULL
93 );
94
95 //
96 // Forward error to caller but ignore warnings given that, very likely,
97 // the host bridge will have a PIO aperture we are explicitly
98 // ignoring here since we care only about MMIO resources.
99 //
100 if (EFI_ERROR (Status)) {
101 return Status;
102 }
103
104 if (HighMem) {
105 UpdateLastAddressIfHigher (&MemAbove4G, LastMmioAddress);
106 UpdateLastAddressIfHigher (&PMemAbove4G, LastMmioAddress);
107 } else {
108 UpdateLastAddressIfHigher (&Mem, LastMmioAddress);
109 UpdateLastAddressIfHigher (&PMem, LastMmioAddress);
110 }
111
112 return EFI_SUCCESS;
113}
114
124STATIC
125VOID
128 )
129{
130 if (Aperture == NULL) {
131 return;
132 }
133
134 Aperture->Base = MAX_UINT64;
135 Aperture->Limit = 0;
136}
137
155STATIC
158 IN UINT64 Start,
159 IN UINT64 Size,
160 IN UINT64 MaxValue,
162 )
163{
164 UINT64 End;
165
166 End = GetRangeEnd (Start, Size, MaxValue);
167
168 if (Aperture == NULL) {
169 if (!IS_RANGE_INVALID (Start, Size, MaxValue)) {
170 //
171 // Report an error to the caller since the range specified in
172 // the host bridge's resources is non-empty but the provided
173 // aperture pointer is null, thus the valid range is ignored.
174 //
175 return EFI_INVALID_PARAMETER;
176 }
177
178 return EFI_WARN_BUFFER_TOO_SMALL;
179 }
180
181 if (IS_RANGE_INVALID (Start, Size, MaxValue)) {
182 //
183 // Fill Aperture with invalid range values to signal the
184 // absence of an address space (empty range)
185 //
187 } else {
188 Aperture->Base = Start;
189 Aperture->Limit = End;
190 }
191
192 return EFI_SUCCESS;
193}
194
216STATIC
219 IN UINT64 Start,
220 IN UINT64 Size,
221 IN UINT64 PStart,
222 IN UINT64 PSize,
223 IN UINT64 MaxValue,
225 )
226{
227 UINT64 PEnd;
228
229 if (Aperture == NULL) {
230 if (!IS_RANGE_INVALID (Start, Size, MaxValue) ||
231 !IS_RANGE_INVALID (PStart, PSize, MaxValue))
232 {
233 //
234 // Report an error to the caller since the range specified in
235 // the host bridge's resources is non-empty but the provided
236 // aperture pointer is null, thus the valid range is ignored.
237 //
238 return EFI_INVALID_PARAMETER;
239 }
240
241 return EFI_WARN_BUFFER_TOO_SMALL;
242 }
243
244 //
245 // Start from an empty range (Limit < Base)
246 //
248
249 if (!IS_RANGE_INVALID (Start, Size, MaxValue)) {
250 Aperture->Base = Start;
251 Aperture->Limit = Start + Size - 1;
252 }
253
254 if (!IS_RANGE_INVALID (PStart, PSize, MaxValue)) {
255 PEnd = PStart + PSize - 1;
256
257 if (PStart < Aperture->Base) {
258 Aperture->Base = PStart;
259 }
260
261 if (PEnd > Aperture->Limit) {
262 Aperture->Limit = PEnd;
263 }
264 }
265
266 return EFI_SUCCESS;
267}
268
271 IN CONST HOST_BRIDGE_INFO *HostBridge,
272 IN UINTN DataSize,
273 OUT UINTN *BusNrStart,
274 OUT UINTN *BusNrLast
275 )
276{
277 if ((HostBridge == NULL) || (DataSize == 0) ||
278 (BusNrStart == NULL) || (BusNrLast == NULL))
279 {
280 return EFI_INVALID_PARAMETER;
281 }
282
283 //
284 // For now only version 0 is supported
285 //
286 if (HostBridge->Version != 0) {
287 return EFI_INCOMPATIBLE_VERSION;
288 }
289
290 *BusNrStart = HostBridge->BusNrStart;
291 *BusNrLast = HostBridge->BusNrLast;
292
293 return EFI_SUCCESS;
294}
295
298 IN CONST HOST_BRIDGE_INFO *HostBridge,
299 IN UINTN DataSize,
302 OUT PCI_ROOT_BRIDGE_APERTURE *MemAbove4G,
304 OUT PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G,
305 OUT PCI_ROOT_BRIDGE_APERTURE *PcieConfig
306 )
307{
308 EFI_STATUS Status;
309 BOOLEAN StickyError;
310
311 StickyError = FALSE;
312 if ((HostBridge == NULL) || (DataSize == 0)) {
313 return EFI_INVALID_PARAMETER;
314 }
315
316 //
317 // For now only version 0 is supported
318 //
319 if (HostBridge->Version != 0) {
320 return EFI_INCOMPATIBLE_VERSION;
321 }
322
323 Status = FillHostBridgeAperture (
324 HostBridge->IoStart,
325 HostBridge->IoSize,
326 MAX_UINT32,
327 Io
328 );
329 StickyError |= EFI_ERROR (Status);
330
331 Status = FillHostBridgeAperture (
332 HostBridge->PcieConfigStart,
333 HostBridge->PcieConfigSize,
334 MAX_UINT64,
335 PcieConfig
336 );
337 StickyError |= EFI_ERROR (Status);
338
339 if (HostBridge->Flags.Bits.CombineMemPMem) {
340 Status = MergeHostBridgeApertures (
341 HostBridge->MemStart,
342 HostBridge->MemSize,
343 HostBridge->PMemStart,
344 HostBridge->PMemSize,
345 MAX_UINT32,
346 Mem
347 );
348 StickyError |= EFI_ERROR (Status);
349
350 Status = MergeHostBridgeApertures (
351 HostBridge->MemAbove4GStart,
352 HostBridge->MemAbove4GSize,
353 HostBridge->PMemAbove4GStart,
354 HostBridge->PMemAbove4GSize,
355 MAX_UINT64,
356 MemAbove4G
357 );
358 StickyError |= EFI_ERROR (Status);
359
360 //
361 // Invalidate unused apertures
362 //
364 InvalidateRootBridgeAperture (PMemAbove4G);
365 } else {
366 Status = FillHostBridgeAperture (
367 HostBridge->MemStart,
368 HostBridge->MemSize,
369 MAX_UINT32,
370 Mem
371 );
372 StickyError |= EFI_ERROR (Status);
373
374 Status = FillHostBridgeAperture (
375 HostBridge->PMemStart,
376 HostBridge->PMemSize,
377 MAX_UINT32,
378 PMem
379 );
380 StickyError |= EFI_ERROR (Status);
381
382 Status = FillHostBridgeAperture (
383 HostBridge->MemAbove4GStart,
384 HostBridge->MemAbove4GSize,
385 MAX_UINT64,
386 MemAbove4G
387 );
388 StickyError |= EFI_ERROR (Status);
389
390 Status = FillHostBridgeAperture (
391 HostBridge->PMemAbove4GStart,
392 HostBridge->PMemAbove4GSize,
393 MAX_UINT64,
394 PMem
395 );
396 StickyError |= EFI_ERROR (Status);
397 }
398
399 if (StickyError) {
400 //
401 // If any function returned an error it is due to a valid range
402 // specified in the host bridge that was ignored due to a NULL
403 // pointer. Translate it to a warning to allow for calling with
404 // only a subset of the apertures.
405 //
406 return EFI_WARN_STALE_DATA;
407 }
408
409 return EFI_SUCCESS;
410}
411
414 IN CONST HOST_BRIDGE_INFO *HostBridge,
415 IN UINTN DataSize,
416 OUT UINT64 *Attributes OPTIONAL,
417 OUT BOOLEAN *DmaAbove4G OPTIONAL,
418 OUT BOOLEAN *NoExtendedConfigSpace OPTIONAL,
419 OUT BOOLEAN *CombineMemPMem OPTIONAL
420 )
421{
422 if ((HostBridge == NULL) || (DataSize == 0)) {
423 return EFI_INVALID_PARAMETER;
424 }
425
426 //
427 // For now only version 0 is supported
428 //
429 if (HostBridge->Version != 0) {
430 return EFI_INCOMPATIBLE_VERSION;
431 }
432
433 if (Attributes) {
434 *Attributes = HostBridge->Attributes;
435 }
436
437 if (DmaAbove4G) {
438 *DmaAbove4G = !!HostBridge->Flags.Bits.DmaAbove4G;
439 }
440
441 if (NoExtendedConfigSpace) {
442 *NoExtendedConfigSpace = !!HostBridge->Flags.Bits.NoExtendedConfigSpace;
443 }
444
445 if (CombineMemPMem) {
446 *CombineMemPMem = !!HostBridge->Flags.Bits.CombineMemPMem;
447 }
448
449 return EFI_SUCCESS;
450}
451
454 IN CONST HOST_BRIDGE_INFO *HostBridge,
455 IN UINTN DataSize,
456 OUT UINTN *BusNrStart,
457 OUT UINTN *BusNrLast,
458 OUT UINT64 *Attributes OPTIONAL,
459 OUT BOOLEAN *DmaAbove4G OPTIONAL,
460 OUT BOOLEAN *NoExtendedConfigSpace OPTIONAL,
461 OUT BOOLEAN *CombineMemPMem OPTIONAL,
462 OUT PCI_ROOT_BRIDGE_APERTURE *Io OPTIONAL,
463 OUT PCI_ROOT_BRIDGE_APERTURE *Mem OPTIONAL,
464 OUT PCI_ROOT_BRIDGE_APERTURE *MemAbove4G OPTIONAL,
465 OUT PCI_ROOT_BRIDGE_APERTURE *PMem OPTIONAL,
466 OUT PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G OPTIONAL,
467 OUT PCI_ROOT_BRIDGE_APERTURE *PcieConfig OPTIONAL
468 )
469{
470 EFI_STATUS Status;
471
473 HostBridge,
474 DataSize,
475 BusNrStart,
476 BusNrLast
477 );
478
479 if (EFI_ERROR (Status)) {
480 return Status;
481 }
482
484 HostBridge,
485 DataSize,
486 Attributes,
487 DmaAbove4G,
488 NoExtendedConfigSpace,
489 CombineMemPMem
490 );
491
492 if (EFI_ERROR (Status)) {
493 return Status;
494 }
495
497 HostBridge,
498 DataSize,
499 Io,
500 Mem,
501 MemAbove4G,
502 PMem,
503 PMemAbove4G,
504 PcieConfig
505 );
506
507 return Status;
508}
UINT64 UINTN
STATIC VOID UpdateLastAddressIfHigher(IN PCI_ROOT_BRIDGE_APERTURE *Mem, OUT UINT64 *LastAddress)
EFI_STATUS HardwareInfoPciHostBridgeLastMmioAddress(IN CONST HOST_BRIDGE_INFO *HostBridge, IN UINTN DataSize, IN BOOLEAN HighMem, OUT UINT64 *LastMmioAddress)
STATIC VOID InvalidateRootBridgeAperture(OUT PCI_ROOT_BRIDGE_APERTURE *Aperture)
STATIC UINT64 GetRangeEnd(IN UINT64 Start, IN UINT64 Size, IN UINT64 MaxValue)
STATIC EFI_STATUS FillHostBridgeAperture(IN UINT64 Start, IN UINT64 Size, IN UINT64 MaxValue, OUT PCI_ROOT_BRIDGE_APERTURE *Aperture)
EFI_STATUS HardwareInfoPciHostBridgeGetFlags(IN CONST HOST_BRIDGE_INFO *HostBridge, IN UINTN DataSize, OUT UINT64 *Attributes OPTIONAL, OUT BOOLEAN *DmaAbove4G OPTIONAL, OUT BOOLEAN *NoExtendedConfigSpace OPTIONAL, OUT BOOLEAN *CombineMemPMem OPTIONAL)
STATIC EFI_STATUS MergeHostBridgeApertures(IN UINT64 Start, IN UINT64 Size, IN UINT64 PStart, IN UINT64 PSize, IN UINT64 MaxValue, OUT PCI_ROOT_BRIDGE_APERTURE *Aperture)
EFI_STATUS HardwareInfoPciHostBridgeGet(IN CONST HOST_BRIDGE_INFO *HostBridge, IN UINTN DataSize, OUT UINTN *BusNrStart, OUT UINTN *BusNrLast, OUT UINT64 *Attributes OPTIONAL, OUT BOOLEAN *DmaAbove4G OPTIONAL, OUT BOOLEAN *NoExtendedConfigSpace OPTIONAL, OUT BOOLEAN *CombineMemPMem OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *Io OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *Mem OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *MemAbove4G OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *PMem OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G OPTIONAL, OUT PCI_ROOT_BRIDGE_APERTURE *PcieConfig OPTIONAL)
EFI_STATUS HardwareInfoPciHostBridgeGetApertures(IN CONST HOST_BRIDGE_INFO *HostBridge, IN UINTN DataSize, OUT PCI_ROOT_BRIDGE_APERTURE *Io, OUT PCI_ROOT_BRIDGE_APERTURE *Mem, OUT PCI_ROOT_BRIDGE_APERTURE *MemAbove4G, OUT PCI_ROOT_BRIDGE_APERTURE *PMem, OUT PCI_ROOT_BRIDGE_APERTURE *PMemAbove4G, OUT PCI_ROOT_BRIDGE_APERTURE *PcieConfig)
EFI_STATUS HardwareInfoPciHostBridgeGetBusNrRange(IN CONST HOST_BRIDGE_INFO *HostBridge, IN UINTN DataSize, OUT UINTN *BusNrStart, OUT UINTN *BusNrLast)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define STATIC
Definition: Base.h:264
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SUCCESS
Definition: UefiBaseType.h:112