3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
5 Copyright (c) 1999 - 2017, 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 Descriptor
->SpecificFlag
= 0;
579 switch (ResAllocNode
->Type
) {
582 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
586 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
588 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
589 Descriptor
->AddrSpaceGranularity
= 32;
593 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
595 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
596 Descriptor
->AddrSpaceGranularity
= 64;
600 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
610 // Terminate the root bridge resources.
612 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
613 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
616 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (End
+ 1);
619 // Terminate the host bridge resources.
621 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
622 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
625 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
626 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
627 FreePool (Resources
);
631 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
632 from GCD range [BaseAddress, Limit).
634 @param Mmio TRUE for MMIO and FALSE for IO.
635 @param Length Length of the resource to allocate.
636 @param BitsOfAlignment Alignment of the resource to allocate.
637 @param BaseAddress The starting address the allocation is from.
638 @param Limit The ending address the allocation is to.
640 @retval The base address of the allocated resource or MAX_UINT64 if allocation
647 UINTN BitsOfAlignment
,
654 if (BaseAddress
< Limit
) {
656 // Have to make sure Aligment is handled since we are doing direct address allocation
658 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
660 while (BaseAddress
+ Length
<= Limit
+ 1) {
662 Status
= gDS
->AllocateMemorySpace (
663 EfiGcdAllocateAddress
,
664 EfiGcdMemoryTypeMemoryMappedIo
,
672 Status
= gDS
->AllocateIoSpace (
673 EfiGcdAllocateAddress
,
683 if (!EFI_ERROR (Status
)) {
686 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
694 Enter a certain phase of the PCI enumeration process.
696 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
697 @param Phase The phase during enumeration.
699 @retval EFI_SUCCESS Succeed.
700 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
701 @retval EFI_NOT_READY Resources have not been submitted yet.
707 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
708 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
711 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
712 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
714 EFI_PHYSICAL_ADDRESS BaseAddress
;
715 UINTN BitsOfAlignment
;
718 EFI_STATUS ReturnStatus
;
719 PCI_RESOURCE_TYPE Index
;
720 PCI_RESOURCE_TYPE Index1
;
721 PCI_RESOURCE_TYPE Index2
;
722 BOOLEAN ResNodeHandled
[TypeMax
];
725 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
728 case EfiPciHostBridgeBeginEnumeration
:
729 if (!HostBridge
->CanRestarted
) {
730 return EFI_NOT_READY
;
735 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
736 ; !IsNull (&HostBridge
->RootBridges
, Link
)
737 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
739 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
740 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
741 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
742 RootBridge
->ResAllocNode
[Index
].Base
= 0;
743 RootBridge
->ResAllocNode
[Index
].Length
= 0;
744 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
746 RootBridge
->ResourceSubmitted
= FALSE
;
750 HostBridge
->CanRestarted
= TRUE
;
753 case EfiPciHostBridgeBeginBusAllocation
:
755 // No specific action is required here, can perform any chipset specific programing
757 HostBridge
->CanRestarted
= FALSE
;
760 case EfiPciHostBridgeEndBusAllocation
:
762 // No specific action is required here, can perform any chipset specific programing
766 case EfiPciHostBridgeBeginResourceAllocation
:
768 // No specific action is required here, can perform any chipset specific programing
772 case EfiPciHostBridgeAllocateResources
:
773 ReturnStatus
= EFI_SUCCESS
;
776 // Make sure the resource for all root bridges has been submitted.
778 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
779 ; !IsNull (&HostBridge
->RootBridges
, Link
)
780 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
782 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
783 if (!RootBridge
->ResourceSubmitted
) {
784 return EFI_NOT_READY
;
788 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
789 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
790 ; !IsNull (&HostBridge
->RootBridges
, Link
)
791 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
793 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
794 ResNodeHandled
[Index
] = FALSE
;
797 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
798 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
800 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
801 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
802 ResNodeHandled
[Index1
] = TRUE
;
805 // Allocate the resource node with max alignment at first
809 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
810 if (ResNodeHandled
[Index2
]) {
813 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
814 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
819 ASSERT (Index
< TypeMax
);
820 ResNodeHandled
[Index
] = TRUE
;
821 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
822 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
823 BaseAddress
= MAX_UINT64
;
827 BaseAddress
= AllocateResource (
829 RootBridge
->ResAllocNode
[Index
].Length
,
830 MIN (15, BitsOfAlignment
),
831 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
837 BaseAddress
= AllocateResource (
839 RootBridge
->ResAllocNode
[Index
].Length
,
840 MIN (63, BitsOfAlignment
),
841 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
842 RootBridge
->MemAbove4G
.Limit
844 if (BaseAddress
!= MAX_UINT64
) {
848 // If memory above 4GB is not available, try memory below 4GB
852 BaseAddress
= AllocateResource (
854 RootBridge
->ResAllocNode
[Index
].Length
,
855 MIN (31, BitsOfAlignment
),
856 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
857 RootBridge
->Mem
.Limit
862 BaseAddress
= AllocateResource (
864 RootBridge
->ResAllocNode
[Index
].Length
,
865 MIN (63, BitsOfAlignment
),
866 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
867 RootBridge
->PMemAbove4G
.Limit
869 if (BaseAddress
!= MAX_UINT64
) {
873 // If memory above 4GB is not available, try memory below 4GB
876 BaseAddress
= AllocateResource (
878 RootBridge
->ResAllocNode
[Index
].Length
,
879 MIN (31, BitsOfAlignment
),
880 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
881 RootBridge
->PMem
.Limit
890 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
891 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
892 if (BaseAddress
!= MAX_UINT64
) {
893 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
894 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
895 DEBUG ((DEBUG_INFO
, "Success\n"));
897 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
898 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
904 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
905 ResourceConflict (HostBridge
);
909 // Set resource to zero for nodes where allocation fails
911 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
912 ; !IsNull (&HostBridge
->RootBridges
, Link
)
913 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
915 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
916 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
917 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
918 RootBridge
->ResAllocNode
[Index
].Length
= 0;
924 case EfiPciHostBridgeSetResources
:
926 // HostBridgeInstance->CanRestarted = FALSE;
930 case EfiPciHostBridgeFreeResources
:
932 // HostBridgeInstance->CanRestarted = FALSE;
934 ReturnStatus
= EFI_SUCCESS
;
935 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
936 ; !IsNull (&HostBridge
->RootBridges
, Link
)
937 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
939 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
940 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
941 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
944 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
945 if (EFI_ERROR (Status
)) {
946 ReturnStatus
= Status
;
954 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
955 if (EFI_ERROR (Status
)) {
956 ReturnStatus
= Status
;
965 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
966 RootBridge
->ResAllocNode
[Index
].Base
= 0;
967 RootBridge
->ResAllocNode
[Index
].Length
= 0;
968 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
972 RootBridge
->ResourceSubmitted
= FALSE
;
975 HostBridge
->CanRestarted
= TRUE
;
978 case EfiPciHostBridgeEndResourceAllocation
:
980 // The resource allocation phase is completed. No specific action is required
981 // here. This notification can be used to perform any chipset specific programming.
985 case EfiPciHostBridgeEndEnumeration
:
987 // The Host Bridge Enumeration is completed. No specific action is required here.
988 // This notification can be used to perform any chipset specific programming.
993 return EFI_INVALID_PARAMETER
;
1001 Return the device handle of the next PCI root bridge that is associated with
1004 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1005 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
1006 On input, it holds the RootBridgeHandle returned by the most
1007 recent call to GetNextRootBridge().The handle for the first
1008 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
1010 @retval EFI_SUCCESS Succeed.
1011 @retval EFI_NOT_FOUND Next PCI root bridge not found.
1012 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
1018 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1019 IN OUT EFI_HANDLE
*RootBridgeHandle
1024 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1025 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1027 if (RootBridgeHandle
== NULL
) {
1028 return EFI_INVALID_PARAMETER
;
1031 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1032 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
1034 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1035 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1036 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1038 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1040 *RootBridgeHandle
= RootBridge
->Handle
;
1044 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
1048 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
1049 return EFI_NOT_FOUND
;
1051 return EFI_INVALID_PARAMETER
;
1057 Returns the attributes of a PCI Root Bridge.
1059 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1060 @param RootBridgeHandle The device handle of the PCI Root Bridge
1061 that the caller is interested in.
1062 @param Attributes The pointer to attributes of the PCI Root Bridge.
1064 @retval EFI_SUCCESS Succeed.
1065 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1066 RootBridgeHandle is not an EFI_HANDLE
1067 that was returned on a previous call to
1068 GetNextRootBridge().
1074 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1075 IN EFI_HANDLE RootBridgeHandle
,
1076 OUT UINT64
*Attributes
1080 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1081 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1083 if (Attributes
== NULL
) {
1084 return EFI_INVALID_PARAMETER
;
1087 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1088 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1089 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1090 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1092 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1093 if (RootBridgeHandle
== RootBridge
->Handle
) {
1094 *Attributes
= RootBridge
->AllocationAttributes
;
1099 return EFI_INVALID_PARAMETER
;
1104 This is the request from the PCI enumerator to set up
1105 the specified PCI Root Bridge for bus enumeration process.
1107 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1108 @param RootBridgeHandle The PCI Root Bridge to be set up.
1109 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1111 @retval EFI_SUCCESS Succeed.
1112 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1113 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1118 StartBusEnumeration (
1119 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1120 IN EFI_HANDLE RootBridgeHandle
,
1121 OUT VOID
**Configuration
1125 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1126 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1127 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1128 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1130 if (Configuration
== NULL
) {
1131 return EFI_INVALID_PARAMETER
;
1134 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1135 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1136 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1137 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1139 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1140 if (RootBridgeHandle
== RootBridge
->Handle
) {
1141 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1142 if (*Configuration
== NULL
) {
1143 return EFI_OUT_OF_RESOURCES
;
1146 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
1147 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1148 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1149 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1150 Descriptor
->GenFlag
= 0;
1151 Descriptor
->SpecificFlag
= 0;
1152 Descriptor
->AddrSpaceGranularity
= 0;
1153 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
1154 Descriptor
->AddrRangeMax
= 0;
1155 Descriptor
->AddrTranslationOffset
= 0;
1156 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
1158 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1159 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1160 End
->Checksum
= 0x0;
1166 return EFI_INVALID_PARAMETER
;
1171 This function programs the PCI Root Bridge hardware so that
1172 it decodes the specified PCI bus range.
1174 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1175 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1176 @param Configuration The pointer to the PCI bus resource descriptor.
1178 @retval EFI_SUCCESS Succeed.
1179 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1185 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1186 IN EFI_HANDLE RootBridgeHandle
,
1187 IN VOID
*Configuration
1191 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1192 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1193 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1194 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1196 if (Configuration
== NULL
) {
1197 return EFI_INVALID_PARAMETER
;
1200 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1201 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1204 // Check the Configuration is valid
1206 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
1207 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
1208 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
1210 return EFI_INVALID_PARAMETER
;
1213 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1214 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1215 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1216 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1218 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1219 if (RootBridgeHandle
== RootBridge
->Handle
) {
1221 if (Descriptor
->AddrLen
== 0) {
1222 return EFI_INVALID_PARAMETER
;
1225 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
1226 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
1228 return EFI_INVALID_PARAMETER
;
1231 // Update the Bus Range
1233 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
1234 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
1235 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
1240 return EFI_INVALID_PARAMETER
;
1245 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1247 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1248 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1249 are being submitted.
1250 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1252 @retval EFI_SUCCESS Succeed.
1253 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1258 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1259 IN EFI_HANDLE RootBridgeHandle
,
1260 IN VOID
*Configuration
1264 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1265 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1266 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1267 PCI_RESOURCE_TYPE Type
;
1270 // Check the input parameter: Configuration
1272 if (Configuration
== NULL
) {
1273 return EFI_INVALID_PARAMETER
;
1276 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1277 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1278 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1279 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1281 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1282 if (RootBridgeHandle
== RootBridge
->Handle
) {
1283 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
1285 // Check the resource descriptors.
1286 // If the Configuration includes one or more invalid resource descriptors, all the resource
1287 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1289 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1290 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1291 return EFI_INVALID_PARAMETER
;
1294 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1295 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
1296 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
1298 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
1299 switch (Descriptor
->ResType
) {
1300 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1301 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
1302 return EFI_INVALID_PARAMETER
;
1304 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
1305 return EFI_INVALID_PARAMETER
;
1308 // If the PCI root bridge does not support separate windows for nonprefetchable and
1309 // prefetchable memory, then the PCI bus driver needs to include requests for
1310 // prefetchable memory in the nonprefetchable memory pool.
1312 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
1313 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
1315 return EFI_INVALID_PARAMETER
;
1317 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1319 // Check aligment, it should be of the form 2^n-1
1321 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
1322 return EFI_INVALID_PARAMETER
;
1330 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1331 return EFI_INVALID_PARAMETER
;
1334 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1335 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1336 if (Descriptor
->AddrSpaceGranularity
== 32) {
1337 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1343 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
1344 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1351 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
1354 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
1355 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
1356 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
1358 RootBridge
->ResourceSubmitted
= TRUE
;
1363 return EFI_INVALID_PARAMETER
;
1368 This function returns the proposed resource settings for the specified
1371 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1372 @param RootBridgeHandle The PCI Root Bridge handle.
1373 @param Configuration The pointer to the pointer to the PCI I/O
1374 and memory resource descriptor.
1376 @retval EFI_SUCCESS Succeed.
1377 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1378 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1383 GetProposedResources (
1384 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1385 IN EFI_HANDLE RootBridgeHandle
,
1386 OUT VOID
**Configuration
1390 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1391 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1395 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1396 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1399 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1400 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1401 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1402 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1404 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1405 if (RootBridgeHandle
== RootBridge
->Handle
) {
1406 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1407 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1412 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1413 if (Buffer
== NULL
) {
1414 return EFI_OUT_OF_RESOURCES
;
1417 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1418 for (Index
= 0; Index
< TypeBus
; Index
++) {
1419 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1420 if (ResStatus
!= ResNone
) {
1421 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1422 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1423 Descriptor
->GenFlag
= 0;
1424 Descriptor
->AddrRangeMin
= RootBridge
->ResAllocNode
[Index
].Base
;
1425 Descriptor
->AddrRangeMax
= 0;
1426 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1427 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1432 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1436 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1438 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1439 Descriptor
->AddrSpaceGranularity
= 32;
1443 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1445 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1446 Descriptor
->AddrSpaceGranularity
= 64;
1453 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1454 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1457 *Configuration
= Buffer
;
1463 return EFI_INVALID_PARAMETER
;
1468 This function is called for all the PCI controllers that the PCI
1469 bus driver finds. Can be used to Preprogram the controller.
1471 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1472 @param RootBridgeHandle The PCI Root Bridge handle.
1473 @param PciAddress Address of the controller on the PCI bus.
1474 @param Phase The Phase during resource allocation.
1476 @retval EFI_SUCCESS Succeed.
1477 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1482 PreprocessController (
1483 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1484 IN EFI_HANDLE RootBridgeHandle
,
1485 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1486 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1490 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1491 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1493 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1494 return EFI_INVALID_PARAMETER
;
1497 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1498 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1499 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1500 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1502 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1503 if (RootBridgeHandle
== RootBridge
->Handle
) {
1508 return EFI_INVALID_PARAMETER
;