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