1/** @file
2  Internal library implementation for PCI Bus module.
3
4Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6This program and the accompanying materials
7are licensed and made available under the terms and conditions of the BSD License
8which accompanies this distribution.  The full text of the license may be found at
9http://opensource.org/licenses/bsd-license.php
10
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14**/
15
16#include "PciBus.h"
17
18GLOBAL_REMOVE_IF_UNREFERENCED
19CHAR16 *mBarTypeStr[] = {
20  L"Unknow",
21  L"  Io16",
22  L"  Io32",
23  L" Mem32",
24  L"PMem32",
25  L" Mem64",
26  L"PMem64",
27  L"    Io",
28  L"   Mem",
29  L"Unknow"
30  };
31
32/**
33  Retrieve the PCI Card device BAR information via PciIo interface.
34
35  @param PciIoDevice        PCI Card device instance.
36
37**/
38VOID
39GetBackPcCardBar (
40  IN  PCI_IO_DEVICE                  *PciIoDevice
41  )
42{
43  UINT32  Address;
44
45  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
46    return;
47  }
48
49  //
50  // Read PciBar information from the bar register
51  //
52  if (!gFullEnumeration) {
53    Address = 0;
54    PciIoDevice->PciIo.Pci.Read (
55                             &(PciIoDevice->PciIo),
56                             EfiPciIoWidthUint32,
57                             PCI_CARD_MEMORY_BASE_0,
58                             1,
59                             &Address
60                             );
61
62    (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress  = (UINT64) (Address);
63    (PciIoDevice->PciBar)[P2C_MEM_1].Length       = 0x2000000;
64    (PciIoDevice->PciBar)[P2C_MEM_1].BarType      = PciBarTypeMem32;
65
66    Address = 0;
67    PciIoDevice->PciIo.Pci.Read (
68                             &(PciIoDevice->PciIo),
69                             EfiPciIoWidthUint32,
70                             PCI_CARD_MEMORY_BASE_1,
71                             1,
72                             &Address
73                             );
74    (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress  = (UINT64) (Address);
75    (PciIoDevice->PciBar)[P2C_MEM_2].Length       = 0x2000000;
76    (PciIoDevice->PciBar)[P2C_MEM_2].BarType      = PciBarTypePMem32;
77
78    Address = 0;
79    PciIoDevice->PciIo.Pci.Read (
80                             &(PciIoDevice->PciIo),
81                             EfiPciIoWidthUint32,
82                             PCI_CARD_IO_BASE_0_LOWER,
83                             1,
84                             &Address
85                             );
86    (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address);
87    (PciIoDevice->PciBar)[P2C_IO_1].Length      = 0x100;
88    (PciIoDevice->PciBar)[P2C_IO_1].BarType     = PciBarTypeIo16;
89
90    Address = 0;
91    PciIoDevice->PciIo.Pci.Read (
92                             &(PciIoDevice->PciIo),
93                             EfiPciIoWidthUint32,
94                             PCI_CARD_IO_BASE_1_LOWER,
95                             1,
96                             &Address
97                             );
98    (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address);
99    (PciIoDevice->PciBar)[P2C_IO_2].Length      = 0x100;
100    (PciIoDevice->PciBar)[P2C_IO_2].BarType     = PciBarTypeIo16;
101
102  }
103
104  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
105    GetResourcePaddingForHpb (PciIoDevice);
106  }
107}
108
109/**
110  Remove rejected pci device from specific root bridge
111  handle.
112
113  @param RootBridgeHandle  Specific parent root bridge handle.
114  @param Bridge            Bridge device instance.
115
116**/
117VOID
118RemoveRejectedPciDevices (
119  IN EFI_HANDLE        RootBridgeHandle,
120  IN PCI_IO_DEVICE     *Bridge
121  )
122{
123  PCI_IO_DEVICE   *Temp;
124  LIST_ENTRY      *CurrentLink;
125  LIST_ENTRY      *LastLink;
126
127  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
128    return;
129  }
130
131  CurrentLink = Bridge->ChildList.ForwardLink;
132
133  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
134
135    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
136
137    if (IS_PCI_BRIDGE (&Temp->Pci)) {
138      //
139      // Remove rejected devices recusively
140      //
141      RemoveRejectedPciDevices (RootBridgeHandle, Temp);
142    } else {
143      //
144      // Skip rejection for all PPBs, while detect rejection for others
145      //
146      if (IsPciDeviceRejected (Temp)) {
147
148        //
149        // For P2C, remove all devices on it
150        //
151        if (!IsListEmpty (&Temp->ChildList)) {
152          RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp);
153        }
154
155        //
156        // Finally remove itself
157        //
158        LastLink = CurrentLink->BackLink;
159        RemoveEntryList (CurrentLink);
160        FreePciDevice (Temp);
161
162        CurrentLink = LastLink;
163      }
164    }
165
166    CurrentLink = CurrentLink->ForwardLink;
167  }
168}
169
170/**
171  Dump the resourc map of the bridge device.
172
173  @param[in] BridgeResource   Resource descriptor of the bridge device.
174**/
175VOID
176DumpBridgeResource (
177  IN PCI_RESOURCE_NODE     *BridgeResource
178  )
179{
180  LIST_ENTRY               *Link;
181  PCI_RESOURCE_NODE        *Resource;
182  PCI_BAR                  *Bar;
183
184  if ((BridgeResource != NULL) && (BridgeResource->Length != 0)) {
185    DEBUG ((
186      EFI_D_INFO, "Type = %s; Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx\n",
187      mBarTypeStr[MIN (BridgeResource->ResType, PciBarTypeMaxType)],
188      BridgeResource->PciDev->PciBar[BridgeResource->Bar].BaseAddress,
189      BridgeResource->Length, BridgeResource->Alignment
190      ));
191    for ( Link = GetFirstNode (&BridgeResource->ChildList)
192        ; !IsNull (&BridgeResource->ChildList, Link)
193        ; Link = GetNextNode (&BridgeResource->ChildList, Link)
194        ) {
195      Resource = RESOURCE_NODE_FROM_LINK (Link);
196      if (Resource->ResourceUsage == PciResUsageTypical) {
197        Bar = Resource->Virtual ? Resource->PciDev->VfPciBar : Resource->PciDev->PciBar;
198        DEBUG ((
199          EFI_D_INFO, "   Base = 0x%lx;\tLength = 0x%lx;\tAlignment = 0x%lx;\tOwner = %s [%02x|%02x|%02x:",
200          Bar[Resource->Bar].BaseAddress, Resource->Length, Resource->Alignment,
201          IS_PCI_BRIDGE (&Resource->PciDev->Pci)     ? L"PPB" :
202          IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) ? L"P2C" :
203                                                       L"PCI",
204          Resource->PciDev->BusNumber, Resource->PciDev->DeviceNumber,
205          Resource->PciDev->FunctionNumber
206          ));
207
208        if ((!IS_PCI_BRIDGE (&Resource->PciDev->Pci) && !IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci)) ||
209            (IS_PCI_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < PPB_IO_RANGE)) ||
210            (IS_CARDBUS_BRIDGE (&Resource->PciDev->Pci) && (Resource->Bar < P2C_MEM_1))
211            ) {
212          //
213          // The resource requirement comes from the device itself.
214          //
215          DEBUG ((EFI_D_INFO, "%02x]", Bar[Resource->Bar].Offset));
216        } else {
217          //
218          // The resource requirement comes from the subordinate devices.
219          //
220          DEBUG ((EFI_D_INFO, "**]"));
221        }
222      } else {
223        DEBUG ((EFI_D_INFO, "   Base = Padding;\tLength = 0x%lx;\tAlignment = 0x%lx", Resource->Length, Resource->Alignment));
224      }
225      if (BridgeResource->ResType != Resource->ResType) {
226        DEBUG ((EFI_D_INFO, "; Type = %s", mBarTypeStr[MIN (Resource->ResType, PciBarTypeMaxType)]));
227      }
228      DEBUG ((EFI_D_INFO, "\n"));
229    }
230  }
231}
232
233/**
234  Find the corresponding resource node for the Device in child list of BridgeResource.
235
236  @param[in]  Device          Pointer to PCI_IO_DEVICE.
237  @param[in]  BridgeResource  Pointer to PCI_RESOURCE_NODE.
238  @param[out] DeviceResources Pointer to a buffer to receive resources for the Device.
239
240  @return Count of the resource descriptors returned.
241**/
242UINTN
243FindResourceNode (
244  IN  PCI_IO_DEVICE     *Device,
245  IN  PCI_RESOURCE_NODE *BridgeResource,
246  OUT PCI_RESOURCE_NODE **DeviceResources OPTIONAL
247  )
248{
249  LIST_ENTRY               *Link;
250  PCI_RESOURCE_NODE        *Resource;
251  UINTN                    Count;
252
253  Count = 0;
254  for ( Link = BridgeResource->ChildList.ForwardLink
255      ; Link != &BridgeResource->ChildList
256      ; Link = Link->ForwardLink
257      ) {
258    Resource = RESOURCE_NODE_FROM_LINK (Link);
259    if (Resource->PciDev == Device) {
260      if (DeviceResources != NULL) {
261        DeviceResources[Count] = Resource;
262      }
263      Count++;
264    }
265  }
266
267  return Count;
268}
269
270/**
271  Dump the resource map of all the devices under Bridge.
272
273  @param[in] Bridge        Bridge device instance.
274  @param[in] Resources     Resource descriptors for the bridge device.
275  @param[in] ResourceCount Count of resource descriptors.
276**/
277VOID
278DumpResourceMap (
279  IN PCI_IO_DEVICE     *Bridge,
280  IN PCI_RESOURCE_NODE **Resources,
281  IN UINTN             ResourceCount
282  )
283{
284  EFI_STATUS           Status;
285  LIST_ENTRY           *Link;
286  PCI_IO_DEVICE        *Device;
287  UINTN                Index;
288  CHAR16               *Str;
289  PCI_RESOURCE_NODE    **ChildResources;
290  UINTN                ChildResourceCount;
291
292  DEBUG ((EFI_D_INFO, "PciBus: Resource Map for "));
293
294  Status = gBS->OpenProtocol (
295                  Bridge->Handle,
296                  &gEfiPciRootBridgeIoProtocolGuid,
297                  NULL,
298                  NULL,
299                  NULL,
300                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
301                  );
302  if (EFI_ERROR (Status)) {
303    DEBUG ((
304      EFI_D_INFO, "Bridge [%02x|%02x|%02x]\n",
305      Bridge->BusNumber, Bridge->DeviceNumber, Bridge->FunctionNumber
306      ));
307  } else {
308    Str = ConvertDevicePathToText (
309            DevicePathFromHandle (Bridge->Handle),
310            FALSE,
311            FALSE
312            );
313    DEBUG ((EFI_D_INFO, "Root Bridge %s\n", Str != NULL ? Str : L""));
314    if (Str != NULL) {
315      FreePool (Str);
316    }
317  }
318
319  for (Index = 0; Index < ResourceCount; Index++) {
320    DumpBridgeResource (Resources[Index]);
321  }
322  DEBUG ((EFI_D_INFO, "\n"));
323
324  for ( Link = Bridge->ChildList.ForwardLink
325      ; Link != &Bridge->ChildList
326      ; Link = Link->ForwardLink
327      ) {
328    Device = PCI_IO_DEVICE_FROM_LINK (Link);
329    if (IS_PCI_BRIDGE (&Device->Pci)) {
330
331      ChildResourceCount = 0;
332      for (Index = 0; Index < ResourceCount; Index++) {
333        ChildResourceCount += FindResourceNode (Device, Resources[Index], NULL);
334      }
335      ChildResources = AllocatePool (sizeof (PCI_RESOURCE_NODE *) * ChildResourceCount);
336      ASSERT (ChildResources != NULL);
337      ChildResourceCount = 0;
338      for (Index = 0; Index < ResourceCount; Index++) {
339        ChildResourceCount += FindResourceNode (Device, Resources[Index], &ChildResources[ChildResourceCount]);
340      }
341
342      DumpResourceMap (Device, ChildResources, ChildResourceCount);
343      FreePool (ChildResources);
344    }
345  }
346}
347
348/**
349  Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
350
351  @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
352
353  @retval EFI_SUCCESS           Successfully finished resource allocation.
354  @retval EFI_NOT_FOUND         Cannot get root bridge instance.
355  @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.
356  @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.
357
358  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
359
360**/
361EFI_STATUS
362PciHostBridgeResourceAllocator (
363  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
364  )
365{
366  PCI_IO_DEVICE                                  *RootBridgeDev;
367  EFI_HANDLE                                     RootBridgeHandle;
368  VOID                                           *AcpiConfig;
369  EFI_STATUS                                     Status;
370  UINT64                                         IoBase;
371  UINT64                                         Mem32Base;
372  UINT64                                         PMem32Base;
373  UINT64                                         Mem64Base;
374  UINT64                                         PMem64Base;
375  UINT64                                         IoResStatus;
376  UINT64                                         Mem32ResStatus;
377  UINT64                                         PMem32ResStatus;
378  UINT64                                         Mem64ResStatus;
379  UINT64                                         PMem64ResStatus;
380  UINT64                                         MaxOptionRomSize;
381  PCI_RESOURCE_NODE                              *IoBridge;
382  PCI_RESOURCE_NODE                              *Mem32Bridge;
383  PCI_RESOURCE_NODE                              *PMem32Bridge;
384  PCI_RESOURCE_NODE                              *Mem64Bridge;
385  PCI_RESOURCE_NODE                              *PMem64Bridge;
386  PCI_RESOURCE_NODE                              IoPool;
387  PCI_RESOURCE_NODE                              Mem32Pool;
388  PCI_RESOURCE_NODE                              PMem32Pool;
389  PCI_RESOURCE_NODE                              Mem64Pool;
390  PCI_RESOURCE_NODE                              PMem64Pool;
391  BOOLEAN                                        ReAllocate;
392  EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD        HandleExtendedData;
393  EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD  AllocFailExtendedData;
394
395  //
396  // Reallocate flag
397  //
398  ReAllocate = FALSE;
399
400  //
401  // It may try several times if the resource allocation fails
402  //
403  while (TRUE) {
404    //
405    // Initialize resource pool
406    //
407    InitializeResourcePool (&IoPool, PciBarTypeIo16);
408    InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
409    InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
410    InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
411    InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
412
413    RootBridgeDev     = NULL;
414    RootBridgeHandle  = 0;
415
416    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
417      //
418      // Get Root Bridge Device by handle
419      //
420      RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
421
422      if (RootBridgeDev == NULL) {
423        return EFI_NOT_FOUND;
424      }
425
426      //
427      // Create the entire system resource map from the information collected by
428      // enumerator. Several resource tree was created
429      //
430
431      //
432      // If non-standard PCI Bridge I/O window alignment is supported,
433      // set I/O aligment to minimum possible alignment for root bridge.
434      //
435      IoBridge = CreateResourceNode (
436                   RootBridgeDev,
437                   0,
438                   FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,
439                   RB_IO_RANGE,
440                   PciBarTypeIo16,
441                   PciResUsageTypical
442                   );
443
444      Mem32Bridge = CreateResourceNode (
445                      RootBridgeDev,
446                      0,
447                      0xFFFFF,
448                      RB_MEM32_RANGE,
449                      PciBarTypeMem32,
450                      PciResUsageTypical
451                      );
452
453      PMem32Bridge = CreateResourceNode (
454                       RootBridgeDev,
455                       0,
456                       0xFFFFF,
457                       RB_PMEM32_RANGE,
458                       PciBarTypePMem32,
459                       PciResUsageTypical
460                       );
461
462      Mem64Bridge = CreateResourceNode (
463                      RootBridgeDev,
464                      0,
465                      0xFFFFF,
466                      RB_MEM64_RANGE,
467                      PciBarTypeMem64,
468                      PciResUsageTypical
469                      );
470
471      PMem64Bridge = CreateResourceNode (
472                       RootBridgeDev,
473                       0,
474                       0xFFFFF,
475                       RB_PMEM64_RANGE,
476                       PciBarTypePMem64,
477                       PciResUsageTypical
478                       );
479
480      //
481      // Create resourcemap by going through all the devices subject to this root bridge
482      //
483      CreateResourceMap (
484        RootBridgeDev,
485        IoBridge,
486        Mem32Bridge,
487        PMem32Bridge,
488        Mem64Bridge,
489        PMem64Bridge
490        );
491
492      //
493      // Get the max ROM size that the root bridge can process
494      //
495      RootBridgeDev->RomSize = Mem32Bridge->Length;
496
497      //
498      // Skip to enlarge the resource request during realloction
499      //
500      if (!ReAllocate) {
501        //
502        // Get Max Option Rom size for current root bridge
503        //
504        MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
505
506        //
507        // Enlarger the mem32 resource to accomdate the option rom
508        // if the mem32 resource is not enough to hold the rom
509        //
510        if (MaxOptionRomSize > Mem32Bridge->Length) {
511
512          Mem32Bridge->Length     = MaxOptionRomSize;
513          RootBridgeDev->RomSize  = MaxOptionRomSize;
514
515          //
516          // Alignment should be adjusted as well
517          //
518          if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) {
519            Mem32Bridge->Alignment = MaxOptionRomSize - 1;
520          }
521        }
522      }
523
524      //
525      // Based on the all the resource tree, construct ACPI resource node to
526      // submit the resource aperture to pci host bridge protocol
527      //
528      Status = ConstructAcpiResourceRequestor (
529                 RootBridgeDev,
530                 IoBridge,
531                 Mem32Bridge,
532                 PMem32Bridge,
533                 Mem64Bridge,
534                 PMem64Bridge,
535                 &AcpiConfig
536                 );
537
538      //
539      // Insert these resource nodes into the database
540      //
541      InsertResourceNode (&IoPool, IoBridge);
542      InsertResourceNode (&Mem32Pool, Mem32Bridge);
543      InsertResourceNode (&PMem32Pool, PMem32Bridge);
544      InsertResourceNode (&Mem64Pool, Mem64Bridge);
545      InsertResourceNode (&PMem64Pool, PMem64Bridge);
546
547      if (Status == EFI_SUCCESS) {
548        //
549        // Submit the resource requirement
550        //
551        Status = PciResAlloc->SubmitResources (
552                                PciResAlloc,
553                                RootBridgeDev->Handle,
554                                AcpiConfig
555                                );
556        //
557        // If SubmitResources returns error, PciBus isn't able to start.
558        // It's a fatal error so assertion is added.
559        //
560        DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));
561        ASSERT_EFI_ERROR (Status);
562      }
563
564      //
565      // Free acpi resource node
566      //
567      if (AcpiConfig != NULL) {
568        FreePool (AcpiConfig);
569      }
570
571      if (EFI_ERROR (Status)) {
572        //
573        // Destroy all the resource tree
574        //
575        DestroyResourceTree (&IoPool);
576        DestroyResourceTree (&Mem32Pool);
577        DestroyResourceTree (&PMem32Pool);
578        DestroyResourceTree (&Mem64Pool);
579        DestroyResourceTree (&PMem64Pool);
580        return Status;
581      }
582    }
583    //
584    // End while, at least one Root Bridge should be found.
585    //
586    ASSERT (RootBridgeDev != NULL);
587
588    //
589    // Notify platform to start to program the resource
590    //
591    Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
592    DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));
593    if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
594      //
595      // If Hot Plug is not supported
596      //
597      if (EFI_ERROR (Status)) {
598        //
599        // Allocation failed, then return
600        //
601        return EFI_OUT_OF_RESOURCES;
602      }
603      //
604      // Allocation succeed.
605      // Get host bridge handle for status report, and then skip the main while
606      //
607      HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
608
609      break;
610
611    } else {
612      //
613      // If Hot Plug is supported
614      //
615      if (!EFI_ERROR (Status)) {
616        //
617        // Allocation succeed, then continue the following
618        //
619        break;
620      }
621
622      //
623      // If the resource allocation is unsuccessful, free resources on bridge
624      //
625
626      RootBridgeDev     = NULL;
627      RootBridgeHandle  = 0;
628
629      IoResStatus       = EFI_RESOURCE_SATISFIED;
630      Mem32ResStatus    = EFI_RESOURCE_SATISFIED;
631      PMem32ResStatus   = EFI_RESOURCE_SATISFIED;
632      Mem64ResStatus    = EFI_RESOURCE_SATISFIED;
633      PMem64ResStatus   = EFI_RESOURCE_SATISFIED;
634
635      while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
636        //
637        // Get RootBridg Device by handle
638        //
639        RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
640        if (RootBridgeDev == NULL) {
641          return EFI_NOT_FOUND;
642        }
643
644        //
645        // Get host bridge handle for status report
646        //
647        HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
648
649        //
650        // Get acpi resource node for all the resource types
651        //
652        AcpiConfig = NULL;
653
654        Status = PciResAlloc->GetProposedResources (
655                                PciResAlloc,
656                                RootBridgeDev->Handle,
657                                &AcpiConfig
658                                );
659
660        if (EFI_ERROR (Status)) {
661          return Status;
662        }
663
664        if (AcpiConfig != NULL) {
665          //
666          // Adjust resource allocation policy for each RB
667          //
668          GetResourceAllocationStatus (
669            AcpiConfig,
670            &IoResStatus,
671            &Mem32ResStatus,
672            &PMem32ResStatus,
673            &Mem64ResStatus,
674            &PMem64ResStatus
675            );
676          FreePool (AcpiConfig);
677        }
678      }
679      //
680      // End while
681      //
682
683      //
684      // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
685      //
686      //
687      // It is very difficult to follow the spec here
688      // Device path , Bar index can not be get here
689      //
690      ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
691
692      REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
693            EFI_PROGRESS_CODE,
694            EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
695            (VOID *) &AllocFailExtendedData,
696            sizeof (AllocFailExtendedData)
697            );
698
699      Status = PciHostBridgeAdjustAllocation (
700                 &IoPool,
701                 &Mem32Pool,
702                 &PMem32Pool,
703                 &Mem64Pool,
704                 &PMem64Pool,
705                 IoResStatus,
706                 Mem32ResStatus,
707                 PMem32ResStatus,
708                 Mem64ResStatus,
709                 PMem64ResStatus
710                 );
711
712      //
713      // Destroy all the resource tree
714      //
715      DestroyResourceTree (&IoPool);
716      DestroyResourceTree (&Mem32Pool);
717      DestroyResourceTree (&PMem32Pool);
718      DestroyResourceTree (&Mem64Pool);
719      DestroyResourceTree (&PMem64Pool);
720
721      NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
722
723      if (EFI_ERROR (Status)) {
724        return Status;
725      }
726
727      ReAllocate = TRUE;
728    }
729  }
730  //
731  // End main while
732  //
733
734  //
735  // Raise the EFI_IOB_PCI_RES_ALLOC status code
736  //
737  REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
738        EFI_PROGRESS_CODE,
739        EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,
740        (VOID *) &HandleExtendedData,
741        sizeof (HandleExtendedData)
742        );
743
744  //
745  // Notify pci bus driver starts to program the resource
746  //
747  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
748
749  if (EFI_ERROR (Status)) {
750    return Status;
751  }
752
753  RootBridgeDev     = NULL;
754
755  RootBridgeHandle  = 0;
756
757  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
758    //
759    // Get RootBridg Device by handle
760    //
761    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
762
763    if (RootBridgeDev == NULL) {
764      return EFI_NOT_FOUND;
765    }
766
767    //
768    // Get acpi resource node for all the resource types
769    //
770    AcpiConfig = NULL;
771    Status = PciResAlloc->GetProposedResources (
772                            PciResAlloc,
773                            RootBridgeDev->Handle,
774                            &AcpiConfig
775                            );
776
777    if (EFI_ERROR (Status)) {
778      return Status;
779    }
780
781    //
782    // Get the resource base by interpreting acpi resource node
783    //
784    //
785    GetResourceBase (
786      AcpiConfig,
787      &IoBase,
788      &Mem32Base,
789      &PMem32Base,
790      &Mem64Base,
791      &PMem64Base
792      );
793
794    //
795    // Process option rom for this root bridge
796    //
797    ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize);
798
799    //
800    // Create the entire system resource map from the information collected by
801    // enumerator. Several resource tree was created
802    //
803    FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);
804    FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);
805    FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);
806    FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);
807    FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);
808
809    ASSERT (IoBridge     != NULL);
810    ASSERT (Mem32Bridge  != NULL);
811    ASSERT (PMem32Bridge != NULL);
812    ASSERT (Mem64Bridge  != NULL);
813    ASSERT (PMem64Bridge != NULL);
814
815    //
816    // Program IO resources
817    //
818    ProgramResource (
819      IoBase,
820      IoBridge
821      );
822
823    //
824    // Program Mem32 resources
825    //
826    ProgramResource (
827      Mem32Base,
828      Mem32Bridge
829      );
830
831    //
832    // Program PMem32 resources
833    //
834    ProgramResource (
835      PMem32Base,
836      PMem32Bridge
837      );
838
839    //
840    // Program Mem64 resources
841    //
842    ProgramResource (
843      Mem64Base,
844      Mem64Bridge
845      );
846
847    //
848    // Program PMem64 resources
849    //
850    ProgramResource (
851      PMem64Base,
852      PMem64Bridge
853      );
854
855    IoBridge    ->PciDev->PciBar[IoBridge    ->Bar].BaseAddress = IoBase;
856    Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;
857    PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;
858    Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;
859    PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;
860
861    //
862    // Dump the resource map for current root bridge
863    //
864    DEBUG_CODE (
865      PCI_RESOURCE_NODE *Resources[5];
866      Resources[0] = IoBridge;
867      Resources[1] = Mem32Bridge;
868      Resources[2] = PMem32Bridge;
869      Resources[3] = Mem64Bridge;
870      Resources[4] = PMem64Bridge;
871      DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));
872    );
873
874    FreePool (AcpiConfig);
875  }
876
877  //
878  // Destroy all the resource tree
879  //
880  DestroyResourceTree (&IoPool);
881  DestroyResourceTree (&Mem32Pool);
882  DestroyResourceTree (&PMem32Pool);
883  DestroyResourceTree (&Mem64Pool);
884  DestroyResourceTree (&PMem64Pool);
885
886  //
887  // Notify the resource allocation phase is to end
888  //
889  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
890
891  return Status;
892}
893
894/**
895  Allocate NumberOfBuses buses and return the next available PCI bus number.
896
897  @param  Bridge           Bridge device instance.
898  @param  StartBusNumber   Current available PCI bus number.
899  @param  NumberOfBuses    Number of buses enumerated below the StartBusNumber.
900  @param  NextBusNumber    Next available PCI bus number.
901
902  @retval EFI_SUCCESS           Available bus number resource is enough. Next available PCI bus number
903                                is returned in NextBusNumber.
904  @retval EFI_OUT_OF_RESOURCES  Available bus number resource is not enough for allocation.
905
906**/
907EFI_STATUS
908PciAllocateBusNumber (
909  IN PCI_IO_DEVICE                      *Bridge,
910  IN UINT8                              StartBusNumber,
911  IN UINT8                              NumberOfBuses,
912  OUT UINT8                             *NextBusNumber
913  )
914{
915  PCI_IO_DEVICE                      *RootBridge;
916  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *BusNumberRanges;
917  UINT8                              NextNumber;
918  UINT64                             MaxNumberInRange;
919
920  //
921  // Get PCI Root Bridge device
922  //
923  RootBridge = Bridge;
924  while (RootBridge->Parent != NULL) {
925    RootBridge = RootBridge->Parent;
926  }
927
928  //
929  // Get next available PCI bus number
930  //
931  BusNumberRanges = RootBridge->BusNumberRanges;
932  while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {
933    MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
934    if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <=  MaxNumberInRange) {
935      NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);
936      while (NextNumber > MaxNumberInRange) {
937        ++BusNumberRanges;
938        if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {
939          return EFI_OUT_OF_RESOURCES;
940        }
941        NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));
942        MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
943      }
944      *NextBusNumber = NextNumber;
945      return EFI_SUCCESS;
946    }
947    BusNumberRanges++;
948  }
949  return EFI_OUT_OF_RESOURCES;
950}
951
952/**
953  Scan pci bus and assign bus number to the given PCI bus system.
954
955  @param  Bridge           Bridge device instance.
956  @param  StartBusNumber   start point.
957  @param  SubBusNumber     Point to sub bus number.
958  @param  PaddedBusRange   Customized bus number.
959
960  @retval EFI_SUCCESS      Successfully scanned and assigned bus number.
961  @retval other            Some error occurred when scanning pci bus.
962
963  @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
964
965**/
966EFI_STATUS
967PciScanBus (
968  IN PCI_IO_DEVICE                      *Bridge,
969  IN UINT8                              StartBusNumber,
970  OUT UINT8                             *SubBusNumber,
971  OUT UINT8                             *PaddedBusRange
972  )
973{
974  EFI_STATUS                        Status;
975  PCI_TYPE00                        Pci;
976  UINT8                             Device;
977  UINT8                             Func;
978  UINT64                            Address;
979  UINT8                             SecondBus;
980  UINT8                             PaddedSubBus;
981  UINT16                            Register;
982  UINTN                             HpIndex;
983  PCI_IO_DEVICE                     *PciDevice;
984  EFI_EVENT                         Event;
985  EFI_HPC_STATE                     State;
986  UINT64                            PciAddress;
987  EFI_HPC_PADDING_ATTRIBUTES        Attributes;
988  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
989  UINT16                            BusRange;
990  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
991  BOOLEAN                           BusPadding;
992  UINT32                            TempReservedBusNum;
993
994  PciRootBridgeIo = Bridge->PciRootBridgeIo;
995  SecondBus       = 0;
996  Register        = 0;
997  State           = 0;
998  Attributes      = (EFI_HPC_PADDING_ATTRIBUTES) 0;
999  BusRange        = 0;
1000  BusPadding      = FALSE;
1001  PciDevice       = NULL;
1002  PciAddress      = 0;
1003
1004  for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1005    TempReservedBusNum = 0;
1006    for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1007
1008      //
1009      // Check to see whether a pci device is present
1010      //
1011      Status = PciDevicePresent (
1012                PciRootBridgeIo,
1013                &Pci,
1014                StartBusNumber,
1015                Device,
1016                Func
1017                );
1018
1019      if (EFI_ERROR (Status) && Func == 0) {
1020        //
1021        // go to next device if there is no Function 0
1022        //
1023        break;
1024      }
1025
1026      if (EFI_ERROR (Status)) {
1027        continue;
1028      }
1029
1030      //
1031      // Get the PCI device information
1032      //
1033      Status = PciSearchDevice (
1034                Bridge,
1035                &Pci,
1036                StartBusNumber,
1037                Device,
1038                Func,
1039                &PciDevice
1040                );
1041
1042      ASSERT (!EFI_ERROR (Status));
1043
1044      PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
1045
1046      if (!IS_PCI_BRIDGE (&Pci)) {
1047        //
1048        // PCI bridges will be called later
1049        // Here just need for PCI device or PCI to cardbus controller
1050        // EfiPciBeforeChildBusEnumeration for PCI Device Node
1051        //
1052        PreprocessController (
1053            PciDevice,
1054            PciDevice->BusNumber,
1055            PciDevice->DeviceNumber,
1056            PciDevice->FunctionNumber,
1057            EfiPciBeforeChildBusEnumeration
1058            );
1059      }
1060
1061      if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1062        //
1063        // For Pci Hotplug controller devcie only
1064        //
1065        if (gPciHotPlugInit != NULL) {
1066          //
1067          // Check if it is a Hotplug PCI controller
1068          //
1069          if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
1070            gPciRootHpcData[HpIndex].Found = TRUE;
1071
1072            if (!gPciRootHpcData[HpIndex].Initialized) {
1073
1074              Status = CreateEventForHpc (HpIndex, &Event);
1075
1076              ASSERT (!EFI_ERROR (Status));
1077
1078              Status = gPciHotPlugInit->InitializeRootHpc (
1079                                          gPciHotPlugInit,
1080                                          gPciRootHpcPool[HpIndex].HpcDevicePath,
1081                                          PciAddress,
1082                                          Event,
1083                                          &State
1084                                          );
1085
1086              PreprocessController (
1087                PciDevice,
1088                PciDevice->BusNumber,
1089                PciDevice->DeviceNumber,
1090                PciDevice->FunctionNumber,
1091                EfiPciBeforeChildBusEnumeration
1092              );
1093            }
1094          }
1095        }
1096      }
1097
1098      if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
1099        //
1100        // For PPB
1101        //
1102        if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1103          //
1104          // If Hot Plug is not supported,
1105          // get the bridge information
1106          //
1107          Status = PciSearchDevice (
1108                    Bridge,
1109                    &Pci,
1110                    StartBusNumber,
1111                    Device,
1112                    Func,
1113                    &PciDevice
1114                    );
1115
1116          if (EFI_ERROR (Status)) {
1117            return Status;
1118          }
1119        } else {
1120          //
1121          // If Hot Plug is supported,
1122          // Get the bridge information
1123          //
1124          BusPadding = FALSE;
1125          if (gPciHotPlugInit != NULL) {
1126
1127            if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) {
1128
1129              //
1130              // If it is initialized, get the padded bus range
1131              //
1132              Status = gPciHotPlugInit->GetResourcePadding (
1133                                          gPciHotPlugInit,
1134                                          gPciRootHpcPool[HpIndex].HpbDevicePath,
1135                                          PciAddress,
1136                                          &State,
1137                                          (VOID **) &Descriptors,
1138                                          &Attributes
1139                                          );
1140
1141              if (EFI_ERROR (Status)) {
1142                return Status;
1143              }
1144
1145              BusRange = 0;
1146              Status = PciGetBusRange (
1147                        &Descriptors,
1148                        NULL,
1149                        NULL,
1150                        &BusRange
1151                        );
1152
1153              FreePool (Descriptors);
1154
1155              if (EFI_ERROR (Status)) {
1156                return Status;
1157              }
1158
1159              BusPadding = TRUE;
1160            }
1161          }
1162        }
1163
1164        Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
1165        if (EFI_ERROR (Status)) {
1166          return Status;
1167        }
1168        SecondBus = *SubBusNumber;
1169
1170        Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1171        Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
1172
1173        Status = PciRootBridgeIo->Pci.Write (
1174                                        PciRootBridgeIo,
1175                                        EfiPciWidthUint16,
1176                                        Address,
1177                                        1,
1178                                        &Register
1179                                        );
1180
1181
1182        //
1183        // If it is PPB, resursively search down this bridge
1184        //
1185        if (IS_PCI_BRIDGE (&Pci)) {
1186
1187          //
1188          // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1189          // PCI configuration transaction to go through any PPB
1190          //
1191          Register  = 0xFF;
1192          Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
1193          Status = PciRootBridgeIo->Pci.Write (
1194                                          PciRootBridgeIo,
1195                                          EfiPciWidthUint8,
1196                                          Address,
1197                                          1,
1198                                          &Register
1199                                          );
1200
1201          //
1202          // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1203          //
1204          PreprocessController (
1205            PciDevice,
1206            PciDevice->BusNumber,
1207            PciDevice->DeviceNumber,
1208            PciDevice->FunctionNumber,
1209            EfiPciBeforeChildBusEnumeration
1210            );
1211
1212          Status = PciScanBus (
1213                    PciDevice,
1214                    SecondBus,
1215                    SubBusNumber,
1216                    PaddedBusRange
1217                    );
1218          if (EFI_ERROR (Status)) {
1219            return Status;
1220          }
1221        }
1222
1223        if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {
1224          //
1225          // Ensure the device is enabled and initialized
1226          //
1227          if ((Attributes == EfiPaddingPciRootBridge) &&
1228              (State & EFI_HPC_STATE_ENABLED) != 0    &&
1229              (State & EFI_HPC_STATE_INITIALIZED) != 0) {
1230            *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange);
1231          } else {
1232            //
1233            // Reserve the larger one between the actual occupied bus number and padded bus number
1234            //
1235            Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus);
1236            if (EFI_ERROR (Status)) {
1237              return Status;
1238            }
1239            *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);
1240          }
1241        }
1242
1243        //
1244        // Set the current maximum bus number under the PPB
1245        //
1246        Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
1247
1248        Status = PciRootBridgeIo->Pci.Write (
1249                                        PciRootBridgeIo,
1250                                        EfiPciWidthUint8,
1251                                        Address,
1252                                        1,
1253                                        SubBusNumber
1254                                        );
1255      } else  {
1256        //
1257        // It is device. Check PCI IOV for Bus reservation
1258        // Go through each function, just reserve the MAX ReservedBusNum for one device
1259        //
1260        if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
1261          if (TempReservedBusNum < PciDevice->ReservedBusNum) {
1262
1263            Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);
1264            if (EFI_ERROR (Status)) {
1265              return Status;
1266            }
1267            TempReservedBusNum = PciDevice->ReservedBusNum;
1268
1269            if (Func == 0) {
1270              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
1271            } else {
1272              DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
1273            }
1274          }
1275        }
1276      }
1277
1278      if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1279
1280        //
1281        // Skip sub functions, this is not a multi function device
1282        //
1283
1284        Func = PCI_MAX_FUNC;
1285      }
1286    }
1287  }
1288
1289  return EFI_SUCCESS;
1290}
1291
1292/**
1293  Process Option Rom on the specified root bridge.
1294
1295  @param Bridge  Pci root bridge device instance.
1296
1297  @retval EFI_SUCCESS   Success process.
1298  @retval other         Some error occurred when processing Option Rom on the root bridge.
1299
1300**/
1301EFI_STATUS
1302PciRootBridgeP2CProcess (
1303  IN PCI_IO_DEVICE *Bridge
1304  )
1305{
1306  LIST_ENTRY      *CurrentLink;
1307  PCI_IO_DEVICE   *Temp;
1308  EFI_HPC_STATE   State;
1309  UINT64          PciAddress;
1310  EFI_STATUS      Status;
1311
1312  CurrentLink = Bridge->ChildList.ForwardLink;
1313
1314  while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1315
1316    Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1317
1318    if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1319
1320      if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1321
1322        //
1323        // Raise the EFI_IOB_PCI_HPC_INIT status code
1324        //
1325        REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1326          EFI_PROGRESS_CODE,
1327          EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,
1328          Temp->DevicePath
1329          );
1330
1331        PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1332        Status = gPciHotPlugInit->InitializeRootHpc (
1333                                    gPciHotPlugInit,
1334                                    Temp->DevicePath,
1335                                    PciAddress,
1336                                    NULL,
1337                                    &State
1338                                    );
1339
1340        if (!EFI_ERROR (Status)) {
1341          Status = PciBridgeEnumerator (Temp);
1342
1343          if (EFI_ERROR (Status)) {
1344            return Status;
1345          }
1346        }
1347
1348        CurrentLink = CurrentLink->ForwardLink;
1349        continue;
1350
1351      }
1352    }
1353
1354    if (!IsListEmpty (&Temp->ChildList)) {
1355      Status = PciRootBridgeP2CProcess (Temp);
1356    }
1357
1358    CurrentLink = CurrentLink->ForwardLink;
1359  }
1360
1361  return EFI_SUCCESS;
1362}
1363
1364/**
1365  Process Option Rom on the specified host bridge.
1366
1367  @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1368
1369  @retval EFI_SUCCESS   Success process.
1370  @retval EFI_NOT_FOUND Can not find the root bridge instance.
1371  @retval other         Some error occurred when processing Option Rom on the host bridge.
1372
1373**/
1374EFI_STATUS
1375PciHostBridgeP2CProcess (
1376  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1377  )
1378{
1379  EFI_HANDLE    RootBridgeHandle;
1380  PCI_IO_DEVICE *RootBridgeDev;
1381  EFI_STATUS    Status;
1382
1383  if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1384    return EFI_SUCCESS;
1385  }
1386
1387  RootBridgeHandle = NULL;
1388
1389  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1390
1391    //
1392    // Get RootBridg Device by handle
1393    //
1394    RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1395
1396    if (RootBridgeDev == NULL) {
1397      return EFI_NOT_FOUND;
1398    }
1399
1400    Status = PciRootBridgeP2CProcess (RootBridgeDev);
1401    if (EFI_ERROR (Status)) {
1402      return Status;
1403    }
1404
1405  }
1406
1407  return EFI_SUCCESS;
1408}
1409
1410/**
1411  This function is used to enumerate the entire host bridge
1412  in a given platform.
1413
1414  @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.
1415
1416  @retval EFI_SUCCESS            Successfully enumerated the host bridge.
1417  @retval EFI_OUT_OF_RESOURCES   No enough memory available.
1418  @retval other                  Some error occurred when enumerating the host bridge.
1419
1420**/
1421EFI_STATUS
1422PciHostBridgeEnumerator (
1423  IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc
1424  )
1425{
1426  EFI_HANDLE                        RootBridgeHandle;
1427  PCI_IO_DEVICE                     *RootBridgeDev;
1428  EFI_STATUS                        Status;
1429  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
1430  UINT16                            MinBus;
1431  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1432  EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1433  UINT8                             StartBusNumber;
1434  LIST_ENTRY                        RootBridgeList;
1435  LIST_ENTRY                        *Link;
1436
1437  if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1438    InitializeHotPlugSupport ();
1439  }
1440
1441  InitializeListHead (&RootBridgeList);
1442
1443  //
1444  // Notify the bus allocation phase is about to start
1445  //
1446  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1447
1448  if (EFI_ERROR (Status)) {
1449    return Status;
1450  }
1451
1452  DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
1453  RootBridgeHandle = NULL;
1454  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1455
1456    //
1457    // if a root bridge instance is found, create root bridge device for it
1458    //
1459
1460    RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1461
1462    if (RootBridgeDev == NULL) {
1463      return EFI_OUT_OF_RESOURCES;
1464    }
1465
1466    //
1467    // Enumerate all the buses under this root bridge
1468    //
1469    Status = PciRootBridgeEnumerator (
1470              PciResAlloc,
1471              RootBridgeDev
1472              );
1473
1474    if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1475      InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1476    } else {
1477      DestroyRootBridge (RootBridgeDev);
1478    }
1479    if (EFI_ERROR (Status)) {
1480      return Status;
1481    }
1482  }
1483
1484  //
1485  // Notify the bus allocation phase is finished for the first time
1486  //
1487  NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1488
1489  if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1490    //
1491    // Reset all assigned PCI bus number in all PPB
1492    //
1493    RootBridgeHandle = NULL;
1494    Link = GetFirstNode (&RootBridgeList);
1495    while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1496      (!IsNull (&RootBridgeList, Link))) {
1497      RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1498      //
1499      // Get the Bus information
1500      //
1501      Status = PciResAlloc->StartBusEnumeration (
1502                              PciResAlloc,
1503                              RootBridgeHandle,
1504                              (VOID **) &Configuration
1505                              );
1506      if (EFI_ERROR (Status)) {
1507        return Status;
1508      }
1509
1510      //
1511      // Get the bus number to start with
1512      //
1513      StartBusNumber  = (UINT8) (Configuration->AddrRangeMin);
1514
1515      ResetAllPpbBusNumber (
1516        RootBridgeDev,
1517        StartBusNumber
1518      );
1519
1520      FreePool (Configuration);
1521      Link = RemoveEntryList (Link);
1522      DestroyRootBridge (RootBridgeDev);
1523    }
1524
1525    //
1526    // Wait for all HPC initialized
1527    //
1528    Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1529
1530    if (EFI_ERROR (Status)) {
1531      DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));
1532      return Status;
1533    }
1534
1535    //
1536    // Notify the bus allocation phase is about to start for the 2nd time
1537    //
1538    Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1539
1540    if (EFI_ERROR (Status)) {
1541      return Status;
1542    }
1543
1544    DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
1545    RootBridgeHandle = NULL;
1546    while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1547
1548      //
1549      // if a root bridge instance is found, create root bridge device for it
1550      //
1551      RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1552
1553      if (RootBridgeDev == NULL) {
1554        return EFI_OUT_OF_RESOURCES;
1555      }
1556
1557      //
1558      // Enumerate all the buses under this root bridge
1559      //
1560      Status = PciRootBridgeEnumerator (
1561                PciResAlloc,
1562                RootBridgeDev
1563                );
1564
1565      DestroyRootBridge (RootBridgeDev);
1566      if (EFI_ERROR (Status)) {
1567        return Status;
1568      }
1569    }
1570
1571    //
1572    // Notify the bus allocation phase is to end for the 2nd time
1573    //
1574    NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1575  }
1576
1577  //
1578  // Notify the resource allocation phase is to start
1579  //
1580  Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1581
1582  if (EFI_ERROR (Status)) {
1583    return Status;
1584  }
1585
1586  RootBridgeHandle = NULL;
1587  while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1588
1589    //
1590    // if a root bridge instance is found, create root bridge device for it
1591    //
1592    RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1593
1594    if (RootBridgeDev == NULL) {
1595      return EFI_OUT_OF_RESOURCES;
1596    }
1597
1598    Status = StartManagingRootBridge (RootBridgeDev);
1599
1600    if (EFI_ERROR (Status)) {
1601      return Status;
1602    }
1603
1604    PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1605    Status          = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1606
1607    if (EFI_ERROR (Status)) {
1608      return Status;
1609    }
1610
1611    Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1612
1613    if (EFI_ERROR (Status)) {
1614      return Status;
1615    }
1616
1617    //
1618    // Determine root bridge attribute by calling interface of Pcihostbridge
1619    // protocol
1620    //
1621    DetermineRootBridgeAttributes (
1622      PciResAlloc,
1623      RootBridgeDev
1624      );
1625
1626    //
1627    // Collect all the resource information under this root bridge
1628    // A database that records all the information about pci device subject to this
1629    // root bridge will then be created
1630    //
1631    Status = PciPciDeviceInfoCollector (
1632              RootBridgeDev,
1633              (UINT8) MinBus
1634              );
1635
1636    if (EFI_ERROR (Status)) {
1637      return Status;
1638    }
1639
1640    InsertRootBridge (RootBridgeDev);
1641
1642    //
1643    // Record the hostbridge handle
1644    //
1645    AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1646  }
1647
1648  return EFI_SUCCESS;
1649}
1650