1 /** @file
2   Internal library implementation for PCI Bus module.
3 
4 Copyright (c) 2006 - 2021, 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   Adjust the Devices' BAR size to minimum value if it support Resizeable BAR capability.
382 
383   @param RootBridgeDev  Pointer to instance of PCI_IO_DEVICE..
384 
385   @return TRUE if BAR size is adjusted.
386 
387 **/
388 BOOLEAN
AdjustPciDeviceBarSize(IN PCI_IO_DEVICE * RootBridgeDev)389 AdjustPciDeviceBarSize (
390   IN PCI_IO_DEVICE *RootBridgeDev
391   )
392 {
393   PCI_IO_DEVICE     *PciIoDevice;
394   LIST_ENTRY        *CurrentLink;
395   BOOLEAN           Adjusted;
396   UINTN             Offset;
397   UINTN             BarIndex;
398 
399   Adjusted    = FALSE;
400   CurrentLink = RootBridgeDev->ChildList.ForwardLink;
401 
402   while (CurrentLink != NULL && CurrentLink != &RootBridgeDev->ChildList) {
403     PciIoDevice = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
404 
405     if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) {
406       if (AdjustPciDeviceBarSize (PciIoDevice)) {
407         Adjusted = TRUE;
408       }
409     } else {
410       if (PciIoDevice->ResizableBarOffset != 0) {
411         DEBUG ((
412           DEBUG_ERROR,
413           "PciBus: [%02x|%02x|%02x] Adjust Pci Device Bar Size\n",
414           PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber
415           ));
416         PciProgramResizableBar (PciIoDevice, PciResizableBarMin);
417         //
418         // Start to parse the bars
419         //
420         for (Offset = 0x10, BarIndex = 0; Offset <= 0x24 && BarIndex < PCI_MAX_BAR; BarIndex++) {
421           Offset = PciParseBar (PciIoDevice, Offset, BarIndex);
422         }
423         Adjusted = TRUE;
424         DEBUG_CODE (DumpPciBars (PciIoDevice););
425       }
426     }
427 
428     CurrentLink = CurrentLink->ForwardLink;
429   }
430 
431   return Adjusted;
432 }
433 
434 /**
435   Submits the I/O and memory resource requirements for the specified PCI Host Bridge.
436 
437   @param PciResAlloc  Point to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
438 
439   @retval EFI_SUCCESS           Successfully finished resource allocation.
440   @retval EFI_NOT_FOUND         Cannot get root bridge instance.
441   @retval EFI_OUT_OF_RESOURCES  Platform failed to program the resources if no hot plug supported.
442   @retval other                 Some error occurred when allocating resources for the PCI Host Bridge.
443 
444   @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
445 
446 **/
447 EFI_STATUS
PciHostBridgeResourceAllocator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)448 PciHostBridgeResourceAllocator (
449   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
450   )
451 {
452   PCI_IO_DEVICE                                  *RootBridgeDev;
453   EFI_HANDLE                                     RootBridgeHandle;
454   VOID                                           *AcpiConfig;
455   EFI_STATUS                                     Status;
456   UINT64                                         IoBase;
457   UINT64                                         Mem32Base;
458   UINT64                                         PMem32Base;
459   UINT64                                         Mem64Base;
460   UINT64                                         PMem64Base;
461   UINT64                                         IoResStatus;
462   UINT64                                         Mem32ResStatus;
463   UINT64                                         PMem32ResStatus;
464   UINT64                                         Mem64ResStatus;
465   UINT64                                         PMem64ResStatus;
466   UINT32                                         MaxOptionRomSize;
467   PCI_RESOURCE_NODE                              *IoBridge;
468   PCI_RESOURCE_NODE                              *Mem32Bridge;
469   PCI_RESOURCE_NODE                              *PMem32Bridge;
470   PCI_RESOURCE_NODE                              *Mem64Bridge;
471   PCI_RESOURCE_NODE                              *PMem64Bridge;
472   PCI_RESOURCE_NODE                              IoPool;
473   PCI_RESOURCE_NODE                              Mem32Pool;
474   PCI_RESOURCE_NODE                              PMem32Pool;
475   PCI_RESOURCE_NODE                              Mem64Pool;
476   PCI_RESOURCE_NODE                              PMem64Pool;
477   EFI_DEVICE_HANDLE_EXTENDED_DATA_PAYLOAD        HandleExtendedData;
478   EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD  AllocFailExtendedData;
479   BOOLEAN                                        ResizableBarNeedAdjust;
480   BOOLEAN                                        ResizableBarAdjusted;
481 
482   ResizableBarNeedAdjust = PcdGetBool (PcdPcieResizableBarSupport);
483 
484   //
485   // It may try several times if the resource allocation fails
486   //
487   while (TRUE) {
488     //
489     // Initialize resource pool
490     //
491     InitializeResourcePool (&IoPool, PciBarTypeIo16);
492     InitializeResourcePool (&Mem32Pool, PciBarTypeMem32);
493     InitializeResourcePool (&PMem32Pool, PciBarTypePMem32);
494     InitializeResourcePool (&Mem64Pool, PciBarTypeMem64);
495     InitializeResourcePool (&PMem64Pool, PciBarTypePMem64);
496 
497     RootBridgeDev     = NULL;
498     RootBridgeHandle  = 0;
499 
500     while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
501       //
502       // Get Root Bridge Device by handle
503       //
504       RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
505 
506       if (RootBridgeDev == NULL) {
507         return EFI_NOT_FOUND;
508       }
509 
510       //
511       // Create the entire system resource map from the information collected by
512       // enumerator. Several resource tree was created
513       //
514 
515       //
516       // If non-standard PCI Bridge I/O window alignment is supported,
517       // set I/O aligment to minimum possible alignment for root bridge.
518       //
519       IoBridge = CreateResourceNode (
520                    RootBridgeDev,
521                    0,
522                    FeaturePcdGet (PcdPciBridgeIoAlignmentProbe) ? 0x1FF: 0xFFF,
523                    RB_IO_RANGE,
524                    PciBarTypeIo16,
525                    PciResUsageTypical
526                    );
527 
528       Mem32Bridge = CreateResourceNode (
529                       RootBridgeDev,
530                       0,
531                       0xFFFFF,
532                       RB_MEM32_RANGE,
533                       PciBarTypeMem32,
534                       PciResUsageTypical
535                       );
536 
537       PMem32Bridge = CreateResourceNode (
538                        RootBridgeDev,
539                        0,
540                        0xFFFFF,
541                        RB_PMEM32_RANGE,
542                        PciBarTypePMem32,
543                        PciResUsageTypical
544                        );
545 
546       Mem64Bridge = CreateResourceNode (
547                       RootBridgeDev,
548                       0,
549                       0xFFFFF,
550                       RB_MEM64_RANGE,
551                       PciBarTypeMem64,
552                       PciResUsageTypical
553                       );
554 
555       PMem64Bridge = CreateResourceNode (
556                        RootBridgeDev,
557                        0,
558                        0xFFFFF,
559                        RB_PMEM64_RANGE,
560                        PciBarTypePMem64,
561                        PciResUsageTypical
562                        );
563 
564       //
565       // Get the max ROM size that the root bridge can process
566       // Insert to resource map so that there will be dedicate MEM32 resource range for Option ROM.
567       // All devices' Option ROM share the same MEM32 resource.
568       //
569       MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev);
570       if (MaxOptionRomSize != 0) {
571         RootBridgeDev->PciBar[0].BarType   = PciBarTypeOpRom;
572         RootBridgeDev->PciBar[0].Length    = MaxOptionRomSize;
573         RootBridgeDev->PciBar[0].Alignment = MaxOptionRomSize - 1;
574         GetResourceFromDevice (RootBridgeDev, IoBridge, Mem32Bridge, PMem32Bridge, Mem64Bridge, PMem64Bridge);
575       }
576 
577       //
578       // Create resourcemap by going through all the devices subject to this root bridge
579       //
580       CreateResourceMap (
581         RootBridgeDev,
582         IoBridge,
583         Mem32Bridge,
584         PMem32Bridge,
585         Mem64Bridge,
586         PMem64Bridge
587         );
588 
589       //
590       // Based on the all the resource tree, construct ACPI resource node to
591       // submit the resource aperture to pci host bridge protocol
592       //
593       Status = ConstructAcpiResourceRequestor (
594                  RootBridgeDev,
595                  IoBridge,
596                  Mem32Bridge,
597                  PMem32Bridge,
598                  Mem64Bridge,
599                  PMem64Bridge,
600                  &AcpiConfig
601                  );
602 
603       //
604       // Insert these resource nodes into the database
605       //
606       InsertResourceNode (&IoPool, IoBridge);
607       InsertResourceNode (&Mem32Pool, Mem32Bridge);
608       InsertResourceNode (&PMem32Pool, PMem32Bridge);
609       InsertResourceNode (&Mem64Pool, Mem64Bridge);
610       InsertResourceNode (&PMem64Pool, PMem64Bridge);
611 
612       if (Status == EFI_SUCCESS) {
613         //
614         // Submit the resource requirement
615         //
616         Status = PciResAlloc->SubmitResources (
617                                 PciResAlloc,
618                                 RootBridgeDev->Handle,
619                                 AcpiConfig
620                                 );
621         //
622         // If SubmitResources returns error, PciBus isn't able to start.
623         // It's a fatal error so assertion is added.
624         //
625         DEBUG ((EFI_D_INFO, "PciBus: HostBridge->SubmitResources() - %r\n", Status));
626         ASSERT_EFI_ERROR (Status);
627       }
628 
629       //
630       // Free acpi resource node
631       //
632       if (AcpiConfig != NULL) {
633         FreePool (AcpiConfig);
634       }
635 
636       if (EFI_ERROR (Status)) {
637         //
638         // Destroy all the resource tree
639         //
640         DestroyResourceTree (&IoPool);
641         DestroyResourceTree (&Mem32Pool);
642         DestroyResourceTree (&PMem32Pool);
643         DestroyResourceTree (&Mem64Pool);
644         DestroyResourceTree (&PMem64Pool);
645         return Status;
646       }
647     }
648     //
649     // End while, at least one Root Bridge should be found.
650     //
651     ASSERT (RootBridgeDev != NULL);
652 
653     //
654     // Notify platform to start to program the resource
655     //
656     Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources);
657     DEBUG ((EFI_D_INFO, "PciBus: HostBridge->NotifyPhase(AllocateResources) - %r\n", Status));
658     if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
659       //
660       // If Hot Plug is not supported
661       //
662       if (EFI_ERROR (Status)) {
663         //
664         // Allocation failed, then return
665         //
666         return EFI_OUT_OF_RESOURCES;
667       }
668       //
669       // Allocation succeed.
670       // Get host bridge handle for status report, and then skip the main while
671       //
672       HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
673 
674       break;
675 
676     } else {
677       //
678       // If Hot Plug is supported
679       //
680       if (!EFI_ERROR (Status)) {
681         //
682         // Allocation succeed, then continue the following
683         //
684         break;
685       }
686 
687       //
688       // If the resource allocation is unsuccessful, free resources on bridge
689       //
690 
691       RootBridgeDev     = NULL;
692       RootBridgeHandle  = 0;
693 
694       IoResStatus       = EFI_RESOURCE_SATISFIED;
695       Mem32ResStatus    = EFI_RESOURCE_SATISFIED;
696       PMem32ResStatus   = EFI_RESOURCE_SATISFIED;
697       Mem64ResStatus    = EFI_RESOURCE_SATISFIED;
698       PMem64ResStatus   = EFI_RESOURCE_SATISFIED;
699 
700       while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
701         //
702         // Get RootBridg Device by handle
703         //
704         RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
705         if (RootBridgeDev == NULL) {
706           return EFI_NOT_FOUND;
707         }
708 
709         //
710         // Get host bridge handle for status report
711         //
712         HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle;
713 
714         //
715         // Get acpi resource node for all the resource types
716         //
717         AcpiConfig = NULL;
718 
719         Status = PciResAlloc->GetProposedResources (
720                                 PciResAlloc,
721                                 RootBridgeDev->Handle,
722                                 &AcpiConfig
723                                 );
724 
725         if (EFI_ERROR (Status)) {
726           return Status;
727         }
728 
729         if (AcpiConfig != NULL) {
730           //
731           // Adjust resource allocation policy for each RB
732           //
733           GetResourceAllocationStatus (
734             AcpiConfig,
735             &IoResStatus,
736             &Mem32ResStatus,
737             &PMem32ResStatus,
738             &Mem64ResStatus,
739             &PMem64ResStatus
740             );
741           FreePool (AcpiConfig);
742         }
743       }
744       //
745       // End while
746       //
747 
748       //
749       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
750       //
751       //
752       // It is very difficult to follow the spec here
753       // Device path , Bar index can not be get here
754       //
755       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
756 
757       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
758             EFI_PROGRESS_CODE,
759             EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
760             (VOID *) &AllocFailExtendedData,
761             sizeof (AllocFailExtendedData)
762             );
763 
764      //
765      // When resource conflict happens, adjust the BAR size first.
766      // Only when adjusting BAR size doesn't help or BAR size cannot be adjusted,
767      // reject the device who requests largest resource that causes conflict.
768      //
769       ResizableBarAdjusted = FALSE;
770       if (ResizableBarNeedAdjust) {
771         ResizableBarAdjusted = AdjustPciDeviceBarSize (RootBridgeDev);
772         ResizableBarNeedAdjust = FALSE;
773       }
774       if (!ResizableBarAdjusted) {
775         Status = PciHostBridgeAdjustAllocation (
776                   &IoPool,
777                   &Mem32Pool,
778                   &PMem32Pool,
779                   &Mem64Pool,
780                   &PMem64Pool,
781                   IoResStatus,
782                   Mem32ResStatus,
783                   PMem32ResStatus,
784                   Mem64ResStatus,
785                   PMem64ResStatus
786                   );
787       }
788       //
789       // Destroy all the resource tree
790       //
791       DestroyResourceTree (&IoPool);
792       DestroyResourceTree (&Mem32Pool);
793       DestroyResourceTree (&PMem32Pool);
794       DestroyResourceTree (&Mem64Pool);
795       DestroyResourceTree (&PMem64Pool);
796 
797       NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources);
798 
799       if (EFI_ERROR (Status)) {
800         return Status;
801       }
802     }
803   }
804   //
805   // End main while
806   //
807 
808   //
809   // Raise the EFI_IOB_PCI_RES_ALLOC status code
810   //
811   REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
812         EFI_PROGRESS_CODE,
813         EFI_IO_BUS_PCI | EFI_IOB_PCI_RES_ALLOC,
814         (VOID *) &HandleExtendedData,
815         sizeof (HandleExtendedData)
816         );
817 
818   //
819   // Notify pci bus driver starts to program the resource
820   //
821   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources);
822 
823   if (EFI_ERROR (Status)) {
824     return Status;
825   }
826 
827   RootBridgeDev     = NULL;
828 
829   RootBridgeHandle  = 0;
830 
831   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
832     //
833     // Get RootBridg Device by handle
834     //
835     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
836 
837     if (RootBridgeDev == NULL) {
838       return EFI_NOT_FOUND;
839     }
840 
841     //
842     // Get acpi resource node for all the resource types
843     //
844     AcpiConfig = NULL;
845     Status = PciResAlloc->GetProposedResources (
846                             PciResAlloc,
847                             RootBridgeDev->Handle,
848                             &AcpiConfig
849                             );
850 
851     if (EFI_ERROR (Status)) {
852       return Status;
853     }
854 
855     //
856     // Get the resource base by interpreting acpi resource node
857     //
858     //
859     GetResourceBase (
860       AcpiConfig,
861       &IoBase,
862       &Mem32Base,
863       &PMem32Base,
864       &Mem64Base,
865       &PMem64Base
866       );
867 
868     //
869     // Create the entire system resource map from the information collected by
870     // enumerator. Several resource tree was created
871     //
872     FindResourceNode (RootBridgeDev, &IoPool, &IoBridge);
873     FindResourceNode (RootBridgeDev, &Mem32Pool, &Mem32Bridge);
874     FindResourceNode (RootBridgeDev, &PMem32Pool, &PMem32Bridge);
875     FindResourceNode (RootBridgeDev, &Mem64Pool, &Mem64Bridge);
876     FindResourceNode (RootBridgeDev, &PMem64Pool, &PMem64Bridge);
877 
878     ASSERT (IoBridge     != NULL);
879     ASSERT (Mem32Bridge  != NULL);
880     ASSERT (PMem32Bridge != NULL);
881     ASSERT (Mem64Bridge  != NULL);
882     ASSERT (PMem64Bridge != NULL);
883 
884     //
885     // Program IO resources
886     //
887     ProgramResource (
888       IoBase,
889       IoBridge
890       );
891 
892     //
893     // Program Mem32 resources
894     //
895     ProgramResource (
896       Mem32Base,
897       Mem32Bridge
898       );
899 
900     //
901     // Program PMem32 resources
902     //
903     ProgramResource (
904       PMem32Base,
905       PMem32Bridge
906       );
907 
908     //
909     // Program Mem64 resources
910     //
911     ProgramResource (
912       Mem64Base,
913       Mem64Bridge
914       );
915 
916     //
917     // Program PMem64 resources
918     //
919     ProgramResource (
920       PMem64Base,
921       PMem64Bridge
922       );
923 
924     //
925     // Process Option ROM for this root bridge after all BARs are programmed.
926     // The PPB's MEM32 RANGE BAR is re-programmed to the Option ROM BAR Base in order to
927     // shadow the Option ROM of the devices under the PPB.
928     // After the shadow, Option ROM BAR decoding is turned off and the PPB's MEM32 RANGE
929     // BAR is restored back to the original value.
930     // The original value is programmed by ProgramResource() above.
931     //
932     DEBUG ((
933       DEBUG_INFO, "Process Option ROM: BAR Base/Length = %lx/%lx\n",
934       RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length
935       ));
936     ProcessOptionRom (RootBridgeDev, RootBridgeDev->PciBar[0].BaseAddress, RootBridgeDev->PciBar[0].Length);
937 
938     IoBridge    ->PciDev->PciBar[IoBridge    ->Bar].BaseAddress = IoBase;
939     Mem32Bridge ->PciDev->PciBar[Mem32Bridge ->Bar].BaseAddress = Mem32Base;
940     PMem32Bridge->PciDev->PciBar[PMem32Bridge->Bar].BaseAddress = PMem32Base;
941     Mem64Bridge ->PciDev->PciBar[Mem64Bridge ->Bar].BaseAddress = Mem64Base;
942     PMem64Bridge->PciDev->PciBar[PMem64Bridge->Bar].BaseAddress = PMem64Base;
943 
944     //
945     // Dump the resource map for current root bridge
946     //
947     DEBUG_CODE (
948       PCI_RESOURCE_NODE *Resources[5];
949       Resources[0] = IoBridge;
950       Resources[1] = Mem32Bridge;
951       Resources[2] = PMem32Bridge;
952       Resources[3] = Mem64Bridge;
953       Resources[4] = PMem64Bridge;
954       DumpResourceMap (RootBridgeDev, Resources, ARRAY_SIZE (Resources));
955     );
956 
957     FreePool (AcpiConfig);
958   }
959 
960   //
961   // Destroy all the resource tree
962   //
963   DestroyResourceTree (&IoPool);
964   DestroyResourceTree (&Mem32Pool);
965   DestroyResourceTree (&PMem32Pool);
966   DestroyResourceTree (&Mem64Pool);
967   DestroyResourceTree (&PMem64Pool);
968 
969   //
970   // Notify the resource allocation phase is to end
971   //
972   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation);
973 
974   return Status;
975 }
976 
977 /**
978   Allocate NumberOfBuses buses and return the next available PCI bus number.
979 
980   @param  Bridge           Bridge device instance.
981   @param  StartBusNumber   Current available PCI bus number.
982   @param  NumberOfBuses    Number of buses enumerated below the StartBusNumber.
983   @param  NextBusNumber    Next available PCI bus number.
984 
985   @retval EFI_SUCCESS           Available bus number resource is enough. Next available PCI bus number
986                                 is returned in NextBusNumber.
987   @retval EFI_OUT_OF_RESOURCES  Available bus number resource is not enough for allocation.
988 
989 **/
990 EFI_STATUS
PciAllocateBusNumber(IN PCI_IO_DEVICE * Bridge,IN UINT8 StartBusNumber,IN UINT8 NumberOfBuses,OUT UINT8 * NextBusNumber)991 PciAllocateBusNumber (
992   IN PCI_IO_DEVICE                      *Bridge,
993   IN UINT8                              StartBusNumber,
994   IN UINT8                              NumberOfBuses,
995   OUT UINT8                             *NextBusNumber
996   )
997 {
998   PCI_IO_DEVICE                      *RootBridge;
999   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR  *BusNumberRanges;
1000   UINT8                              NextNumber;
1001   UINT64                             MaxNumberInRange;
1002 
1003   //
1004   // Get PCI Root Bridge device
1005   //
1006   RootBridge = Bridge;
1007   while (RootBridge->Parent != NULL) {
1008     RootBridge = RootBridge->Parent;
1009   }
1010 
1011   //
1012   // Get next available PCI bus number
1013   //
1014   BusNumberRanges = RootBridge->BusNumberRanges;
1015   while (BusNumberRanges->Desc != ACPI_END_TAG_DESCRIPTOR) {
1016     MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
1017     if (StartBusNumber >= BusNumberRanges->AddrRangeMin && StartBusNumber <=  MaxNumberInRange) {
1018       NextNumber = (UINT8)(StartBusNumber + NumberOfBuses);
1019       while (NextNumber > MaxNumberInRange) {
1020         ++BusNumberRanges;
1021         if (BusNumberRanges->Desc == ACPI_END_TAG_DESCRIPTOR) {
1022           return EFI_OUT_OF_RESOURCES;
1023         }
1024         NextNumber = (UINT8)(NextNumber + (BusNumberRanges->AddrRangeMin - (MaxNumberInRange + 1)));
1025         MaxNumberInRange = BusNumberRanges->AddrRangeMin + BusNumberRanges->AddrLen - 1;
1026       }
1027       *NextBusNumber = NextNumber;
1028       return EFI_SUCCESS;
1029     }
1030     BusNumberRanges++;
1031   }
1032   return EFI_OUT_OF_RESOURCES;
1033 }
1034 
1035 /**
1036   Scan pci bus and assign bus number to the given PCI bus system.
1037 
1038   @param  Bridge           Bridge device instance.
1039   @param  StartBusNumber   start point.
1040   @param  SubBusNumber     Point to sub bus number.
1041   @param  PaddedBusRange   Customized bus number.
1042 
1043   @retval EFI_SUCCESS      Successfully scanned and assigned bus number.
1044   @retval other            Some error occurred when scanning pci bus.
1045 
1046   @note   Feature flag PcdPciBusHotplugDeviceSupport determine whether need support hotplug.
1047 
1048 **/
1049 EFI_STATUS
PciScanBus(IN PCI_IO_DEVICE * Bridge,IN UINT8 StartBusNumber,OUT UINT8 * SubBusNumber,OUT UINT8 * PaddedBusRange)1050 PciScanBus (
1051   IN PCI_IO_DEVICE                      *Bridge,
1052   IN UINT8                              StartBusNumber,
1053   OUT UINT8                             *SubBusNumber,
1054   OUT UINT8                             *PaddedBusRange
1055   )
1056 {
1057   EFI_STATUS                        Status;
1058   PCI_TYPE00                        Pci;
1059   UINT8                             Device;
1060   UINT8                             Func;
1061   UINT64                            Address;
1062   UINT8                             SecondBus;
1063   UINT8                             PaddedSubBus;
1064   UINT16                            Register;
1065   UINTN                             HpIndex;
1066   PCI_IO_DEVICE                     *PciDevice;
1067   EFI_EVENT                         Event;
1068   EFI_HPC_STATE                     State;
1069   UINT64                            PciAddress;
1070   EFI_HPC_PADDING_ATTRIBUTES        Attributes;
1071   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1072   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *NextDescriptors;
1073   UINT16                            BusRange;
1074   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
1075   BOOLEAN                           BusPadding;
1076   UINT32                            TempReservedBusNum;
1077 
1078   PciRootBridgeIo = Bridge->PciRootBridgeIo;
1079   SecondBus       = 0;
1080   Register        = 0;
1081   State           = 0;
1082   Attributes      = (EFI_HPC_PADDING_ATTRIBUTES) 0;
1083   BusRange        = 0;
1084   BusPadding      = FALSE;
1085   PciDevice       = NULL;
1086   PciAddress      = 0;
1087 
1088   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
1089     TempReservedBusNum = 0;
1090     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
1091 
1092       //
1093       // Check to see whether a pci device is present
1094       //
1095       Status = PciDevicePresent (
1096                 PciRootBridgeIo,
1097                 &Pci,
1098                 StartBusNumber,
1099                 Device,
1100                 Func
1101                 );
1102 
1103       if (EFI_ERROR (Status) && Func == 0) {
1104         //
1105         // go to next device if there is no Function 0
1106         //
1107         break;
1108       }
1109 
1110       if (EFI_ERROR (Status)) {
1111         continue;
1112       }
1113 
1114       //
1115       // Get the PCI device information
1116       //
1117       Status = PciSearchDevice (
1118                 Bridge,
1119                 &Pci,
1120                 StartBusNumber,
1121                 Device,
1122                 Func,
1123                 &PciDevice
1124                 );
1125 
1126       if (EFI_ERROR (Status)) {
1127         continue;
1128       }
1129 
1130       PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);
1131 
1132       if (!IS_PCI_BRIDGE (&Pci)) {
1133         //
1134         // PCI bridges will be called later
1135         // Here just need for PCI device or PCI to cardbus controller
1136         // EfiPciBeforeChildBusEnumeration for PCI Device Node
1137         //
1138         PreprocessController (
1139             PciDevice,
1140             PciDevice->BusNumber,
1141             PciDevice->DeviceNumber,
1142             PciDevice->FunctionNumber,
1143             EfiPciBeforeChildBusEnumeration
1144             );
1145       }
1146 
1147       if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1148         //
1149         // For Pci Hotplug controller devcie only
1150         //
1151         if (gPciHotPlugInit != NULL) {
1152           //
1153           // Check if it is a Hotplug PCI controller
1154           //
1155           if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) {
1156             gPciRootHpcData[HpIndex].Found = TRUE;
1157 
1158             if (!gPciRootHpcData[HpIndex].Initialized) {
1159 
1160               Status = CreateEventForHpc (HpIndex, &Event);
1161 
1162               ASSERT (!EFI_ERROR (Status));
1163 
1164               Status = gPciHotPlugInit->InitializeRootHpc (
1165                                           gPciHotPlugInit,
1166                                           gPciRootHpcPool[HpIndex].HpcDevicePath,
1167                                           PciAddress,
1168                                           Event,
1169                                           &State
1170                                           );
1171 
1172               PreprocessController (
1173                 PciDevice,
1174                 PciDevice->BusNumber,
1175                 PciDevice->DeviceNumber,
1176                 PciDevice->FunctionNumber,
1177                 EfiPciBeforeChildBusEnumeration
1178               );
1179             }
1180           }
1181         }
1182       }
1183 
1184       if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) {
1185         //
1186         // For PPB
1187         //
1188         if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1189           //
1190           // If Hot Plug is supported,
1191           // Get the bridge information
1192           //
1193           BusPadding = FALSE;
1194           if (gPciHotPlugInit != NULL) {
1195 
1196             if (IsPciHotPlugBus (PciDevice)) {
1197 
1198               //
1199               // If it is initialized, get the padded bus range
1200               //
1201               Status = gPciHotPlugInit->GetResourcePadding (
1202                                           gPciHotPlugInit,
1203                                           PciDevice->DevicePath,
1204                                           PciAddress,
1205                                           &State,
1206                                           (VOID **) &Descriptors,
1207                                           &Attributes
1208                                           );
1209 
1210               if (EFI_ERROR (Status)) {
1211                 return Status;
1212               }
1213 
1214               BusRange = 0;
1215               NextDescriptors = Descriptors;
1216               Status = PciGetBusRange (
1217                         &NextDescriptors,
1218                         NULL,
1219                         NULL,
1220                         &BusRange
1221                         );
1222 
1223               FreePool (Descriptors);
1224 
1225               if (!EFI_ERROR (Status)) {
1226                 BusPadding = TRUE;
1227               } else if (Status != EFI_NOT_FOUND) {
1228                 //
1229                 // EFI_NOT_FOUND is not a real error. It indicates no bus number padding requested.
1230                 //
1231                 return Status;
1232               }
1233             }
1234           }
1235         }
1236 
1237         Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
1238         if (EFI_ERROR (Status)) {
1239           return Status;
1240         }
1241         SecondBus = *SubBusNumber;
1242 
1243         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
1244         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET);
1245 
1246         Status = PciRootBridgeIo->Pci.Write (
1247                                         PciRootBridgeIo,
1248                                         EfiPciWidthUint16,
1249                                         Address,
1250                                         1,
1251                                         &Register
1252                                         );
1253 
1254 
1255         //
1256         // If it is PPB, resursively search down this bridge
1257         //
1258         if (IS_PCI_BRIDGE (&Pci)) {
1259 
1260           //
1261           // Temporarily initialize SubBusNumber to maximum bus number to ensure the
1262           // PCI configuration transaction to go through any PPB
1263           //
1264           Register  = PciGetMaxBusNumber (Bridge);
1265           Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
1266           Status = PciRootBridgeIo->Pci.Write (
1267                                           PciRootBridgeIo,
1268                                           EfiPciWidthUint8,
1269                                           Address,
1270                                           1,
1271                                           &Register
1272                                           );
1273 
1274           //
1275           // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige
1276           //
1277           PreprocessController (
1278             PciDevice,
1279             PciDevice->BusNumber,
1280             PciDevice->DeviceNumber,
1281             PciDevice->FunctionNumber,
1282             EfiPciBeforeChildBusEnumeration
1283             );
1284 
1285           Status = PciScanBus (
1286                     PciDevice,
1287                     SecondBus,
1288                     SubBusNumber,
1289                     PaddedBusRange
1290                     );
1291           if (EFI_ERROR (Status)) {
1292             return Status;
1293           }
1294         }
1295 
1296         if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport) && BusPadding) {
1297           //
1298           // Ensure the device is enabled and initialized
1299           //
1300           if ((Attributes == EfiPaddingPciRootBridge) &&
1301               (State & EFI_HPC_STATE_ENABLED) != 0    &&
1302               (State & EFI_HPC_STATE_INITIALIZED) != 0) {
1303             *PaddedBusRange = (UINT8) ((UINT8) (BusRange) + *PaddedBusRange);
1304           } else {
1305             //
1306             // Reserve the larger one between the actual occupied bus number and padded bus number
1307             //
1308             Status = PciAllocateBusNumber (PciDevice, SecondBus, (UINT8) (BusRange), &PaddedSubBus);
1309             if (EFI_ERROR (Status)) {
1310               return Status;
1311             }
1312             *SubBusNumber = MAX (PaddedSubBus, *SubBusNumber);
1313           }
1314         }
1315 
1316         //
1317         // Set the current maximum bus number under the PPB
1318         //
1319         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET);
1320 
1321         Status = PciRootBridgeIo->Pci.Write (
1322                                         PciRootBridgeIo,
1323                                         EfiPciWidthUint8,
1324                                         Address,
1325                                         1,
1326                                         SubBusNumber
1327                                         );
1328       } else  {
1329         //
1330         // It is device. Check PCI IOV for Bus reservation
1331         // Go through each function, just reserve the MAX ReservedBusNum for one device
1332         //
1333         if (PcdGetBool (PcdSrIovSupport) && PciDevice->SrIovCapabilityOffset != 0) {
1334           if (TempReservedBusNum < PciDevice->ReservedBusNum) {
1335 
1336             Status = PciAllocateBusNumber (PciDevice, *SubBusNumber, (UINT8) (PciDevice->ReservedBusNum - TempReservedBusNum), SubBusNumber);
1337             if (EFI_ERROR (Status)) {
1338               return Status;
1339             }
1340             TempReservedBusNum = PciDevice->ReservedBusNum;
1341 
1342             if (Func == 0) {
1343               DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x\n", *SubBusNumber));
1344             } else {
1345               DEBUG ((EFI_D_INFO, "PCI-IOV ScanBus - SubBusNumber - 0x%x (Update)\n", *SubBusNumber));
1346             }
1347           }
1348         }
1349       }
1350 
1351       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
1352 
1353         //
1354         // Skip sub functions, this is not a multi function device
1355         //
1356 
1357         Func = PCI_MAX_FUNC;
1358       }
1359     }
1360   }
1361 
1362   return EFI_SUCCESS;
1363 }
1364 
1365 /**
1366   Process Option Rom on the specified root bridge.
1367 
1368   @param Bridge  Pci root bridge device instance.
1369 
1370   @retval EFI_SUCCESS   Success process.
1371   @retval other         Some error occurred when processing Option Rom on the root bridge.
1372 
1373 **/
1374 EFI_STATUS
PciRootBridgeP2CProcess(IN PCI_IO_DEVICE * Bridge)1375 PciRootBridgeP2CProcess (
1376   IN PCI_IO_DEVICE *Bridge
1377   )
1378 {
1379   LIST_ENTRY      *CurrentLink;
1380   PCI_IO_DEVICE   *Temp;
1381   EFI_HPC_STATE   State;
1382   UINT64          PciAddress;
1383   EFI_STATUS      Status;
1384 
1385   CurrentLink = Bridge->ChildList.ForwardLink;
1386 
1387   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
1388 
1389     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
1390 
1391     if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
1392 
1393       if (gPciHotPlugInit != NULL && Temp->Allocated && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1394 
1395         //
1396         // Raise the EFI_IOB_PCI_HPC_INIT status code
1397         //
1398         REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1399           EFI_PROGRESS_CODE,
1400           EFI_IO_BUS_PCI | EFI_IOB_PCI_HPC_INIT,
1401           Temp->DevicePath
1402           );
1403 
1404         PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0);
1405         Status = gPciHotPlugInit->InitializeRootHpc (
1406                                     gPciHotPlugInit,
1407                                     Temp->DevicePath,
1408                                     PciAddress,
1409                                     NULL,
1410                                     &State
1411                                     );
1412 
1413         if (!EFI_ERROR (Status)) {
1414           Status = PciBridgeEnumerator (Temp);
1415 
1416           if (EFI_ERROR (Status)) {
1417             return Status;
1418           }
1419         }
1420 
1421         CurrentLink = CurrentLink->ForwardLink;
1422         continue;
1423 
1424       }
1425     }
1426 
1427     if (!IsListEmpty (&Temp->ChildList)) {
1428       Status = PciRootBridgeP2CProcess (Temp);
1429     }
1430 
1431     CurrentLink = CurrentLink->ForwardLink;
1432   }
1433 
1434   return EFI_SUCCESS;
1435 }
1436 
1437 /**
1438   Process Option Rom on the specified host bridge.
1439 
1440   @param PciResAlloc    Pointer to instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
1441 
1442   @retval EFI_SUCCESS   Success process.
1443   @retval EFI_NOT_FOUND Can not find the root bridge instance.
1444   @retval other         Some error occurred when processing Option Rom on the host bridge.
1445 
1446 **/
1447 EFI_STATUS
PciHostBridgeP2CProcess(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)1448 PciHostBridgeP2CProcess (
1449   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
1450   )
1451 {
1452   EFI_HANDLE    RootBridgeHandle;
1453   PCI_IO_DEVICE *RootBridgeDev;
1454   EFI_STATUS    Status;
1455 
1456   if (!FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1457     return EFI_SUCCESS;
1458   }
1459 
1460   RootBridgeHandle = NULL;
1461 
1462   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1463 
1464     //
1465     // Get RootBridg Device by handle
1466     //
1467     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
1468 
1469     if (RootBridgeDev == NULL) {
1470       return EFI_NOT_FOUND;
1471     }
1472 
1473     Status = PciRootBridgeP2CProcess (RootBridgeDev);
1474     if (EFI_ERROR (Status)) {
1475       return Status;
1476     }
1477 
1478   }
1479 
1480   return EFI_SUCCESS;
1481 }
1482 
1483 /**
1484   This function is used to enumerate the entire host bridge
1485   in a given platform.
1486 
1487   @param PciResAlloc   A pointer to the PCI Host Resource Allocation protocol.
1488 
1489   @retval EFI_SUCCESS            Successfully enumerated the host bridge.
1490   @retval EFI_OUT_OF_RESOURCES   No enough memory available.
1491   @retval other                  Some error occurred when enumerating the host bridge.
1492 
1493 **/
1494 EFI_STATUS
PciHostBridgeEnumerator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)1495 PciHostBridgeEnumerator (
1496   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc
1497   )
1498 {
1499   EFI_HANDLE                        RootBridgeHandle;
1500   PCI_IO_DEVICE                     *RootBridgeDev;
1501   EFI_STATUS                        Status;
1502   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL   *PciRootBridgeIo;
1503   UINT16                            MinBus;
1504   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
1505   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
1506   UINT8                             StartBusNumber;
1507   LIST_ENTRY                        RootBridgeList;
1508   LIST_ENTRY                        *Link;
1509 
1510   if (FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1511     InitializeHotPlugSupport ();
1512   }
1513 
1514   InitializeListHead (&RootBridgeList);
1515 
1516   //
1517   // Notify the bus allocation phase is about to start
1518   //
1519   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1520 
1521   if (EFI_ERROR (Status)) {
1522     return Status;
1523   }
1524 
1525   DEBUG((EFI_D_INFO, "PCI Bus First Scanning\n"));
1526   RootBridgeHandle = NULL;
1527   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1528 
1529     //
1530     // if a root bridge instance is found, create root bridge device for it
1531     //
1532 
1533     RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1534 
1535     if (RootBridgeDev == NULL) {
1536       return EFI_OUT_OF_RESOURCES;
1537     }
1538 
1539     //
1540     // Enumerate all the buses under this root bridge
1541     //
1542     Status = PciRootBridgeEnumerator (
1543               PciResAlloc,
1544               RootBridgeDev
1545               );
1546 
1547     if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1548       InsertTailList (&RootBridgeList, &(RootBridgeDev->Link));
1549     } else {
1550       DestroyRootBridge (RootBridgeDev);
1551     }
1552     if (EFI_ERROR (Status)) {
1553       return Status;
1554     }
1555   }
1556 
1557   //
1558   // Notify the bus allocation phase is finished for the first time
1559   //
1560   NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1561 
1562   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
1563     //
1564     // Reset all assigned PCI bus number in all PPB
1565     //
1566     RootBridgeHandle = NULL;
1567     Link = GetFirstNode (&RootBridgeList);
1568     while ((PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) &&
1569       (!IsNull (&RootBridgeList, Link))) {
1570       RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (Link);
1571       //
1572       // Get the Bus information
1573       //
1574       Status = PciResAlloc->StartBusEnumeration (
1575                               PciResAlloc,
1576                               RootBridgeHandle,
1577                               (VOID **) &Configuration
1578                               );
1579       if (EFI_ERROR (Status)) {
1580         return Status;
1581       }
1582 
1583       //
1584       // Get the bus number to start with
1585       //
1586       StartBusNumber  = (UINT8) (Configuration->AddrRangeMin);
1587 
1588       ResetAllPpbBusNumber (
1589         RootBridgeDev,
1590         StartBusNumber
1591       );
1592 
1593       FreePool (Configuration);
1594       Link = RemoveEntryList (Link);
1595       DestroyRootBridge (RootBridgeDev);
1596     }
1597 
1598     //
1599     // Wait for all HPC initialized
1600     //
1601     Status = AllRootHPCInitialized (STALL_1_SECOND * 15);
1602 
1603     if (EFI_ERROR (Status)) {
1604       DEBUG ((EFI_D_ERROR, "Some root HPC failed to initialize\n"));
1605       return Status;
1606     }
1607 
1608     //
1609     // Notify the bus allocation phase is about to start for the 2nd time
1610     //
1611     Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation);
1612 
1613     if (EFI_ERROR (Status)) {
1614       return Status;
1615     }
1616 
1617     DEBUG((EFI_D_INFO, "PCI Bus Second Scanning\n"));
1618     RootBridgeHandle = NULL;
1619     while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1620 
1621       //
1622       // if a root bridge instance is found, create root bridge device for it
1623       //
1624       RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1625 
1626       if (RootBridgeDev == NULL) {
1627         return EFI_OUT_OF_RESOURCES;
1628       }
1629 
1630       //
1631       // Enumerate all the buses under this root bridge
1632       //
1633       Status = PciRootBridgeEnumerator (
1634                 PciResAlloc,
1635                 RootBridgeDev
1636                 );
1637 
1638       DestroyRootBridge (RootBridgeDev);
1639       if (EFI_ERROR (Status)) {
1640         return Status;
1641       }
1642     }
1643 
1644     //
1645     // Notify the bus allocation phase is to end for the 2nd time
1646     //
1647     NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation);
1648   }
1649 
1650   //
1651   // Notify the resource allocation phase is to start
1652   //
1653   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation);
1654 
1655   if (EFI_ERROR (Status)) {
1656     return Status;
1657   }
1658 
1659   RootBridgeHandle = NULL;
1660   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
1661 
1662     //
1663     // if a root bridge instance is found, create root bridge device for it
1664     //
1665     RootBridgeDev = CreateRootBridge (RootBridgeHandle);
1666 
1667     if (RootBridgeDev == NULL) {
1668       return EFI_OUT_OF_RESOURCES;
1669     }
1670 
1671     Status = StartManagingRootBridge (RootBridgeDev);
1672 
1673     if (EFI_ERROR (Status)) {
1674       return Status;
1675     }
1676 
1677     PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo;
1678     Status          = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors);
1679 
1680     if (EFI_ERROR (Status)) {
1681       return Status;
1682     }
1683 
1684     Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL);
1685 
1686     if (EFI_ERROR (Status)) {
1687       return Status;
1688     }
1689 
1690     //
1691     // Determine root bridge attribute by calling interface of Pcihostbridge
1692     // protocol
1693     //
1694     DetermineRootBridgeAttributes (
1695       PciResAlloc,
1696       RootBridgeDev
1697       );
1698 
1699     //
1700     // Collect all the resource information under this root bridge
1701     // A database that records all the information about pci device subject to this
1702     // root bridge will then be created
1703     //
1704     Status = PciPciDeviceInfoCollector (
1705               RootBridgeDev,
1706               (UINT8) MinBus
1707               );
1708 
1709     if (EFI_ERROR (Status)) {
1710       return Status;
1711     }
1712 
1713     InsertRootBridge (RootBridgeDev);
1714 
1715     //
1716     // Record the hostbridge handle
1717     //
1718     AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle);
1719   }
1720 
1721   return EFI_SUCCESS;
1722 }
1723 
1724 /**
1725   This function is used to program the Resizable BAR Register.
1726 
1727   @param PciIoDevice            A pointer to the PCI_IO_DEVICE.
1728   @param ResizableBarOp         PciResizableBarMax: Set BAR to max size
1729                                 PciResizableBarMin: set BAR to min size.
1730 
1731   @retval EFI_SUCCESS           Successfully enumerated the host bridge.
1732   @retval other                 Some error occurred when enumerating the host bridge.
1733 
1734 **/
1735 EFI_STATUS
PciProgramResizableBar(IN PCI_IO_DEVICE * PciIoDevice,IN PCI_RESIZABLE_BAR_OPERATION ResizableBarOp)1736 PciProgramResizableBar (
1737   IN PCI_IO_DEVICE                *PciIoDevice,
1738   IN PCI_RESIZABLE_BAR_OPERATION  ResizableBarOp
1739   )
1740 {
1741   EFI_PCI_IO_PROTOCOL  *PciIo;
1742   UINT64                Capabilities;
1743   UINT32                Index;
1744   UINT32                Offset;
1745   INTN                  Bit;
1746   UINTN                 ResizableBarNumber;
1747   EFI_STATUS            Status;
1748   PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY   Entries[PCI_MAX_BAR];
1749 
1750   ASSERT (PciIoDevice->ResizableBarOffset != 0);
1751 
1752   DEBUG ((DEBUG_INFO, "   Programs Resizable BAR register, offset: 0x%08x, number: %d\n",
1753         PciIoDevice->ResizableBarOffset, PciIoDevice->ResizableBarNumber));
1754 
1755   ResizableBarNumber = MIN (PciIoDevice->ResizableBarNumber, PCI_MAX_BAR);
1756   PciIo = &PciIoDevice->PciIo;
1757   Status = PciIo->Pci.Read (
1758           PciIo,
1759           EfiPciIoWidthUint8,
1760           PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER),
1761           sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY) * ResizableBarNumber,
1762           (VOID *)(&Entries)
1763           );
1764   ASSERT_EFI_ERROR (Status);
1765 
1766   for (Index = 0; Index < ResizableBarNumber; Index++) {
1767 
1768     //
1769     // When the bit of Capabilities Set, indicates that the Function supports
1770     // operating with the BAR sized to (2^Bit) MB.
1771     // Example:
1772     // Bit 0 is set: supports operating with the BAR sized to 1 MB
1773     // Bit 1 is set: supports operating with the BAR sized to 2 MB
1774     // Bit n is set: supports operating with the BAR sized to (2^n) MB
1775     //
1776     Capabilities = LShiftU64(Entries[Index].ResizableBarControl.Bits.BarSizeCapability, 28)
1777                   | Entries[Index].ResizableBarCapability.Bits.BarSizeCapability;
1778 
1779     if (ResizableBarOp == PciResizableBarMax) {
1780       Bit = HighBitSet64(Capabilities);
1781     } else if (ResizableBarOp == PciResizableBarMin) {
1782       Bit = LowBitSet64(Capabilities);
1783     } else {
1784       ASSERT ((ResizableBarOp == PciResizableBarMax) || (ResizableBarOp == PciResizableBarMin));
1785     }
1786 
1787     ASSERT (Bit >= 0);
1788 
1789     Offset = PciIoDevice->ResizableBarOffset + sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_HEADER)
1790             + Index * sizeof (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY)
1791             + OFFSET_OF (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY, ResizableBarControl);
1792 
1793     Entries[Index].ResizableBarControl.Bits.BarSize = (UINT32) Bit;
1794     DEBUG ((
1795       DEBUG_INFO,
1796       "   Resizable Bar: Offset = 0x%x, Bar Size Capability = 0x%016lx, New Bar Size = 0x%lx\n",
1797       OFFSET_OF (PCI_TYPE00, Device.Bar[Entries[Index].ResizableBarControl.Bits.BarIndex]),
1798       Capabilities, LShiftU64 (SIZE_1MB, Bit)
1799       ));
1800     PciIo->Pci.Write (
1801             PciIo,
1802             EfiPciIoWidthUint32,
1803             Offset,
1804             1,
1805             &Entries[Index].ResizableBarControl.Uint32
1806             );
1807   }
1808 
1809   return EFI_SUCCESS;
1810 }
1811