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 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "PciHostBridge.h"
17 #include "PciRootBridge.h"
18 #include "PciHostResource.h"
20 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
22 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mAcpiAddressSpaceTypeStr
[] = {
23 L
"Mem", L
"I/O", L
"Bus"
25 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mPciResourceTypeStr
[] = {
26 L
"I/O", L
"Mem", L
"PMem", L
"Mem64", L
"PMem64", L
"Bus"
29 EDKII_IOMMU_PROTOCOL
*mIoMmuProtocol
;
30 EFI_EVENT mIoMmuEvent
;
31 VOID
*mIoMmuRegistration
;
34 This routine gets translation offset from a root bridge instance by resource type.
36 @param RootBridge The Root Bridge Instance for the resources.
37 @param ResourceType The Resource Type of the translation offset.
39 @retval The Translation Offset of the specified resource.
42 GetTranslationByResourceType (
43 IN PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
,
44 IN PCI_RESOURCE_TYPE ResourceType
47 switch (ResourceType
) {
49 return RootBridge
->Io
.Translation
;
51 return RootBridge
->Mem
.Translation
;
53 return RootBridge
->PMem
.Translation
;
55 return RootBridge
->MemAbove4G
.Translation
;
57 return RootBridge
->PMemAbove4G
.Translation
;
59 return RootBridge
->Bus
.Translation
;
67 Ensure the compatibility of an IO space descriptor with the IO aperture.
69 The IO space descriptor can come from the GCD IO space map, or it can
70 represent a gap between two neighboring IO space descriptors. In the latter
71 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
73 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
74 taken -- it is by definition compatible with the aperture.
76 Otherwise, the intersection of the IO space descriptor is calculated with the
77 aperture. If the intersection is the empty set (no overlap), no action is
78 taken; the IO space descriptor is compatible with the aperture.
80 Otherwise, the type of the descriptor is investigated again. If the type is
81 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
82 such a type), then an attempt is made to add the intersection as IO space to
83 the GCD IO space map. This ensures continuity for the aperture, and the
84 descriptor is deemed compatible with the aperture.
86 Otherwise, the IO space descriptor is incompatible with the IO aperture.
88 @param[in] Base Base address of the aperture.
89 @param[in] Length Length of the aperture.
90 @param[in] Descriptor The descriptor to ensure compatibility with the
93 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space
94 map may have been updated, for continuity
96 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
97 @return Error codes from gDS->AddIoSpace().
100 IntersectIoDescriptor (
103 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
106 UINT64 IntersectionBase
;
107 UINT64 IntersectionEnd
;
110 if (Descriptor
->GcdIoType
== EfiGcdIoTypeIo
) {
114 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
115 IntersectionEnd
= MIN (Base
+ Length
,
116 Descriptor
->BaseAddress
+ Descriptor
->Length
);
117 if (IntersectionBase
>= IntersectionEnd
) {
119 // The descriptor and the aperture don't overlap.
124 if (Descriptor
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
125 Status
= gDS
->AddIoSpace (EfiGcdIoTypeIo
, IntersectionBase
,
126 IntersectionEnd
- IntersectionBase
);
128 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
129 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
130 IntersectionBase
, IntersectionEnd
, Status
));
134 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
135 "aperture [%Lx, %Lx)\n", gEfiCallerBaseName
, __FUNCTION__
,
136 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
137 (UINT32
)Descriptor
->GcdIoType
, Base
, Base
+ Length
));
138 return EFI_INVALID_PARAMETER
;
143 The routine checks the GCD database and only adds those which are
144 not added in the specified range to GCD.
146 @param Base Base address of the IO space.
147 @param Length Length of the IO space.
149 @retval EFI_SUCCES The IO space was added successfully.
159 UINTN NumberOfDescriptors
;
160 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
162 Status
= gDS
->GetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
163 if (EFI_ERROR (Status
)) {
164 DEBUG ((EFI_D_ERROR
, "%a: %a: GetIoSpaceMap(): %r\n",
165 gEfiCallerBaseName
, __FUNCTION__
, Status
));
169 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
170 Status
= IntersectIoDescriptor (Base
, Length
, &IoSpaceMap
[Index
]);
171 if (EFI_ERROR (Status
)) {
178 // Make sure there are adjacent descriptors covering [Base, Base + Length).
179 // It is possible that they have not been merged; merging can be prevented
183 EFI_STATUS CheckStatus
;
184 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor
;
186 for (CheckBase
= Base
;
187 CheckBase
< Base
+ Length
;
188 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
189 CheckStatus
= gDS
->GetIoSpaceDescriptor (CheckBase
, &Descriptor
);
190 ASSERT_EFI_ERROR (CheckStatus
);
191 ASSERT (Descriptor
.GcdIoType
== EfiGcdIoTypeIo
);
196 FreePool (IoSpaceMap
);
202 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
204 The memory space descriptor can come from the GCD memory space map, or it can
205 represent a gap between two neighboring memory space descriptors. In the
206 latter case, the GcdMemoryType field is expected to be
207 EfiGcdMemoryTypeNonExistent.
209 If the memory space descriptor already has type
210 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
211 required capabilities, then no action is taken -- it is by definition
212 compatible with the aperture.
214 Otherwise, the intersection of the memory space descriptor is calculated with
215 the aperture. If the intersection is the empty set (no overlap), no action is
216 taken; the memory space descriptor is compatible with the aperture.
218 Otherwise, the type of the descriptor is investigated again. If the type is
219 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
220 such a type), then an attempt is made to add the intersection as MMIO space
221 to the GCD memory space map, with the specified capabilities. This ensures
222 continuity for the aperture, and the descriptor is deemed compatible with the
225 Otherwise, the memory space descriptor is incompatible with the MMIO
228 @param[in] Base Base address of the aperture.
229 @param[in] Length Length of the aperture.
230 @param[in] Capabilities Capabilities required by the aperture.
231 @param[in] Descriptor The descriptor to ensure compatibility with the
234 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
235 space map may have been updated, for
236 continuity within the aperture.
237 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
238 @return Error codes from gDS->AddMemorySpace().
241 IntersectMemoryDescriptor (
244 IN UINT64 Capabilities
,
245 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
248 UINT64 IntersectionBase
;
249 UINT64 IntersectionEnd
;
252 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
&&
253 (Descriptor
->Capabilities
& Capabilities
) == Capabilities
) {
257 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
258 IntersectionEnd
= MIN (Base
+ Length
,
259 Descriptor
->BaseAddress
+ Descriptor
->Length
);
260 if (IntersectionBase
>= IntersectionEnd
) {
262 // The descriptor and the aperture don't overlap.
267 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
268 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo
,
269 IntersectionBase
, IntersectionEnd
- IntersectionBase
,
272 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
273 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
274 IntersectionBase
, IntersectionEnd
, Status
));
278 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
279 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName
, __FUNCTION__
,
280 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
281 (UINT32
)Descriptor
->GcdMemoryType
, Descriptor
->Capabilities
,
282 Base
, Base
+ Length
, Capabilities
));
283 return EFI_INVALID_PARAMETER
;
287 Add MMIO space to GCD.
288 The routine checks the GCD database and only adds those which are
289 not added in the specified range to GCD.
291 @param Base Base address of the MMIO space.
292 @param Length Length of the MMIO space.
293 @param Capabilities Capabilities of the MMIO space.
295 @retval EFI_SUCCES The MMIO space was added successfully.
298 AddMemoryMappedIoSpace (
301 IN UINT64 Capabilities
306 UINTN NumberOfDescriptors
;
307 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
309 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
310 if (EFI_ERROR (Status
)) {
311 DEBUG ((EFI_D_ERROR
, "%a: %a: GetMemorySpaceMap(): %r\n",
312 gEfiCallerBaseName
, __FUNCTION__
, Status
));
316 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
317 Status
= IntersectMemoryDescriptor (Base
, Length
, Capabilities
,
318 &MemorySpaceMap
[Index
]);
319 if (EFI_ERROR (Status
)) {
320 goto FreeMemorySpaceMap
;
326 // Make sure there are adjacent descriptors covering [Base, Base + Length).
327 // It is possible that they have not been merged; merging can be prevented
328 // by allocation and different capabilities.
331 EFI_STATUS CheckStatus
;
332 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
334 for (CheckBase
= Base
;
335 CheckBase
< Base
+ Length
;
336 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
337 CheckStatus
= gDS
->GetMemorySpaceDescriptor (CheckBase
, &Descriptor
);
338 ASSERT_EFI_ERROR (CheckStatus
);
339 ASSERT (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
);
340 ASSERT ((Descriptor
.Capabilities
& Capabilities
) == Capabilities
);
345 FreePool (MemorySpaceMap
);
351 Event notification that is fired when IOMMU protocol is installed.
353 @param Event The Event that is being processed.
354 @param Context Event Context.
359 IoMmuProtocolCallback (
366 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
, (VOID
**)&mIoMmuProtocol
);
367 if (!EFI_ERROR(Status
)) {
368 gBS
->CloseEvent (mIoMmuEvent
);
374 Entry point of this driver.
376 @param ImageHandle Image handle of this driver.
377 @param SystemTable Pointer to standard EFI system table.
379 @retval EFI_SUCCESS Succeed.
380 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
385 InitializePciHostBridge (
386 IN EFI_HANDLE ImageHandle
,
387 IN EFI_SYSTEM_TABLE
*SystemTable
391 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
392 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
393 PCI_ROOT_BRIDGE
*RootBridges
;
394 UINTN RootBridgeCount
;
396 PCI_ROOT_BRIDGE_APERTURE
*MemApertures
[4];
397 UINTN MemApertureIndex
;
398 BOOLEAN ResourceAssigned
;
402 RootBridges
= PciHostBridgeGetRootBridges (&RootBridgeCount
);
403 if ((RootBridges
== NULL
) || (RootBridgeCount
== 0)) {
404 return EFI_UNSUPPORTED
;
407 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**) &mCpuIo
);
408 ASSERT_EFI_ERROR (Status
);
411 // Most systems in the world including complex servers have only one Host Bridge.
413 HostBridge
= AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE
));
414 ASSERT (HostBridge
!= NULL
);
416 HostBridge
->Signature
= PCI_HOST_BRIDGE_SIGNATURE
;
417 HostBridge
->CanRestarted
= TRUE
;
418 InitializeListHead (&HostBridge
->RootBridges
);
419 ResourceAssigned
= FALSE
;
422 // Create Root Bridge Device Handle in this Host Bridge
424 for (Index
= 0; Index
< RootBridgeCount
; Index
++) {
426 // Create Root Bridge Handle Instance
428 RootBridge
= CreateRootBridge (&RootBridges
[Index
]);
429 ASSERT (RootBridge
!= NULL
);
430 if (RootBridge
== NULL
) {
435 // Make sure all root bridges share the same ResourceAssigned value.
438 ResourceAssigned
= RootBridges
[Index
].ResourceAssigned
;
440 ASSERT (ResourceAssigned
== RootBridges
[Index
].ResourceAssigned
);
443 if (RootBridges
[Index
].Io
.Base
<= RootBridges
[Index
].Io
.Limit
) {
445 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
446 // For GCD resource manipulation, we need to use host address.
448 HostAddress
= TO_HOST_ADDRESS (RootBridges
[Index
].Io
.Base
,
449 RootBridges
[Index
].Io
.Translation
);
451 Status
= AddIoSpace (
453 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1
455 ASSERT_EFI_ERROR (Status
);
456 if (ResourceAssigned
) {
457 Status
= gDS
->AllocateIoSpace (
458 EfiGcdAllocateAddress
,
461 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1,
466 ASSERT_EFI_ERROR (Status
);
471 // Add all the Mem/PMem aperture to GCD
472 // Mem/PMem shouldn't overlap with each other
473 // Root bridge which needs to combine MEM and PMEM should only report
474 // the MEM aperture in Mem
476 MemApertures
[0] = &RootBridges
[Index
].Mem
;
477 MemApertures
[1] = &RootBridges
[Index
].MemAbove4G
;
478 MemApertures
[2] = &RootBridges
[Index
].PMem
;
479 MemApertures
[3] = &RootBridges
[Index
].PMemAbove4G
;
481 for (MemApertureIndex
= 0; MemApertureIndex
< ARRAY_SIZE (MemApertures
); MemApertureIndex
++) {
482 if (MemApertures
[MemApertureIndex
]->Base
<= MemApertures
[MemApertureIndex
]->Limit
) {
484 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
485 // For GCD resource manipulation, we need to use host address.
487 HostAddress
= TO_HOST_ADDRESS (MemApertures
[MemApertureIndex
]->Base
,
488 MemApertures
[MemApertureIndex
]->Translation
);
489 Status
= AddMemoryMappedIoSpace (
491 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
494 ASSERT_EFI_ERROR (Status
);
495 Status
= gDS
->SetMemorySpaceAttributes (
497 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
500 if (EFI_ERROR (Status
)) {
501 DEBUG ((DEBUG_WARN
, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status
));
503 if (ResourceAssigned
) {
504 Status
= gDS
->AllocateMemorySpace (
505 EfiGcdAllocateAddress
,
506 EfiGcdMemoryTypeMemoryMappedIo
,
508 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
513 ASSERT_EFI_ERROR (Status
);
518 // Insert Root Bridge Handle Instance
520 InsertTailList (&HostBridge
->RootBridges
, &RootBridge
->Link
);
524 // When resources were assigned, it's not needed to expose
525 // PciHostBridgeResourceAllocation protocol.
527 if (!ResourceAssigned
) {
528 HostBridge
->ResAlloc
.NotifyPhase
= NotifyPhase
;
529 HostBridge
->ResAlloc
.GetNextRootBridge
= GetNextRootBridge
;
530 HostBridge
->ResAlloc
.GetAllocAttributes
= GetAttributes
;
531 HostBridge
->ResAlloc
.StartBusEnumeration
= StartBusEnumeration
;
532 HostBridge
->ResAlloc
.SetBusNumbers
= SetBusNumbers
;
533 HostBridge
->ResAlloc
.SubmitResources
= SubmitResources
;
534 HostBridge
->ResAlloc
.GetProposedResources
= GetProposedResources
;
535 HostBridge
->ResAlloc
.PreprocessController
= PreprocessController
;
537 Status
= gBS
->InstallMultipleProtocolInterfaces (
539 &gEfiPciHostBridgeResourceAllocationProtocolGuid
, &HostBridge
->ResAlloc
,
542 ASSERT_EFI_ERROR (Status
);
545 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
546 ; !IsNull (&HostBridge
->RootBridges
, Link
)
547 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
549 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
550 RootBridge
->RootBridgeIo
.ParentHandle
= HostBridge
->Handle
;
552 Status
= gBS
->InstallMultipleProtocolInterfaces (
554 &gEfiDevicePathProtocolGuid
, RootBridge
->DevicePath
,
555 &gEfiPciRootBridgeIoProtocolGuid
, &RootBridge
->RootBridgeIo
,
558 ASSERT_EFI_ERROR (Status
);
560 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
562 if (!EFI_ERROR (Status
)) {
563 mIoMmuEvent
= EfiCreateProtocolNotifyEvent (
564 &gEdkiiIoMmuProtocolGuid
,
566 IoMmuProtocolCallback
,
576 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
578 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
582 IN PCI_HOST_BRIDGE_INSTANCE
*HostBridge
585 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
586 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
587 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
588 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
590 UINTN RootBridgeCount
;
591 PCI_RESOURCE_TYPE Index
;
592 PCI_RES_NODE
*ResAllocNode
;
595 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
596 ; !IsNull (&HostBridge
->RootBridges
, Link
)
597 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
602 Resources
= AllocatePool (
603 RootBridgeCount
* (TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)) +
604 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
606 ASSERT (Resources
!= NULL
);
608 for (Link
= GetFirstNode (&HostBridge
->RootBridges
), Descriptor
= Resources
609 ; !IsNull (&HostBridge
->RootBridges
, Link
)
610 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
612 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
613 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
614 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
616 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
617 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
618 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
619 Descriptor
->AddrRangeMax
= ResAllocNode
->Alignment
;
620 Descriptor
->AddrLen
= ResAllocNode
->Length
;
621 Descriptor
->SpecificFlag
= 0;
622 switch (ResAllocNode
->Type
) {
625 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
629 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
631 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
632 Descriptor
->AddrSpaceGranularity
= 32;
636 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
638 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
639 Descriptor
->AddrSpaceGranularity
= 64;
643 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
653 // Terminate the root bridge resources.
655 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
656 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
659 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (End
+ 1);
662 // Terminate the host bridge resources.
664 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
665 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
668 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
669 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
670 FreePool (Resources
);
674 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
675 from GCD range [BaseAddress, Limit).
677 @param Mmio TRUE for MMIO and FALSE for IO.
678 @param Length Length of the resource to allocate.
679 @param BitsOfAlignment Alignment of the resource to allocate.
680 @param BaseAddress The starting address the allocation is from.
681 @param Limit The ending address the allocation is to.
683 @retval The base address of the allocated resource or MAX_UINT64 if allocation
690 UINTN BitsOfAlignment
,
697 if (BaseAddress
< Limit
) {
699 // Have to make sure Aligment is handled since we are doing direct address allocation
700 // Strictly speaking, alignment requirement should be applied to device
701 // address instead of host address which is used in GCD manipulation below,
702 // but as we restrict the alignment of Translation to be larger than any BAR
703 // alignment in the root bridge, we can simplify the situation and consider
704 // the same alignment requirement is also applied to host address.
706 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
708 while (BaseAddress
+ Length
<= Limit
+ 1) {
710 Status
= gDS
->AllocateMemorySpace (
711 EfiGcdAllocateAddress
,
712 EfiGcdMemoryTypeMemoryMappedIo
,
720 Status
= gDS
->AllocateIoSpace (
721 EfiGcdAllocateAddress
,
731 if (!EFI_ERROR (Status
)) {
734 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
742 Enter a certain phase of the PCI enumeration process.
744 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
745 @param Phase The phase during enumeration.
747 @retval EFI_SUCCESS Succeed.
748 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
749 @retval EFI_NOT_READY Resources have not been submitted yet.
755 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
756 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
759 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
760 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
762 EFI_PHYSICAL_ADDRESS BaseAddress
;
763 UINTN BitsOfAlignment
;
766 EFI_STATUS ReturnStatus
;
767 PCI_RESOURCE_TYPE Index
;
768 PCI_RESOURCE_TYPE Index1
;
769 PCI_RESOURCE_TYPE Index2
;
770 BOOLEAN ResNodeHandled
[TypeMax
];
774 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
777 case EfiPciHostBridgeBeginEnumeration
:
778 if (!HostBridge
->CanRestarted
) {
779 return EFI_NOT_READY
;
784 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
785 ; !IsNull (&HostBridge
->RootBridges
, Link
)
786 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
788 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
789 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
790 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
791 RootBridge
->ResAllocNode
[Index
].Base
= 0;
792 RootBridge
->ResAllocNode
[Index
].Length
= 0;
793 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
795 RootBridge
->ResourceSubmitted
= FALSE
;
799 HostBridge
->CanRestarted
= TRUE
;
802 case EfiPciHostBridgeBeginBusAllocation
:
804 // No specific action is required here, can perform any chipset specific programing
806 HostBridge
->CanRestarted
= FALSE
;
809 case EfiPciHostBridgeEndBusAllocation
:
811 // No specific action is required here, can perform any chipset specific programing
815 case EfiPciHostBridgeBeginResourceAllocation
:
817 // No specific action is required here, can perform any chipset specific programing
821 case EfiPciHostBridgeAllocateResources
:
822 ReturnStatus
= EFI_SUCCESS
;
825 // Make sure the resource for all root bridges has been submitted.
827 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
828 ; !IsNull (&HostBridge
->RootBridges
, Link
)
829 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
831 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
832 if (!RootBridge
->ResourceSubmitted
) {
833 return EFI_NOT_READY
;
837 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
838 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
839 ; !IsNull (&HostBridge
->RootBridges
, Link
)
840 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
842 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
843 ResNodeHandled
[Index
] = FALSE
;
846 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
847 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
849 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
850 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
851 ResNodeHandled
[Index1
] = TRUE
;
854 // Allocate the resource node with max alignment at first
858 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
859 if (ResNodeHandled
[Index2
]) {
862 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
863 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
868 ASSERT (Index
< TypeMax
);
869 ResNodeHandled
[Index
] = TRUE
;
870 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
871 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
872 BaseAddress
= MAX_UINT64
;
875 // RESTRICTION: To simplify the situation, we require the alignment of
876 // Translation must be larger than any BAR alignment in the same root
877 // bridge, so that resource allocation alignment can be applied to
878 // both device address and host address.
880 Translation
= GetTranslationByResourceType (RootBridge
, Index
);
881 if ((Translation
& Alignment
) != 0) {
882 DEBUG ((DEBUG_ERROR
, "[%a:%d] Translation %lx is not aligned to %lx!\n",
883 __FUNCTION__
, __LINE__
, Translation
, Alignment
885 ASSERT ((Translation
& Alignment
) == 0);
887 // This may be caused by too large alignment or too small
888 // Translation; pick the 1st possibility and return out of resource,
889 // which can also go thru the same process for out of resource
892 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
899 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
900 // For AllocateResource is manipulating GCD resource, we need to use
901 // host address here.
903 BaseAddress
= AllocateResource (
905 RootBridge
->ResAllocNode
[Index
].Length
,
906 MIN (15, BitsOfAlignment
),
907 TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
908 RootBridge
->Io
.Translation
),
909 TO_HOST_ADDRESS (RootBridge
->Io
.Limit
,
910 RootBridge
->Io
.Translation
)
915 BaseAddress
= AllocateResource (
917 RootBridge
->ResAllocNode
[Index
].Length
,
918 MIN (63, BitsOfAlignment
),
919 TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
920 RootBridge
->MemAbove4G
.Translation
),
921 TO_HOST_ADDRESS (RootBridge
->MemAbove4G
.Limit
,
922 RootBridge
->MemAbove4G
.Translation
)
924 if (BaseAddress
!= MAX_UINT64
) {
928 // If memory above 4GB is not available, try memory below 4GB
932 BaseAddress
= AllocateResource (
934 RootBridge
->ResAllocNode
[Index
].Length
,
935 MIN (31, BitsOfAlignment
),
936 TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
937 RootBridge
->Mem
.Translation
),
938 TO_HOST_ADDRESS (RootBridge
->Mem
.Limit
,
939 RootBridge
->Mem
.Translation
)
944 BaseAddress
= AllocateResource (
946 RootBridge
->ResAllocNode
[Index
].Length
,
947 MIN (63, BitsOfAlignment
),
948 TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
949 RootBridge
->PMemAbove4G
.Translation
),
950 TO_HOST_ADDRESS (RootBridge
->PMemAbove4G
.Limit
,
951 RootBridge
->PMemAbove4G
.Translation
)
953 if (BaseAddress
!= MAX_UINT64
) {
957 // If memory above 4GB is not available, try memory below 4GB
960 BaseAddress
= AllocateResource (
962 RootBridge
->ResAllocNode
[Index
].Length
,
963 MIN (31, BitsOfAlignment
),
964 TO_HOST_ADDRESS (ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
965 RootBridge
->PMem
.Translation
),
966 TO_HOST_ADDRESS (RootBridge
->PMem
.Limit
,
967 RootBridge
->PMem
.Translation
)
976 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
977 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
978 if (BaseAddress
!= MAX_UINT64
) {
979 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
980 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
981 DEBUG ((DEBUG_INFO
, "Success\n"));
983 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
984 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
990 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
991 ResourceConflict (HostBridge
);
995 // Set resource to zero for nodes where allocation fails
997 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
998 ; !IsNull (&HostBridge
->RootBridges
, Link
)
999 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1001 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1002 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
1003 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
1004 RootBridge
->ResAllocNode
[Index
].Length
= 0;
1008 return ReturnStatus
;
1010 case EfiPciHostBridgeSetResources
:
1012 // HostBridgeInstance->CanRestarted = FALSE;
1016 case EfiPciHostBridgeFreeResources
:
1018 // HostBridgeInstance->CanRestarted = FALSE;
1020 ReturnStatus
= EFI_SUCCESS
;
1021 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1022 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1023 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1025 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1026 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
1027 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
1030 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
1031 if (EFI_ERROR (Status
)) {
1032 ReturnStatus
= Status
;
1040 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
1041 if (EFI_ERROR (Status
)) {
1042 ReturnStatus
= Status
;
1051 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
1052 RootBridge
->ResAllocNode
[Index
].Base
= 0;
1053 RootBridge
->ResAllocNode
[Index
].Length
= 0;
1054 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
1058 RootBridge
->ResourceSubmitted
= FALSE
;
1061 HostBridge
->CanRestarted
= TRUE
;
1062 return ReturnStatus
;
1064 case EfiPciHostBridgeEndResourceAllocation
:
1066 // The resource allocation phase is completed. No specific action is required
1067 // here. This notification can be used to perform any chipset specific programming.
1071 case EfiPciHostBridgeEndEnumeration
:
1073 // The Host Bridge Enumeration is completed. No specific action is required here.
1074 // This notification can be used to perform any chipset specific programming.
1079 return EFI_INVALID_PARAMETER
;
1087 Return the device handle of the next PCI root bridge that is associated with
1090 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1091 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
1092 On input, it holds the RootBridgeHandle returned by the most
1093 recent call to GetNextRootBridge().The handle for the first
1094 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
1096 @retval EFI_SUCCESS Succeed.
1097 @retval EFI_NOT_FOUND Next PCI root bridge not found.
1098 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
1104 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1105 IN OUT EFI_HANDLE
*RootBridgeHandle
1110 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1111 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1113 if (RootBridgeHandle
== NULL
) {
1114 return EFI_INVALID_PARAMETER
;
1117 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1118 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
1120 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1121 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1122 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1124 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1126 *RootBridgeHandle
= RootBridge
->Handle
;
1130 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
1134 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
1135 return EFI_NOT_FOUND
;
1137 return EFI_INVALID_PARAMETER
;
1143 Returns the attributes of a PCI Root Bridge.
1145 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1146 @param RootBridgeHandle The device handle of the PCI Root Bridge
1147 that the caller is interested in.
1148 @param Attributes The pointer to attributes of the PCI Root Bridge.
1150 @retval EFI_SUCCESS Succeed.
1151 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1152 RootBridgeHandle is not an EFI_HANDLE
1153 that was returned on a previous call to
1154 GetNextRootBridge().
1160 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1161 IN EFI_HANDLE RootBridgeHandle
,
1162 OUT UINT64
*Attributes
1166 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1167 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1169 if (Attributes
== NULL
) {
1170 return EFI_INVALID_PARAMETER
;
1173 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1174 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1175 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1176 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1178 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1179 if (RootBridgeHandle
== RootBridge
->Handle
) {
1180 *Attributes
= RootBridge
->AllocationAttributes
;
1185 return EFI_INVALID_PARAMETER
;
1190 This is the request from the PCI enumerator to set up
1191 the specified PCI Root Bridge for bus enumeration process.
1193 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1194 @param RootBridgeHandle The PCI Root Bridge to be set up.
1195 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1197 @retval EFI_SUCCESS Succeed.
1198 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1199 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1204 StartBusEnumeration (
1205 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1206 IN EFI_HANDLE RootBridgeHandle
,
1207 OUT VOID
**Configuration
1211 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1212 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1213 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1214 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1216 if (Configuration
== NULL
) {
1217 return EFI_INVALID_PARAMETER
;
1220 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1221 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1222 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1223 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1225 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1226 if (RootBridgeHandle
== RootBridge
->Handle
) {
1227 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1228 if (*Configuration
== NULL
) {
1229 return EFI_OUT_OF_RESOURCES
;
1232 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
1233 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1234 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1235 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1236 Descriptor
->GenFlag
= 0;
1237 Descriptor
->SpecificFlag
= 0;
1238 Descriptor
->AddrSpaceGranularity
= 0;
1239 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
1240 Descriptor
->AddrRangeMax
= 0;
1241 Descriptor
->AddrTranslationOffset
= 0;
1242 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
1244 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1245 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1246 End
->Checksum
= 0x0;
1252 return EFI_INVALID_PARAMETER
;
1257 This function programs the PCI Root Bridge hardware so that
1258 it decodes the specified PCI bus range.
1260 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1261 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1262 @param Configuration The pointer to the PCI bus resource descriptor.
1264 @retval EFI_SUCCESS Succeed.
1265 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1271 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1272 IN EFI_HANDLE RootBridgeHandle
,
1273 IN VOID
*Configuration
1277 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1278 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1279 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1280 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1282 if (Configuration
== NULL
) {
1283 return EFI_INVALID_PARAMETER
;
1286 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1287 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1290 // Check the Configuration is valid
1292 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
1293 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
1294 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
1296 return EFI_INVALID_PARAMETER
;
1299 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1300 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1301 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1302 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1304 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1305 if (RootBridgeHandle
== RootBridge
->Handle
) {
1307 if (Descriptor
->AddrLen
== 0) {
1308 return EFI_INVALID_PARAMETER
;
1311 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
1312 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
1314 return EFI_INVALID_PARAMETER
;
1317 // Update the Bus Range
1319 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
1320 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
1321 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
1326 return EFI_INVALID_PARAMETER
;
1331 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1333 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1334 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1335 are being submitted.
1336 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1338 @retval EFI_SUCCESS Succeed.
1339 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1344 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1345 IN EFI_HANDLE RootBridgeHandle
,
1346 IN VOID
*Configuration
1350 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1351 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1352 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1353 PCI_RESOURCE_TYPE Type
;
1356 // Check the input parameter: Configuration
1358 if (Configuration
== NULL
) {
1359 return EFI_INVALID_PARAMETER
;
1362 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1363 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1364 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1365 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1367 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1368 if (RootBridgeHandle
== RootBridge
->Handle
) {
1369 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
1371 // Check the resource descriptors.
1372 // If the Configuration includes one or more invalid resource descriptors, all the resource
1373 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1375 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1376 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1377 return EFI_INVALID_PARAMETER
;
1380 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1381 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
1382 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
1384 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
1385 switch (Descriptor
->ResType
) {
1386 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1387 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
1388 return EFI_INVALID_PARAMETER
;
1390 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
1391 return EFI_INVALID_PARAMETER
;
1394 // If the PCI root bridge does not support separate windows for nonprefetchable and
1395 // prefetchable memory, then the PCI bus driver needs to include requests for
1396 // prefetchable memory in the nonprefetchable memory pool.
1398 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
1399 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
1401 return EFI_INVALID_PARAMETER
;
1403 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1405 // Check aligment, it should be of the form 2^n-1
1407 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
1408 return EFI_INVALID_PARAMETER
;
1416 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1417 return EFI_INVALID_PARAMETER
;
1420 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1421 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1422 if (Descriptor
->AddrSpaceGranularity
== 32) {
1423 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1429 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
1430 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1437 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
1440 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
1441 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
1442 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
1444 RootBridge
->ResourceSubmitted
= TRUE
;
1449 return EFI_INVALID_PARAMETER
;
1454 This function returns the proposed resource settings for the specified
1457 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1458 @param RootBridgeHandle The PCI Root Bridge handle.
1459 @param Configuration The pointer to the pointer to the PCI I/O
1460 and memory resource descriptor.
1462 @retval EFI_SUCCESS Succeed.
1463 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1464 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1469 GetProposedResources (
1470 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1471 IN EFI_HANDLE RootBridgeHandle
,
1472 OUT VOID
**Configuration
1476 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1477 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1481 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1482 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1485 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1486 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1487 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1488 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1490 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1491 if (RootBridgeHandle
== RootBridge
->Handle
) {
1492 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1493 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1498 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1499 if (Buffer
== NULL
) {
1500 return EFI_OUT_OF_RESOURCES
;
1503 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1504 for (Index
= 0; Index
< TypeBus
; Index
++) {
1505 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1506 if (ResStatus
!= ResNone
) {
1507 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1508 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1509 Descriptor
->GenFlag
= 0;
1511 // AddrRangeMin in Resource Descriptor here should be device address
1512 // instead of host address, or else PCI bus driver cannot set correct
1513 // address into PCI BAR registers.
1514 // Base in ResAllocNode is a host address, so conversion is needed.
1516 Descriptor
->AddrRangeMin
= TO_DEVICE_ADDRESS (RootBridge
->ResAllocNode
[Index
].Base
,
1517 GetTranslationByResourceType (RootBridge
, Index
));
1518 Descriptor
->AddrRangeMax
= 0;
1519 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1520 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1525 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1529 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1531 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1532 Descriptor
->AddrSpaceGranularity
= 32;
1536 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1538 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1539 Descriptor
->AddrSpaceGranularity
= 64;
1546 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1547 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1550 *Configuration
= Buffer
;
1556 return EFI_INVALID_PARAMETER
;
1561 This function is called for all the PCI controllers that the PCI
1562 bus driver finds. Can be used to Preprogram the controller.
1564 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1565 @param RootBridgeHandle The PCI Root Bridge handle.
1566 @param PciAddress Address of the controller on the PCI bus.
1567 @param Phase The Phase during resource allocation.
1569 @retval EFI_SUCCESS Succeed.
1570 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1575 PreprocessController (
1576 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1577 IN EFI_HANDLE RootBridgeHandle
,
1578 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1579 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1583 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1584 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1586 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1587 return EFI_INVALID_PARAMETER
;
1590 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1591 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1592 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1593 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1595 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1596 if (RootBridgeHandle
== RootBridge
->Handle
) {
1601 return EFI_INVALID_PARAMETER
;