3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
5 Copyright (c) 1999 - 2016, 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"
21 EFI_METRONOME_ARCH_PROTOCOL
*mMetronome
;
22 EFI_CPU_IO2_PROTOCOL
*mCpuIo
;
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mAcpiAddressSpaceTypeStr
[] = {
25 L
"Mem", L
"I/O", L
"Bus"
27 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16
*mPciResourceTypeStr
[] = {
28 L
"I/O", L
"Mem", L
"PMem", L
"Mem64", L
"PMem64", L
"Bus"
31 EDKII_IOMMU_PROTOCOL
*mIoMmuProtocol
;
32 EFI_EVENT mIoMmuEvent
;
33 VOID
*mIoMmuRegistration
;
36 Ensure the compatibility of an IO space descriptor with the IO aperture.
38 The IO space descriptor can come from the GCD IO space map, or it can
39 represent a gap between two neighboring IO space descriptors. In the latter
40 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
42 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
43 taken -- it is by definition compatible with the aperture.
45 Otherwise, the intersection of the IO space descriptor is calculated with the
46 aperture. If the intersection is the empty set (no overlap), no action is
47 taken; the IO space descriptor is compatible with the aperture.
49 Otherwise, the type of the descriptor is investigated again. If the type is
50 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
51 such a type), then an attempt is made to add the intersection as IO space to
52 the GCD IO space map. This ensures continuity for the aperture, and the
53 descriptor is deemed compatible with the aperture.
55 Otherwise, the IO space descriptor is incompatible with the IO aperture.
57 @param[in] Base Base address of the aperture.
58 @param[in] Length Length of the aperture.
59 @param[in] Descriptor The descriptor to ensure compatibility with the
62 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space
63 map may have been updated, for continuity
65 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
66 @return Error codes from gDS->AddIoSpace().
69 IntersectIoDescriptor (
72 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
75 UINT64 IntersectionBase
;
76 UINT64 IntersectionEnd
;
79 if (Descriptor
->GcdIoType
== EfiGcdIoTypeIo
) {
83 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
84 IntersectionEnd
= MIN (Base
+ Length
,
85 Descriptor
->BaseAddress
+ Descriptor
->Length
);
86 if (IntersectionBase
>= IntersectionEnd
) {
88 // The descriptor and the aperture don't overlap.
93 if (Descriptor
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
94 Status
= gDS
->AddIoSpace (EfiGcdIoTypeIo
, IntersectionBase
,
95 IntersectionEnd
- IntersectionBase
);
97 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
98 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
99 IntersectionBase
, IntersectionEnd
, Status
));
103 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
104 "aperture [%Lx, %Lx)\n", gEfiCallerBaseName
, __FUNCTION__
,
105 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
106 (UINT32
)Descriptor
->GcdIoType
, Base
, Base
+ Length
));
107 return EFI_INVALID_PARAMETER
;
112 The routine checks the GCD database and only adds those which are
113 not added in the specified range to GCD.
115 @param Base Base address of the IO space.
116 @param Length Length of the IO space.
118 @retval EFI_SUCCES The IO space was added successfully.
128 UINTN NumberOfDescriptors
;
129 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
131 Status
= gDS
->GetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
132 if (EFI_ERROR (Status
)) {
133 DEBUG ((EFI_D_ERROR
, "%a: %a: GetIoSpaceMap(): %r\n",
134 gEfiCallerBaseName
, __FUNCTION__
, Status
));
138 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
139 Status
= IntersectIoDescriptor (Base
, Length
, &IoSpaceMap
[Index
]);
140 if (EFI_ERROR (Status
)) {
147 // Make sure there are adjacent descriptors covering [Base, Base + Length).
148 // It is possible that they have not been merged; merging can be prevented
152 EFI_STATUS CheckStatus
;
153 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor
;
155 for (CheckBase
= Base
;
156 CheckBase
< Base
+ Length
;
157 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
158 CheckStatus
= gDS
->GetIoSpaceDescriptor (CheckBase
, &Descriptor
);
159 ASSERT_EFI_ERROR (CheckStatus
);
160 ASSERT (Descriptor
.GcdIoType
== EfiGcdIoTypeIo
);
165 FreePool (IoSpaceMap
);
171 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
173 The memory space descriptor can come from the GCD memory space map, or it can
174 represent a gap between two neighboring memory space descriptors. In the
175 latter case, the GcdMemoryType field is expected to be
176 EfiGcdMemoryTypeNonExistent.
178 If the memory space descriptor already has type
179 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
180 required capabilities, then no action is taken -- it is by definition
181 compatible with the aperture.
183 Otherwise, the intersection of the memory space descriptor is calculated with
184 the aperture. If the intersection is the empty set (no overlap), no action is
185 taken; the memory space descriptor is compatible with the aperture.
187 Otherwise, the type of the descriptor is investigated again. If the type is
188 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
189 such a type), then an attempt is made to add the intersection as MMIO space
190 to the GCD memory space map, with the specified capabilities. This ensures
191 continuity for the aperture, and the descriptor is deemed compatible with the
194 Otherwise, the memory space descriptor is incompatible with the MMIO
197 @param[in] Base Base address of the aperture.
198 @param[in] Length Length of the aperture.
199 @param[in] Capabilities Capabilities required by the aperture.
200 @param[in] Descriptor The descriptor to ensure compatibility with the
203 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
204 space map may have been updated, for
205 continuity within the aperture.
206 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
207 @return Error codes from gDS->AddMemorySpace().
210 IntersectMemoryDescriptor (
213 IN UINT64 Capabilities
,
214 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
217 UINT64 IntersectionBase
;
218 UINT64 IntersectionEnd
;
221 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
&&
222 (Descriptor
->Capabilities
& Capabilities
) == Capabilities
) {
226 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
227 IntersectionEnd
= MIN (Base
+ Length
,
228 Descriptor
->BaseAddress
+ Descriptor
->Length
);
229 if (IntersectionBase
>= IntersectionEnd
) {
231 // The descriptor and the aperture don't overlap.
236 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
237 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo
,
238 IntersectionBase
, IntersectionEnd
- IntersectionBase
,
241 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
242 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
243 IntersectionBase
, IntersectionEnd
, Status
));
247 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
248 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName
, __FUNCTION__
,
249 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
250 (UINT32
)Descriptor
->GcdMemoryType
, Descriptor
->Capabilities
,
251 Base
, Base
+ Length
, Capabilities
));
252 return EFI_INVALID_PARAMETER
;
256 Add MMIO space to GCD.
257 The routine checks the GCD database and only adds those which are
258 not added in the specified range to GCD.
260 @param Base Base address of the MMIO space.
261 @param Length Length of the MMIO space.
262 @param Capabilities Capabilities of the MMIO space.
264 @retval EFI_SUCCES The MMIO space was added successfully.
267 AddMemoryMappedIoSpace (
270 IN UINT64 Capabilities
275 UINTN NumberOfDescriptors
;
276 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
278 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
279 if (EFI_ERROR (Status
)) {
280 DEBUG ((EFI_D_ERROR
, "%a: %a: GetMemorySpaceMap(): %r\n",
281 gEfiCallerBaseName
, __FUNCTION__
, Status
));
285 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
286 Status
= IntersectMemoryDescriptor (Base
, Length
, Capabilities
,
287 &MemorySpaceMap
[Index
]);
288 if (EFI_ERROR (Status
)) {
289 goto FreeMemorySpaceMap
;
295 // Make sure there are adjacent descriptors covering [Base, Base + Length).
296 // It is possible that they have not been merged; merging can be prevented
297 // by allocation and different capabilities.
300 EFI_STATUS CheckStatus
;
301 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
303 for (CheckBase
= Base
;
304 CheckBase
< Base
+ Length
;
305 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
306 CheckStatus
= gDS
->GetMemorySpaceDescriptor (CheckBase
, &Descriptor
);
307 ASSERT_EFI_ERROR (CheckStatus
);
308 ASSERT (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
);
309 ASSERT ((Descriptor
.Capabilities
& Capabilities
) == Capabilities
);
314 FreePool (MemorySpaceMap
);
320 Event notification that is fired when IOMMU protocol is installed.
322 @param Event The Event that is being processed.
323 @param Context Event Context.
328 IoMmuProtocolCallback (
335 Status
= gBS
->LocateProtocol (&gEdkiiIoMmuProtocolGuid
, NULL
, (VOID
**)&mIoMmuProtocol
);
336 if (!EFI_ERROR(Status
)) {
337 gBS
->CloseEvent (mIoMmuEvent
);
343 Entry point of this driver.
345 @param ImageHandle Image handle of this driver.
346 @param SystemTable Pointer to standard EFI system table.
348 @retval EFI_SUCCESS Succeed.
349 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
354 InitializePciHostBridge (
355 IN EFI_HANDLE ImageHandle
,
356 IN EFI_SYSTEM_TABLE
*SystemTable
360 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
361 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
362 PCI_ROOT_BRIDGE
*RootBridges
;
363 UINTN RootBridgeCount
;
365 PCI_ROOT_BRIDGE_APERTURE
*MemApertures
[4];
366 UINTN MemApertureIndex
;
367 BOOLEAN ResourceAssigned
;
370 RootBridges
= PciHostBridgeGetRootBridges (&RootBridgeCount
);
371 if ((RootBridges
== NULL
) || (RootBridgeCount
== 0)) {
372 return EFI_UNSUPPORTED
;
375 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**) &mMetronome
);
376 ASSERT_EFI_ERROR (Status
);
377 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**) &mCpuIo
);
378 ASSERT_EFI_ERROR (Status
);
381 // Most systems in the world including complex servers have only one Host Bridge.
383 HostBridge
= AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE
));
384 ASSERT (HostBridge
!= NULL
);
386 HostBridge
->Signature
= PCI_HOST_BRIDGE_SIGNATURE
;
387 HostBridge
->CanRestarted
= TRUE
;
388 InitializeListHead (&HostBridge
->RootBridges
);
389 ResourceAssigned
= FALSE
;
392 // Create Root Bridge Device Handle in this Host Bridge
394 for (Index
= 0; Index
< RootBridgeCount
; Index
++) {
396 // Create Root Bridge Handle Instance
398 RootBridge
= CreateRootBridge (&RootBridges
[Index
]);
399 ASSERT (RootBridge
!= NULL
);
400 if (RootBridge
== NULL
) {
405 // Make sure all root bridges share the same ResourceAssigned value.
408 ResourceAssigned
= RootBridges
[Index
].ResourceAssigned
;
410 ASSERT (ResourceAssigned
== RootBridges
[Index
].ResourceAssigned
);
413 if (RootBridges
[Index
].Io
.Base
<= RootBridges
[Index
].Io
.Limit
) {
414 Status
= AddIoSpace (
415 RootBridges
[Index
].Io
.Base
,
416 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1
418 ASSERT_EFI_ERROR (Status
);
419 if (ResourceAssigned
) {
420 Status
= gDS
->AllocateIoSpace (
421 EfiGcdAllocateAddress
,
424 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1,
425 &RootBridges
[Index
].Io
.Base
,
429 ASSERT_EFI_ERROR (Status
);
434 // Add all the Mem/PMem aperture to GCD
435 // Mem/PMem shouldn't overlap with each other
436 // Root bridge which needs to combine MEM and PMEM should only report
437 // the MEM aperture in Mem
439 MemApertures
[0] = &RootBridges
[Index
].Mem
;
440 MemApertures
[1] = &RootBridges
[Index
].MemAbove4G
;
441 MemApertures
[2] = &RootBridges
[Index
].PMem
;
442 MemApertures
[3] = &RootBridges
[Index
].PMemAbove4G
;
444 for (MemApertureIndex
= 0; MemApertureIndex
< ARRAY_SIZE (MemApertures
); MemApertureIndex
++) {
445 if (MemApertures
[MemApertureIndex
]->Base
<= MemApertures
[MemApertureIndex
]->Limit
) {
446 Status
= AddMemoryMappedIoSpace (
447 MemApertures
[MemApertureIndex
]->Base
,
448 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
451 ASSERT_EFI_ERROR (Status
);
452 Status
= gDS
->SetMemorySpaceAttributes (
453 MemApertures
[MemApertureIndex
]->Base
,
454 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
457 if (EFI_ERROR (Status
)) {
458 DEBUG ((DEBUG_WARN
, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status
));
460 if (ResourceAssigned
) {
461 Status
= gDS
->AllocateMemorySpace (
462 EfiGcdAllocateAddress
,
463 EfiGcdMemoryTypeMemoryMappedIo
,
465 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
466 &MemApertures
[MemApertureIndex
]->Base
,
470 ASSERT_EFI_ERROR (Status
);
475 // Insert Root Bridge Handle Instance
477 InsertTailList (&HostBridge
->RootBridges
, &RootBridge
->Link
);
481 // When resources were assigned, it's not needed to expose
482 // PciHostBridgeResourceAllocation protocol.
484 if (!ResourceAssigned
) {
485 HostBridge
->ResAlloc
.NotifyPhase
= NotifyPhase
;
486 HostBridge
->ResAlloc
.GetNextRootBridge
= GetNextRootBridge
;
487 HostBridge
->ResAlloc
.GetAllocAttributes
= GetAttributes
;
488 HostBridge
->ResAlloc
.StartBusEnumeration
= StartBusEnumeration
;
489 HostBridge
->ResAlloc
.SetBusNumbers
= SetBusNumbers
;
490 HostBridge
->ResAlloc
.SubmitResources
= SubmitResources
;
491 HostBridge
->ResAlloc
.GetProposedResources
= GetProposedResources
;
492 HostBridge
->ResAlloc
.PreprocessController
= PreprocessController
;
494 Status
= gBS
->InstallMultipleProtocolInterfaces (
496 &gEfiPciHostBridgeResourceAllocationProtocolGuid
, &HostBridge
->ResAlloc
,
499 ASSERT_EFI_ERROR (Status
);
502 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
503 ; !IsNull (&HostBridge
->RootBridges
, Link
)
504 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
506 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
507 RootBridge
->RootBridgeIo
.ParentHandle
= HostBridge
->Handle
;
509 Status
= gBS
->InstallMultipleProtocolInterfaces (
511 &gEfiDevicePathProtocolGuid
, RootBridge
->DevicePath
,
512 &gEfiPciRootBridgeIoProtocolGuid
, &RootBridge
->RootBridgeIo
,
515 ASSERT_EFI_ERROR (Status
);
517 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
519 if (!EFI_ERROR (Status
)) {
520 mIoMmuEvent
= EfiCreateProtocolNotifyEvent (
521 &gEdkiiIoMmuProtocolGuid
,
523 IoMmuProtocolCallback
,
533 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
535 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
539 IN PCI_HOST_BRIDGE_INSTANCE
*HostBridge
542 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
543 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
544 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
545 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
547 UINTN RootBridgeCount
;
548 PCI_RESOURCE_TYPE Index
;
549 PCI_RES_NODE
*ResAllocNode
;
552 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
553 ; !IsNull (&HostBridge
->RootBridges
, Link
)
554 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
559 Resources
= AllocatePool (
560 RootBridgeCount
* (TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)) +
561 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
563 ASSERT (Resources
!= NULL
);
565 for (Link
= GetFirstNode (&HostBridge
->RootBridges
), Descriptor
= Resources
566 ; !IsNull (&HostBridge
->RootBridges
, Link
)
567 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
569 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
570 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
571 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
573 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
574 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
575 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
576 Descriptor
->AddrRangeMax
= ResAllocNode
->Alignment
;
577 Descriptor
->AddrLen
= ResAllocNode
->Length
;
578 switch (ResAllocNode
->Type
) {
581 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
585 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
587 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
588 Descriptor
->AddrSpaceGranularity
= 32;
592 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
594 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
595 Descriptor
->AddrSpaceGranularity
= 64;
599 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
609 // Terminate the root bridge resources.
611 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
612 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
615 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (End
+ 1);
618 // Terminate the host bridge resources.
620 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
621 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
624 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
625 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
626 FreePool (Resources
);
630 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
631 from GCD range [BaseAddress, Limit).
633 @param Mmio TRUE for MMIO and FALSE for IO.
634 @param Length Length of the resource to allocate.
635 @param BitsOfAlignment Alignment of the resource to allocate.
636 @param BaseAddress The starting address the allocation is from.
637 @param Limit The ending address the allocation is to.
639 @retval The base address of the allocated resource or MAX_UINT64 if allocation
646 UINTN BitsOfAlignment
,
653 if (BaseAddress
< Limit
) {
655 // Have to make sure Aligment is handled since we are doing direct address allocation
657 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
659 while (BaseAddress
+ Length
<= Limit
+ 1) {
661 Status
= gDS
->AllocateMemorySpace (
662 EfiGcdAllocateAddress
,
663 EfiGcdMemoryTypeMemoryMappedIo
,
671 Status
= gDS
->AllocateIoSpace (
672 EfiGcdAllocateAddress
,
682 if (!EFI_ERROR (Status
)) {
685 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
693 Enter a certain phase of the PCI enumeration process.
695 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
696 @param Phase The phase during enumeration.
698 @retval EFI_SUCCESS Succeed.
699 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
700 @retval EFI_NOT_READY Resources have not been submitted yet.
706 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
707 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
710 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
711 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
713 EFI_PHYSICAL_ADDRESS BaseAddress
;
714 UINTN BitsOfAlignment
;
717 EFI_STATUS ReturnStatus
;
718 PCI_RESOURCE_TYPE Index
;
719 PCI_RESOURCE_TYPE Index1
;
720 PCI_RESOURCE_TYPE Index2
;
721 BOOLEAN ResNodeHandled
[TypeMax
];
724 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
727 case EfiPciHostBridgeBeginEnumeration
:
728 if (!HostBridge
->CanRestarted
) {
729 return EFI_NOT_READY
;
734 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
735 ; !IsNull (&HostBridge
->RootBridges
, Link
)
736 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
738 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
739 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
740 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
741 RootBridge
->ResAllocNode
[Index
].Base
= 0;
742 RootBridge
->ResAllocNode
[Index
].Length
= 0;
743 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
745 RootBridge
->ResourceSubmitted
= FALSE
;
749 HostBridge
->CanRestarted
= TRUE
;
752 case EfiPciHostBridgeBeginBusAllocation
:
754 // No specific action is required here, can perform any chipset specific programing
756 HostBridge
->CanRestarted
= FALSE
;
759 case EfiPciHostBridgeEndBusAllocation
:
761 // No specific action is required here, can perform any chipset specific programing
765 case EfiPciHostBridgeBeginResourceAllocation
:
767 // No specific action is required here, can perform any chipset specific programing
771 case EfiPciHostBridgeAllocateResources
:
772 ReturnStatus
= EFI_SUCCESS
;
775 // Make sure the resource for all root bridges has been submitted.
777 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
778 ; !IsNull (&HostBridge
->RootBridges
, Link
)
779 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
781 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
782 if (!RootBridge
->ResourceSubmitted
) {
783 return EFI_NOT_READY
;
787 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
788 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
789 ; !IsNull (&HostBridge
->RootBridges
, Link
)
790 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
792 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
793 ResNodeHandled
[Index
] = FALSE
;
796 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
797 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
799 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
800 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
801 ResNodeHandled
[Index1
] = TRUE
;
804 // Allocate the resource node with max alignment at first
808 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
809 if (ResNodeHandled
[Index2
]) {
812 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
813 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
818 ASSERT (Index
< TypeMax
);
819 ResNodeHandled
[Index
] = TRUE
;
820 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
821 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
822 BaseAddress
= MAX_UINT64
;
826 BaseAddress
= AllocateResource (
828 RootBridge
->ResAllocNode
[Index
].Length
,
829 MIN (15, BitsOfAlignment
),
830 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
836 BaseAddress
= AllocateResource (
838 RootBridge
->ResAllocNode
[Index
].Length
,
839 MIN (63, BitsOfAlignment
),
840 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
841 RootBridge
->MemAbove4G
.Limit
843 if (BaseAddress
!= MAX_UINT64
) {
847 // If memory above 4GB is not available, try memory below 4GB
851 BaseAddress
= AllocateResource (
853 RootBridge
->ResAllocNode
[Index
].Length
,
854 MIN (31, BitsOfAlignment
),
855 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
856 RootBridge
->Mem
.Limit
861 BaseAddress
= AllocateResource (
863 RootBridge
->ResAllocNode
[Index
].Length
,
864 MIN (63, BitsOfAlignment
),
865 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
866 RootBridge
->PMemAbove4G
.Limit
868 if (BaseAddress
!= MAX_UINT64
) {
872 // If memory above 4GB is not available, try memory below 4GB
875 BaseAddress
= AllocateResource (
877 RootBridge
->ResAllocNode
[Index
].Length
,
878 MIN (31, BitsOfAlignment
),
879 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
880 RootBridge
->PMem
.Limit
889 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
890 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
891 if (BaseAddress
!= MAX_UINT64
) {
892 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
893 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
894 DEBUG ((DEBUG_INFO
, "Success\n"));
896 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
897 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
903 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
904 ResourceConflict (HostBridge
);
908 // Set resource to zero for nodes where allocation fails
910 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
911 ; !IsNull (&HostBridge
->RootBridges
, Link
)
912 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
914 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
915 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
916 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
917 RootBridge
->ResAllocNode
[Index
].Length
= 0;
923 case EfiPciHostBridgeSetResources
:
925 // HostBridgeInstance->CanRestarted = FALSE;
929 case EfiPciHostBridgeFreeResources
:
931 // HostBridgeInstance->CanRestarted = FALSE;
933 ReturnStatus
= EFI_SUCCESS
;
934 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
935 ; !IsNull (&HostBridge
->RootBridges
, Link
)
936 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
938 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
939 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
940 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
943 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
944 if (EFI_ERROR (Status
)) {
945 ReturnStatus
= Status
;
953 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
954 if (EFI_ERROR (Status
)) {
955 ReturnStatus
= Status
;
964 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
965 RootBridge
->ResAllocNode
[Index
].Base
= 0;
966 RootBridge
->ResAllocNode
[Index
].Length
= 0;
967 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
971 RootBridge
->ResourceSubmitted
= FALSE
;
974 HostBridge
->CanRestarted
= TRUE
;
977 case EfiPciHostBridgeEndResourceAllocation
:
979 // The resource allocation phase is completed. No specific action is required
980 // here. This notification can be used to perform any chipset specific programming.
984 case EfiPciHostBridgeEndEnumeration
:
986 // The Host Bridge Enumeration is completed. No specific action is required here.
987 // This notification can be used to perform any chipset specific programming.
992 return EFI_INVALID_PARAMETER
;
1000 Return the device handle of the next PCI root bridge that is associated with
1003 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1004 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
1005 On input, it holds the RootBridgeHandle returned by the most
1006 recent call to GetNextRootBridge().The handle for the first
1007 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
1009 @retval EFI_SUCCESS Succeed.
1010 @retval EFI_NOT_FOUND Next PCI root bridge not found.
1011 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
1017 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1018 IN OUT EFI_HANDLE
*RootBridgeHandle
1023 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1024 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1026 if (RootBridgeHandle
== NULL
) {
1027 return EFI_INVALID_PARAMETER
;
1030 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1031 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
1033 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1034 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1035 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1037 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1039 *RootBridgeHandle
= RootBridge
->Handle
;
1043 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
1047 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
1048 return EFI_NOT_FOUND
;
1050 return EFI_INVALID_PARAMETER
;
1056 Returns the attributes of a PCI Root Bridge.
1058 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1059 @param RootBridgeHandle The device handle of the PCI Root Bridge
1060 that the caller is interested in.
1061 @param Attributes The pointer to attributes of the PCI Root Bridge.
1063 @retval EFI_SUCCESS Succeed.
1064 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1065 RootBridgeHandle is not an EFI_HANDLE
1066 that was returned on a previous call to
1067 GetNextRootBridge().
1073 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1074 IN EFI_HANDLE RootBridgeHandle
,
1075 OUT UINT64
*Attributes
1079 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1080 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1082 if (Attributes
== NULL
) {
1083 return EFI_INVALID_PARAMETER
;
1086 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1087 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1088 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1089 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1091 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1092 if (RootBridgeHandle
== RootBridge
->Handle
) {
1093 *Attributes
= RootBridge
->AllocationAttributes
;
1098 return EFI_INVALID_PARAMETER
;
1103 This is the request from the PCI enumerator to set up
1104 the specified PCI Root Bridge for bus enumeration process.
1106 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1107 @param RootBridgeHandle The PCI Root Bridge to be set up.
1108 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1110 @retval EFI_SUCCESS Succeed.
1111 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1112 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1117 StartBusEnumeration (
1118 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1119 IN EFI_HANDLE RootBridgeHandle
,
1120 OUT VOID
**Configuration
1124 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1125 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1126 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1127 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1129 if (Configuration
== NULL
) {
1130 return EFI_INVALID_PARAMETER
;
1133 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1134 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1135 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1136 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1138 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1139 if (RootBridgeHandle
== RootBridge
->Handle
) {
1140 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1141 if (*Configuration
== NULL
) {
1142 return EFI_OUT_OF_RESOURCES
;
1145 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
1146 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1147 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1148 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1149 Descriptor
->GenFlag
= 0;
1150 Descriptor
->SpecificFlag
= 0;
1151 Descriptor
->AddrSpaceGranularity
= 0;
1152 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
1153 Descriptor
->AddrRangeMax
= 0;
1154 Descriptor
->AddrTranslationOffset
= 0;
1155 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
1157 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1158 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1159 End
->Checksum
= 0x0;
1165 return EFI_INVALID_PARAMETER
;
1170 This function programs the PCI Root Bridge hardware so that
1171 it decodes the specified PCI bus range.
1173 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1174 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1175 @param Configuration The pointer to the PCI bus resource descriptor.
1177 @retval EFI_SUCCESS Succeed.
1178 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1184 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1185 IN EFI_HANDLE RootBridgeHandle
,
1186 IN VOID
*Configuration
1190 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1191 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1192 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1193 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1195 if (Configuration
== NULL
) {
1196 return EFI_INVALID_PARAMETER
;
1199 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1200 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1203 // Check the Configuration is valid
1205 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
1206 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
1207 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
1209 return EFI_INVALID_PARAMETER
;
1212 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1213 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1214 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1215 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1217 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1218 if (RootBridgeHandle
== RootBridge
->Handle
) {
1220 if (Descriptor
->AddrLen
== 0) {
1221 return EFI_INVALID_PARAMETER
;
1224 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
1225 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
1227 return EFI_INVALID_PARAMETER
;
1230 // Update the Bus Range
1232 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
1233 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
1234 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
1239 return EFI_INVALID_PARAMETER
;
1244 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1246 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1247 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1248 are being submitted.
1249 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1251 @retval EFI_SUCCESS Succeed.
1252 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1257 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1258 IN EFI_HANDLE RootBridgeHandle
,
1259 IN VOID
*Configuration
1263 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1264 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1265 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1266 PCI_RESOURCE_TYPE Type
;
1269 // Check the input parameter: Configuration
1271 if (Configuration
== NULL
) {
1272 return EFI_INVALID_PARAMETER
;
1275 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1276 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1277 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1278 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1280 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1281 if (RootBridgeHandle
== RootBridge
->Handle
) {
1282 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
1284 // Check the resource descriptors.
1285 // If the Configuration includes one or more invalid resource descriptors, all the resource
1286 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1288 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1289 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1290 return EFI_INVALID_PARAMETER
;
1293 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1294 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
1295 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
1297 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
1298 switch (Descriptor
->ResType
) {
1299 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1300 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
1301 return EFI_INVALID_PARAMETER
;
1303 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
1304 return EFI_INVALID_PARAMETER
;
1307 // If the PCI root bridge does not support separate windows for nonprefetchable and
1308 // prefetchable memory, then the PCI bus driver needs to include requests for
1309 // prefetchable memory in the nonprefetchable memory pool.
1311 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
1312 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
1314 return EFI_INVALID_PARAMETER
;
1316 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1318 // Check aligment, it should be of the form 2^n-1
1320 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
1321 return EFI_INVALID_PARAMETER
;
1329 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1330 return EFI_INVALID_PARAMETER
;
1333 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1334 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1335 if (Descriptor
->AddrSpaceGranularity
== 32) {
1336 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1342 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
1343 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1350 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
1353 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
1354 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
1355 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
1357 RootBridge
->ResourceSubmitted
= TRUE
;
1362 return EFI_INVALID_PARAMETER
;
1367 This function returns the proposed resource settings for the specified
1370 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1371 @param RootBridgeHandle The PCI Root Bridge handle.
1372 @param Configuration The pointer to the pointer to the PCI I/O
1373 and memory resource descriptor.
1375 @retval EFI_SUCCESS Succeed.
1376 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1377 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1382 GetProposedResources (
1383 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1384 IN EFI_HANDLE RootBridgeHandle
,
1385 OUT VOID
**Configuration
1389 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1390 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1394 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1395 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1398 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1399 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1400 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1401 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1403 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1404 if (RootBridgeHandle
== RootBridge
->Handle
) {
1405 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1406 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1411 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1412 if (Buffer
== NULL
) {
1413 return EFI_OUT_OF_RESOURCES
;
1416 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1417 for (Index
= 0; Index
< TypeBus
; Index
++) {
1418 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1419 if (ResStatus
!= ResNone
) {
1420 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1421 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1422 Descriptor
->GenFlag
= 0;
1423 Descriptor
->AddrRangeMin
= RootBridge
->ResAllocNode
[Index
].Base
;
1424 Descriptor
->AddrRangeMax
= 0;
1425 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1426 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1431 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1435 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1437 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1438 Descriptor
->AddrSpaceGranularity
= 32;
1442 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1444 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1445 Descriptor
->AddrSpaceGranularity
= 64;
1452 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1453 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1456 *Configuration
= Buffer
;
1462 return EFI_INVALID_PARAMETER
;
1467 This function is called for all the PCI controllers that the PCI
1468 bus driver finds. Can be used to Preprogram the controller.
1470 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1471 @param RootBridgeHandle The PCI Root Bridge handle.
1472 @param PciAddress Address of the controller on the PCI bus.
1473 @param Phase The Phase during resource allocation.
1475 @retval EFI_SUCCESS Succeed.
1476 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1481 PreprocessController (
1482 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1483 IN EFI_HANDLE RootBridgeHandle
,
1484 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1485 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1489 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1490 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1492 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1493 return EFI_INVALID_PARAMETER
;
1496 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1497 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1498 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1499 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1501 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1502 if (RootBridgeHandle
== RootBridge
->Handle
) {
1507 return EFI_INVALID_PARAMETER
;