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
);
265 UINTN BitsOfAlignment
,
272 if (BaseAddress
< Limit
) {
274 // Have to make sure Aligment is handled since we are doing direct address allocation
276 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
278 while (BaseAddress
+ Length
<= Limit
+ 1) {
280 Status
= gDS
->AllocateMemorySpace (
281 EfiGcdAllocateAddress
,
282 EfiGcdMemoryTypeMemoryMappedIo
,
290 Status
= gDS
->AllocateIoSpace (
291 EfiGcdAllocateAddress
,
301 if (!EFI_ERROR (Status
)) {
304 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
311 Enter a certain phase of the PCI enumeration process.
313 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
314 @param Phase The phase during enumeration.
316 @retval EFI_SUCCESS Succeed.
317 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
318 @retval EFI_NOT_READY Resources have not been submitted yet.
324 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
325 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
328 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
329 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
331 EFI_PHYSICAL_ADDRESS BaseAddress
;
333 UINTN BitsOfAlignment
;
336 EFI_STATUS ReturnStatus
;
337 PCI_RESOURCE_TYPE Index
;
338 PCI_RESOURCE_TYPE Index1
;
339 PCI_RESOURCE_TYPE Index2
;
340 BOOLEAN ResNodeHandled
[TypeMax
];
343 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
346 case EfiPciHostBridgeBeginEnumeration
:
347 if (!HostBridge
->CanRestarted
) {
348 return EFI_NOT_READY
;
353 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
354 ; !IsNull (&HostBridge
->RootBridges
, Link
)
355 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
357 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
358 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
359 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
360 RootBridge
->ResAllocNode
[Index
].Base
= 0;
361 RootBridge
->ResAllocNode
[Index
].Length
= 0;
362 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
364 RootBridge
->ResourceSubmitted
= FALSE
;
368 HostBridge
->CanRestarted
= TRUE
;
371 case EfiPciHostBridgeBeginBusAllocation
:
373 // No specific action is required here, can perform any chipset specific programing
375 HostBridge
->CanRestarted
= FALSE
;
378 case EfiPciHostBridgeEndBusAllocation
:
380 // No specific action is required here, can perform any chipset specific programing
384 case EfiPciHostBridgeBeginResourceAllocation
:
386 // No specific action is required here, can perform any chipset specific programing
390 case EfiPciHostBridgeAllocateResources
:
391 ReturnStatus
= EFI_SUCCESS
;
394 // Make sure the resource for all root bridges has been submitted.
396 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
397 ; !IsNull (&HostBridge
->RootBridges
, Link
)
398 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
400 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
401 if (!RootBridge
->ResourceSubmitted
) {
402 return EFI_NOT_READY
;
406 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
407 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
408 ; !IsNull (&HostBridge
->RootBridges
, Link
)
409 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
411 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
412 ResNodeHandled
[Index
] = FALSE
;
415 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
416 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
418 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
419 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
420 ResNodeHandled
[Index1
] = TRUE
;
423 // Allocate the resource node with max alignment at first
427 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
428 if (ResNodeHandled
[Index2
]) {
431 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
432 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
437 ASSERT (Index
< TypeMax
);
438 ResNodeHandled
[Index
] = TRUE
;
439 AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
440 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
441 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
442 BaseAddress
= MAX_UINT64
;
446 BaseAddress
= AllocateResource (
448 RootBridge
->ResAllocNode
[Index
].Length
,
449 MIN (15, BitsOfAlignment
),
450 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
456 BaseAddress
= AllocateResource (
458 RootBridge
->ResAllocNode
[Index
].Length
,
459 MIN (63, BitsOfAlignment
),
460 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
461 RootBridge
->MemAbove4G
.Limit
463 if (BaseAddress
!= MAX_UINT64
) {
467 // If memory above 4GB is not available, try memory below 4GB
471 BaseAddress
= AllocateResource (
473 RootBridge
->ResAllocNode
[Index
].Length
,
474 MIN (31, BitsOfAlignment
),
475 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
476 RootBridge
->Mem
.Limit
481 BaseAddress
= AllocateResource (
483 RootBridge
->ResAllocNode
[Index
].Length
,
484 MIN (63, BitsOfAlignment
),
485 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
486 RootBridge
->PMemAbove4G
.Limit
488 if (BaseAddress
!= MAX_UINT64
) {
492 // If memory above 4GB is not available, try memory below 4GB
495 BaseAddress
= AllocateResource (
497 RootBridge
->ResAllocNode
[Index
].Length
,
498 MIN (31, BitsOfAlignment
),
499 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
500 RootBridge
->PMem
.Limit
509 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
510 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
511 if (BaseAddress
!= MAX_UINT64
) {
512 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
513 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
514 DEBUG ((DEBUG_INFO
, "Success\n"));
516 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
517 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
523 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
524 ResourceConflict (HostBridge
);
528 // Set resource to zero for nodes where allocation fails
530 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
531 ; !IsNull (&HostBridge
->RootBridges
, Link
)
532 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
534 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
535 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
536 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
537 RootBridge
->ResAllocNode
[Index
].Length
= 0;
543 case EfiPciHostBridgeSetResources
:
545 // HostBridgeInstance->CanRestarted = FALSE;
549 case EfiPciHostBridgeFreeResources
:
551 // HostBridgeInstance->CanRestarted = FALSE;
553 ReturnStatus
= EFI_SUCCESS
;
554 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
555 ; !IsNull (&HostBridge
->RootBridges
, Link
)
556 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
558 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
559 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
560 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
563 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
564 if (EFI_ERROR (Status
)) {
565 ReturnStatus
= Status
;
573 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
574 if (EFI_ERROR (Status
)) {
575 ReturnStatus
= Status
;
584 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
585 RootBridge
->ResAllocNode
[Index
].Base
= 0;
586 RootBridge
->ResAllocNode
[Index
].Length
= 0;
587 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
591 RootBridge
->ResourceSubmitted
= FALSE
;
594 HostBridge
->CanRestarted
= TRUE
;
597 case EfiPciHostBridgeEndResourceAllocation
:
599 // The resource allocation phase is completed. No specific action is required
600 // here. This notification can be used to perform any chipset specific programming.
604 case EfiPciHostBridgeEndEnumeration
:
606 // The Host Bridge Enumeration is completed. No specific action is required here.
607 // This notification can be used to perform any chipset specific programming.
612 return EFI_INVALID_PARAMETER
;
620 Return the device handle of the next PCI root bridge that is associated with
623 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
624 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
625 On input, it holds the RootBridgeHandle returned by the most
626 recent call to GetNextRootBridge().The handle for the first
627 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
629 @retval EFI_SUCCESS Succeed.
630 @retval EFI_NOT_FOUND Next PCI root bridge not found.
631 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
637 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
638 IN OUT EFI_HANDLE
*RootBridgeHandle
643 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
644 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
646 if (RootBridgeHandle
== NULL
) {
647 return EFI_INVALID_PARAMETER
;
650 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
651 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
653 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
654 ; !IsNull (&HostBridge
->RootBridges
, Link
)
655 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
657 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
659 *RootBridgeHandle
= RootBridge
->Handle
;
663 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
667 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
668 return EFI_NOT_FOUND
;
670 return EFI_INVALID_PARAMETER
;
676 Returns the attributes of a PCI Root Bridge.
678 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
679 @param RootBridgeHandle The device handle of the PCI Root Bridge
680 that the caller is interested in.
681 @param Attributes The pointer to attributes of the PCI Root Bridge.
683 @retval EFI_SUCCESS Succeed.
684 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
685 RootBridgeHandle is not an EFI_HANDLE
686 that was returned on a previous call to
693 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
694 IN EFI_HANDLE RootBridgeHandle
,
695 OUT UINT64
*Attributes
699 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
700 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
702 if (Attributes
== NULL
) {
703 return EFI_INVALID_PARAMETER
;
706 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
707 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
708 ; !IsNull (&HostBridge
->RootBridges
, Link
)
709 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
711 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
712 if (RootBridgeHandle
== RootBridge
->Handle
) {
713 *Attributes
= RootBridge
->AllocationAttributes
;
718 return EFI_INVALID_PARAMETER
;
723 This is the request from the PCI enumerator to set up
724 the specified PCI Root Bridge for bus enumeration process.
726 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
727 @param RootBridgeHandle The PCI Root Bridge to be set up.
728 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
730 @retval EFI_SUCCESS Succeed.
731 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
732 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
737 StartBusEnumeration (
738 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
739 IN EFI_HANDLE RootBridgeHandle
,
740 OUT VOID
**Configuration
744 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
745 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
746 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
747 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
749 if (Configuration
== NULL
) {
750 return EFI_INVALID_PARAMETER
;
753 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
754 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
755 ; !IsNull (&HostBridge
->RootBridges
, Link
)
756 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
758 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
759 if (RootBridgeHandle
== RootBridge
->Handle
) {
760 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
761 if (*Configuration
== NULL
) {
762 return EFI_OUT_OF_RESOURCES
;
765 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
766 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
767 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
768 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
769 Descriptor
->GenFlag
= 0;
770 Descriptor
->SpecificFlag
= 0;
771 Descriptor
->AddrSpaceGranularity
= 0;
772 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
773 Descriptor
->AddrRangeMax
= 0;
774 Descriptor
->AddrTranslationOffset
= 0;
775 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
777 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
778 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
785 return EFI_INVALID_PARAMETER
;
790 This function programs the PCI Root Bridge hardware so that
791 it decodes the specified PCI bus range.
793 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
794 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
795 @param Configuration The pointer to the PCI bus resource descriptor.
797 @retval EFI_SUCCESS Succeed.
798 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
804 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
805 IN EFI_HANDLE RootBridgeHandle
,
806 IN VOID
*Configuration
810 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
811 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
812 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
813 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
818 if (Configuration
== NULL
) {
819 return EFI_INVALID_PARAMETER
;
822 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
823 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
826 // Check the Configuration is valid
828 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
829 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
830 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
832 return EFI_INVALID_PARAMETER
;
835 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
836 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
837 ; !IsNull (&HostBridge
->RootBridges
, Link
)
838 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
840 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
841 if (RootBridgeHandle
== RootBridge
->Handle
) {
842 BusStart
= (UINTN
) Descriptor
->AddrRangeMin
;
843 BusLen
= (UINTN
) Descriptor
->AddrLen
;
844 BusEnd
= BusStart
+ BusLen
- 1;
846 if (Descriptor
->AddrLen
== 0) {
847 return EFI_INVALID_PARAMETER
;
850 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
851 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
853 return EFI_INVALID_PARAMETER
;
856 // Update the Bus Range
858 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
859 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
860 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
865 return EFI_INVALID_PARAMETER
;
870 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
872 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
873 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
875 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
877 @retval EFI_SUCCESS Succeed.
878 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
883 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
884 IN EFI_HANDLE RootBridgeHandle
,
885 IN VOID
*Configuration
889 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
890 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
891 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
892 PCI_RESOURCE_TYPE Type
;
895 // Check the input parameter: Configuration
897 if (Configuration
== NULL
) {
898 return EFI_INVALID_PARAMETER
;
901 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
902 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
903 ; !IsNull (&HostBridge
->RootBridges
, Link
)
904 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
906 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
907 if (RootBridgeHandle
== RootBridge
->Handle
) {
908 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
910 // Check the resource descriptors.
911 // If the Configuration includes one or more invalid resource descriptors, all the resource
912 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
914 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
915 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
916 return EFI_INVALID_PARAMETER
;
919 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
920 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
921 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
923 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
924 switch (Descriptor
->ResType
) {
925 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
926 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
927 return EFI_INVALID_PARAMETER
;
929 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
930 return EFI_INVALID_PARAMETER
;
933 // If the PCI root bridge does not support separate windows for nonprefetchable and
934 // prefetchable memory, then the PCI bus driver needs to include requests for
935 // prefetchable memory in the nonprefetchable memory pool.
937 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
938 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
940 return EFI_INVALID_PARAMETER
;
942 case ACPI_ADDRESS_SPACE_TYPE_IO
:
944 // Check aligment, it should be of the form 2^n-1
946 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
947 return EFI_INVALID_PARAMETER
;
955 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
956 return EFI_INVALID_PARAMETER
;
959 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
960 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
961 if (Descriptor
->AddrSpaceGranularity
== 32) {
962 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
968 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
969 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
976 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
979 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
980 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
981 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
983 RootBridge
->ResourceSubmitted
= TRUE
;
988 return EFI_INVALID_PARAMETER
;
993 This function returns the proposed resource settings for the specified
996 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
997 @param RootBridgeHandle The PCI Root Bridge handle.
998 @param Configuration The pointer to the pointer to the PCI I/O
999 and memory resource descriptor.
1001 @retval EFI_SUCCESS Succeed.
1002 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1003 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1008 GetProposedResources (
1009 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1010 IN EFI_HANDLE RootBridgeHandle
,
1011 OUT VOID
**Configuration
1015 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1016 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1020 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1021 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1024 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1025 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1026 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1027 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1029 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1030 if (RootBridgeHandle
== RootBridge
->Handle
) {
1031 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1032 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1037 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1038 if (Buffer
== NULL
) {
1039 return EFI_OUT_OF_RESOURCES
;
1042 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1043 for (Index
= 0; Index
< TypeBus
; Index
++) {
1044 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1045 if (ResStatus
!= ResNone
) {
1046 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1047 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1048 Descriptor
->GenFlag
= 0;
1049 Descriptor
->AddrRangeMin
= RootBridge
->ResAllocNode
[Index
].Base
;
1050 Descriptor
->AddrRangeMax
= 0;
1051 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1052 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1057 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1061 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1063 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1064 Descriptor
->AddrSpaceGranularity
= 32;
1068 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1070 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1071 Descriptor
->AddrSpaceGranularity
= 64;
1078 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1079 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1082 *Configuration
= Buffer
;
1088 return EFI_INVALID_PARAMETER
;
1093 This function is called for all the PCI controllers that the PCI
1094 bus driver finds. Can be used to Preprogram the controller.
1096 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1097 @param RootBridgeHandle The PCI Root Bridge handle.
1098 @param PciAddress Address of the controller on the PCI bus.
1099 @param Phase The Phase during resource allocation.
1101 @retval EFI_SUCCESS Succeed.
1102 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1107 PreprocessController (
1108 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1109 IN EFI_HANDLE RootBridgeHandle
,
1110 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1111 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1115 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1116 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1118 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1119 return EFI_INVALID_PARAMETER
;
1122 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1123 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1124 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1125 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1127 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1128 if (RootBridgeHandle
== RootBridge
->Handle
) {
1133 return EFI_INVALID_PARAMETER
;