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"
33 Entry point of this driver.
35 @param ImageHandle Image handle of this driver.
36 @param SystemTable Pointer to standard EFI system table.
38 @retval EFI_SUCCESS Succeed.
39 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
44 InitializePciHostBridge (
45 IN EFI_HANDLE ImageHandle
,
46 IN EFI_SYSTEM_TABLE
*SystemTable
50 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
51 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
52 PCI_ROOT_BRIDGE
*RootBridges
;
53 UINTN RootBridgeCount
;
55 PCI_ROOT_BRIDGE_APERTURE
*MemApertures
[4];
56 UINTN MemApertureIndex
;
58 RootBridges
= PciHostBridgeGetRootBridges (&RootBridgeCount
);
59 if ((RootBridges
== NULL
) || (RootBridgeCount
== 0)) {
60 return EFI_UNSUPPORTED
;
63 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**) &mMetronome
);
64 ASSERT_EFI_ERROR (Status
);
65 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**) &mCpuIo
);
66 ASSERT_EFI_ERROR (Status
);
69 // Most systems in the world including complex servers have only one Host Bridge.
71 HostBridge
= AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE
));
72 ASSERT (HostBridge
!= NULL
);
74 HostBridge
->Signature
= PCI_HOST_BRIDGE_SIGNATURE
;
75 HostBridge
->CanRestarted
= TRUE
;
76 InitializeListHead (&HostBridge
->RootBridges
);
78 HostBridge
->ResAlloc
.NotifyPhase
= NotifyPhase
;
79 HostBridge
->ResAlloc
.GetNextRootBridge
= GetNextRootBridge
;
80 HostBridge
->ResAlloc
.GetAllocAttributes
= GetAttributes
;
81 HostBridge
->ResAlloc
.StartBusEnumeration
= StartBusEnumeration
;
82 HostBridge
->ResAlloc
.SetBusNumbers
= SetBusNumbers
;
83 HostBridge
->ResAlloc
.SubmitResources
= SubmitResources
;
84 HostBridge
->ResAlloc
.GetProposedResources
= GetProposedResources
;
85 HostBridge
->ResAlloc
.PreprocessController
= PreprocessController
;
87 Status
= gBS
->InstallMultipleProtocolInterfaces (
89 &gEfiPciHostBridgeResourceAllocationProtocolGuid
, &HostBridge
->ResAlloc
,
92 if (EFI_ERROR (Status
)) {
93 FreePool (HostBridge
);
94 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
99 // Create Root Bridge Device Handle in this Host Bridge
101 for (Index
= 0; Index
< RootBridgeCount
; Index
++) {
103 // Create Root Bridge Handle Instance
105 RootBridge
= CreateRootBridge (&RootBridges
[Index
], HostBridge
->Handle
);
106 ASSERT (RootBridge
!= NULL
);
107 if (RootBridge
== NULL
) {
111 if (RootBridges
[Index
].Io
.Limit
> RootBridges
[Index
].Io
.Base
) {
112 Status
= gDS
->AddIoSpace (
114 RootBridges
[Index
].Io
.Base
,
115 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1
117 ASSERT_EFI_ERROR (Status
);
121 // Add all the Mem/PMem aperture to GCD
122 // Mem/PMem shouldn't overlap with each other
123 // Root bridge which needs to combine MEM and PMEM should only report
124 // the MEM aperture in Mem
126 MemApertures
[0] = &RootBridges
[Index
].Mem
;
127 MemApertures
[1] = &RootBridges
[Index
].MemAbove4G
;
128 MemApertures
[2] = &RootBridges
[Index
].PMem
;
129 MemApertures
[3] = &RootBridges
[Index
].PMemAbove4G
;
131 for (MemApertureIndex
= 0; MemApertureIndex
< sizeof (MemApertures
) / sizeof (MemApertures
[0]); MemApertureIndex
++) {
132 if (MemApertures
[MemApertureIndex
]->Limit
> MemApertures
[MemApertureIndex
]->Base
) {
133 Status
= gDS
->AddMemorySpace (
134 EfiGcdMemoryTypeMemoryMappedIo
,
135 MemApertures
[MemApertureIndex
]->Base
,
136 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
139 ASSERT_EFI_ERROR (Status
);
140 Status
= gDS
->SetMemorySpaceAttributes (
141 MemApertures
[MemApertureIndex
]->Base
,
142 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
145 ASSERT_EFI_ERROR (Status
);
149 // Insert Root Bridge Handle Instance
151 Status
= gBS
->InstallMultipleProtocolInterfaces (
153 &gEfiDevicePathProtocolGuid
, RootBridge
->DevicePath
,
154 &gEfiPciRootBridgeIoProtocolGuid
, &RootBridge
->RootBridgeIo
,
157 ASSERT_EFI_ERROR (Status
);
158 InsertTailList (&HostBridge
->RootBridges
, &RootBridge
->Link
);
160 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
165 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
167 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
171 IN PCI_HOST_BRIDGE_INSTANCE
*HostBridge
174 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
175 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
176 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
177 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
179 UINTN RootBridgeCount
;
180 PCI_RESOURCE_TYPE Index
;
181 PCI_RES_NODE
*ResAllocNode
;
184 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
185 ; !IsNull (&HostBridge
->RootBridges
, Link
)
186 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
191 Resources
= AllocatePool (
192 RootBridgeCount
* (TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)) +
193 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
195 ASSERT (Resources
!= NULL
);
197 for (Link
= GetFirstNode (&HostBridge
->RootBridges
), Descriptor
= Resources
198 ; !IsNull (&HostBridge
->RootBridges
, Link
)
199 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
201 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
202 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
203 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
205 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
206 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
207 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
208 Descriptor
->AddrRangeMax
= ResAllocNode
->Alignment
;
209 Descriptor
->AddrLen
= ResAllocNode
->Length
;
210 switch (ResAllocNode
->Type
) {
213 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
217 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
219 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
220 Descriptor
->AddrSpaceGranularity
= 32;
224 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
226 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
227 Descriptor
->AddrSpaceGranularity
= 64;
231 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
241 // Terminate the root bridge resources.
243 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
244 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
247 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (End
+ 1);
250 // Terminate the host bridge resources.
252 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
253 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
256 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
257 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
258 FreePool (Resources
);
262 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
263 from GCD range [BaseAddress, Limit).
265 @param Mmio TRUE for MMIO and FALSE for IO.
266 @param Length Length of the resource to allocate.
267 @param BitsOfAlignment Alignment of the resource to allocate.
268 @param BaseAddress The starting address the allocation is from.
269 @param Limit The ending address the allocation is to.
271 @retval The base address of the allocated resource or MAX_UINT64 if allocation
278 UINTN BitsOfAlignment
,
285 if (BaseAddress
< Limit
) {
287 // Have to make sure Aligment is handled since we are doing direct address allocation
289 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
291 while (BaseAddress
+ Length
<= Limit
+ 1) {
293 Status
= gDS
->AllocateMemorySpace (
294 EfiGcdAllocateAddress
,
295 EfiGcdMemoryTypeMemoryMappedIo
,
303 Status
= gDS
->AllocateIoSpace (
304 EfiGcdAllocateAddress
,
314 if (!EFI_ERROR (Status
)) {
317 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
325 Enter a certain phase of the PCI enumeration process.
327 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
328 @param Phase The phase during enumeration.
330 @retval EFI_SUCCESS Succeed.
331 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
332 @retval EFI_NOT_READY Resources have not been submitted yet.
338 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
339 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
342 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
343 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
345 EFI_PHYSICAL_ADDRESS BaseAddress
;
347 UINTN BitsOfAlignment
;
350 EFI_STATUS ReturnStatus
;
351 PCI_RESOURCE_TYPE Index
;
352 PCI_RESOURCE_TYPE Index1
;
353 PCI_RESOURCE_TYPE Index2
;
354 BOOLEAN ResNodeHandled
[TypeMax
];
357 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
360 case EfiPciHostBridgeBeginEnumeration
:
361 if (!HostBridge
->CanRestarted
) {
362 return EFI_NOT_READY
;
367 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
368 ; !IsNull (&HostBridge
->RootBridges
, Link
)
369 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
371 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
372 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
373 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
374 RootBridge
->ResAllocNode
[Index
].Base
= 0;
375 RootBridge
->ResAllocNode
[Index
].Length
= 0;
376 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
378 RootBridge
->ResourceSubmitted
= FALSE
;
382 HostBridge
->CanRestarted
= TRUE
;
385 case EfiPciHostBridgeBeginBusAllocation
:
387 // No specific action is required here, can perform any chipset specific programing
389 HostBridge
->CanRestarted
= FALSE
;
392 case EfiPciHostBridgeEndBusAllocation
:
394 // No specific action is required here, can perform any chipset specific programing
398 case EfiPciHostBridgeBeginResourceAllocation
:
400 // No specific action is required here, can perform any chipset specific programing
404 case EfiPciHostBridgeAllocateResources
:
405 ReturnStatus
= EFI_SUCCESS
;
408 // Make sure the resource for all root bridges has been submitted.
410 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
411 ; !IsNull (&HostBridge
->RootBridges
, Link
)
412 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
414 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
415 if (!RootBridge
->ResourceSubmitted
) {
416 return EFI_NOT_READY
;
420 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
421 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
422 ; !IsNull (&HostBridge
->RootBridges
, Link
)
423 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
425 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
426 ResNodeHandled
[Index
] = FALSE
;
429 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
430 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
432 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
433 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
434 ResNodeHandled
[Index1
] = TRUE
;
437 // Allocate the resource node with max alignment at first
441 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
442 if (ResNodeHandled
[Index2
]) {
445 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
446 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
451 ASSERT (Index
< TypeMax
);
452 ResNodeHandled
[Index
] = TRUE
;
453 AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
454 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
455 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
456 BaseAddress
= MAX_UINT64
;
460 BaseAddress
= AllocateResource (
462 RootBridge
->ResAllocNode
[Index
].Length
,
463 MIN (15, BitsOfAlignment
),
464 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
470 BaseAddress
= AllocateResource (
472 RootBridge
->ResAllocNode
[Index
].Length
,
473 MIN (63, BitsOfAlignment
),
474 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
475 RootBridge
->MemAbove4G
.Limit
477 if (BaseAddress
!= MAX_UINT64
) {
481 // If memory above 4GB is not available, try memory below 4GB
485 BaseAddress
= AllocateResource (
487 RootBridge
->ResAllocNode
[Index
].Length
,
488 MIN (31, BitsOfAlignment
),
489 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
490 RootBridge
->Mem
.Limit
495 BaseAddress
= AllocateResource (
497 RootBridge
->ResAllocNode
[Index
].Length
,
498 MIN (63, BitsOfAlignment
),
499 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
500 RootBridge
->PMemAbove4G
.Limit
502 if (BaseAddress
!= MAX_UINT64
) {
506 // If memory above 4GB is not available, try memory below 4GB
509 BaseAddress
= AllocateResource (
511 RootBridge
->ResAllocNode
[Index
].Length
,
512 MIN (31, BitsOfAlignment
),
513 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
514 RootBridge
->PMem
.Limit
523 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
524 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
525 if (BaseAddress
!= MAX_UINT64
) {
526 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
527 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
528 DEBUG ((DEBUG_INFO
, "Success\n"));
530 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
531 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
537 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
538 ResourceConflict (HostBridge
);
542 // Set resource to zero for nodes where allocation fails
544 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
545 ; !IsNull (&HostBridge
->RootBridges
, Link
)
546 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
548 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
549 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
550 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
551 RootBridge
->ResAllocNode
[Index
].Length
= 0;
557 case EfiPciHostBridgeSetResources
:
559 // HostBridgeInstance->CanRestarted = FALSE;
563 case EfiPciHostBridgeFreeResources
:
565 // HostBridgeInstance->CanRestarted = FALSE;
567 ReturnStatus
= EFI_SUCCESS
;
568 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
569 ; !IsNull (&HostBridge
->RootBridges
, Link
)
570 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
572 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
573 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
574 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
577 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
578 if (EFI_ERROR (Status
)) {
579 ReturnStatus
= Status
;
587 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
588 if (EFI_ERROR (Status
)) {
589 ReturnStatus
= Status
;
598 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
599 RootBridge
->ResAllocNode
[Index
].Base
= 0;
600 RootBridge
->ResAllocNode
[Index
].Length
= 0;
601 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
605 RootBridge
->ResourceSubmitted
= FALSE
;
608 HostBridge
->CanRestarted
= TRUE
;
611 case EfiPciHostBridgeEndResourceAllocation
:
613 // The resource allocation phase is completed. No specific action is required
614 // here. This notification can be used to perform any chipset specific programming.
618 case EfiPciHostBridgeEndEnumeration
:
620 // The Host Bridge Enumeration is completed. No specific action is required here.
621 // This notification can be used to perform any chipset specific programming.
626 return EFI_INVALID_PARAMETER
;
634 Return the device handle of the next PCI root bridge that is associated with
637 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
638 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
639 On input, it holds the RootBridgeHandle returned by the most
640 recent call to GetNextRootBridge().The handle for the first
641 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
643 @retval EFI_SUCCESS Succeed.
644 @retval EFI_NOT_FOUND Next PCI root bridge not found.
645 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
651 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
652 IN OUT EFI_HANDLE
*RootBridgeHandle
657 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
658 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
660 if (RootBridgeHandle
== NULL
) {
661 return EFI_INVALID_PARAMETER
;
664 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
665 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
667 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
668 ; !IsNull (&HostBridge
->RootBridges
, Link
)
669 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
671 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
673 *RootBridgeHandle
= RootBridge
->Handle
;
677 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
681 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
682 return EFI_NOT_FOUND
;
684 return EFI_INVALID_PARAMETER
;
690 Returns the attributes of a PCI Root Bridge.
692 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
693 @param RootBridgeHandle The device handle of the PCI Root Bridge
694 that the caller is interested in.
695 @param Attributes The pointer to attributes of the PCI Root Bridge.
697 @retval EFI_SUCCESS Succeed.
698 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
699 RootBridgeHandle is not an EFI_HANDLE
700 that was returned on a previous call to
707 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
708 IN EFI_HANDLE RootBridgeHandle
,
709 OUT UINT64
*Attributes
713 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
714 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
716 if (Attributes
== NULL
) {
717 return EFI_INVALID_PARAMETER
;
720 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
721 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
722 ; !IsNull (&HostBridge
->RootBridges
, Link
)
723 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
725 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
726 if (RootBridgeHandle
== RootBridge
->Handle
) {
727 *Attributes
= RootBridge
->AllocationAttributes
;
732 return EFI_INVALID_PARAMETER
;
737 This is the request from the PCI enumerator to set up
738 the specified PCI Root Bridge for bus enumeration process.
740 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
741 @param RootBridgeHandle The PCI Root Bridge to be set up.
742 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
744 @retval EFI_SUCCESS Succeed.
745 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
746 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
751 StartBusEnumeration (
752 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
753 IN EFI_HANDLE RootBridgeHandle
,
754 OUT VOID
**Configuration
758 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
759 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
760 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
761 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
763 if (Configuration
== NULL
) {
764 return EFI_INVALID_PARAMETER
;
767 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
768 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
769 ; !IsNull (&HostBridge
->RootBridges
, Link
)
770 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
772 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
773 if (RootBridgeHandle
== RootBridge
->Handle
) {
774 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
775 if (*Configuration
== NULL
) {
776 return EFI_OUT_OF_RESOURCES
;
779 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
780 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
781 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
782 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
783 Descriptor
->GenFlag
= 0;
784 Descriptor
->SpecificFlag
= 0;
785 Descriptor
->AddrSpaceGranularity
= 0;
786 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
787 Descriptor
->AddrRangeMax
= 0;
788 Descriptor
->AddrTranslationOffset
= 0;
789 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
791 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
792 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
799 return EFI_INVALID_PARAMETER
;
804 This function programs the PCI Root Bridge hardware so that
805 it decodes the specified PCI bus range.
807 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
808 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
809 @param Configuration The pointer to the PCI bus resource descriptor.
811 @retval EFI_SUCCESS Succeed.
812 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
818 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
819 IN EFI_HANDLE RootBridgeHandle
,
820 IN VOID
*Configuration
824 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
825 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
826 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
827 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
832 if (Configuration
== NULL
) {
833 return EFI_INVALID_PARAMETER
;
836 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
837 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
840 // Check the Configuration is valid
842 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
843 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
844 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
846 return EFI_INVALID_PARAMETER
;
849 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
850 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
851 ; !IsNull (&HostBridge
->RootBridges
, Link
)
852 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
854 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
855 if (RootBridgeHandle
== RootBridge
->Handle
) {
856 BusStart
= (UINTN
) Descriptor
->AddrRangeMin
;
857 BusLen
= (UINTN
) Descriptor
->AddrLen
;
858 BusEnd
= BusStart
+ BusLen
- 1;
860 if (Descriptor
->AddrLen
== 0) {
861 return EFI_INVALID_PARAMETER
;
864 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
865 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
867 return EFI_INVALID_PARAMETER
;
870 // Update the Bus Range
872 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
873 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
874 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
879 return EFI_INVALID_PARAMETER
;
884 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
886 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
887 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
889 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
891 @retval EFI_SUCCESS Succeed.
892 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
897 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
898 IN EFI_HANDLE RootBridgeHandle
,
899 IN VOID
*Configuration
903 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
904 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
905 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
906 PCI_RESOURCE_TYPE Type
;
909 // Check the input parameter: Configuration
911 if (Configuration
== NULL
) {
912 return EFI_INVALID_PARAMETER
;
915 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
916 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
917 ; !IsNull (&HostBridge
->RootBridges
, Link
)
918 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
920 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
921 if (RootBridgeHandle
== RootBridge
->Handle
) {
922 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
924 // Check the resource descriptors.
925 // If the Configuration includes one or more invalid resource descriptors, all the resource
926 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
928 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
929 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
930 return EFI_INVALID_PARAMETER
;
933 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
934 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
935 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
937 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
938 switch (Descriptor
->ResType
) {
939 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
940 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
941 return EFI_INVALID_PARAMETER
;
943 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
944 return EFI_INVALID_PARAMETER
;
947 // If the PCI root bridge does not support separate windows for nonprefetchable and
948 // prefetchable memory, then the PCI bus driver needs to include requests for
949 // prefetchable memory in the nonprefetchable memory pool.
951 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
952 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
954 return EFI_INVALID_PARAMETER
;
956 case ACPI_ADDRESS_SPACE_TYPE_IO
:
958 // Check aligment, it should be of the form 2^n-1
960 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
961 return EFI_INVALID_PARAMETER
;
969 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
970 return EFI_INVALID_PARAMETER
;
973 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
974 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
975 if (Descriptor
->AddrSpaceGranularity
== 32) {
976 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
982 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
983 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
990 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
993 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
994 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
995 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
997 RootBridge
->ResourceSubmitted
= TRUE
;
1002 return EFI_INVALID_PARAMETER
;
1007 This function returns the proposed resource settings for the specified
1010 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1011 @param RootBridgeHandle The PCI Root Bridge handle.
1012 @param Configuration The pointer to the pointer to the PCI I/O
1013 and memory resource descriptor.
1015 @retval EFI_SUCCESS Succeed.
1016 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1017 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1022 GetProposedResources (
1023 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1024 IN EFI_HANDLE RootBridgeHandle
,
1025 OUT VOID
**Configuration
1029 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1030 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1034 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1035 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1038 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1039 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1040 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1041 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1043 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1044 if (RootBridgeHandle
== RootBridge
->Handle
) {
1045 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1046 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1051 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1052 if (Buffer
== NULL
) {
1053 return EFI_OUT_OF_RESOURCES
;
1056 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1057 for (Index
= 0; Index
< TypeBus
; Index
++) {
1058 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1059 if (ResStatus
!= ResNone
) {
1060 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1061 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1062 Descriptor
->GenFlag
= 0;
1063 Descriptor
->AddrRangeMin
= RootBridge
->ResAllocNode
[Index
].Base
;
1064 Descriptor
->AddrRangeMax
= 0;
1065 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1066 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1071 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1075 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1077 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1078 Descriptor
->AddrSpaceGranularity
= 32;
1082 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1084 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1085 Descriptor
->AddrSpaceGranularity
= 64;
1092 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1093 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1096 *Configuration
= Buffer
;
1102 return EFI_INVALID_PARAMETER
;
1107 This function is called for all the PCI controllers that the PCI
1108 bus driver finds. Can be used to Preprogram the controller.
1110 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1111 @param RootBridgeHandle The PCI Root Bridge handle.
1112 @param PciAddress Address of the controller on the PCI bus.
1113 @param Phase The Phase during resource allocation.
1115 @retval EFI_SUCCESS Succeed.
1116 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1121 PreprocessController (
1122 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1123 IN EFI_HANDLE RootBridgeHandle
,
1124 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1125 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1129 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1130 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1132 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1133 return EFI_INVALID_PARAMETER
;
1136 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1137 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1138 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1139 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1141 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1142 if (RootBridgeHandle
== RootBridge
->Handle
) {
1147 return EFI_INVALID_PARAMETER
;