• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Internal library implementation for PCI Bus module.
3 
4 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<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 "PciBus.h"
17 
18 GLOBAL_REMOVE_IF_UNREFERENCED
19 CHAR16 *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 **/
38 VOID
GetBackPcCardBar(IN PCI_IO_DEVICE * PciIoDevice)39 GetBackPcCardBar (
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 **/
117 VOID
RemoveRejectedPciDevices(IN EFI_HANDLE RootBridgeHandle,IN PCI_IO_DEVICE * Bridge)118 RemoveRejectedPciDevices (
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 **/
175 VOID
DumpBridgeResource(IN PCI_RESOURCE_NODE * BridgeResource)176 DumpBridgeResource (
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 **/
242 UINTN
FindResourceNode(IN PCI_IO_DEVICE * Device,IN PCI_RESOURCE_NODE * BridgeResource,OUT PCI_RESOURCE_NODE ** DeviceResources OPTIONAL)243 FindResourceNode (
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 **/
277 VOID
DumpResourceMap(IN PCI_IO_DEVICE * Bridge,IN PCI_RESOURCE_NODE ** Resources,IN UINTN ResourceCount)278 DumpResourceMap (
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 **/
361 EFI_STATUS
PciHostBridgeResourceAllocator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)362 PciHostBridgeResourceAllocator (
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 **/
907 EFI_STATUS
PciAllocateBusNumber(IN PCI_IO_DEVICE * Bridge,IN UINT8 StartBusNumber,IN UINT8 NumberOfBuses,OUT UINT8 * NextBusNumber)908 PciAllocateBusNumber (
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 **/
966 EFI_STATUS
PciScanBus(IN PCI_IO_DEVICE * Bridge,IN UINT8 StartBusNumber,OUT UINT8 * SubBusNumber,OUT UINT8 * PaddedBusRange)967 PciScanBus (
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 **/
1301 EFI_STATUS
PciRootBridgeP2CProcess(IN PCI_IO_DEVICE * Bridge)1302 PciRootBridgeP2CProcess (
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 **/
1374 EFI_STATUS
PciHostBridgeP2CProcess(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)1375 PciHostBridgeP2CProcess (
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 **/
1421 EFI_STATUS
PciHostBridgeEnumerator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)1422 PciHostBridgeEnumerator (
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