]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg/PciHostBridge: Refine function header comments.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
4
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
10
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.
13
14 **/
15
16 #include "PciHostBridge.h"
17 #include "PciRootBridge.h"
18 #include "PciHostResource.h"
19
20
21 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
22 EFI_CPU_IO2_PROTOCOL *mCpuIo;
23
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
25 L"Mem", L"I/O", L"Bus"
26 };
27 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
28 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
29 };
30
31 /**
32
33 Entry point of this driver.
34
35 @param ImageHandle Image handle of this driver.
36 @param SystemTable Pointer to standard EFI system table.
37
38 @retval EFI_SUCCESS Succeed.
39 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
40
41 **/
42 EFI_STATUS
43 EFIAPI
44 InitializePciHostBridge (
45 IN EFI_HANDLE ImageHandle,
46 IN EFI_SYSTEM_TABLE *SystemTable
47 )
48 {
49 EFI_STATUS Status;
50 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
51 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
52 PCI_ROOT_BRIDGE *RootBridges;
53 UINTN RootBridgeCount;
54 UINTN Index;
55 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];
56 UINTN MemApertureIndex;
57
58 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
59 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
60 return EFI_UNSUPPORTED;
61 }
62
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);
67
68 //
69 // Most systems in the world including complex servers have only one Host Bridge.
70 //
71 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
72 ASSERT (HostBridge != NULL);
73
74 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
75 HostBridge->CanRestarted = TRUE;
76 InitializeListHead (&HostBridge->RootBridges);
77
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;
86
87 Status = gBS->InstallMultipleProtocolInterfaces (
88 &HostBridge->Handle,
89 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
90 NULL
91 );
92 if (EFI_ERROR (Status)) {
93 FreePool (HostBridge);
94 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
95 return Status;
96 }
97
98 //
99 // Create Root Bridge Device Handle in this Host Bridge
100 //
101 for (Index = 0; Index < RootBridgeCount; Index++) {
102 //
103 // Create Root Bridge Handle Instance
104 //
105 RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);
106 ASSERT (RootBridge != NULL);
107 if (RootBridge == NULL) {
108 continue;
109 }
110
111 if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {
112 Status = gDS->AddIoSpace (
113 EfiGcdIoTypeIo,
114 RootBridges[Index].Io.Base,
115 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
116 );
117 ASSERT_EFI_ERROR (Status);
118 }
119
120 //
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
125 //
126 MemApertures[0] = &RootBridges[Index].Mem;
127 MemApertures[1] = &RootBridges[Index].MemAbove4G;
128 MemApertures[2] = &RootBridges[Index].PMem;
129 MemApertures[3] = &RootBridges[Index].PMemAbove4G;
130
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,
137 EFI_MEMORY_UC
138 );
139 ASSERT_EFI_ERROR (Status);
140 Status = gDS->SetMemorySpaceAttributes (
141 MemApertures[MemApertureIndex]->Base,
142 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
143 EFI_MEMORY_UC
144 );
145 ASSERT_EFI_ERROR (Status);
146 }
147 }
148 //
149 // Insert Root Bridge Handle Instance
150 //
151 Status = gBS->InstallMultipleProtocolInterfaces (
152 &RootBridge->Handle,
153 &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,
154 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,
155 NULL
156 );
157 ASSERT_EFI_ERROR (Status);
158 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
159 }
160 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
161 return Status;
162 }
163
164 /**
165 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
166
167 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
168 **/
169 VOID
170 ResourceConflict (
171 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
172 )
173 {
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;
178 LIST_ENTRY *Link;
179 UINTN RootBridgeCount;
180 PCI_RESOURCE_TYPE Index;
181 PCI_RES_NODE *ResAllocNode;
182
183 RootBridgeCount = 0;
184 for (Link = GetFirstNode (&HostBridge->RootBridges)
185 ; !IsNull (&HostBridge->RootBridges, Link)
186 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
187 ) {
188 RootBridgeCount++;
189 }
190
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)
194 );
195 ASSERT (Resources != NULL);
196
197 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
198 ; !IsNull (&HostBridge->RootBridges, Link)
199 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
200 ) {
201 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
202 for (Index = TypeIo; Index < TypeMax; Index++) {
203 ResAllocNode = &RootBridge->ResAllocNode[Index];
204
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) {
211
212 case TypeIo:
213 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
214 break;
215
216 case TypePMem32:
217 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
218 case TypeMem32:
219 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
220 Descriptor->AddrSpaceGranularity = 32;
221 break;
222
223 case TypePMem64:
224 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
225 case TypeMem64:
226 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
227 Descriptor->AddrSpaceGranularity = 64;
228 break;
229
230 case TypeBus:
231 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
232 break;
233
234 default:
235 break;
236 }
237
238 Descriptor++;
239 }
240 //
241 // Terminate the root bridge resources.
242 //
243 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
244 End->Desc = ACPI_END_TAG_DESCRIPTOR;
245 End->Checksum = 0x0;
246
247 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);
248 }
249 //
250 // Terminate the host bridge resources.
251 //
252 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
253 End->Desc = ACPI_END_TAG_DESCRIPTOR;
254 End->Checksum = 0x0;
255
256 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
257 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
258 FreePool (Resources);
259 }
260
261 /**
262 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
263 from GCD range [BaseAddress, Limit).
264
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.
270
271 @retval The base address of the allocated resource or MAX_UINT64 if allocation
272 fails.
273 **/
274 UINT64
275 AllocateResource (
276 BOOLEAN Mmio,
277 UINT64 Length,
278 UINTN BitsOfAlignment,
279 UINT64 BaseAddress,
280 UINT64 Limit
281 )
282 {
283 EFI_STATUS Status;
284
285 if (BaseAddress < Limit) {
286 //
287 // Have to make sure Aligment is handled since we are doing direct address allocation
288 //
289 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
290
291 while (BaseAddress + Length <= Limit + 1) {
292 if (Mmio) {
293 Status = gDS->AllocateMemorySpace (
294 EfiGcdAllocateAddress,
295 EfiGcdMemoryTypeMemoryMappedIo,
296 BitsOfAlignment,
297 Length,
298 &BaseAddress,
299 gImageHandle,
300 NULL
301 );
302 } else {
303 Status = gDS->AllocateIoSpace (
304 EfiGcdAllocateAddress,
305 EfiGcdIoTypeIo,
306 BitsOfAlignment,
307 Length,
308 &BaseAddress,
309 gImageHandle,
310 NULL
311 );
312 }
313
314 if (!EFI_ERROR (Status)) {
315 return BaseAddress;
316 }
317 BaseAddress += LShiftU64 (1, BitsOfAlignment);
318 }
319 }
320 return MAX_UINT64;
321 }
322
323 /**
324
325 Enter a certain phase of the PCI enumeration process.
326
327 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
328 @param Phase The phase during enumeration.
329
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.
333
334 **/
335 EFI_STATUS
336 EFIAPI
337 NotifyPhase (
338 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
339 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
340 )
341 {
342 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
343 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
344 LIST_ENTRY *Link;
345 EFI_PHYSICAL_ADDRESS BaseAddress;
346 UINT64 AddrLen;
347 UINTN BitsOfAlignment;
348 UINT64 Alignment;
349 EFI_STATUS Status;
350 EFI_STATUS ReturnStatus;
351 PCI_RESOURCE_TYPE Index;
352 PCI_RESOURCE_TYPE Index1;
353 PCI_RESOURCE_TYPE Index2;
354 BOOLEAN ResNodeHandled[TypeMax];
355 UINT64 MaxAlignment;
356
357 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
358
359 switch (Phase) {
360 case EfiPciHostBridgeBeginEnumeration:
361 if (!HostBridge->CanRestarted) {
362 return EFI_NOT_READY;
363 }
364 //
365 // Reset Root Bridge
366 //
367 for (Link = GetFirstNode (&HostBridge->RootBridges)
368 ; !IsNull (&HostBridge->RootBridges, Link)
369 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
370 ) {
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;
377
378 RootBridge->ResourceSubmitted = FALSE;
379 }
380 }
381
382 HostBridge->CanRestarted = TRUE;
383 break;
384
385 case EfiPciHostBridgeBeginBusAllocation:
386 //
387 // No specific action is required here, can perform any chipset specific programing
388 //
389 HostBridge->CanRestarted = FALSE;
390 break;
391
392 case EfiPciHostBridgeEndBusAllocation:
393 //
394 // No specific action is required here, can perform any chipset specific programing
395 //
396 break;
397
398 case EfiPciHostBridgeBeginResourceAllocation:
399 //
400 // No specific action is required here, can perform any chipset specific programing
401 //
402 break;
403
404 case EfiPciHostBridgeAllocateResources:
405 ReturnStatus = EFI_SUCCESS;
406
407 //
408 // Make sure the resource for all root bridges has been submitted.
409 //
410 for (Link = GetFirstNode (&HostBridge->RootBridges)
411 ; !IsNull (&HostBridge->RootBridges, Link)
412 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
413 ) {
414 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
415 if (!RootBridge->ResourceSubmitted) {
416 return EFI_NOT_READY;
417 }
418 }
419
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)
424 ) {
425 for (Index = TypeIo; Index < TypeBus; Index++) {
426 ResNodeHandled[Index] = FALSE;
427 }
428
429 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
430 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
431
432 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
433 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
434 ResNodeHandled[Index1] = TRUE;
435 } else {
436 //
437 // Allocate the resource node with max alignment at first
438 //
439 MaxAlignment = 0;
440 Index = TypeMax;
441 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
442 if (ResNodeHandled[Index2]) {
443 continue;
444 }
445 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
446 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
447 Index = Index2;
448 }
449 }
450
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;
457
458 switch (Index) {
459 case TypeIo:
460 BaseAddress = AllocateResource (
461 FALSE,
462 RootBridge->ResAllocNode[Index].Length,
463 MIN (15, BitsOfAlignment),
464 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
465 RootBridge->Io.Limit
466 );
467 break;
468
469 case TypeMem64:
470 BaseAddress = AllocateResource (
471 TRUE,
472 RootBridge->ResAllocNode[Index].Length,
473 MIN (63, BitsOfAlignment),
474 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
475 RootBridge->MemAbove4G.Limit
476 );
477 if (BaseAddress != MAX_UINT64) {
478 break;
479 }
480 //
481 // If memory above 4GB is not available, try memory below 4GB
482 //
483
484 case TypeMem32:
485 BaseAddress = AllocateResource (
486 TRUE,
487 RootBridge->ResAllocNode[Index].Length,
488 MIN (31, BitsOfAlignment),
489 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
490 RootBridge->Mem.Limit
491 );
492 break;
493
494 case TypePMem64:
495 BaseAddress = AllocateResource (
496 TRUE,
497 RootBridge->ResAllocNode[Index].Length,
498 MIN (63, BitsOfAlignment),
499 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
500 RootBridge->PMemAbove4G.Limit
501 );
502 if (BaseAddress != MAX_UINT64) {
503 break;
504 }
505 //
506 // If memory above 4GB is not available, try memory below 4GB
507 //
508 case TypePMem32:
509 BaseAddress = AllocateResource (
510 TRUE,
511 RootBridge->ResAllocNode[Index].Length,
512 MIN (31, BitsOfAlignment),
513 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
514 RootBridge->PMem.Limit
515 );
516 break;
517
518 default:
519 ASSERT (FALSE);
520 break;
521 }
522
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"));
529 } else {
530 ReturnStatus = EFI_OUT_OF_RESOURCES;
531 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
532 }
533 }
534 }
535 }
536
537 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
538 ResourceConflict (HostBridge);
539 }
540
541 //
542 // Set resource to zero for nodes where allocation fails
543 //
544 for (Link = GetFirstNode (&HostBridge->RootBridges)
545 ; !IsNull (&HostBridge->RootBridges, Link)
546 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
547 ) {
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;
552 }
553 }
554 }
555 return ReturnStatus;
556
557 case EfiPciHostBridgeSetResources:
558 //
559 // HostBridgeInstance->CanRestarted = FALSE;
560 //
561 break;
562
563 case EfiPciHostBridgeFreeResources:
564 //
565 // HostBridgeInstance->CanRestarted = FALSE;
566 //
567 ReturnStatus = EFI_SUCCESS;
568 for (Link = GetFirstNode (&HostBridge->RootBridges)
569 ; !IsNull (&HostBridge->RootBridges, Link)
570 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
571 ) {
572 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
573 for (Index = TypeIo; Index < TypeBus; Index++) {
574 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
575 switch (Index) {
576 case TypeIo:
577 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
578 if (EFI_ERROR (Status)) {
579 ReturnStatus = Status;
580 }
581 break;
582
583 case TypeMem32:
584 case TypePMem32:
585 case TypeMem64:
586 case TypePMem64:
587 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
588 if (EFI_ERROR (Status)) {
589 ReturnStatus = Status;
590 }
591 break;
592
593 default:
594 ASSERT (FALSE);
595 break;
596 }
597
598 RootBridge->ResAllocNode[Index].Type = Index;
599 RootBridge->ResAllocNode[Index].Base = 0;
600 RootBridge->ResAllocNode[Index].Length = 0;
601 RootBridge->ResAllocNode[Index].Status = ResNone;
602 }
603 }
604
605 RootBridge->ResourceSubmitted = FALSE;
606 }
607
608 HostBridge->CanRestarted = TRUE;
609 return ReturnStatus;
610
611 case EfiPciHostBridgeEndResourceAllocation:
612 //
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.
615 //
616 break;
617
618 case EfiPciHostBridgeEndEnumeration:
619 //
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.
622 //
623 break;
624
625 default:
626 return EFI_INVALID_PARAMETER;
627 }
628
629 return EFI_SUCCESS;
630 }
631
632 /**
633
634 Return the device handle of the next PCI root bridge that is associated with
635 this Host Bridge.
636
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.
642
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.
646
647 **/
648 EFI_STATUS
649 EFIAPI
650 GetNextRootBridge (
651 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
652 IN OUT EFI_HANDLE *RootBridgeHandle
653 )
654 {
655 BOOLEAN ReturnNext;
656 LIST_ENTRY *Link;
657 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
658 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
659
660 if (RootBridgeHandle == NULL) {
661 return EFI_INVALID_PARAMETER;
662 }
663
664 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
665 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);
666
667 for (Link = GetFirstNode (&HostBridge->RootBridges)
668 ; !IsNull (&HostBridge->RootBridges, Link)
669 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
670 ) {
671 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
672 if (ReturnNext) {
673 *RootBridgeHandle = RootBridge->Handle;
674 return EFI_SUCCESS;
675 }
676
677 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);
678 }
679
680 if (ReturnNext) {
681 ASSERT (IsNull (&HostBridge->RootBridges, Link));
682 return EFI_NOT_FOUND;
683 } else {
684 return EFI_INVALID_PARAMETER;
685 }
686 }
687
688 /**
689
690 Returns the attributes of a PCI Root Bridge.
691
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.
696
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
701 GetNextRootBridge().
702
703 **/
704 EFI_STATUS
705 EFIAPI
706 GetAttributes (
707 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
708 IN EFI_HANDLE RootBridgeHandle,
709 OUT UINT64 *Attributes
710 )
711 {
712 LIST_ENTRY *Link;
713 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
714 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
715
716 if (Attributes == NULL) {
717 return EFI_INVALID_PARAMETER;
718 }
719
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)
724 ) {
725 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
726 if (RootBridgeHandle == RootBridge->Handle) {
727 *Attributes = RootBridge->AllocationAttributes;
728 return EFI_SUCCESS;
729 }
730 }
731
732 return EFI_INVALID_PARAMETER;
733 }
734
735 /**
736
737 This is the request from the PCI enumerator to set up
738 the specified PCI Root Bridge for bus enumeration process.
739
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.
743
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.
747
748 **/
749 EFI_STATUS
750 EFIAPI
751 StartBusEnumeration (
752 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
753 IN EFI_HANDLE RootBridgeHandle,
754 OUT VOID **Configuration
755 )
756 {
757 LIST_ENTRY *Link;
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;
762
763 if (Configuration == NULL) {
764 return EFI_INVALID_PARAMETER;
765 }
766
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)
771 ) {
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;
777 }
778
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;
790
791 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
792 End->Desc = ACPI_END_TAG_DESCRIPTOR;
793 End->Checksum = 0x0;
794
795 return EFI_SUCCESS;
796 }
797 }
798
799 return EFI_INVALID_PARAMETER;
800 }
801
802 /**
803
804 This function programs the PCI Root Bridge hardware so that
805 it decodes the specified PCI bus range.
806
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.
810
811 @retval EFI_SUCCESS Succeed.
812 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
813
814 **/
815 EFI_STATUS
816 EFIAPI
817 SetBusNumbers (
818 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
819 IN EFI_HANDLE RootBridgeHandle,
820 IN VOID *Configuration
821 )
822 {
823 LIST_ENTRY *Link;
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;
828 UINTN BusStart;
829 UINTN BusEnd;
830 UINTN BusLen;
831
832 if (Configuration == NULL) {
833 return EFI_INVALID_PARAMETER;
834 }
835
836 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
837 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
838
839 //
840 // Check the Configuration is valid
841 //
842 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
843 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
844 (End->Desc != ACPI_END_TAG_DESCRIPTOR)
845 ) {
846 return EFI_INVALID_PARAMETER;
847 }
848
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)
853 ) {
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;
859
860 if (Descriptor->AddrLen == 0) {
861 return EFI_INVALID_PARAMETER;
862 }
863
864 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
865 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
866 ) {
867 return EFI_INVALID_PARAMETER;
868 }
869 //
870 // Update the Bus Range
871 //
872 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;
873 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;
874 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;
875 return EFI_SUCCESS;
876 }
877 }
878
879 return EFI_INVALID_PARAMETER;
880 }
881
882 /**
883
884 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
885
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.
888 are being submitted.
889 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
890
891 @retval EFI_SUCCESS Succeed.
892 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
893 **/
894 EFI_STATUS
895 EFIAPI
896 SubmitResources (
897 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
898 IN EFI_HANDLE RootBridgeHandle,
899 IN VOID *Configuration
900 )
901 {
902 LIST_ENTRY *Link;
903 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
904 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
905 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
906 PCI_RESOURCE_TYPE Type;
907
908 //
909 // Check the input parameter: Configuration
910 //
911 if (Configuration == NULL) {
912 return EFI_INVALID_PARAMETER;
913 }
914
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)
919 ) {
920 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
921 if (RootBridgeHandle == RootBridge->Handle) {
922 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
923 //
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.
927 //
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;
931 }
932
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""
936 ));
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;
942 }
943 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {
944 return EFI_INVALID_PARAMETER;
945 }
946 //
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.
950 //
951 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
952 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
953 ) {
954 return EFI_INVALID_PARAMETER;
955 }
956 case ACPI_ADDRESS_SPACE_TYPE_IO:
957 //
958 // Check aligment, it should be of the form 2^n-1
959 //
960 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
961 return EFI_INVALID_PARAMETER;
962 }
963 break;
964 default:
965 ASSERT (FALSE);
966 break;
967 }
968 }
969 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
970 return EFI_INVALID_PARAMETER;
971 }
972
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) {
977 Type = TypePMem32;
978 } else {
979 Type = TypeMem32;
980 }
981 } else {
982 ASSERT (Descriptor->AddrSpaceGranularity == 64);
983 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
984 Type = TypePMem64;
985 } else {
986 Type = TypeMem64;
987 }
988 }
989 } else {
990 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
991 Type = TypeIo;
992 }
993 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;
994 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
995 RootBridge->ResAllocNode[Type].Status = ResSubmitted;
996 }
997 RootBridge->ResourceSubmitted = TRUE;
998 return EFI_SUCCESS;
999 }
1000 }
1001
1002 return EFI_INVALID_PARAMETER;
1003 }
1004
1005 /**
1006
1007 This function returns the proposed resource settings for the specified
1008 PCI Root Bridge.
1009
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.
1014
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.
1018
1019 **/
1020 EFI_STATUS
1021 EFIAPI
1022 GetProposedResources (
1023 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1024 IN EFI_HANDLE RootBridgeHandle,
1025 OUT VOID **Configuration
1026 )
1027 {
1028 LIST_ENTRY *Link;
1029 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1030 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1031 UINTN Index;
1032 UINTN Number;
1033 VOID *Buffer;
1034 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1035 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1036 UINT64 ResStatus;
1037
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)
1042 ) {
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) {
1047 Number++;
1048 }
1049 }
1050
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;
1054 }
1055
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;
1067
1068 switch (Index) {
1069
1070 case TypeIo:
1071 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1072 break;
1073
1074 case TypePMem32:
1075 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1076 case TypeMem32:
1077 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1078 Descriptor->AddrSpaceGranularity = 32;
1079 break;
1080
1081 case TypePMem64:
1082 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1083 case TypeMem64:
1084 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1085 Descriptor->AddrSpaceGranularity = 64;
1086 break;
1087 }
1088
1089 Descriptor++;
1090 }
1091 }
1092 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
1093 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1094 End->Checksum = 0;
1095
1096 *Configuration = Buffer;
1097
1098 return EFI_SUCCESS;
1099 }
1100 }
1101
1102 return EFI_INVALID_PARAMETER;
1103 }
1104
1105 /**
1106
1107 This function is called for all the PCI controllers that the PCI
1108 bus driver finds. Can be used to Preprogram the controller.
1109
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.
1114
1115 @retval EFI_SUCCESS Succeed.
1116 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1117
1118 **/
1119 EFI_STATUS
1120 EFIAPI
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
1126 )
1127 {
1128 LIST_ENTRY *Link;
1129 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1130 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1131
1132 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {
1133 return EFI_INVALID_PARAMETER;
1134 }
1135
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)
1140 ) {
1141 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1142 if (RootBridgeHandle == RootBridge->Handle) {
1143 return EFI_SUCCESS;
1144 }
1145 }
1146
1147 return EFI_INVALID_PARAMETER;
1148 }