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"
32 Ensure the compatibility of an IO space descriptor with the IO aperture.
34 The IO space descriptor can come from the GCD IO space map, or it can
35 represent a gap between two neighboring IO space descriptors. In the latter
36 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
38 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
39 taken -- it is by definition compatible with the aperture.
41 Otherwise, the intersection of the IO space descriptor is calculated with the
42 aperture. If the intersection is the empty set (no overlap), no action is
43 taken; the IO space descriptor is compatible with the aperture.
45 Otherwise, the type of the descriptor is investigated again. If the type is
46 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
47 such a type), then an attempt is made to add the intersection as IO space to
48 the GCD IO space map. This ensures continuity for the aperture, and the
49 descriptor is deemed compatible with the aperture.
51 Otherwise, the IO space descriptor is incompatible with the IO aperture.
53 @param[in] Base Base address of the aperture.
54 @param[in] Length Length of the aperture.
55 @param[in] Descriptor The descriptor to ensure compatibility with the
58 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space
59 map may have been updated, for continuity
61 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
62 @return Error codes from gDS->AddIoSpace().
65 IntersectIoDescriptor (
68 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR
*Descriptor
71 UINT64 IntersectionBase
;
72 UINT64 IntersectionEnd
;
75 if (Descriptor
->GcdIoType
== EfiGcdIoTypeIo
) {
79 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
80 IntersectionEnd
= MIN (Base
+ Length
,
81 Descriptor
->BaseAddress
+ Descriptor
->Length
);
82 if (IntersectionBase
>= IntersectionEnd
) {
84 // The descriptor and the aperture don't overlap.
89 if (Descriptor
->GcdIoType
== EfiGcdIoTypeNonExistent
) {
90 Status
= gDS
->AddIoSpace (EfiGcdIoTypeIo
, IntersectionBase
,
91 IntersectionEnd
- IntersectionBase
);
93 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
94 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
95 IntersectionBase
, IntersectionEnd
, Status
));
99 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
100 "aperture [%Lx, %Lx)\n", gEfiCallerBaseName
, __FUNCTION__
,
101 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
102 (UINT32
)Descriptor
->GcdIoType
, Base
, Base
+ Length
));
103 return EFI_INVALID_PARAMETER
;
108 The routine checks the GCD database and only adds those which are
109 not added in the specified range to GCD.
111 @param Base Base address of the IO space.
112 @param Length Length of the IO space.
114 @retval EFI_SUCCES The IO space was added successfully.
124 UINTN NumberOfDescriptors
;
125 EFI_GCD_IO_SPACE_DESCRIPTOR
*IoSpaceMap
;
127 Status
= gDS
->GetIoSpaceMap (&NumberOfDescriptors
, &IoSpaceMap
);
128 if (EFI_ERROR (Status
)) {
129 DEBUG ((EFI_D_ERROR
, "%a: %a: GetIoSpaceMap(): %r\n",
130 gEfiCallerBaseName
, __FUNCTION__
, Status
));
134 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
135 Status
= IntersectIoDescriptor (Base
, Length
, &IoSpaceMap
[Index
]);
136 if (EFI_ERROR (Status
)) {
143 // Make sure there are adjacent descriptors covering [Base, Base + Length).
144 // It is possible that they have not been merged; merging can be prevented
148 EFI_STATUS CheckStatus
;
149 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor
;
151 for (CheckBase
= Base
;
152 CheckBase
< Base
+ Length
;
153 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
154 CheckStatus
= gDS
->GetIoSpaceDescriptor (CheckBase
, &Descriptor
);
155 ASSERT_EFI_ERROR (CheckStatus
);
156 ASSERT (Descriptor
.GcdIoType
== EfiGcdIoTypeIo
);
161 FreePool (IoSpaceMap
);
167 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
169 The memory space descriptor can come from the GCD memory space map, or it can
170 represent a gap between two neighboring memory space descriptors. In the
171 latter case, the GcdMemoryType field is expected to be
172 EfiGcdMemoryTypeNonExistent.
174 If the memory space descriptor already has type
175 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
176 required capabilities, then no action is taken -- it is by definition
177 compatible with the aperture.
179 Otherwise, the intersection of the memory space descriptor is calculated with
180 the aperture. If the intersection is the empty set (no overlap), no action is
181 taken; the memory space descriptor is compatible with the aperture.
183 Otherwise, the type of the descriptor is investigated again. If the type is
184 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
185 such a type), then an attempt is made to add the intersection as MMIO space
186 to the GCD memory space map, with the specified capabilities. This ensures
187 continuity for the aperture, and the descriptor is deemed compatible with the
190 Otherwise, the memory space descriptor is incompatible with the MMIO
193 @param[in] Base Base address of the aperture.
194 @param[in] Length Length of the aperture.
195 @param[in] Capabilities Capabilities required by the aperture.
196 @param[in] Descriptor The descriptor to ensure compatibility with the
199 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
200 space map may have been updated, for
201 continuity within the aperture.
202 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
203 @return Error codes from gDS->AddMemorySpace().
206 IntersectMemoryDescriptor (
209 IN UINT64 Capabilities
,
210 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*Descriptor
213 UINT64 IntersectionBase
;
214 UINT64 IntersectionEnd
;
217 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
&&
218 (Descriptor
->Capabilities
& Capabilities
) == Capabilities
) {
222 IntersectionBase
= MAX (Base
, Descriptor
->BaseAddress
);
223 IntersectionEnd
= MIN (Base
+ Length
,
224 Descriptor
->BaseAddress
+ Descriptor
->Length
);
225 if (IntersectionBase
>= IntersectionEnd
) {
227 // The descriptor and the aperture don't overlap.
232 if (Descriptor
->GcdMemoryType
== EfiGcdMemoryTypeNonExistent
) {
233 Status
= gDS
->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo
,
234 IntersectionBase
, IntersectionEnd
- IntersectionBase
,
237 DEBUG ((EFI_ERROR (Status
) ? EFI_D_ERROR
: EFI_D_VERBOSE
,
238 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName
, __FUNCTION__
,
239 IntersectionBase
, IntersectionEnd
, Status
));
243 DEBUG ((EFI_D_ERROR
, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
244 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName
, __FUNCTION__
,
245 Descriptor
->BaseAddress
, Descriptor
->BaseAddress
+ Descriptor
->Length
,
246 (UINT32
)Descriptor
->GcdMemoryType
, Descriptor
->Capabilities
,
247 Base
, Base
+ Length
, Capabilities
));
248 return EFI_INVALID_PARAMETER
;
252 Add MMIO space to GCD.
253 The routine checks the GCD database and only adds those which are
254 not added in the specified range to GCD.
256 @param Base Base address of the MMIO space.
257 @param Length Length of the MMIO space.
258 @param Capabilities Capabilities of the MMIO space.
260 @retval EFI_SUCCES The MMIO space was added successfully.
263 AddMemoryMappedIoSpace (
266 IN UINT64 Capabilities
271 UINTN NumberOfDescriptors
;
272 EFI_GCD_MEMORY_SPACE_DESCRIPTOR
*MemorySpaceMap
;
274 Status
= gDS
->GetMemorySpaceMap (&NumberOfDescriptors
, &MemorySpaceMap
);
275 if (EFI_ERROR (Status
)) {
276 DEBUG ((EFI_D_ERROR
, "%a: %a: GetMemorySpaceMap(): %r\n",
277 gEfiCallerBaseName
, __FUNCTION__
, Status
));
281 for (Index
= 0; Index
< NumberOfDescriptors
; Index
++) {
282 Status
= IntersectMemoryDescriptor (Base
, Length
, Capabilities
,
283 &MemorySpaceMap
[Index
]);
284 if (EFI_ERROR (Status
)) {
285 goto FreeMemorySpaceMap
;
291 // Make sure there are adjacent descriptors covering [Base, Base + Length).
292 // It is possible that they have not been merged; merging can be prevented
293 // by allocation and different capabilities.
296 EFI_STATUS CheckStatus
;
297 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor
;
299 for (CheckBase
= Base
;
300 CheckBase
< Base
+ Length
;
301 CheckBase
= Descriptor
.BaseAddress
+ Descriptor
.Length
) {
302 CheckStatus
= gDS
->GetMemorySpaceDescriptor (CheckBase
, &Descriptor
);
303 ASSERT_EFI_ERROR (CheckStatus
);
304 ASSERT (Descriptor
.GcdMemoryType
== EfiGcdMemoryTypeMemoryMappedIo
);
305 ASSERT ((Descriptor
.Capabilities
& Capabilities
) == Capabilities
);
310 FreePool (MemorySpaceMap
);
317 Entry point of this driver.
319 @param ImageHandle Image handle of this driver.
320 @param SystemTable Pointer to standard EFI system table.
322 @retval EFI_SUCCESS Succeed.
323 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
328 InitializePciHostBridge (
329 IN EFI_HANDLE ImageHandle
,
330 IN EFI_SYSTEM_TABLE
*SystemTable
334 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
335 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
336 PCI_ROOT_BRIDGE
*RootBridges
;
337 UINTN RootBridgeCount
;
339 PCI_ROOT_BRIDGE_APERTURE
*MemApertures
[4];
340 UINTN MemApertureIndex
;
341 BOOLEAN ResourceAssigned
;
344 RootBridges
= PciHostBridgeGetRootBridges (&RootBridgeCount
);
345 if ((RootBridges
== NULL
) || (RootBridgeCount
== 0)) {
346 return EFI_UNSUPPORTED
;
349 Status
= gBS
->LocateProtocol (&gEfiMetronomeArchProtocolGuid
, NULL
, (VOID
**) &mMetronome
);
350 ASSERT_EFI_ERROR (Status
);
351 Status
= gBS
->LocateProtocol (&gEfiCpuIo2ProtocolGuid
, NULL
, (VOID
**) &mCpuIo
);
352 ASSERT_EFI_ERROR (Status
);
355 // Most systems in the world including complex servers have only one Host Bridge.
357 HostBridge
= AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE
));
358 ASSERT (HostBridge
!= NULL
);
360 HostBridge
->Signature
= PCI_HOST_BRIDGE_SIGNATURE
;
361 HostBridge
->CanRestarted
= TRUE
;
362 InitializeListHead (&HostBridge
->RootBridges
);
363 ResourceAssigned
= FALSE
;
366 // Create Root Bridge Device Handle in this Host Bridge
368 for (Index
= 0; Index
< RootBridgeCount
; Index
++) {
370 // Create Root Bridge Handle Instance
372 RootBridge
= CreateRootBridge (&RootBridges
[Index
]);
373 ASSERT (RootBridge
!= NULL
);
374 if (RootBridge
== NULL
) {
379 // Make sure all root bridges share the same ResourceAssigned value.
382 ResourceAssigned
= RootBridges
[Index
].ResourceAssigned
;
384 ASSERT (ResourceAssigned
== RootBridges
[Index
].ResourceAssigned
);
387 if (RootBridges
[Index
].Io
.Base
<= RootBridges
[Index
].Io
.Limit
) {
388 Status
= AddIoSpace (
389 RootBridges
[Index
].Io
.Base
,
390 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1
392 ASSERT_EFI_ERROR (Status
);
393 if (ResourceAssigned
) {
394 Status
= gDS
->AllocateIoSpace (
395 EfiGcdAllocateAddress
,
398 RootBridges
[Index
].Io
.Limit
- RootBridges
[Index
].Io
.Base
+ 1,
399 &RootBridges
[Index
].Io
.Base
,
403 ASSERT_EFI_ERROR (Status
);
408 // Add all the Mem/PMem aperture to GCD
409 // Mem/PMem shouldn't overlap with each other
410 // Root bridge which needs to combine MEM and PMEM should only report
411 // the MEM aperture in Mem
413 MemApertures
[0] = &RootBridges
[Index
].Mem
;
414 MemApertures
[1] = &RootBridges
[Index
].MemAbove4G
;
415 MemApertures
[2] = &RootBridges
[Index
].PMem
;
416 MemApertures
[3] = &RootBridges
[Index
].PMemAbove4G
;
418 for (MemApertureIndex
= 0; MemApertureIndex
< ARRAY_SIZE (MemApertures
); MemApertureIndex
++) {
419 if (MemApertures
[MemApertureIndex
]->Base
<= MemApertures
[MemApertureIndex
]->Limit
) {
420 Status
= AddMemoryMappedIoSpace (
421 MemApertures
[MemApertureIndex
]->Base
,
422 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
425 ASSERT_EFI_ERROR (Status
);
426 Status
= gDS
->SetMemorySpaceAttributes (
427 MemApertures
[MemApertureIndex
]->Base
,
428 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
431 if (EFI_ERROR (Status
)) {
432 DEBUG ((DEBUG_WARN
, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status
));
434 if (ResourceAssigned
) {
435 Status
= gDS
->AllocateMemorySpace (
436 EfiGcdAllocateAddress
,
437 EfiGcdMemoryTypeMemoryMappedIo
,
439 MemApertures
[MemApertureIndex
]->Limit
- MemApertures
[MemApertureIndex
]->Base
+ 1,
440 &MemApertures
[MemApertureIndex
]->Base
,
444 ASSERT_EFI_ERROR (Status
);
449 // Insert Root Bridge Handle Instance
451 InsertTailList (&HostBridge
->RootBridges
, &RootBridge
->Link
);
455 // When resources were assigned, it's not needed to expose
456 // PciHostBridgeResourceAllocation protocol.
458 if (!ResourceAssigned
) {
459 HostBridge
->ResAlloc
.NotifyPhase
= NotifyPhase
;
460 HostBridge
->ResAlloc
.GetNextRootBridge
= GetNextRootBridge
;
461 HostBridge
->ResAlloc
.GetAllocAttributes
= GetAttributes
;
462 HostBridge
->ResAlloc
.StartBusEnumeration
= StartBusEnumeration
;
463 HostBridge
->ResAlloc
.SetBusNumbers
= SetBusNumbers
;
464 HostBridge
->ResAlloc
.SubmitResources
= SubmitResources
;
465 HostBridge
->ResAlloc
.GetProposedResources
= GetProposedResources
;
466 HostBridge
->ResAlloc
.PreprocessController
= PreprocessController
;
468 Status
= gBS
->InstallMultipleProtocolInterfaces (
470 &gEfiPciHostBridgeResourceAllocationProtocolGuid
, &HostBridge
->ResAlloc
,
473 ASSERT_EFI_ERROR (Status
);
476 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
477 ; !IsNull (&HostBridge
->RootBridges
, Link
)
478 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
480 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
481 RootBridge
->RootBridgeIo
.ParentHandle
= HostBridge
->Handle
;
483 Status
= gBS
->InstallMultipleProtocolInterfaces (
485 &gEfiDevicePathProtocolGuid
, RootBridge
->DevicePath
,
486 &gEfiPciRootBridgeIoProtocolGuid
, &RootBridge
->RootBridgeIo
,
489 ASSERT_EFI_ERROR (Status
);
491 PciHostBridgeFreeRootBridges (RootBridges
, RootBridgeCount
);
496 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
498 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
502 IN PCI_HOST_BRIDGE_INSTANCE
*HostBridge
505 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
506 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
507 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
508 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
510 UINTN RootBridgeCount
;
511 PCI_RESOURCE_TYPE Index
;
512 PCI_RES_NODE
*ResAllocNode
;
515 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
516 ; !IsNull (&HostBridge
->RootBridges
, Link
)
517 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
522 Resources
= AllocatePool (
523 RootBridgeCount
* (TypeMax
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)) +
524 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
)
526 ASSERT (Resources
!= NULL
);
528 for (Link
= GetFirstNode (&HostBridge
->RootBridges
), Descriptor
= Resources
529 ; !IsNull (&HostBridge
->RootBridges
, Link
)
530 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
532 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
533 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
534 ResAllocNode
= &RootBridge
->ResAllocNode
[Index
];
536 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
537 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
538 Descriptor
->AddrRangeMin
= ResAllocNode
->Base
;
539 Descriptor
->AddrRangeMax
= ResAllocNode
->Alignment
;
540 Descriptor
->AddrLen
= ResAllocNode
->Length
;
541 switch (ResAllocNode
->Type
) {
544 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
548 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
550 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
551 Descriptor
->AddrSpaceGranularity
= 32;
555 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
557 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
558 Descriptor
->AddrSpaceGranularity
= 64;
562 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
572 // Terminate the root bridge resources.
574 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
575 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
578 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) (End
+ 1);
581 // Terminate the host bridge resources.
583 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
584 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
587 DEBUG ((DEBUG_ERROR
, "Call PciHostBridgeResourceConflict().\n"));
588 PciHostBridgeResourceConflict (HostBridge
->Handle
, Resources
);
589 FreePool (Resources
);
593 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
594 from GCD range [BaseAddress, Limit).
596 @param Mmio TRUE for MMIO and FALSE for IO.
597 @param Length Length of the resource to allocate.
598 @param BitsOfAlignment Alignment of the resource to allocate.
599 @param BaseAddress The starting address the allocation is from.
600 @param Limit The ending address the allocation is to.
602 @retval The base address of the allocated resource or MAX_UINT64 if allocation
609 UINTN BitsOfAlignment
,
616 if (BaseAddress
< Limit
) {
618 // Have to make sure Aligment is handled since we are doing direct address allocation
620 BaseAddress
= ALIGN_VALUE (BaseAddress
, LShiftU64 (1, BitsOfAlignment
));
622 while (BaseAddress
+ Length
<= Limit
+ 1) {
624 Status
= gDS
->AllocateMemorySpace (
625 EfiGcdAllocateAddress
,
626 EfiGcdMemoryTypeMemoryMappedIo
,
634 Status
= gDS
->AllocateIoSpace (
635 EfiGcdAllocateAddress
,
645 if (!EFI_ERROR (Status
)) {
648 BaseAddress
+= LShiftU64 (1, BitsOfAlignment
);
656 Enter a certain phase of the PCI enumeration process.
658 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
659 @param Phase The phase during enumeration.
661 @retval EFI_SUCCESS Succeed.
662 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
663 @retval EFI_NOT_READY Resources have not been submitted yet.
669 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
670 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
673 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
674 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
676 EFI_PHYSICAL_ADDRESS BaseAddress
;
677 UINTN BitsOfAlignment
;
680 EFI_STATUS ReturnStatus
;
681 PCI_RESOURCE_TYPE Index
;
682 PCI_RESOURCE_TYPE Index1
;
683 PCI_RESOURCE_TYPE Index2
;
684 BOOLEAN ResNodeHandled
[TypeMax
];
687 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
690 case EfiPciHostBridgeBeginEnumeration
:
691 if (!HostBridge
->CanRestarted
) {
692 return EFI_NOT_READY
;
697 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
698 ; !IsNull (&HostBridge
->RootBridges
, Link
)
699 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
701 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
702 for (Index
= TypeIo
; Index
< TypeMax
; Index
++) {
703 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
704 RootBridge
->ResAllocNode
[Index
].Base
= 0;
705 RootBridge
->ResAllocNode
[Index
].Length
= 0;
706 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
708 RootBridge
->ResourceSubmitted
= FALSE
;
712 HostBridge
->CanRestarted
= TRUE
;
715 case EfiPciHostBridgeBeginBusAllocation
:
717 // No specific action is required here, can perform any chipset specific programing
719 HostBridge
->CanRestarted
= FALSE
;
722 case EfiPciHostBridgeEndBusAllocation
:
724 // No specific action is required here, can perform any chipset specific programing
728 case EfiPciHostBridgeBeginResourceAllocation
:
730 // No specific action is required here, can perform any chipset specific programing
734 case EfiPciHostBridgeAllocateResources
:
735 ReturnStatus
= EFI_SUCCESS
;
738 // Make sure the resource for all root bridges has been submitted.
740 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
741 ; !IsNull (&HostBridge
->RootBridges
, Link
)
742 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
744 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
745 if (!RootBridge
->ResourceSubmitted
) {
746 return EFI_NOT_READY
;
750 DEBUG ((EFI_D_INFO
, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
751 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
752 ; !IsNull (&HostBridge
->RootBridges
, Link
)
753 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
755 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
756 ResNodeHandled
[Index
] = FALSE
;
759 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
760 DEBUG ((EFI_D_INFO
, " RootBridge: %s\n", RootBridge
->DevicePathStr
));
762 for (Index1
= TypeIo
; Index1
< TypeBus
; Index1
++) {
763 if (RootBridge
->ResAllocNode
[Index1
].Status
== ResNone
) {
764 ResNodeHandled
[Index1
] = TRUE
;
767 // Allocate the resource node with max alignment at first
771 for (Index2
= TypeIo
; Index2
< TypeBus
; Index2
++) {
772 if (ResNodeHandled
[Index2
]) {
775 if (MaxAlignment
<= RootBridge
->ResAllocNode
[Index2
].Alignment
) {
776 MaxAlignment
= RootBridge
->ResAllocNode
[Index2
].Alignment
;
781 ASSERT (Index
< TypeMax
);
782 ResNodeHandled
[Index
] = TRUE
;
783 Alignment
= RootBridge
->ResAllocNode
[Index
].Alignment
;
784 BitsOfAlignment
= LowBitSet64 (Alignment
+ 1);
785 BaseAddress
= MAX_UINT64
;
789 BaseAddress
= AllocateResource (
791 RootBridge
->ResAllocNode
[Index
].Length
,
792 MIN (15, BitsOfAlignment
),
793 ALIGN_VALUE (RootBridge
->Io
.Base
, Alignment
+ 1),
799 BaseAddress
= AllocateResource (
801 RootBridge
->ResAllocNode
[Index
].Length
,
802 MIN (63, BitsOfAlignment
),
803 ALIGN_VALUE (RootBridge
->MemAbove4G
.Base
, Alignment
+ 1),
804 RootBridge
->MemAbove4G
.Limit
806 if (BaseAddress
!= MAX_UINT64
) {
810 // If memory above 4GB is not available, try memory below 4GB
814 BaseAddress
= AllocateResource (
816 RootBridge
->ResAllocNode
[Index
].Length
,
817 MIN (31, BitsOfAlignment
),
818 ALIGN_VALUE (RootBridge
->Mem
.Base
, Alignment
+ 1),
819 RootBridge
->Mem
.Limit
824 BaseAddress
= AllocateResource (
826 RootBridge
->ResAllocNode
[Index
].Length
,
827 MIN (63, BitsOfAlignment
),
828 ALIGN_VALUE (RootBridge
->PMemAbove4G
.Base
, Alignment
+ 1),
829 RootBridge
->PMemAbove4G
.Limit
831 if (BaseAddress
!= MAX_UINT64
) {
835 // If memory above 4GB is not available, try memory below 4GB
838 BaseAddress
= AllocateResource (
840 RootBridge
->ResAllocNode
[Index
].Length
,
841 MIN (31, BitsOfAlignment
),
842 ALIGN_VALUE (RootBridge
->PMem
.Base
, Alignment
+ 1),
843 RootBridge
->PMem
.Limit
852 DEBUG ((DEBUG_INFO
, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
853 mPciResourceTypeStr
[Index
], BaseAddress
, RootBridge
->ResAllocNode
[Index
].Length
, Alignment
));
854 if (BaseAddress
!= MAX_UINT64
) {
855 RootBridge
->ResAllocNode
[Index
].Base
= BaseAddress
;
856 RootBridge
->ResAllocNode
[Index
].Status
= ResAllocated
;
857 DEBUG ((DEBUG_INFO
, "Success\n"));
859 ReturnStatus
= EFI_OUT_OF_RESOURCES
;
860 DEBUG ((DEBUG_ERROR
, "Out Of Resource!\n"));
866 if (ReturnStatus
== EFI_OUT_OF_RESOURCES
) {
867 ResourceConflict (HostBridge
);
871 // Set resource to zero for nodes where allocation fails
873 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
874 ; !IsNull (&HostBridge
->RootBridges
, Link
)
875 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
877 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
878 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
879 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResAllocated
) {
880 RootBridge
->ResAllocNode
[Index
].Length
= 0;
886 case EfiPciHostBridgeSetResources
:
888 // HostBridgeInstance->CanRestarted = FALSE;
892 case EfiPciHostBridgeFreeResources
:
894 // HostBridgeInstance->CanRestarted = FALSE;
896 ReturnStatus
= EFI_SUCCESS
;
897 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
898 ; !IsNull (&HostBridge
->RootBridges
, Link
)
899 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
901 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
902 for (Index
= TypeIo
; Index
< TypeBus
; Index
++) {
903 if (RootBridge
->ResAllocNode
[Index
].Status
== ResAllocated
) {
906 Status
= gDS
->FreeIoSpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
907 if (EFI_ERROR (Status
)) {
908 ReturnStatus
= Status
;
916 Status
= gDS
->FreeMemorySpace (RootBridge
->ResAllocNode
[Index
].Base
, RootBridge
->ResAllocNode
[Index
].Length
);
917 if (EFI_ERROR (Status
)) {
918 ReturnStatus
= Status
;
927 RootBridge
->ResAllocNode
[Index
].Type
= Index
;
928 RootBridge
->ResAllocNode
[Index
].Base
= 0;
929 RootBridge
->ResAllocNode
[Index
].Length
= 0;
930 RootBridge
->ResAllocNode
[Index
].Status
= ResNone
;
934 RootBridge
->ResourceSubmitted
= FALSE
;
937 HostBridge
->CanRestarted
= TRUE
;
940 case EfiPciHostBridgeEndResourceAllocation
:
942 // The resource allocation phase is completed. No specific action is required
943 // here. This notification can be used to perform any chipset specific programming.
947 case EfiPciHostBridgeEndEnumeration
:
949 // The Host Bridge Enumeration is completed. No specific action is required here.
950 // This notification can be used to perform any chipset specific programming.
955 return EFI_INVALID_PARAMETER
;
963 Return the device handle of the next PCI root bridge that is associated with
966 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
967 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
968 On input, it holds the RootBridgeHandle returned by the most
969 recent call to GetNextRootBridge().The handle for the first
970 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
972 @retval EFI_SUCCESS Succeed.
973 @retval EFI_NOT_FOUND Next PCI root bridge not found.
974 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
980 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
981 IN OUT EFI_HANDLE
*RootBridgeHandle
986 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
987 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
989 if (RootBridgeHandle
== NULL
) {
990 return EFI_INVALID_PARAMETER
;
993 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
994 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== NULL
);
996 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
997 ; !IsNull (&HostBridge
->RootBridges
, Link
)
998 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1000 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1002 *RootBridgeHandle
= RootBridge
->Handle
;
1006 ReturnNext
= (BOOLEAN
) (*RootBridgeHandle
== RootBridge
->Handle
);
1010 ASSERT (IsNull (&HostBridge
->RootBridges
, Link
));
1011 return EFI_NOT_FOUND
;
1013 return EFI_INVALID_PARAMETER
;
1019 Returns the attributes of a PCI Root Bridge.
1021 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1022 @param RootBridgeHandle The device handle of the PCI Root Bridge
1023 that the caller is interested in.
1024 @param Attributes The pointer to attributes of the PCI Root Bridge.
1026 @retval EFI_SUCCESS Succeed.
1027 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1028 RootBridgeHandle is not an EFI_HANDLE
1029 that was returned on a previous call to
1030 GetNextRootBridge().
1036 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1037 IN EFI_HANDLE RootBridgeHandle
,
1038 OUT UINT64
*Attributes
1042 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1043 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1045 if (Attributes
== NULL
) {
1046 return EFI_INVALID_PARAMETER
;
1049 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1050 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1051 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1052 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1054 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1055 if (RootBridgeHandle
== RootBridge
->Handle
) {
1056 *Attributes
= RootBridge
->AllocationAttributes
;
1061 return EFI_INVALID_PARAMETER
;
1066 This is the request from the PCI enumerator to set up
1067 the specified PCI Root Bridge for bus enumeration process.
1069 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1070 @param RootBridgeHandle The PCI Root Bridge to be set up.
1071 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1073 @retval EFI_SUCCESS Succeed.
1074 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1075 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1080 StartBusEnumeration (
1081 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1082 IN EFI_HANDLE RootBridgeHandle
,
1083 OUT VOID
**Configuration
1087 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1088 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1089 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1090 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1092 if (Configuration
== NULL
) {
1093 return EFI_INVALID_PARAMETER
;
1096 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1097 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1098 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1099 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1101 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1102 if (RootBridgeHandle
== RootBridge
->Handle
) {
1103 *Configuration
= AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1104 if (*Configuration
== NULL
) {
1105 return EFI_OUT_OF_RESOURCES
;
1108 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) *Configuration
;
1109 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1110 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;
1111 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_BUS
;
1112 Descriptor
->GenFlag
= 0;
1113 Descriptor
->SpecificFlag
= 0;
1114 Descriptor
->AddrSpaceGranularity
= 0;
1115 Descriptor
->AddrRangeMin
= RootBridge
->Bus
.Base
;
1116 Descriptor
->AddrRangeMax
= 0;
1117 Descriptor
->AddrTranslationOffset
= 0;
1118 Descriptor
->AddrLen
= RootBridge
->Bus
.Limit
- RootBridge
->Bus
.Base
+ 1;
1120 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1121 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1122 End
->Checksum
= 0x0;
1128 return EFI_INVALID_PARAMETER
;
1133 This function programs the PCI Root Bridge hardware so that
1134 it decodes the specified PCI bus range.
1136 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1137 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1138 @param Configuration The pointer to the PCI bus resource descriptor.
1140 @retval EFI_SUCCESS Succeed.
1141 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1147 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1148 IN EFI_HANDLE RootBridgeHandle
,
1149 IN VOID
*Configuration
1153 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1154 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1155 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1156 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1158 if (Configuration
== NULL
) {
1159 return EFI_INVALID_PARAMETER
;
1162 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
;
1163 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) (Descriptor
+ 1);
1166 // Check the Configuration is valid
1168 if ((Descriptor
->Desc
!= ACPI_ADDRESS_SPACE_DESCRIPTOR
) ||
1169 (Descriptor
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_BUS
) ||
1170 (End
->Desc
!= ACPI_END_TAG_DESCRIPTOR
)
1172 return EFI_INVALID_PARAMETER
;
1175 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1176 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1177 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1178 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1180 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1181 if (RootBridgeHandle
== RootBridge
->Handle
) {
1183 if (Descriptor
->AddrLen
== 0) {
1184 return EFI_INVALID_PARAMETER
;
1187 if ((Descriptor
->AddrRangeMin
< RootBridge
->Bus
.Base
) ||
1188 (Descriptor
->AddrRangeMin
+ Descriptor
->AddrLen
- 1 > RootBridge
->Bus
.Limit
)
1190 return EFI_INVALID_PARAMETER
;
1193 // Update the Bus Range
1195 RootBridge
->ResAllocNode
[TypeBus
].Base
= Descriptor
->AddrRangeMin
;
1196 RootBridge
->ResAllocNode
[TypeBus
].Length
= Descriptor
->AddrLen
;
1197 RootBridge
->ResAllocNode
[TypeBus
].Status
= ResAllocated
;
1202 return EFI_INVALID_PARAMETER
;
1207 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1209 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1210 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1211 are being submitted.
1212 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1214 @retval EFI_SUCCESS Succeed.
1215 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1220 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1221 IN EFI_HANDLE RootBridgeHandle
,
1222 IN VOID
*Configuration
1226 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1227 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1228 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1229 PCI_RESOURCE_TYPE Type
;
1232 // Check the input parameter: Configuration
1234 if (Configuration
== NULL
) {
1235 return EFI_INVALID_PARAMETER
;
1238 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1239 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1240 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1241 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1243 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1244 if (RootBridgeHandle
== RootBridge
->Handle
) {
1245 DEBUG ((EFI_D_INFO
, "PciHostBridge: SubmitResources for %s\n", RootBridge
->DevicePathStr
));
1247 // Check the resource descriptors.
1248 // If the Configuration includes one or more invalid resource descriptors, all the resource
1249 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1251 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1252 if (Descriptor
->ResType
> ACPI_ADDRESS_SPACE_TYPE_BUS
) {
1253 return EFI_INVALID_PARAMETER
;
1256 DEBUG ((EFI_D_INFO
, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1257 mAcpiAddressSpaceTypeStr
[Descriptor
->ResType
], Descriptor
->AddrSpaceGranularity
, Descriptor
->SpecificFlag
,
1258 (Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0 ? L
" (Prefetchable)" : L
""
1260 DEBUG ((EFI_D_INFO
, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor
->AddrLen
, Descriptor
->AddrRangeMax
));
1261 switch (Descriptor
->ResType
) {
1262 case ACPI_ADDRESS_SPACE_TYPE_MEM
:
1263 if (Descriptor
->AddrSpaceGranularity
!= 32 && Descriptor
->AddrSpaceGranularity
!= 64) {
1264 return EFI_INVALID_PARAMETER
;
1266 if (Descriptor
->AddrSpaceGranularity
== 32 && Descriptor
->AddrLen
>= SIZE_4GB
) {
1267 return EFI_INVALID_PARAMETER
;
1270 // If the PCI root bridge does not support separate windows for nonprefetchable and
1271 // prefetchable memory, then the PCI bus driver needs to include requests for
1272 // prefetchable memory in the nonprefetchable memory pool.
1274 if (((RootBridge
->AllocationAttributes
& EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
) != 0) &&
1275 ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0)
1277 return EFI_INVALID_PARAMETER
;
1279 case ACPI_ADDRESS_SPACE_TYPE_IO
:
1281 // Check aligment, it should be of the form 2^n-1
1283 if (GetPowerOfTwo64 (Descriptor
->AddrRangeMax
+ 1) != (Descriptor
->AddrRangeMax
+ 1)) {
1284 return EFI_INVALID_PARAMETER
;
1292 if (Descriptor
->Desc
!= ACPI_END_TAG_DESCRIPTOR
) {
1293 return EFI_INVALID_PARAMETER
;
1296 for (Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Configuration
; Descriptor
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
; Descriptor
++) {
1297 if (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) {
1298 if (Descriptor
->AddrSpaceGranularity
== 32) {
1299 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1305 ASSERT (Descriptor
->AddrSpaceGranularity
== 64);
1306 if ((Descriptor
->SpecificFlag
& EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
) != 0) {
1313 ASSERT (Descriptor
->ResType
== ACPI_ADDRESS_SPACE_TYPE_IO
);
1316 RootBridge
->ResAllocNode
[Type
].Length
= Descriptor
->AddrLen
;
1317 RootBridge
->ResAllocNode
[Type
].Alignment
= Descriptor
->AddrRangeMax
;
1318 RootBridge
->ResAllocNode
[Type
].Status
= ResSubmitted
;
1320 RootBridge
->ResourceSubmitted
= TRUE
;
1325 return EFI_INVALID_PARAMETER
;
1330 This function returns the proposed resource settings for the specified
1333 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1334 @param RootBridgeHandle The PCI Root Bridge handle.
1335 @param Configuration The pointer to the pointer to the PCI I/O
1336 and memory resource descriptor.
1338 @retval EFI_SUCCESS Succeed.
1339 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1340 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1345 GetProposedResources (
1346 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1347 IN EFI_HANDLE RootBridgeHandle
,
1348 OUT VOID
**Configuration
1352 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1353 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1357 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Descriptor
;
1358 EFI_ACPI_END_TAG_DESCRIPTOR
*End
;
1361 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1362 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1363 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1364 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1366 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1367 if (RootBridgeHandle
== RootBridge
->Handle
) {
1368 for (Index
= 0, Number
= 0; Index
< TypeBus
; Index
++) {
1369 if (RootBridge
->ResAllocNode
[Index
].Status
!= ResNone
) {
1374 Buffer
= AllocateZeroPool (Number
* sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR
));
1375 if (Buffer
== NULL
) {
1376 return EFI_OUT_OF_RESOURCES
;
1379 Descriptor
= (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*) Buffer
;
1380 for (Index
= 0; Index
< TypeBus
; Index
++) {
1381 ResStatus
= RootBridge
->ResAllocNode
[Index
].Status
;
1382 if (ResStatus
!= ResNone
) {
1383 Descriptor
->Desc
= ACPI_ADDRESS_SPACE_DESCRIPTOR
;
1384 Descriptor
->Len
= sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3;;
1385 Descriptor
->GenFlag
= 0;
1386 Descriptor
->AddrRangeMin
= RootBridge
->ResAllocNode
[Index
].Base
;
1387 Descriptor
->AddrRangeMax
= 0;
1388 Descriptor
->AddrTranslationOffset
= (ResStatus
== ResAllocated
) ? EFI_RESOURCE_SATISFIED
: PCI_RESOURCE_LESS
;
1389 Descriptor
->AddrLen
= RootBridge
->ResAllocNode
[Index
].Length
;
1394 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_IO
;
1398 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1400 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1401 Descriptor
->AddrSpaceGranularity
= 32;
1405 Descriptor
->SpecificFlag
= EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
;
1407 Descriptor
->ResType
= ACPI_ADDRESS_SPACE_TYPE_MEM
;
1408 Descriptor
->AddrSpaceGranularity
= 64;
1415 End
= (EFI_ACPI_END_TAG_DESCRIPTOR
*) Descriptor
;
1416 End
->Desc
= ACPI_END_TAG_DESCRIPTOR
;
1419 *Configuration
= Buffer
;
1425 return EFI_INVALID_PARAMETER
;
1430 This function is called for all the PCI controllers that the PCI
1431 bus driver finds. Can be used to Preprogram the controller.
1433 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1434 @param RootBridgeHandle The PCI Root Bridge handle.
1435 @param PciAddress Address of the controller on the PCI bus.
1436 @param Phase The Phase during resource allocation.
1438 @retval EFI_SUCCESS Succeed.
1439 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1444 PreprocessController (
1445 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
*This
,
1446 IN EFI_HANDLE RootBridgeHandle
,
1447 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress
,
1448 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1452 PCI_HOST_BRIDGE_INSTANCE
*HostBridge
;
1453 PCI_ROOT_BRIDGE_INSTANCE
*RootBridge
;
1455 if ((UINT32
) Phase
> EfiPciBeforeResourceCollection
) {
1456 return EFI_INVALID_PARAMETER
;
1459 HostBridge
= PCI_HOST_BRIDGE_FROM_THIS (This
);
1460 for (Link
= GetFirstNode (&HostBridge
->RootBridges
)
1461 ; !IsNull (&HostBridge
->RootBridges
, Link
)
1462 ; Link
= GetNextNode (&HostBridge
->RootBridges
, Link
)
1464 RootBridge
= ROOT_BRIDGE_FROM_LINK (Link
);
1465 if (RootBridgeHandle
== RootBridge
->Handle
) {
1470 return EFI_INVALID_PARAMETER
;