3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
5 Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include "PciHostBridge.h"
11 #include "PciRootBridge.h"
12 #include "PciHostResource.h"
14 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
16 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mAcpiAddressSpaceTypeStr
[] = {
17 L
"Mem", L
"I/O", L
"Bus"
19 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mPciResourceTypeStr
[] = {
20 L
"I/O", L
"Mem", L
"PMem", L
"Mem64", L
"PMem64", L
"Bus"
23 EDKII_IOMMU_PROTOCOL
*mIoMmu
;
24 EFI_EVENT mIoMmuEvent
;
25 VOID
*mIoMmuRegistration
;
28 This routine gets translation offset from a root bridge instance by resource type.
30 @param RootBridge The Root Bridge Instance for the resources.
31 @param ResourceType The Resource Type of the translation offset.
33 @retval The Translation Offset of the specified resource.
36 GetTranslationByResourceType (
37 IN PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
,
38 IN PCI_RESOURCE_TYPE ResourceType
41 switch (ResourceType
) {
43 return RootBridge
->Io
.Translation
;
45 return RootBridge
->Mem
.Translation
;
47 return RootBridge
->PMem
.Translation
;
49 return RootBridge
->MemAbove4G
.Translation
;
51 return RootBridge
->PMemAbove4G
.Translation
;
53 return RootBridge
->Bus
.Translation
;
61 Ensure the compatibility of an IO space descriptor with the IO aperture.
63 The IO space descriptor can come from the GCD IO space map, or it can
64 represent a gap between two neighboring IO space descriptors. In the latter
65 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
67 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
68 taken -- it is by definition compatible with the aperture.
70 Otherwise, the intersection of the IO space descriptor is calculated with the
71 aperture. If the intersection is the empty set (no overlap), no action is
72 taken; the IO space descriptor is compatible with the aperture.
74 Otherwise, the type of the descriptor is investigated again. If the type is
75 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
76 such a type), then an attempt is made to add the intersection as IO space to
77 the GCD IO space map. This ensures continuity for the aperture, and the
78 descriptor is deemed compatible with the aperture.
80 Otherwise, the IO space descriptor is incompatible with the IO aperture.
82 @param[in] Base Base address of the aperture.
83 @param[in] Length Length of the aperture.
84 @param[in] Descriptor The descriptor to ensure compatibility with the
87 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space
88 map may have been updated, for continuity
90 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
91 @return Error codes from gDS->AddIoSpace().
94 IntersectIoDescriptor (
97 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
100 UINT64 IntersectionBase
;
101 UINT64 IntersectionEnd
;
104 if (Descriptor
->GcdIoType
== EfiGcdIoTypeIo
) {
108 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
109 IntersectionEnd
= MIN (
111 Descriptor
->BaseAddress
+ Descriptor
->Length
113 if (IntersectionBase
>= IntersectionEnd
) {
115 // The descriptor and the aperture don't overlap.
120 if (Descriptor
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
121 Status
= gDS
->AddIoSpace (
124 IntersectionEnd
- IntersectionBase
128 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
129 "%a: %a: add [%Lx, %Lx): %r\n",
141 "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
142 "aperture [%Lx, %Lx)\n",
145 Descriptor
->BaseAddress
,
146 Descriptor
->BaseAddress
+ Descriptor
->Length
,
147 (UINT32
)Descriptor
->GcdIoType
,
151 return EFI_INVALID_PARAMETER
;
156 The routine checks the GCD database and only adds those which are
157 not added in the specified range to GCD.
159 @param Base Base address of the IO space.
160 @param Length Length of the IO space.
162 @retval EFI_SUCCES The IO space was added successfully.
172 UINTN NumberOfDescriptors
;
173 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
175 Status
= gDS
->GetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
176 if (EFI_ERROR (Status
)) {
179 "%a: %a: GetIoSpaceMap(): %r\n",
187 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
188 Status
= IntersectIoDescriptor (Base
, Length
, &IoSpaceMap
[Index
]);
189 if (EFI_ERROR (Status
)) {
196 // Make sure there are adjacent descriptors covering [Base, Base + Length).
197 // It is possible that they have not been merged; merging can be prevented
201 EFI_STATUS CheckStatus
;
202 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor
;
204 for (CheckBase
= Base
;
205 CheckBase
< Base
+ Length
;
206 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
)
208 CheckStatus
= gDS
->GetIoSpaceDescriptor (CheckBase
, &Descriptor
);
209 ASSERT_EFI_ERROR (CheckStatus
);
210 ASSERT (Descriptor
.GcdIoType
== EfiGcdIoTypeIo
);
216 FreePool (IoSpaceMap
);
222 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
224 The memory space descriptor can come from the GCD memory space map, or it can
225 represent a gap between two neighboring memory space descriptors. In the
226 latter case, the GcdMemoryType field is expected to be
227 EfiGcdMemoryTypeNonExistent.
229 If the memory space descriptor already has type
230 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
231 required capabilities, then no action is taken -- it is by definition
232 compatible with the aperture.
234 Otherwise, the intersection of the memory space descriptor is calculated with
235 the aperture. If the intersection is the empty set (no overlap), no action is
236 taken; the memory space descriptor is compatible with the aperture.
238 Otherwise, the type of the descriptor is investigated again. If the type is
239 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
240 such a type), then an attempt is made to add the intersection as MMIO space
241 to the GCD memory space map, with the specified capabilities. This ensures
242 continuity for the aperture, and the descriptor is deemed compatible with the
245 Otherwise, the memory space descriptor is incompatible with the MMIO
248 @param[in] Base Base address of the aperture.
249 @param[in] Length Length of the aperture.
250 @param[in] Capabilities Capabilities required by the aperture.
251 @param[in] Descriptor The descriptor to ensure compatibility with the
254 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
255 space map may have been updated, for
256 continuity within the aperture.
257 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
258 @return Error codes from gDS->AddMemorySpace().
261 IntersectMemoryDescriptor (
264 IN UINT64 Capabilities
,
265 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
268 UINT64 IntersectionBase
;
269 UINT64 IntersectionEnd
;
272 if ((Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
) &&
273 ((Descriptor
->Capabilities
& Capabilities
) == Capabilities
))
278 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
279 IntersectionEnd
= MIN (
281 Descriptor
->BaseAddress
+ Descriptor
->Length
283 if (IntersectionBase
>= IntersectionEnd
) {
285 // The descriptor and the aperture don't overlap.
290 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
291 Status
= gDS
->AddMemorySpace (
292 EfiGcdMemoryTypeMemoryMappedIo
,
294 IntersectionEnd
- IntersectionBase
,
299 EFI_ERROR (Status
) ? DEBUG_ERROR
: DEBUG_VERBOSE
,
300 "%a: %a: add [%Lx, %Lx): %r\n",
312 "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
313 "with aperture [%Lx, %Lx) cap %Lx\n",
316 Descriptor
->BaseAddress
,
317 Descriptor
->BaseAddress
+ Descriptor
->Length
,
318 (UINT32
)Descriptor
->GcdMemoryType
,
319 Descriptor
->Capabilities
,
324 return EFI_INVALID_PARAMETER
;
328 Add MMIO space to GCD.
329 The routine checks the GCD database and only adds those which are
330 not added in the specified range to GCD.
332 @param Base Base address of the MMIO space.
333 @param Length Length of the MMIO space.
334 @param Capabilities Capabilities of the MMIO space.
336 @retval EFI_SUCCES The MMIO space was added successfully.
339 AddMemoryMappedIoSpace (
342 IN UINT64 Capabilities
347 UINTN NumberOfDescriptors
;
348 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
350 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
351 if (EFI_ERROR (Status
)) {
354 "%a: %a: GetMemorySpaceMap(): %r\n",
362 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
363 Status
= IntersectMemoryDescriptor (
367 &MemorySpaceMap
[Index
]
369 if (EFI_ERROR (Status
)) {
370 goto FreeMemorySpaceMap
;
376 // Make sure there are adjacent descriptors covering [Base, Base + Length).
377 // It is possible that they have not been merged; merging can be prevented
378 // by allocation and different capabilities.
381 EFI_STATUS CheckStatus
;
382 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
384 for (CheckBase
= Base
;
385 CheckBase
< Base
+ Length
;
386 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
)
388 CheckStatus
= gDS
->GetMemorySpaceDescriptor (CheckBase
, &Descriptor
);
389 ASSERT_EFI_ERROR (CheckStatus
);
390 ASSERT (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
);
391 ASSERT ((Descriptor
.Capabilities
& Capabilities
) == Capabilities
);
397 FreePool (MemorySpaceMap
);
403 Event notification that is fired when IOMMU protocol is installed.
405 @param Event The Event that is being processed.
406 @param Context Event Context.
411 IoMmuProtocolCallback (
418 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
, (VOID
**)&mIoMmu
);
419 if (!EFI_ERROR (Status
)) {
420 gBS
->CloseEvent (mIoMmuEvent
);
426 Entry point of this driver.
428 @param ImageHandle Image handle of this driver.
429 @param SystemTable Pointer to standard EFI system table.
431 @retval EFI_SUCCESS Succeed.
432 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
437 InitializePciHostBridge (
438 IN EFI_HANDLE ImageHandle
,
439 IN EFI_SYSTEM_TABLE
*SystemTable
443 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
444 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
445 PCI_ROOT_BRIDGE
*RootBridges
;
446 UINTN RootBridgeCount
;
448 PCI_ROOT_BRIDGE_APERTURE
*MemApertures
[4];
449 UINTN MemApertureIndex
;
450 BOOLEAN ResourceAssigned
;
454 RootBridges
= PciHostBridgeGetRootBridges (&RootBridgeCount
);
455 if ((RootBridges
== NULL
) || (RootBridgeCount
== 0)) {
456 return EFI_UNSUPPORTED
;
459 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**)&mCpuIo
);
460 ASSERT_EFI_ERROR (Status
);
463 // Most systems in the world including complex servers have only one Host Bridge.
465 HostBridge
= AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE
));
466 ASSERT (HostBridge
!= NULL
);
468 HostBridge
->Signature
= PCI_HOST_BRIDGE_SIGNATURE
;
469 HostBridge
->CanRestarted
= TRUE
;
470 InitializeListHead (&HostBridge
->RootBridges
);
471 ResourceAssigned
= FALSE
;
474 // Create Root Bridge Device Handle in this Host Bridge
476 for (Index
= 0; Index
< RootBridgeCount
; Index
++) {
478 // Create Root Bridge Handle Instance
480 RootBridge
= CreateRootBridge (&RootBridges
[Index
]);
481 ASSERT (RootBridge
!= NULL
);
482 if (RootBridge
== NULL
) {
487 // Make sure all root bridges share the same ResourceAssigned value.
490 ResourceAssigned
= RootBridges
[Index
].ResourceAssigned
;
492 ASSERT (ResourceAssigned
== RootBridges
[Index
].ResourceAssigned
);
495 if (RootBridges
[Index
].Io
.Base
<= RootBridges
[Index
].Io
.Limit
) {
497 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
498 // For GCD resource manipulation, we need to use host address.
500 HostAddress
= TO_HOST_ADDRESS (
501 RootBridges
[Index
].Io
.Base
,
502 RootBridges
[Index
].Io
.Translation
505 Status
= AddIoSpace (
507 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1
509 ASSERT_EFI_ERROR (Status
);
510 if (ResourceAssigned
) {
511 Status
= gDS
->AllocateIoSpace (
512 EfiGcdAllocateAddress
,
515 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1,
520 ASSERT_EFI_ERROR (Status
);
525 // Add all the Mem/PMem aperture to GCD
526 // Mem/PMem shouldn't overlap with each other
527 // Root bridge which needs to combine MEM and PMEM should only report
528 // the MEM aperture in Mem
530 MemApertures
[0] = &RootBridges
[Index
].Mem
;
531 MemApertures
[1] = &RootBridges
[Index
].MemAbove4G
;
532 MemApertures
[2] = &RootBridges
[Index
].PMem
;
533 MemApertures
[3] = &RootBridges
[Index
].PMemAbove4G
;
535 for (MemApertureIndex
= 0; MemApertureIndex
< ARRAY_SIZE (MemApertures
); MemApertureIndex
++) {
536 if (MemApertures
[MemApertureIndex
]->Base
<= MemApertures
[MemApertureIndex
]->Limit
) {
538 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
539 // For GCD resource manipulation, we need to use host address.
541 HostAddress
= TO_HOST_ADDRESS (
542 MemApertures
[MemApertureIndex
]->Base
,
543 MemApertures
[MemApertureIndex
]->Translation
545 Status
= AddMemoryMappedIoSpace (
547 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
550 ASSERT_EFI_ERROR (Status
);
551 Status
= gDS
->SetMemorySpaceAttributes (
553 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
556 if (EFI_ERROR (Status
)) {
557 DEBUG ((DEBUG_WARN
, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status
));
560 if (ResourceAssigned
) {
561 Status
= gDS
->AllocateMemorySpace (
562 EfiGcdAllocateAddress
,
563 EfiGcdMemoryTypeMemoryMappedIo
,
565 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
570 ASSERT_EFI_ERROR (Status
);
576 // Insert Root Bridge Handle Instance
578 InsertTailList (&HostBridge
->RootBridges
, &RootBridge
->Link
);
582 // When resources were assigned, it's not needed to expose
583 // PciHostBridgeResourceAllocation protocol.
585 if (!ResourceAssigned
) {
586 HostBridge
->ResAlloc
.NotifyPhase
= NotifyPhase
;
587 HostBridge
->ResAlloc
.GetNextRootBridge
= GetNextRootBridge
;
588 HostBridge
->ResAlloc
.GetAllocAttributes
= GetAttributes
;
589 HostBridge
->ResAlloc
.StartBusEnumeration
= StartBusEnumeration
;
590 HostBridge
->ResAlloc
.SetBusNumbers
= SetBusNumbers
;
591 HostBridge
->ResAlloc
.SubmitResources
= SubmitResources
;
592 HostBridge
->ResAlloc
.GetProposedResources
= GetProposedResources
;
593 HostBridge
->ResAlloc
.PreprocessController
= PreprocessController
;
595 Status
= gBS
->InstallMultipleProtocolInterfaces (
597 &gEfiPciHostBridgeResourceAllocationProtocolGuid
,
598 &HostBridge
->ResAlloc
,
601 ASSERT_EFI_ERROR (Status
);
604 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
605 ; !IsNull (&HostBridge
->RootBridges
, Link
)
606 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
609 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
610 RootBridge
->RootBridgeIo
.ParentHandle
= HostBridge
->Handle
;
612 Status
= gBS
->InstallMultipleProtocolInterfaces (
614 &gEfiDevicePathProtocolGuid
,
615 RootBridge
->DevicePath
,
616 &gEfiPciRootBridgeIoProtocolGuid
,
617 &RootBridge
->RootBridgeIo
,
620 ASSERT_EFI_ERROR (Status
);
623 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
625 if (!EFI_ERROR (Status
)) {
626 mIoMmuEvent
= EfiCreateProtocolNotifyEvent (
627 &gEdkiiIoMmuProtocolGuid
,
629 IoMmuProtocolCallback
,
639 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
641 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
645 IN PCI_HOST_BRIDGE_INSTANCE
*HostBridge
648 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
649 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
650 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
651 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
653 UINTN RootBridgeCount
;
654 PCI_RESOURCE_TYPE Index
;
655 PCI_RES_NODE
*ResAllocNode
;
658 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
659 ; !IsNull (&HostBridge
->RootBridges
, Link
)
660 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
666 Resources
= AllocatePool (
667 RootBridgeCount
* (TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)) +
668 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
670 ASSERT (Resources
!= NULL
);
672 for (Link
= GetFirstNode (&HostBridge
->RootBridges
), Descriptor
= Resources
673 ; !IsNull (&HostBridge
->RootBridges
, Link
)
674 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
677 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
678 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
679 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
681 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
682 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
683 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
684 Descriptor
->AddrRangeMax
= ResAllocNode
->Alignment
;
685 Descriptor
->AddrLen
= ResAllocNode
->Length
;
686 Descriptor
->SpecificFlag
= 0;
687 switch (ResAllocNode
->Type
) {
689 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
693 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
695 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
696 Descriptor
->AddrSpaceGranularity
= 32;
700 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
702 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
703 Descriptor
->AddrSpaceGranularity
= 64;
707 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
718 // Terminate the root bridge resources.
720 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)Descriptor
;
721 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
724 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)(End
+ 1);
728 // Terminate the host bridge resources.
730 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)Descriptor
;
731 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
734 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
735 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
736 FreePool (Resources
);
740 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
741 from GCD range [BaseAddress, Limit).
743 @param Mmio TRUE for MMIO and FALSE for IO.
744 @param Length Length of the resource to allocate.
745 @param BitsOfAlignment Alignment of the resource to allocate.
746 @param BaseAddress The starting address the allocation is from.
747 @param Limit The ending address the allocation is to.
749 @retval The base address of the allocated resource or MAX_UINT64 if allocation
756 UINTN BitsOfAlignment
,
763 if (BaseAddress
< Limit
) {
765 // Have to make sure Aligment is handled since we are doing direct address allocation
766 // Strictly speaking, alignment requirement should be applied to device
767 // address instead of host address which is used in GCD manipulation below,
768 // but as we restrict the alignment of Translation to be larger than any BAR
769 // alignment in the root bridge, we can simplify the situation and consider
770 // the same alignment requirement is also applied to host address.
772 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
774 while (BaseAddress
+ Length
<= Limit
+ 1) {
776 Status
= gDS
->AllocateMemorySpace (
777 EfiGcdAllocateAddress
,
778 EfiGcdMemoryTypeMemoryMappedIo
,
786 Status
= gDS
->AllocateIoSpace (
787 EfiGcdAllocateAddress
,
797 if (!EFI_ERROR (Status
)) {
801 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
810 Enter a certain phase of the PCI enumeration process.
812 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
813 @param Phase The phase during enumeration.
815 @retval EFI_SUCCESS Succeed.
816 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
817 @retval EFI_NOT_READY Resources have not been submitted yet.
823 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
824 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
827 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
828 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
830 EFI_PHYSICAL_ADDRESS BaseAddress
;
831 UINTN BitsOfAlignment
;
834 EFI_STATUS ReturnStatus
;
835 PCI_RESOURCE_TYPE Index
;
836 PCI_RESOURCE_TYPE Index1
;
837 PCI_RESOURCE_TYPE Index2
;
838 BOOLEAN ResNodeHandled
[TypeMax
];
842 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
845 case EfiPciHostBridgeBeginEnumeration
:
846 if (!HostBridge
->CanRestarted
) {
847 return EFI_NOT_READY
;
853 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
854 ; !IsNull (&HostBridge
->RootBridges
, Link
)
855 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
858 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
859 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
860 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
861 RootBridge
->ResAllocNode
[Index
].Base
= 0;
862 RootBridge
->ResAllocNode
[Index
].Length
= 0;
863 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
865 RootBridge
->ResourceSubmitted
= FALSE
;
869 HostBridge
->CanRestarted
= TRUE
;
872 case EfiPciHostBridgeBeginBusAllocation
:
874 // No specific action is required here, can perform any chipset specific programing
876 HostBridge
->CanRestarted
= FALSE
;
879 case EfiPciHostBridgeEndBusAllocation
:
881 // No specific action is required here, can perform any chipset specific programing
885 case EfiPciHostBridgeBeginResourceAllocation
:
887 // No specific action is required here, can perform any chipset specific programing
891 case EfiPciHostBridgeAllocateResources
:
892 ReturnStatus
= EFI_SUCCESS
;
895 // Make sure the resource for all root bridges has been submitted.
897 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
898 ; !IsNull (&HostBridge
->RootBridges
, Link
)
899 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
902 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
903 if (!RootBridge
->ResourceSubmitted
) {
904 return EFI_NOT_READY
;
908 DEBUG ((DEBUG_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
909 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
910 ; !IsNull (&HostBridge
->RootBridges
, Link
)
911 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
914 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
915 ResNodeHandled
[Index
] = FALSE
;
918 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
919 DEBUG ((DEBUG_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
921 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
922 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
923 ResNodeHandled
[Index1
] = TRUE
;
926 // Allocate the resource node with max alignment at first
930 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
931 if (ResNodeHandled
[Index2
]) {
935 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
936 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
941 ASSERT (Index
< TypeMax
);
942 ResNodeHandled
[Index
] = TRUE
;
943 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
944 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
945 BaseAddress
= MAX_UINT64
;
948 // RESTRICTION: To simplify the situation, we require the alignment of
949 // Translation must be larger than any BAR alignment in the same root
950 // bridge, so that resource allocation alignment can be applied to
951 // both device address and host address.
953 Translation
= GetTranslationByResourceType (RootBridge
, Index
);
954 if ((Translation
& Alignment
) != 0) {
957 "[%a:%d] Translation %lx is not aligned to %lx!\n",
963 ASSERT ((Translation
& Alignment
) == 0);
965 // This may be caused by too large alignment or too small
966 // Translation; pick the 1st possibility and return out of resource,
967 // which can also go thru the same process for out of resource
970 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
977 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
978 // For AllocateResource is manipulating GCD resource, we need to use
979 // host address here.
981 BaseAddress
= AllocateResource (
983 RootBridge
->ResAllocNode
[Index
].Length
,
984 MIN (15, BitsOfAlignment
),
986 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
987 RootBridge
->Io
.Translation
990 RootBridge
->Io
.Limit
,
991 RootBridge
->Io
.Translation
997 BaseAddress
= AllocateResource (
999 RootBridge
->ResAllocNode
[Index
].Length
,
1000 MIN (63, BitsOfAlignment
),
1002 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
1003 RootBridge
->MemAbove4G
.Translation
1006 RootBridge
->MemAbove4G
.Limit
,
1007 RootBridge
->MemAbove4G
.Translation
1010 if (BaseAddress
!= MAX_UINT64
) {
1015 // If memory above 4GB is not available, try memory below 4GB
1019 BaseAddress
= AllocateResource (
1021 RootBridge
->ResAllocNode
[Index
].Length
,
1022 MIN (31, BitsOfAlignment
),
1024 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
1025 RootBridge
->Mem
.Translation
1028 RootBridge
->Mem
.Limit
,
1029 RootBridge
->Mem
.Translation
1035 BaseAddress
= AllocateResource (
1037 RootBridge
->ResAllocNode
[Index
].Length
,
1038 MIN (63, BitsOfAlignment
),
1040 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
1041 RootBridge
->PMemAbove4G
.Translation
1044 RootBridge
->PMemAbove4G
.Limit
,
1045 RootBridge
->PMemAbove4G
.Translation
1048 if (BaseAddress
!= MAX_UINT64
) {
1053 // If memory above 4GB is not available, try memory below 4GB
1056 BaseAddress
= AllocateResource (
1058 RootBridge
->ResAllocNode
[Index
].Length
,
1059 MIN (31, BitsOfAlignment
),
1061 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
1062 RootBridge
->PMem
.Translation
1065 RootBridge
->PMem
.Limit
,
1066 RootBridge
->PMem
.Translation
1078 " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
1079 mPciResourceTypeStr
[Index
],
1081 RootBridge
->ResAllocNode
[Index
].Length
,
1084 if (BaseAddress
!= MAX_UINT64
) {
1085 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
1086 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
1087 DEBUG ((DEBUG_INFO
, "Success\n"));
1089 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
1090 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
1096 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
1097 ResourceConflict (HostBridge
);
1101 // Set resource to zero for nodes where allocation fails
1103 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1104 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1105 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1108 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1109 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
1110 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
1111 RootBridge
->ResAllocNode
[Index
].Length
= 0;
1116 return ReturnStatus
;
1118 case EfiPciHostBridgeSetResources
:
1120 // HostBridgeInstance->CanRestarted = FALSE;
1124 case EfiPciHostBridgeFreeResources
:
1126 // HostBridgeInstance->CanRestarted = FALSE;
1128 ReturnStatus
= EFI_SUCCESS
;
1129 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1130 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1131 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1134 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1135 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
1136 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
1139 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
1140 if (EFI_ERROR (Status
)) {
1141 ReturnStatus
= Status
;
1150 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
1151 if (EFI_ERROR (Status
)) {
1152 ReturnStatus
= Status
;
1162 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
1163 RootBridge
->ResAllocNode
[Index
].Base
= 0;
1164 RootBridge
->ResAllocNode
[Index
].Length
= 0;
1165 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
1169 RootBridge
->ResourceSubmitted
= FALSE
;
1172 HostBridge
->CanRestarted
= TRUE
;
1173 return ReturnStatus
;
1175 case EfiPciHostBridgeEndResourceAllocation
:
1177 // The resource allocation phase is completed. No specific action is required
1178 // here. This notification can be used to perform any chipset specific programming.
1182 case EfiPciHostBridgeEndEnumeration
:
1184 // The Host Bridge Enumeration is completed. No specific action is required here.
1185 // This notification can be used to perform any chipset specific programming.
1190 return EFI_INVALID_PARAMETER
;
1198 Return the device handle of the next PCI root bridge that is associated with
1201 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1202 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
1203 On input, it holds the RootBridgeHandle returned by the most
1204 recent call to GetNextRootBridge().The handle for the first
1205 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
1207 @retval EFI_SUCCESS Succeed.
1208 @retval EFI_NOT_FOUND Next PCI root bridge not found.
1209 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
1215 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1216 IN OUT EFI_HANDLE
*RootBridgeHandle
1221 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1222 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1224 if (RootBridgeHandle
== NULL
) {
1225 return EFI_INVALID_PARAMETER
;
1228 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1229 ReturnNext
= (BOOLEAN
)(*RootBridgeHandle
== NULL
);
1231 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1232 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1233 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1236 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1238 *RootBridgeHandle
= RootBridge
->Handle
;
1242 ReturnNext
= (BOOLEAN
)(*RootBridgeHandle
== RootBridge
->Handle
);
1246 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
1247 return EFI_NOT_FOUND
;
1249 return EFI_INVALID_PARAMETER
;
1255 Returns the attributes of a PCI Root Bridge.
1257 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1258 @param RootBridgeHandle The device handle of the PCI Root Bridge
1259 that the caller is interested in.
1260 @param Attributes The pointer to attributes of the PCI Root Bridge.
1262 @retval EFI_SUCCESS Succeed.
1263 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1264 RootBridgeHandle is not an EFI_HANDLE
1265 that was returned on a previous call to
1266 GetNextRootBridge().
1272 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1273 IN EFI_HANDLE RootBridgeHandle
,
1274 OUT UINT64
*Attributes
1278 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1279 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1281 if (Attributes
== NULL
) {
1282 return EFI_INVALID_PARAMETER
;
1285 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1286 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1287 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1288 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1291 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1292 if (RootBridgeHandle
== RootBridge
->Handle
) {
1293 *Attributes
= RootBridge
->AllocationAttributes
;
1298 return EFI_INVALID_PARAMETER
;
1303 This is the request from the PCI enumerator to set up
1304 the specified PCI Root Bridge for bus enumeration process.
1306 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1307 @param RootBridgeHandle The PCI Root Bridge to be set up.
1308 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1310 @retval EFI_SUCCESS Succeed.
1311 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1312 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1317 StartBusEnumeration (
1318 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1319 IN EFI_HANDLE RootBridgeHandle
,
1320 OUT VOID
**Configuration
1324 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1325 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1326 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1327 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1329 if (Configuration
== NULL
) {
1330 return EFI_INVALID_PARAMETER
;
1333 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1334 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1335 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1336 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1339 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1340 if (RootBridgeHandle
== RootBridge
->Handle
) {
1341 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1342 if (*Configuration
== NULL
) {
1343 return EFI_OUT_OF_RESOURCES
;
1346 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)*Configuration
;
1347 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1348 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1349 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1350 Descriptor
->GenFlag
= 0;
1351 Descriptor
->SpecificFlag
= 0;
1352 Descriptor
->AddrSpaceGranularity
= 0;
1353 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
1354 Descriptor
->AddrRangeMax
= 0;
1355 Descriptor
->AddrTranslationOffset
= 0;
1356 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
1358 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Descriptor
+ 1);
1359 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1360 End
->Checksum
= 0x0;
1366 return EFI_INVALID_PARAMETER
;
1371 This function programs the PCI Root Bridge hardware so that
1372 it decodes the specified PCI bus range.
1374 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1375 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1376 @param Configuration The pointer to the PCI bus resource descriptor.
1378 @retval EFI_SUCCESS Succeed.
1379 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1385 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1386 IN EFI_HANDLE RootBridgeHandle
,
1387 IN VOID
*Configuration
1391 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1392 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1393 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1394 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1396 if (Configuration
== NULL
) {
1397 return EFI_INVALID_PARAMETER
;
1400 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Configuration
;
1401 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)(Descriptor
+ 1);
1404 // Check the Configuration is valid
1406 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
1407 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
1408 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
1411 return EFI_INVALID_PARAMETER
;
1414 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1415 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1416 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1417 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1420 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1421 if (RootBridgeHandle
== RootBridge
->Handle
) {
1422 if (Descriptor
->AddrLen
== 0) {
1423 return EFI_INVALID_PARAMETER
;
1426 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
1427 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
1430 return EFI_INVALID_PARAMETER
;
1434 // Update the Bus Range
1436 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
1437 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
1438 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
1443 return EFI_INVALID_PARAMETER
;
1448 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1450 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1451 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1452 are being submitted.
1453 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1455 @retval EFI_SUCCESS Succeed.
1456 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1461 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1462 IN EFI_HANDLE RootBridgeHandle
,
1463 IN VOID
*Configuration
1467 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1468 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1469 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1470 PCI_RESOURCE_TYPE Type
;
1473 // Check the input parameter: Configuration
1475 if (Configuration
== NULL
) {
1476 return EFI_INVALID_PARAMETER
;
1479 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1480 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1481 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1482 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1485 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1486 if (RootBridgeHandle
== RootBridge
->Handle
) {
1487 DEBUG ((DEBUG_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
1489 // Check the resource descriptors.
1490 // If the Configuration includes one or more invalid resource descriptors, all the resource
1491 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1493 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1494 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1495 return EFI_INVALID_PARAMETER
;
1500 " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1501 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
],
1502 Descriptor
->AddrSpaceGranularity
,
1503 Descriptor
->SpecificFlag
,
1504 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
1506 DEBUG ((DEBUG_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
1507 switch (Descriptor
->ResType
) {
1508 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1509 if ((Descriptor
->AddrSpaceGranularity
!= 32) && (Descriptor
->AddrSpaceGranularity
!= 64)) {
1510 return EFI_INVALID_PARAMETER
;
1513 if ((Descriptor
->AddrSpaceGranularity
== 32) && (Descriptor
->AddrLen
>= SIZE_4GB
)) {
1514 return EFI_INVALID_PARAMETER
;
1518 // If the PCI root bridge does not support separate windows for nonprefetchable and
1519 // prefetchable memory, then the PCI bus driver needs to include requests for
1520 // prefetchable memory in the nonprefetchable memory pool.
1522 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
1523 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
1526 return EFI_INVALID_PARAMETER
;
1529 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1531 // Check aligment, it should be of the form 2^n-1
1533 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
1534 return EFI_INVALID_PARAMETER
;
1544 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1545 return EFI_INVALID_PARAMETER
;
1548 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1549 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1550 if (Descriptor
->AddrSpaceGranularity
== 32) {
1551 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1557 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
1558 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1565 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
1569 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
1570 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
1571 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
1574 RootBridge
->ResourceSubmitted
= TRUE
;
1579 return EFI_INVALID_PARAMETER
;
1584 This function returns the proposed resource settings for the specified
1587 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1588 @param RootBridgeHandle The PCI Root Bridge handle.
1589 @param Configuration The pointer to the pointer to the PCI I/O
1590 and memory resource descriptor.
1592 @retval EFI_SUCCESS Succeed.
1593 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1594 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1599 GetProposedResources (
1600 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1601 IN EFI_HANDLE RootBridgeHandle
,
1602 OUT VOID
**Configuration
1606 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1607 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1611 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1612 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1615 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1616 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1617 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1618 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1621 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1622 if (RootBridgeHandle
== RootBridge
->Handle
) {
1623 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1624 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1629 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1630 if (Buffer
== NULL
) {
1631 return EFI_OUT_OF_RESOURCES
;
1634 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*)Buffer
;
1635 for (Index
= 0; Index
< TypeBus
; Index
++) {
1636 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1637 if (ResStatus
!= ResNone
) {
1638 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1639 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1640 Descriptor
->GenFlag
= 0;
1642 // AddrRangeMin in Resource Descriptor here should be device address
1643 // instead of host address, or else PCI bus driver cannot set correct
1644 // address into PCI BAR registers.
1645 // Base in ResAllocNode is a host address, so conversion is needed.
1647 Descriptor
->AddrRangeMin
= TO_DEVICE_ADDRESS (
1648 RootBridge
->ResAllocNode
[Index
].Base
,
1649 GetTranslationByResourceType (RootBridge
, Index
)
1651 Descriptor
->AddrRangeMax
= 0;
1652 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1653 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1657 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1661 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1663 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1664 Descriptor
->AddrSpaceGranularity
= 32;
1668 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1670 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1671 Descriptor
->AddrSpaceGranularity
= 64;
1679 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*)Descriptor
;
1680 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1683 *Configuration
= Buffer
;
1689 return EFI_INVALID_PARAMETER
;
1694 This function is called for all the PCI controllers that the PCI
1695 bus driver finds. Can be used to Preprogram the controller.
1697 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1698 @param RootBridgeHandle The PCI Root Bridge handle.
1699 @param PciAddress Address of the controller on the PCI bus.
1700 @param Phase The Phase during resource allocation.
1702 @retval EFI_SUCCESS Succeed.
1703 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1708 PreprocessController (
1709 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1710 IN EFI_HANDLE RootBridgeHandle
,
1711 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1712 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1716 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1717 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1719 if ((UINT32
)Phase
> EfiPciBeforeResourceCollection
) {
1720 return EFI_INVALID_PARAMETER
;
1723 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1724 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1725 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1726 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1729 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1730 if (RootBridgeHandle
== RootBridge
->Handle
) {
1735 return EFI_INVALID_PARAMETER
;