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