1 /** @file
2   PCI resources support functions implementation for PCI Bus module.
3 
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6 
7 **/
8 
9 #include "PciBus.h"
10 
11 //
12 // The default policy for the PCI bus driver is NOT to reserve I/O ranges for both ISA aliases and VGA aliases.
13 //
14 BOOLEAN mReserveIsaAliases = FALSE;
15 BOOLEAN mReserveVgaAliases = FALSE;
16 BOOLEAN mPolicyDetermined  = FALSE;
17 
18 /**
19   The function is used to skip VGA range.
20 
21   @param Start    Returned start address including VGA range.
22   @param Length   The length of VGA range.
23 
24 **/
25 VOID
SkipVGAAperture(OUT UINT64 * Start,IN UINT64 Length)26 SkipVGAAperture (
27   OUT UINT64   *Start,
28   IN  UINT64   Length
29   )
30 {
31   UINT64  Original;
32   UINT64  Mask;
33   UINT64  StartOffset;
34   UINT64  LimitOffset;
35 
36   ASSERT (Start != NULL);
37   //
38   // For legacy VGA, bit 10 to bit 15 is not decoded
39   //
40   Mask        = 0x3FF;
41 
42   Original    = *Start;
43   StartOffset = Original & Mask;
44   LimitOffset = ((*Start) + Length - 1) & Mask;
45   if (LimitOffset >= VGABASE1) {
46     *Start = *Start - StartOffset + VGALIMIT2 + 1;
47   }
48 }
49 
50 /**
51   This function is used to skip ISA aliasing aperture.
52 
53   @param Start    Returned start address including ISA aliasing aperture.
54   @param Length   The length of ISA aliasing aperture.
55 
56 **/
57 VOID
SkipIsaAliasAperture(OUT UINT64 * Start,IN UINT64 Length)58 SkipIsaAliasAperture (
59   OUT UINT64   *Start,
60   IN  UINT64   Length
61   )
62 {
63 
64   UINT64  Original;
65   UINT64  Mask;
66   UINT64  StartOffset;
67   UINT64  LimitOffset;
68 
69   ASSERT (Start != NULL);
70 
71   //
72   // For legacy ISA, bit 10 to bit 15 is not decoded
73   //
74   Mask        = 0x3FF;
75 
76   Original    = *Start;
77   StartOffset = Original & Mask;
78   LimitOffset = ((*Start) + Length - 1) & Mask;
79 
80   if (LimitOffset >= ISABASE) {
81     *Start = *Start - StartOffset + ISALIMIT + 1;
82   }
83 }
84 
85 /**
86   This function inserts a resource node into the resource list.
87   The resource list is sorted in descend order.
88 
89   @param Bridge  PCI resource node for bridge.
90   @param ResNode Resource node want to be inserted.
91 
92 **/
93 VOID
InsertResourceNode(IN OUT PCI_RESOURCE_NODE * Bridge,IN PCI_RESOURCE_NODE * ResNode)94 InsertResourceNode (
95   IN OUT PCI_RESOURCE_NODE   *Bridge,
96   IN     PCI_RESOURCE_NODE   *ResNode
97   )
98 {
99   LIST_ENTRY        *CurrentLink;
100   PCI_RESOURCE_NODE *Temp;
101   UINT64            ResNodeAlignRest;
102   UINT64            TempAlignRest;
103 
104   ASSERT (Bridge  != NULL);
105   ASSERT (ResNode != NULL);
106 
107   InsertHeadList (&Bridge->ChildList, &ResNode->Link);
108 
109   CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink;
110   while (CurrentLink != &Bridge->ChildList) {
111     Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
112 
113     if (ResNode->Alignment > Temp->Alignment) {
114       break;
115     } else if (ResNode->Alignment == Temp->Alignment) {
116       ResNodeAlignRest  = ResNode->Length & ResNode->Alignment;
117       TempAlignRest     = Temp->Length & Temp->Alignment;
118       if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) {
119         break;
120       }
121     }
122 
123     SwapListEntries (&ResNode->Link, CurrentLink);
124 
125     CurrentLink = ResNode->Link.ForwardLink;
126   }
127 }
128 
129 /**
130   This routine is used to merge two different resource trees in need of
131   resource degradation.
132 
133   For example, if an upstream PPB doesn't support,
134   prefetchable memory decoding, the PCI bus driver will choose to call this function
135   to merge prefetchable memory resource list into normal memory list.
136 
137   If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource
138   type.
139   If Dst is NULL or Res is NULL, ASSERT ().
140 
141   @param Dst        Point to destination resource tree.
142   @param Res        Point to source resource tree.
143   @param TypeMerge  If the TypeMerge is TRUE, Res resource type is changed to the type of
144                     destination resource type.
145 
146 **/
147 VOID
MergeResourceTree(IN PCI_RESOURCE_NODE * Dst,IN PCI_RESOURCE_NODE * Res,IN BOOLEAN TypeMerge)148 MergeResourceTree (
149   IN PCI_RESOURCE_NODE   *Dst,
150   IN PCI_RESOURCE_NODE   *Res,
151   IN BOOLEAN             TypeMerge
152   )
153 {
154 
155   LIST_ENTRY        *CurrentLink;
156   PCI_RESOURCE_NODE *Temp;
157 
158   ASSERT (Dst != NULL);
159   ASSERT (Res != NULL);
160 
161   while (!IsListEmpty (&Res->ChildList)) {
162     CurrentLink = Res->ChildList.ForwardLink;
163 
164     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
165 
166     if (TypeMerge) {
167       Temp->ResType = Dst->ResType;
168     }
169 
170     RemoveEntryList (CurrentLink);
171     InsertResourceNode (Dst, Temp);
172   }
173 }
174 
175 /**
176   This function is used to calculate the IO16 aperture
177   for a bridge.
178 
179   @param Bridge    PCI resource node for bridge.
180 
181 **/
182 VOID
CalculateApertureIo16(IN PCI_RESOURCE_NODE * Bridge)183 CalculateApertureIo16 (
184   IN PCI_RESOURCE_NODE    *Bridge
185   )
186 {
187   EFI_STATUS              Status;
188   UINT64                  Aperture;
189   LIST_ENTRY              *CurrentLink;
190   PCI_RESOURCE_NODE       *Node;
191   UINT64                  Offset;
192   EFI_PCI_PLATFORM_POLICY PciPolicy;
193   UINT64                  PaddingAperture;
194 
195   if (!mPolicyDetermined) {
196     //
197     // Check PciPlatform policy
198     //
199     Status = EFI_NOT_FOUND;
200     PciPolicy = 0;
201     if (gPciPlatformProtocol != NULL) {
202       Status = gPciPlatformProtocol->GetPlatformPolicy (
203                                        gPciPlatformProtocol,
204                                        &PciPolicy
205                                        );
206     }
207 
208     if (EFI_ERROR (Status) && gPciOverrideProtocol != NULL) {
209       Status = gPciOverrideProtocol->GetPlatformPolicy (
210                                        gPciOverrideProtocol,
211                                        &PciPolicy
212                                        );
213     }
214 
215     if (!EFI_ERROR (Status)) {
216       if ((PciPolicy & EFI_RESERVE_ISA_IO_ALIAS) != 0) {
217         mReserveIsaAliases = TRUE;
218       }
219       if ((PciPolicy & EFI_RESERVE_VGA_IO_ALIAS) != 0) {
220         mReserveVgaAliases = TRUE;
221       }
222     }
223     mPolicyDetermined = TRUE;
224   }
225 
226   Aperture        = 0;
227   PaddingAperture = 0;
228 
229   if (Bridge == NULL) {
230     return ;
231   }
232 
233   //
234   // Assume the bridge is aligned
235   //
236   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
237       ; !IsNull (&Bridge->ChildList, CurrentLink)
238       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
239       ) {
240 
241     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
242     if (Node->ResourceUsage == PciResUsagePadding) {
243       ASSERT (PaddingAperture == 0);
244       PaddingAperture = Node->Length;
245       continue;
246     }
247     //
248     // Consider the aperture alignment
249     //
250     Offset = Aperture & (Node->Alignment);
251 
252     if (Offset != 0) {
253 
254       Aperture = Aperture + (Node->Alignment + 1) - Offset;
255 
256     }
257 
258     //
259     // IsaEnable and VGAEnable can not be implemented now.
260     // If both of them are enabled, then the IO resource would
261     // become too limited to meet the requirement of most of devices.
262     //
263     if (mReserveIsaAliases || mReserveVgaAliases) {
264       if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci)) && !IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
265         //
266         // Check if there is need to support ISA/VGA decoding
267         // If so, we need to avoid isa/vga aliasing range
268         //
269         if (mReserveIsaAliases) {
270           SkipIsaAliasAperture (
271             &Aperture,
272             Node->Length
273             );
274           Offset = Aperture & (Node->Alignment);
275           if (Offset != 0) {
276             Aperture = Aperture + (Node->Alignment + 1) - Offset;
277           }
278         } else if (mReserveVgaAliases) {
279           SkipVGAAperture (
280             &Aperture,
281             Node->Length
282             );
283           Offset = Aperture & (Node->Alignment);
284           if (Offset != 0) {
285             Aperture = Aperture + (Node->Alignment + 1) - Offset;
286           }
287         }
288       }
289     }
290 
291     Node->Offset = Aperture;
292 
293     //
294     // Increment aperture by the length of node
295     //
296     Aperture += Node->Length;
297   }
298 
299   //
300   // Adjust the aperture with the bridge's alignment
301   //
302   Offset = Aperture & (Bridge->Alignment);
303 
304   if (Offset != 0) {
305     Aperture = Aperture + (Bridge->Alignment + 1) - Offset;
306   }
307 
308   Bridge->Length = Aperture;
309   //
310   // At last, adjust the bridge's alignment to the first child's alignment
311   // if the bridge has at least one child
312   //
313   CurrentLink = Bridge->ChildList.ForwardLink;
314   if (CurrentLink != &Bridge->ChildList) {
315     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
316     if (Node->Alignment > Bridge->Alignment) {
317       Bridge->Alignment = Node->Alignment;
318     }
319   }
320 
321   //
322   // Hotplug controller needs padding resources.
323   // Use the larger one between the padding resource and actual occupied resource.
324   //
325   Bridge->Length = MAX (Bridge->Length, PaddingAperture);
326 }
327 
328 /**
329   This function is used to calculate the resource aperture
330   for a given bridge device.
331 
332   @param Bridge      PCI resource node for given bridge device.
333 
334 **/
335 VOID
CalculateResourceAperture(IN PCI_RESOURCE_NODE * Bridge)336 CalculateResourceAperture (
337   IN PCI_RESOURCE_NODE    *Bridge
338   )
339 {
340   UINT64            Aperture[2];
341   LIST_ENTRY        *CurrentLink;
342   PCI_RESOURCE_NODE *Node;
343 
344   if (Bridge == NULL) {
345     return ;
346   }
347 
348   if (Bridge->ResType == PciBarTypeIo16) {
349 
350     CalculateApertureIo16 (Bridge);
351     return ;
352   }
353 
354   Aperture[PciResUsageTypical] = 0;
355   Aperture[PciResUsagePadding] = 0;
356   //
357   // Assume the bridge is aligned
358   //
359   for ( CurrentLink = GetFirstNode (&Bridge->ChildList)
360       ; !IsNull (&Bridge->ChildList, CurrentLink)
361       ; CurrentLink = GetNextNode (&Bridge->ChildList, CurrentLink)
362       ) {
363     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
364 
365     //
366     // It's possible for a bridge to contain multiple padding resource
367     // nodes due to DegradeResource().
368     //
369     ASSERT ((Node->ResourceUsage == PciResUsageTypical) ||
370             (Node->ResourceUsage == PciResUsagePadding));
371     ASSERT (Node->ResourceUsage < ARRAY_SIZE (Aperture));
372     //
373     // Recode current aperture as a offset
374     // Apply padding resource to meet alignment requirement
375     // Node offset will be used in future real allocation
376     //
377     Node->Offset = ALIGN_VALUE (Aperture[Node->ResourceUsage], Node->Alignment + 1);
378 
379     //
380     // Record the total aperture.
381     //
382     Aperture[Node->ResourceUsage] = Node->Offset + Node->Length;
383   }
384 
385   //
386   // Adjust the aperture with the bridge's alignment
387   //
388   Aperture[PciResUsageTypical] = ALIGN_VALUE (Aperture[PciResUsageTypical], Bridge->Alignment + 1);
389   Aperture[PciResUsagePadding] = ALIGN_VALUE (Aperture[PciResUsagePadding], Bridge->Alignment + 1);
390 
391   //
392   // Hotplug controller needs padding resources.
393   // Use the larger one between the padding resource and actual occupied resource.
394   //
395   Bridge->Length = MAX (Aperture[PciResUsageTypical], Aperture[PciResUsagePadding]);
396 
397   //
398   // Adjust the bridge's alignment to the MAX (first) alignment of all children.
399   //
400   CurrentLink = Bridge->ChildList.ForwardLink;
401   if (CurrentLink != &Bridge->ChildList) {
402     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
403     if (Node->Alignment > Bridge->Alignment) {
404       Bridge->Alignment = Node->Alignment;
405     }
406   }
407 }
408 
409 /**
410   Get IO/Memory resource info for given PCI device.
411 
412   @param PciDev     Pci device instance.
413   @param IoNode     Resource info node for IO .
414   @param Mem32Node  Resource info node for 32-bit memory.
415   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
416   @param Mem64Node  Resource info node for 64-bit memory.
417   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
418 
419 **/
420 VOID
GetResourceFromDevice(IN PCI_IO_DEVICE * PciDev,IN OUT PCI_RESOURCE_NODE * IoNode,IN OUT PCI_RESOURCE_NODE * Mem32Node,IN OUT PCI_RESOURCE_NODE * PMem32Node,IN OUT PCI_RESOURCE_NODE * Mem64Node,IN OUT PCI_RESOURCE_NODE * PMem64Node)421 GetResourceFromDevice (
422   IN     PCI_IO_DEVICE     *PciDev,
423   IN OUT PCI_RESOURCE_NODE *IoNode,
424   IN OUT PCI_RESOURCE_NODE *Mem32Node,
425   IN OUT PCI_RESOURCE_NODE *PMem32Node,
426   IN OUT PCI_RESOURCE_NODE *Mem64Node,
427   IN OUT PCI_RESOURCE_NODE *PMem64Node
428   )
429 {
430 
431   UINT8             Index;
432   PCI_RESOURCE_NODE *Node;
433   BOOLEAN           ResourceRequested;
434 
435   Node              = NULL;
436   ResourceRequested = FALSE;
437 
438   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
439 
440     switch ((PciDev->PciBar)[Index].BarType) {
441 
442     case PciBarTypeMem32:
443     case PciBarTypeOpRom:
444 
445       Node = CreateResourceNode (
446               PciDev,
447               (PciDev->PciBar)[Index].Length,
448               (PciDev->PciBar)[Index].Alignment,
449               Index,
450               (PciDev->PciBar)[Index].BarType,
451               PciResUsageTypical
452               );
453 
454       InsertResourceNode (
455         Mem32Node,
456         Node
457         );
458 
459       ResourceRequested = TRUE;
460       break;
461 
462     case PciBarTypeMem64:
463 
464       Node = CreateResourceNode (
465               PciDev,
466               (PciDev->PciBar)[Index].Length,
467               (PciDev->PciBar)[Index].Alignment,
468               Index,
469               PciBarTypeMem64,
470               PciResUsageTypical
471               );
472 
473       InsertResourceNode (
474         Mem64Node,
475         Node
476         );
477 
478       ResourceRequested = TRUE;
479       break;
480 
481     case PciBarTypePMem64:
482 
483       Node = CreateResourceNode (
484               PciDev,
485               (PciDev->PciBar)[Index].Length,
486               (PciDev->PciBar)[Index].Alignment,
487               Index,
488               PciBarTypePMem64,
489               PciResUsageTypical
490               );
491 
492       InsertResourceNode (
493         PMem64Node,
494         Node
495         );
496 
497       ResourceRequested = TRUE;
498       break;
499 
500     case PciBarTypePMem32:
501 
502       Node = CreateResourceNode (
503               PciDev,
504               (PciDev->PciBar)[Index].Length,
505               (PciDev->PciBar)[Index].Alignment,
506               Index,
507               PciBarTypePMem32,
508               PciResUsageTypical
509               );
510 
511       InsertResourceNode (
512         PMem32Node,
513         Node
514         );
515       ResourceRequested = TRUE;
516       break;
517 
518     case PciBarTypeIo16:
519     case PciBarTypeIo32:
520 
521       Node = CreateResourceNode (
522               PciDev,
523               (PciDev->PciBar)[Index].Length,
524               (PciDev->PciBar)[Index].Alignment,
525               Index,
526               PciBarTypeIo16,
527               PciResUsageTypical
528               );
529 
530       InsertResourceNode (
531         IoNode,
532         Node
533         );
534       ResourceRequested = TRUE;
535       break;
536 
537     case PciBarTypeUnknown:
538       break;
539 
540     default:
541       break;
542     }
543   }
544 
545   //
546   // Add VF resource
547   //
548   for (Index = 0; Index < PCI_MAX_BAR; Index++) {
549 
550     switch ((PciDev->VfPciBar)[Index].BarType) {
551 
552     case PciBarTypeMem32:
553 
554       Node = CreateVfResourceNode (
555               PciDev,
556               (PciDev->VfPciBar)[Index].Length,
557               (PciDev->VfPciBar)[Index].Alignment,
558               Index,
559               PciBarTypeMem32,
560               PciResUsageTypical
561               );
562 
563       InsertResourceNode (
564         Mem32Node,
565         Node
566         );
567 
568       break;
569 
570     case PciBarTypeMem64:
571 
572       Node = CreateVfResourceNode (
573               PciDev,
574               (PciDev->VfPciBar)[Index].Length,
575               (PciDev->VfPciBar)[Index].Alignment,
576               Index,
577               PciBarTypeMem64,
578               PciResUsageTypical
579               );
580 
581       InsertResourceNode (
582         Mem64Node,
583         Node
584         );
585 
586       break;
587 
588     case PciBarTypePMem64:
589 
590       Node = CreateVfResourceNode (
591               PciDev,
592               (PciDev->VfPciBar)[Index].Length,
593               (PciDev->VfPciBar)[Index].Alignment,
594               Index,
595               PciBarTypePMem64,
596               PciResUsageTypical
597               );
598 
599       InsertResourceNode (
600         PMem64Node,
601         Node
602         );
603 
604       break;
605 
606     case PciBarTypePMem32:
607 
608       Node = CreateVfResourceNode (
609               PciDev,
610               (PciDev->VfPciBar)[Index].Length,
611               (PciDev->VfPciBar)[Index].Alignment,
612               Index,
613               PciBarTypePMem32,
614               PciResUsageTypical
615               );
616 
617       InsertResourceNode (
618         PMem32Node,
619         Node
620         );
621       break;
622 
623     case PciBarTypeIo16:
624     case PciBarTypeIo32:
625       break;
626 
627     case PciBarTypeUnknown:
628       break;
629 
630     default:
631       break;
632     }
633   }
634   // If there is no resource requested from this device,
635   // then we indicate this device has been allocated naturally.
636   //
637   if (!ResourceRequested) {
638     PciDev->Allocated = TRUE;
639   }
640 }
641 
642 /**
643   This function is used to create a resource node.
644 
645   @param PciDev       Pci device instance.
646   @param Length       Length of Io/Memory resource.
647   @param Alignment    Alignment of resource.
648   @param Bar          Bar index.
649   @param ResType      Type of resource: IO/Memory.
650   @param ResUsage     Resource usage.
651 
652   @return PCI resource node created for given PCI device.
653           NULL means PCI resource node is not created.
654 
655 **/
656 PCI_RESOURCE_NODE *
CreateResourceNode(IN PCI_IO_DEVICE * PciDev,IN UINT64 Length,IN UINT64 Alignment,IN UINT8 Bar,IN PCI_BAR_TYPE ResType,IN PCI_RESOURCE_USAGE ResUsage)657 CreateResourceNode (
658   IN PCI_IO_DEVICE         *PciDev,
659   IN UINT64                Length,
660   IN UINT64                Alignment,
661   IN UINT8                 Bar,
662   IN PCI_BAR_TYPE          ResType,
663   IN PCI_RESOURCE_USAGE    ResUsage
664   )
665 {
666   PCI_RESOURCE_NODE *Node;
667 
668   Node    = NULL;
669 
670   Node    = AllocateZeroPool (sizeof (PCI_RESOURCE_NODE));
671   ASSERT (Node != NULL);
672   if (Node == NULL) {
673     return NULL;
674   }
675 
676   Node->Signature     = PCI_RESOURCE_SIGNATURE;
677   Node->PciDev        = PciDev;
678   Node->Length        = Length;
679   Node->Alignment     = Alignment;
680   Node->Bar           = Bar;
681   Node->ResType       = ResType;
682   Node->Reserved      = FALSE;
683   Node->ResourceUsage = ResUsage;
684   InitializeListHead (&Node->ChildList);
685 
686   return Node;
687 }
688 
689 /**
690   This function is used to create a IOV VF resource node.
691 
692   @param PciDev       Pci device instance.
693   @param Length       Length of Io/Memory resource.
694   @param Alignment    Alignment of resource.
695   @param Bar          Bar index.
696   @param ResType      Type of resource: IO/Memory.
697   @param ResUsage     Resource usage.
698 
699   @return PCI resource node created for given VF PCI device.
700           NULL means PCI resource node is not created.
701 
702 **/
703 PCI_RESOURCE_NODE *
CreateVfResourceNode(IN PCI_IO_DEVICE * PciDev,IN UINT64 Length,IN UINT64 Alignment,IN UINT8 Bar,IN PCI_BAR_TYPE ResType,IN PCI_RESOURCE_USAGE ResUsage)704 CreateVfResourceNode (
705   IN PCI_IO_DEVICE         *PciDev,
706   IN UINT64                Length,
707   IN UINT64                Alignment,
708   IN UINT8                 Bar,
709   IN PCI_BAR_TYPE          ResType,
710   IN PCI_RESOURCE_USAGE    ResUsage
711   )
712 {
713   PCI_RESOURCE_NODE *Node;
714 
715   Node = CreateResourceNode (PciDev, Length, Alignment, Bar, ResType, ResUsage);
716   if (Node == NULL) {
717     return Node;
718   }
719 
720   Node->Virtual = TRUE;
721 
722   return Node;
723 }
724 
725 /**
726   This function is used to extract resource request from
727   device node list.
728 
729   @param Bridge     Pci device instance.
730   @param IoNode     Resource info node for IO.
731   @param Mem32Node  Resource info node for 32-bit memory.
732   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
733   @param Mem64Node  Resource info node for 64-bit memory.
734   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
735 
736 **/
737 VOID
CreateResourceMap(IN PCI_IO_DEVICE * Bridge,IN OUT PCI_RESOURCE_NODE * IoNode,IN OUT PCI_RESOURCE_NODE * Mem32Node,IN OUT PCI_RESOURCE_NODE * PMem32Node,IN OUT PCI_RESOURCE_NODE * Mem64Node,IN OUT PCI_RESOURCE_NODE * PMem64Node)738 CreateResourceMap (
739   IN     PCI_IO_DEVICE     *Bridge,
740   IN OUT PCI_RESOURCE_NODE *IoNode,
741   IN OUT PCI_RESOURCE_NODE *Mem32Node,
742   IN OUT PCI_RESOURCE_NODE *PMem32Node,
743   IN OUT PCI_RESOURCE_NODE *Mem64Node,
744   IN OUT PCI_RESOURCE_NODE *PMem64Node
745   )
746 {
747   PCI_IO_DEVICE     *Temp;
748   PCI_RESOURCE_NODE *IoBridge;
749   PCI_RESOURCE_NODE *Mem32Bridge;
750   PCI_RESOURCE_NODE *PMem32Bridge;
751   PCI_RESOURCE_NODE *Mem64Bridge;
752   PCI_RESOURCE_NODE *PMem64Bridge;
753   LIST_ENTRY        *CurrentLink;
754 
755   CurrentLink = Bridge->ChildList.ForwardLink;
756 
757   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
758 
759     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
760 
761     //
762     // Create resource nodes for this device by scanning the
763     // Bar array in the device private data
764     // If the upstream bridge doesn't support this device,
765     // no any resource node will be created for this device
766     //
767     GetResourceFromDevice (
768       Temp,
769       IoNode,
770       Mem32Node,
771       PMem32Node,
772       Mem64Node,
773       PMem64Node
774       );
775 
776     if (IS_PCI_BRIDGE (&Temp->Pci)) {
777 
778       //
779       // If the device has children, create a bridge resource node for this PPB
780       // Note: For PPB, memory aperture is aligned with 1MB and IO aperture
781       // is aligned with 4KB (smaller alignments may be supported).
782       //
783       IoBridge = CreateResourceNode (
784                    Temp,
785                    0,
786                    Temp->BridgeIoAlignment,
787                    PPB_IO_RANGE,
788                    PciBarTypeIo16,
789                    PciResUsageTypical
790                    );
791 
792       Mem32Bridge = CreateResourceNode (
793                       Temp,
794                       0,
795                       0xFFFFF,
796                       PPB_MEM32_RANGE,
797                       PciBarTypeMem32,
798                       PciResUsageTypical
799                       );
800 
801       PMem32Bridge = CreateResourceNode (
802                        Temp,
803                        0,
804                        0xFFFFF,
805                        PPB_PMEM32_RANGE,
806                        PciBarTypePMem32,
807                        PciResUsageTypical
808                        );
809 
810       Mem64Bridge = CreateResourceNode (
811                       Temp,
812                       0,
813                       0xFFFFF,
814                       PPB_MEM64_RANGE,
815                       PciBarTypeMem64,
816                       PciResUsageTypical
817                       );
818 
819       PMem64Bridge = CreateResourceNode (
820                        Temp,
821                        0,
822                        0xFFFFF,
823                        PPB_PMEM64_RANGE,
824                        PciBarTypePMem64,
825                        PciResUsageTypical
826                        );
827 
828       //
829       // Recursively create resource map on this bridge
830       //
831       CreateResourceMap (
832         Temp,
833         IoBridge,
834         Mem32Bridge,
835         PMem32Bridge,
836         Mem64Bridge,
837         PMem64Bridge
838         );
839 
840       if (ResourceRequestExisted (IoBridge)) {
841         InsertResourceNode (
842           IoNode,
843           IoBridge
844           );
845       } else {
846         FreePool (IoBridge);
847         IoBridge = NULL;
848       }
849 
850       //
851       // If there is node under this resource bridge,
852       // then calculate bridge's aperture of this type
853       // and insert it into the respective resource tree.
854       // If no, delete this resource bridge
855       //
856       if (ResourceRequestExisted (Mem32Bridge)) {
857         InsertResourceNode (
858           Mem32Node,
859           Mem32Bridge
860           );
861       } else {
862         FreePool (Mem32Bridge);
863         Mem32Bridge = NULL;
864       }
865 
866       //
867       // If there is node under this resource bridge,
868       // then calculate bridge's aperture of this type
869       // and insert it into the respective resource tree.
870       // If no, delete this resource bridge
871       //
872       if (ResourceRequestExisted (PMem32Bridge)) {
873         InsertResourceNode (
874           PMem32Node,
875           PMem32Bridge
876           );
877       } else {
878         FreePool (PMem32Bridge);
879         PMem32Bridge = NULL;
880       }
881 
882       //
883       // If there is node under this resource bridge,
884       // then calculate bridge's aperture of this type
885       // and insert it into the respective resource tree.
886       // If no, delete this resource bridge
887       //
888       if (ResourceRequestExisted (Mem64Bridge)) {
889         InsertResourceNode (
890           Mem64Node,
891           Mem64Bridge
892           );
893       } else {
894         FreePool (Mem64Bridge);
895         Mem64Bridge = NULL;
896       }
897 
898       //
899       // If there is node under this resource bridge,
900       // then calculate bridge's aperture of this type
901       // and insert it into the respective resource tree.
902       // If no, delete this resource bridge
903       //
904       if (ResourceRequestExisted (PMem64Bridge)) {
905         InsertResourceNode (
906           PMem64Node,
907           PMem64Bridge
908           );
909       } else {
910         FreePool (PMem64Bridge);
911         PMem64Bridge = NULL;
912       }
913 
914     }
915 
916     //
917     // If it is P2C, apply hard coded resource padding
918     //
919     if (IS_CARDBUS_BRIDGE (&Temp->Pci)) {
920       ResourcePaddingForCardBusBridge (
921         Temp,
922         IoNode,
923         Mem32Node,
924         PMem32Node,
925         Mem64Node,
926         PMem64Node
927         );
928     }
929 
930     CurrentLink = CurrentLink->ForwardLink;
931   }
932 
933   //
934   // To do some platform specific resource padding ...
935   //
936   ResourcePaddingPolicy (
937     Bridge,
938     IoNode,
939     Mem32Node,
940     PMem32Node,
941     Mem64Node,
942     PMem64Node
943     );
944 
945   //
946   // Degrade resource if necessary
947   //
948   DegradeResource (
949     Bridge,
950     Mem32Node,
951     PMem32Node,
952     Mem64Node,
953     PMem64Node
954     );
955 
956   //
957   // Calculate resource aperture for this bridge device
958   //
959   CalculateResourceAperture (Mem32Node);
960   CalculateResourceAperture (PMem32Node);
961   CalculateResourceAperture (Mem64Node);
962   CalculateResourceAperture (PMem64Node);
963   CalculateResourceAperture (IoNode);
964 }
965 
966 /**
967   This function is used to do the resource padding for a specific platform.
968 
969   @param PciDev     Pci device instance.
970   @param IoNode     Resource info node for IO.
971   @param Mem32Node  Resource info node for 32-bit memory.
972   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
973   @param Mem64Node  Resource info node for 64-bit memory.
974   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
975 
976 **/
977 VOID
ResourcePaddingPolicy(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)978 ResourcePaddingPolicy (
979   IN PCI_IO_DEVICE     *PciDev,
980   IN PCI_RESOURCE_NODE *IoNode,
981   IN PCI_RESOURCE_NODE *Mem32Node,
982   IN PCI_RESOURCE_NODE *PMem32Node,
983   IN PCI_RESOURCE_NODE *Mem64Node,
984   IN PCI_RESOURCE_NODE *PMem64Node
985   )
986 {
987   //
988   // Create padding resource node
989   //
990   if (PciDev->ResourcePaddingDescriptors != NULL) {
991     ApplyResourcePadding (
992       PciDev,
993       IoNode,
994       Mem32Node,
995       PMem32Node,
996       Mem64Node,
997       PMem64Node
998       );
999   }
1000 }
1001 
1002 /**
1003   This function is used to degrade resource if the upstream bridge
1004   doesn't support certain resource. Degradation path is
1005   PMEM64 -> MEM64  -> MEM32
1006   PMEM64 -> PMEM32 -> MEM32
1007   IO32   -> IO16.
1008 
1009   @param Bridge     Pci device instance.
1010   @param Mem32Node  Resource info node for 32-bit memory.
1011   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1012   @param Mem64Node  Resource info node for 64-bit memory.
1013   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1014 
1015 **/
1016 VOID
DegradeResource(IN PCI_IO_DEVICE * Bridge,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)1017 DegradeResource (
1018   IN PCI_IO_DEVICE     *Bridge,
1019   IN PCI_RESOURCE_NODE *Mem32Node,
1020   IN PCI_RESOURCE_NODE *PMem32Node,
1021   IN PCI_RESOURCE_NODE *Mem64Node,
1022   IN PCI_RESOURCE_NODE *PMem64Node
1023   )
1024 {
1025   PCI_IO_DEVICE        *PciIoDevice;
1026   LIST_ENTRY           *ChildDeviceLink;
1027   LIST_ENTRY           *ChildNodeLink;
1028   LIST_ENTRY           *NextChildNodeLink;
1029   PCI_RESOURCE_NODE    *ResourceNode;
1030 
1031   if (FeaturePcdGet (PcdPciDegradeResourceForOptionRom)) {
1032     //
1033     // If any child device has both option ROM and 64-bit BAR, degrade its PMEM64/MEM64
1034     // requests in case that if a legacy option ROM image can not access 64-bit resources.
1035     //
1036     ChildDeviceLink = Bridge->ChildList.ForwardLink;
1037     while (ChildDeviceLink != NULL && ChildDeviceLink != &Bridge->ChildList) {
1038       PciIoDevice = PCI_IO_DEVICE_FROM_LINK (ChildDeviceLink);
1039       if (PciIoDevice->RomSize != 0) {
1040         if (!IsListEmpty (&Mem64Node->ChildList)) {
1041           ChildNodeLink = Mem64Node->ChildList.ForwardLink;
1042           while (ChildNodeLink != &Mem64Node->ChildList) {
1043             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1044             NextChildNodeLink = ChildNodeLink->ForwardLink;
1045 
1046             if ((ResourceNode->PciDev == PciIoDevice) &&
1047                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1048                 ) {
1049               RemoveEntryList (ChildNodeLink);
1050               InsertResourceNode (Mem32Node, ResourceNode);
1051             }
1052             ChildNodeLink = NextChildNodeLink;
1053           }
1054         }
1055 
1056         if (!IsListEmpty (&PMem64Node->ChildList)) {
1057           ChildNodeLink = PMem64Node->ChildList.ForwardLink;
1058           while (ChildNodeLink != &PMem64Node->ChildList) {
1059             ResourceNode = RESOURCE_NODE_FROM_LINK (ChildNodeLink);
1060             NextChildNodeLink = ChildNodeLink->ForwardLink;
1061 
1062             if ((ResourceNode->PciDev == PciIoDevice) &&
1063                 (ResourceNode->Virtual || !PciIoDevice->PciBar[ResourceNode->Bar].BarTypeFixed)
1064                 ) {
1065               RemoveEntryList (ChildNodeLink);
1066               InsertResourceNode (PMem32Node, ResourceNode);
1067             }
1068             ChildNodeLink = NextChildNodeLink;
1069           }
1070         }
1071 
1072       }
1073       ChildDeviceLink = ChildDeviceLink->ForwardLink;
1074     }
1075   }
1076 
1077   //
1078   // If firmware is in 32-bit mode,
1079   // then degrade PMEM64/MEM64 requests
1080   //
1081   if (sizeof (UINTN) <= 4) {
1082     MergeResourceTree (
1083       Mem32Node,
1084       Mem64Node,
1085       TRUE
1086       );
1087 
1088     MergeResourceTree (
1089       PMem32Node,
1090       PMem64Node,
1091       TRUE
1092       );
1093   } else {
1094     //
1095     // if the bridge does not support MEM64, degrade MEM64 to MEM32
1096     //
1097     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) {
1098         MergeResourceTree (
1099           Mem32Node,
1100           Mem64Node,
1101           TRUE
1102           );
1103     }
1104 
1105     //
1106     // if the bridge does not support PMEM64, degrade PMEM64 to PMEM32
1107     //
1108     if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) {
1109       MergeResourceTree (
1110         PMem32Node,
1111         PMem64Node,
1112         TRUE
1113         );
1114     }
1115 
1116     //
1117     // if both PMEM64 and PMEM32 requests from child devices, which can not be satisfied
1118     // by a P2P bridge simultaneously, keep PMEM64 and degrade PMEM32 to MEM32.
1119     //
1120     if (!IsListEmpty (&PMem64Node->ChildList) && Bridge->Parent != NULL) {
1121       MergeResourceTree (
1122         Mem32Node,
1123         PMem32Node,
1124         TRUE
1125         );
1126     }
1127   }
1128 
1129   //
1130   // If bridge doesn't support Pmem32
1131   // degrade it to mem32
1132   //
1133   if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) {
1134     MergeResourceTree (
1135       Mem32Node,
1136       PMem32Node,
1137       TRUE
1138       );
1139   }
1140 
1141   //
1142   // if root bridge supports combined Pmem Mem decoding
1143   // merge these two type of resource
1144   //
1145   if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) {
1146     MergeResourceTree (
1147       Mem32Node,
1148       PMem32Node,
1149       FALSE
1150       );
1151 
1152     //
1153     // No need to check if to degrade MEM64 after merge, because
1154     // if there are PMEM64 still here, 64-bit decode should be supported
1155     // by the root bride.
1156     //
1157     MergeResourceTree (
1158       Mem64Node,
1159       PMem64Node,
1160       FALSE
1161       );
1162   }
1163 }
1164 
1165 /**
1166   Test whether bridge device support decode resource.
1167 
1168   @param Bridge    Bridge device instance.
1169   @param Decode    Decode type according to resource type.
1170 
1171   @return TRUE     The bridge device support decode resource.
1172   @return FALSE    The bridge device don't support decode resource.
1173 
1174 **/
1175 BOOLEAN
BridgeSupportResourceDecode(IN PCI_IO_DEVICE * Bridge,IN UINT32 Decode)1176 BridgeSupportResourceDecode (
1177   IN PCI_IO_DEVICE *Bridge,
1178   IN UINT32        Decode
1179   )
1180 {
1181   if (((Bridge->Decodes) & Decode) != 0) {
1182     return TRUE;
1183   }
1184 
1185   return FALSE;
1186 }
1187 
1188 /**
1189   This function is used to program the resource allocated
1190   for each resource node under specified bridge.
1191 
1192   @param Base     Base address of resource to be programmed.
1193   @param Bridge   PCI resource node for the bridge device.
1194 
1195   @retval EFI_SUCCESS            Successfully to program all resources
1196                                  on given PCI bridge device.
1197   @retval EFI_OUT_OF_RESOURCES   Base is all one.
1198 
1199 **/
1200 EFI_STATUS
ProgramResource(IN UINT64 Base,IN PCI_RESOURCE_NODE * Bridge)1201 ProgramResource (
1202   IN UINT64            Base,
1203   IN PCI_RESOURCE_NODE *Bridge
1204   )
1205 {
1206   LIST_ENTRY        *CurrentLink;
1207   PCI_RESOURCE_NODE *Node;
1208   EFI_STATUS        Status;
1209 
1210   if (Base == gAllOne) {
1211     return EFI_OUT_OF_RESOURCES;
1212   }
1213 
1214   CurrentLink = Bridge->ChildList.ForwardLink;
1215 
1216   while (CurrentLink != &Bridge->ChildList) {
1217 
1218     Node = RESOURCE_NODE_FROM_LINK (CurrentLink);
1219 
1220     if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) {
1221 
1222       if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) {
1223         //
1224         // Program the PCI Card Bus device
1225         //
1226         ProgramP2C (Base, Node);
1227       } else {
1228         //
1229         // Program the PCI device BAR
1230         //
1231         ProgramBar (Base, Node);
1232       }
1233     } else {
1234       //
1235       // Program the PCI devices under this bridge
1236       //
1237       Status = ProgramResource (Base + Node->Offset, Node);
1238       if (EFI_ERROR (Status)) {
1239         return Status;
1240       }
1241 
1242       ProgramPpbApperture (Base, Node);
1243     }
1244 
1245     CurrentLink = CurrentLink->ForwardLink;
1246   }
1247 
1248   return EFI_SUCCESS;
1249 }
1250 
1251 /**
1252   Program Bar register for PCI device.
1253 
1254   @param Base  Base address for PCI device resource to be programmed.
1255   @param Node  Point to resource node structure.
1256 
1257 **/
1258 VOID
ProgramBar(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1259 ProgramBar (
1260   IN UINT64            Base,
1261   IN PCI_RESOURCE_NODE *Node
1262   )
1263 {
1264   EFI_PCI_IO_PROTOCOL *PciIo;
1265   UINT64              Address;
1266   UINT32              Address32;
1267 
1268   ASSERT (Node->Bar < PCI_MAX_BAR);
1269 
1270   //
1271   // Check VF BAR
1272   //
1273   if (Node->Virtual) {
1274     ProgramVfBar (Base, Node);
1275     return;
1276   }
1277 
1278   Address = 0;
1279   PciIo   = &(Node->PciDev->PciIo);
1280 
1281   Address = Base + Node->Offset;
1282 
1283   //
1284   // Indicate pci bus driver has allocated
1285   // resource for this device
1286   // It might be a temporary solution here since
1287   // pci device could have multiple bar
1288   //
1289   Node->PciDev->Allocated = TRUE;
1290 
1291   switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1292 
1293   case PciBarTypeIo16:
1294   case PciBarTypeIo32:
1295   case PciBarTypeMem32:
1296   case PciBarTypePMem32:
1297 
1298     PciIo->Pci.Write (
1299                  PciIo,
1300                  EfiPciIoWidthUint32,
1301                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1302                  1,
1303                  &Address
1304                  );
1305   //
1306   // Continue to the case PciBarTypeOpRom to set the BaseAddress.
1307   // PciBarTypeOpRom is a virtual BAR only in root bridge, to capture
1308   // the MEM32 resource requirement for Option ROM shadow.
1309   //
1310 
1311   case PciBarTypeOpRom:
1312     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1313 
1314     break;
1315 
1316   case PciBarTypeMem64:
1317   case PciBarTypePMem64:
1318 
1319     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1320 
1321     PciIo->Pci.Write (
1322                  PciIo,
1323                  EfiPciIoWidthUint32,
1324                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1325                  1,
1326                  &Address32
1327                  );
1328 
1329     Address32 = (UINT32) RShiftU64 (Address, 32);
1330 
1331     PciIo->Pci.Write (
1332                  PciIo,
1333                  EfiPciIoWidthUint32,
1334                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1335                  1,
1336                  &Address32
1337                  );
1338 
1339     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1340 
1341     break;
1342 
1343   default:
1344     break;
1345   }
1346 }
1347 
1348 /**
1349   Program IOV VF Bar register for PCI device.
1350 
1351   @param Base  Base address for PCI device resource to be programmed.
1352   @param Node  Point to resource node structure.
1353 
1354 **/
1355 EFI_STATUS
ProgramVfBar(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1356 ProgramVfBar (
1357   IN UINT64            Base,
1358   IN PCI_RESOURCE_NODE *Node
1359   )
1360 {
1361   EFI_PCI_IO_PROTOCOL *PciIo;
1362   UINT64              Address;
1363   UINT32              Address32;
1364 
1365   ASSERT (Node->Bar < PCI_MAX_BAR);
1366   ASSERT (Node->Virtual);
1367 
1368   Address = 0;
1369   PciIo   = &(Node->PciDev->PciIo);
1370 
1371   Address = Base + Node->Offset;
1372 
1373   //
1374   // Indicate pci bus driver has allocated
1375   // resource for this device
1376   // It might be a temporary solution here since
1377   // pci device could have multiple bar
1378   //
1379   Node->PciDev->Allocated = TRUE;
1380 
1381   switch ((Node->PciDev->VfPciBar[Node->Bar]).BarType) {
1382 
1383   case PciBarTypeMem32:
1384   case PciBarTypePMem32:
1385 
1386     PciIo->Pci.Write (
1387                 PciIo,
1388                 EfiPciIoWidthUint32,
1389                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1390                 1,
1391                 &Address
1392                 );
1393 
1394     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1395     break;
1396 
1397   case PciBarTypeMem64:
1398   case PciBarTypePMem64:
1399 
1400     Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1401 
1402     PciIo->Pci.Write (
1403                 PciIo,
1404                 EfiPciIoWidthUint32,
1405                 (Node->PciDev->VfPciBar[Node->Bar]).Offset,
1406                 1,
1407                 &Address32
1408                 );
1409 
1410     Address32 = (UINT32) RShiftU64 (Address, 32);
1411 
1412     PciIo->Pci.Write (
1413                 PciIo,
1414                 EfiPciIoWidthUint32,
1415                 ((Node->PciDev->VfPciBar[Node->Bar]).Offset + 4),
1416                 1,
1417                 &Address32
1418                 );
1419 
1420     Node->PciDev->VfPciBar[Node->Bar].BaseAddress = Address;
1421     break;
1422 
1423   case PciBarTypeIo16:
1424   case PciBarTypeIo32:
1425     break;
1426 
1427   default:
1428     break;
1429   }
1430 
1431   return EFI_SUCCESS;
1432 }
1433 
1434 /**
1435   Program PCI-PCI bridge aperture.
1436 
1437   @param Base  Base address for resource.
1438   @param Node  Point to resource node structure.
1439 
1440 **/
1441 VOID
ProgramPpbApperture(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1442 ProgramPpbApperture (
1443   IN UINT64            Base,
1444   IN PCI_RESOURCE_NODE *Node
1445   )
1446 {
1447   EFI_PCI_IO_PROTOCOL *PciIo;
1448   UINT64              Address;
1449   UINT32              Address32;
1450 
1451   Address = 0;
1452   //
1453   // If no device resource of this PPB, return anyway
1454   // Aperture is set default in the initialization code
1455   //
1456   if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) {
1457     //
1458     // For padding resource node, just ignore when programming
1459     //
1460     return ;
1461   }
1462 
1463   PciIo   = &(Node->PciDev->PciIo);
1464   Address = Base + Node->Offset;
1465 
1466   //
1467   // Indicate the PPB resource has been allocated
1468   //
1469   Node->PciDev->Allocated = TRUE;
1470 
1471   switch (Node->Bar) {
1472 
1473   case PPB_BAR_0:
1474   case PPB_BAR_1:
1475     switch ((Node->PciDev->PciBar[Node->Bar]).BarType) {
1476 
1477       case PciBarTypeIo16:
1478       case PciBarTypeIo32:
1479       case PciBarTypeMem32:
1480       case PciBarTypePMem32:
1481 
1482         PciIo->Pci.Write (
1483                  PciIo,
1484                  EfiPciIoWidthUint32,
1485                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1486                  1,
1487                  &Address
1488                  );
1489 
1490         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1491         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1492         break;
1493 
1494       case PciBarTypeMem64:
1495       case PciBarTypePMem64:
1496 
1497         Address32 = (UINT32) (Address & 0x00000000FFFFFFFF);
1498 
1499         PciIo->Pci.Write (
1500                  PciIo,
1501                  EfiPciIoWidthUint32,
1502                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1503                  1,
1504                  &Address32
1505                  );
1506 
1507         Address32 = (UINT32) RShiftU64 (Address, 32);
1508 
1509         PciIo->Pci.Write (
1510                  PciIo,
1511                  EfiPciIoWidthUint32,
1512                  (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4),
1513                  1,
1514                  &Address32
1515                  );
1516 
1517         Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1518         Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1519         break;
1520 
1521       default:
1522         break;
1523     }
1524     break;
1525 
1526   case PPB_IO_RANGE:
1527 
1528     Address32 = ((UINT32) (Address)) >> 8;
1529     PciIo->Pci.Write (
1530                  PciIo,
1531                  EfiPciIoWidthUint8,
1532                  0x1C,
1533                  1,
1534                  &Address32
1535                  );
1536 
1537     Address32 >>= 8;
1538     PciIo->Pci.Write (
1539                  PciIo,
1540                  EfiPciIoWidthUint16,
1541                  0x30,
1542                  1,
1543                  &Address32
1544                  );
1545 
1546     Address32 = (UINT32) (Address + Node->Length - 1);
1547     Address32 = ((UINT32) (Address32)) >> 8;
1548     PciIo->Pci.Write (
1549                  PciIo,
1550                  EfiPciIoWidthUint8,
1551                  0x1D,
1552                  1,
1553                  &Address32
1554                  );
1555 
1556     Address32 >>= 8;
1557     PciIo->Pci.Write (
1558                  PciIo,
1559                  EfiPciIoWidthUint16,
1560                  0x32,
1561                  1,
1562                  &Address32
1563                  );
1564 
1565     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1566     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1567     break;
1568 
1569   case PPB_MEM32_RANGE:
1570 
1571     Address32 = ((UINT32) (Address)) >> 16;
1572     PciIo->Pci.Write (
1573                  PciIo,
1574                  EfiPciIoWidthUint16,
1575                  0x20,
1576                  1,
1577                  &Address32
1578                  );
1579 
1580     Address32 = (UINT32) (Address + Node->Length - 1);
1581     Address32 = ((UINT32) (Address32)) >> 16;
1582     PciIo->Pci.Write (
1583                  PciIo,
1584                  EfiPciIoWidthUint16,
1585                  0x22,
1586                  1,
1587                  &Address32
1588                  );
1589 
1590     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1591     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1592     break;
1593 
1594   case PPB_PMEM32_RANGE:
1595   case PPB_PMEM64_RANGE:
1596 
1597     Address32 = ((UINT32) (Address)) >> 16;
1598     PciIo->Pci.Write (
1599                  PciIo,
1600                  EfiPciIoWidthUint16,
1601                  0x24,
1602                  1,
1603                  &Address32
1604                  );
1605 
1606     Address32 = (UINT32) (Address + Node->Length - 1);
1607     Address32 = ((UINT32) (Address32)) >> 16;
1608     PciIo->Pci.Write (
1609                  PciIo,
1610                  EfiPciIoWidthUint16,
1611                  0x26,
1612                  1,
1613                  &Address32
1614                  );
1615 
1616     Address32 = (UINT32) RShiftU64 (Address, 32);
1617     PciIo->Pci.Write (
1618                  PciIo,
1619                  EfiPciIoWidthUint32,
1620                  0x28,
1621                  1,
1622                  &Address32
1623                  );
1624 
1625     Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32);
1626     PciIo->Pci.Write (
1627                  PciIo,
1628                  EfiPciIoWidthUint32,
1629                  0x2C,
1630                  1,
1631                  &Address32
1632                  );
1633 
1634     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1635     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1636     break;
1637 
1638   default:
1639     break;
1640   }
1641 }
1642 
1643 /**
1644   Program parent bridge for Option Rom.
1645 
1646   @param PciDevice      Pci device instance.
1647   @param OptionRomBase  Base address for Option Rom.
1648   @param Enable         Enable or disable PCI memory.
1649 
1650 **/
1651 VOID
ProgramUpstreamBridgeForRom(IN PCI_IO_DEVICE * PciDevice,IN UINT32 OptionRomBase,IN BOOLEAN Enable)1652 ProgramUpstreamBridgeForRom (
1653   IN PCI_IO_DEVICE   *PciDevice,
1654   IN UINT32          OptionRomBase,
1655   IN BOOLEAN         Enable
1656   )
1657 {
1658   PCI_IO_DEVICE       *Parent;
1659   EFI_PCI_IO_PROTOCOL *PciIo;
1660   UINT16              Base;
1661   UINT16              Limit;
1662   //
1663   // For root bridge, just return.
1664   //
1665   Parent = PciDevice->Parent;
1666   while (Parent != NULL) {
1667     if (!IS_PCI_BRIDGE (&Parent->Pci)) {
1668       break;
1669     }
1670 
1671     PciIo = &Parent->PciIo;
1672 
1673     //
1674     // Program PPB to only open a single <= 16MB aperture
1675     //
1676     if (Enable) {
1677       //
1678       // Only cover MMIO for Option ROM.
1679       //
1680       Base  = (UINT16) (OptionRomBase >> 16);
1681       Limit = (UINT16) ((OptionRomBase + PciDevice->RomSize - 1) >> 16);
1682       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);
1683       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
1684 
1685       PCI_ENABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1686     } else {
1687       //
1688       // Cover 32bit MMIO for devices below the bridge.
1689       //
1690       if (Parent->PciBar[PPB_MEM32_RANGE].Length == 0) {
1691         //
1692         // When devices under the bridge contains Option ROM and doesn't require 32bit MMIO.
1693         //
1694         Base  = (UINT16) gAllOne;
1695         Limit = (UINT16) gAllZero;
1696       } else {
1697         Base  = (UINT16) ((UINT32) Parent->PciBar[PPB_MEM32_RANGE].BaseAddress >> 16);
1698         Limit = (UINT16) ((UINT32) (Parent->PciBar[PPB_MEM32_RANGE].BaseAddress
1699                                     + Parent->PciBar[PPB_MEM32_RANGE].Length - 1) >> 16);
1700       }
1701       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryBase),  1, &Base);
1702       PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, OFFSET_OF (PCI_TYPE01, Bridge.MemoryLimit), 1, &Limit);
1703 
1704       PCI_DISABLE_COMMAND_REGISTER (Parent, EFI_PCI_COMMAND_MEMORY_SPACE);
1705     }
1706 
1707     Parent = Parent->Parent;
1708   }
1709 }
1710 
1711 /**
1712   Test whether resource exists for a bridge.
1713 
1714   @param Bridge  Point to resource node for a bridge.
1715 
1716   @retval TRUE   There is resource on the given bridge.
1717   @retval FALSE  There isn't resource on the given bridge.
1718 
1719 **/
1720 BOOLEAN
ResourceRequestExisted(IN PCI_RESOURCE_NODE * Bridge)1721 ResourceRequestExisted (
1722   IN PCI_RESOURCE_NODE    *Bridge
1723   )
1724 {
1725   if (Bridge != NULL) {
1726     if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) {
1727       return TRUE;
1728     }
1729   }
1730 
1731   return FALSE;
1732 }
1733 
1734 /**
1735   Initialize resource pool structure.
1736 
1737   @param ResourcePool Point to resource pool structure. This pool
1738                       is reset to all zero when returned.
1739   @param ResourceType Type of resource.
1740 
1741 **/
1742 VOID
InitializeResourcePool(IN OUT PCI_RESOURCE_NODE * ResourcePool,IN PCI_BAR_TYPE ResourceType)1743 InitializeResourcePool (
1744   IN OUT PCI_RESOURCE_NODE   *ResourcePool,
1745   IN     PCI_BAR_TYPE        ResourceType
1746   )
1747 {
1748   ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE));
1749   ResourcePool->ResType   = ResourceType;
1750   ResourcePool->Signature = PCI_RESOURCE_SIGNATURE;
1751   InitializeListHead (&ResourcePool->ChildList);
1752 }
1753 
1754 /**
1755   Destroy given resource tree.
1756 
1757   @param Bridge  PCI resource root node of resource tree.
1758 
1759 **/
1760 VOID
DestroyResourceTree(IN PCI_RESOURCE_NODE * Bridge)1761 DestroyResourceTree (
1762   IN PCI_RESOURCE_NODE *Bridge
1763   )
1764 {
1765   PCI_RESOURCE_NODE *Temp;
1766   LIST_ENTRY        *CurrentLink;
1767 
1768   while (!IsListEmpty (&Bridge->ChildList)) {
1769 
1770     CurrentLink = Bridge->ChildList.ForwardLink;
1771 
1772     Temp        = RESOURCE_NODE_FROM_LINK (CurrentLink);
1773     ASSERT (Temp);
1774 
1775     RemoveEntryList (CurrentLink);
1776 
1777     if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) {
1778       DestroyResourceTree (Temp);
1779     }
1780 
1781     FreePool (Temp);
1782   }
1783 }
1784 
1785 /**
1786   Insert resource padding for P2C.
1787 
1788   @param PciDev     Pci device instance.
1789   @param IoNode     Resource info node for IO.
1790   @param Mem32Node  Resource info node for 32-bit memory.
1791   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
1792   @param Mem64Node  Resource info node for 64-bit memory.
1793   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
1794 
1795 **/
1796 VOID
ResourcePaddingForCardBusBridge(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)1797 ResourcePaddingForCardBusBridge (
1798   IN PCI_IO_DEVICE        *PciDev,
1799   IN PCI_RESOURCE_NODE    *IoNode,
1800   IN PCI_RESOURCE_NODE    *Mem32Node,
1801   IN PCI_RESOURCE_NODE    *PMem32Node,
1802   IN PCI_RESOURCE_NODE    *Mem64Node,
1803   IN PCI_RESOURCE_NODE    *PMem64Node
1804   )
1805 {
1806   PCI_RESOURCE_NODE *Node;
1807 
1808   Node = NULL;
1809 
1810   //
1811   // Memory Base/Limit Register 0
1812   // Bar 1 decodes memory range 0
1813   //
1814   Node = CreateResourceNode (
1815            PciDev,
1816            0x2000000,
1817            0x1ffffff,
1818            1,
1819            PciBarTypeMem32,
1820            PciResUsagePadding
1821            );
1822 
1823   InsertResourceNode (
1824     Mem32Node,
1825     Node
1826     );
1827 
1828   //
1829   // Memory Base/Limit Register 1
1830   // Bar 2 decodes memory range1
1831   //
1832   Node = CreateResourceNode (
1833            PciDev,
1834            0x2000000,
1835            0x1ffffff,
1836            2,
1837            PciBarTypePMem32,
1838            PciResUsagePadding
1839            );
1840 
1841   InsertResourceNode (
1842     PMem32Node,
1843     Node
1844     );
1845 
1846   //
1847   // Io Base/Limit
1848   // Bar 3 decodes io range 0
1849   //
1850   Node = CreateResourceNode (
1851            PciDev,
1852            0x100,
1853            0xff,
1854            3,
1855            PciBarTypeIo16,
1856            PciResUsagePadding
1857            );
1858 
1859   InsertResourceNode (
1860     IoNode,
1861     Node
1862     );
1863 
1864   //
1865   // Io Base/Limit
1866   // Bar 4 decodes io range 0
1867   //
1868   Node = CreateResourceNode (
1869            PciDev,
1870            0x100,
1871            0xff,
1872            4,
1873            PciBarTypeIo16,
1874            PciResUsagePadding
1875            );
1876 
1877   InsertResourceNode (
1878     IoNode,
1879     Node
1880     );
1881 }
1882 
1883 /**
1884   Program PCI Card device register for given resource node.
1885 
1886   @param Base    Base address of PCI Card device to be programmed.
1887   @param Node    Given resource node.
1888 
1889 **/
1890 VOID
ProgramP2C(IN UINT64 Base,IN PCI_RESOURCE_NODE * Node)1891 ProgramP2C (
1892   IN UINT64            Base,
1893   IN PCI_RESOURCE_NODE *Node
1894   )
1895 {
1896   EFI_PCI_IO_PROTOCOL *PciIo;
1897   UINT64              Address;
1898   UINT64              TempAddress;
1899   UINT16              BridgeControl;
1900 
1901   Address = 0;
1902   PciIo   = &(Node->PciDev->PciIo);
1903 
1904   Address = Base + Node->Offset;
1905 
1906   //
1907   // Indicate pci bus driver has allocated
1908   // resource for this device
1909   // It might be a temporary solution here since
1910   // pci device could have multiple bar
1911   //
1912   Node->PciDev->Allocated = TRUE;
1913 
1914   switch (Node->Bar) {
1915 
1916   case P2C_BAR_0:
1917     PciIo->Pci.Write (
1918                  PciIo,
1919                  EfiPciIoWidthUint32,
1920                  (Node->PciDev->PciBar[Node->Bar]).Offset,
1921                  1,
1922                  &Address
1923                  );
1924 
1925     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1926     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1927     break;
1928 
1929   case P2C_MEM_1:
1930     PciIo->Pci.Write (
1931                  PciIo,
1932                  EfiPciIoWidthUint32,
1933                  PCI_CARD_MEMORY_BASE_0,
1934                  1,
1935                  &Address
1936                  );
1937 
1938     TempAddress = Address + Node->Length - 1;
1939     PciIo->Pci.Write (
1940                  PciIo,
1941                  EfiPciIoWidthUint32,
1942                  PCI_CARD_MEMORY_LIMIT_0,
1943                  1,
1944                  &TempAddress
1945                  );
1946 
1947     if (Node->ResType == PciBarTypeMem32) {
1948       //
1949       // Set non-prefetchable bit
1950       //
1951       PciIo->Pci.Read (
1952                    PciIo,
1953                    EfiPciIoWidthUint16,
1954                    PCI_CARD_BRIDGE_CONTROL,
1955                    1,
1956                    &BridgeControl
1957                    );
1958 
1959       BridgeControl &= (UINT16) ~PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1960       PciIo->Pci.Write (
1961                    PciIo,
1962                    EfiPciIoWidthUint16,
1963                    PCI_CARD_BRIDGE_CONTROL,
1964                    1,
1965                    &BridgeControl
1966                    );
1967 
1968     } else {
1969       //
1970       // Set prefetchable bit
1971       //
1972       PciIo->Pci.Read (
1973                    PciIo,
1974                    EfiPciIoWidthUint16,
1975                    PCI_CARD_BRIDGE_CONTROL,
1976                    1,
1977                    &BridgeControl
1978                    );
1979 
1980       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_0_ENABLE;
1981       PciIo->Pci.Write (
1982                    PciIo,
1983                    EfiPciIoWidthUint16,
1984                    PCI_CARD_BRIDGE_CONTROL,
1985                    1,
1986                    &BridgeControl
1987                    );
1988     }
1989 
1990     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
1991     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
1992     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
1993 
1994     break;
1995 
1996   case P2C_MEM_2:
1997     PciIo->Pci.Write (
1998                  PciIo,
1999                  EfiPciIoWidthUint32,
2000                  PCI_CARD_MEMORY_BASE_1,
2001                  1,
2002                  &Address
2003                  );
2004 
2005     TempAddress = Address + Node->Length - 1;
2006 
2007     PciIo->Pci.Write (
2008                  PciIo,
2009                  EfiPciIoWidthUint32,
2010                  PCI_CARD_MEMORY_LIMIT_1,
2011                  1,
2012                  &TempAddress
2013                  );
2014 
2015     if (Node->ResType == PciBarTypeMem32) {
2016 
2017       //
2018       // Set non-prefetchable bit
2019       //
2020       PciIo->Pci.Read (
2021                    PciIo,
2022                    EfiPciIoWidthUint16,
2023                    PCI_CARD_BRIDGE_CONTROL,
2024                    1,
2025                    &BridgeControl
2026                    );
2027 
2028       BridgeControl &= (UINT16) ~(PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE);
2029       PciIo->Pci.Write (
2030                    PciIo,
2031                    EfiPciIoWidthUint16,
2032                    PCI_CARD_BRIDGE_CONTROL,
2033                    1,
2034                    &BridgeControl
2035                    );
2036 
2037     } else {
2038 
2039       //
2040       // Set prefetchable bit
2041       //
2042       PciIo->Pci.Read (
2043                    PciIo,
2044                    EfiPciIoWidthUint16,
2045                    PCI_CARD_BRIDGE_CONTROL,
2046                    1,
2047                    &BridgeControl
2048                    );
2049 
2050       BridgeControl |= PCI_CARD_PREFETCHABLE_MEMORY_1_ENABLE;
2051       PciIo->Pci.Write (
2052                    PciIo,
2053                    EfiPciIoWidthUint16,
2054                    PCI_CARD_BRIDGE_CONTROL,
2055                    1,
2056                    &BridgeControl
2057                    );
2058     }
2059 
2060     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2061     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2062     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2063     break;
2064 
2065   case P2C_IO_1:
2066     PciIo->Pci.Write (
2067                  PciIo,
2068                  EfiPciIoWidthUint32,
2069                  PCI_CARD_IO_BASE_0_LOWER,
2070                  1,
2071                  &Address
2072                  );
2073 
2074     TempAddress = Address + Node->Length - 1;
2075     PciIo->Pci.Write (
2076                  PciIo,
2077                  EfiPciIoWidthUint32,
2078                  PCI_CARD_IO_LIMIT_0_LOWER,
2079                  1,
2080                  &TempAddress
2081                  );
2082 
2083     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2084     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2085     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2086 
2087     break;
2088 
2089   case P2C_IO_2:
2090     PciIo->Pci.Write (
2091                  PciIo,
2092                  EfiPciIoWidthUint32,
2093                  PCI_CARD_IO_BASE_1_LOWER,
2094                  1,
2095                  &Address
2096                  );
2097 
2098     TempAddress = Address + Node->Length - 1;
2099     PciIo->Pci.Write (
2100                  PciIo,
2101                  EfiPciIoWidthUint32,
2102                  PCI_CARD_IO_LIMIT_1_LOWER,
2103                  1,
2104                  &TempAddress
2105                  );
2106 
2107     Node->PciDev->PciBar[Node->Bar].BaseAddress = Address;
2108     Node->PciDev->PciBar[Node->Bar].Length      = Node->Length;
2109     Node->PciDev->PciBar[Node->Bar].BarType     = Node->ResType;
2110     break;
2111 
2112   default:
2113     break;
2114   }
2115 }
2116 
2117 /**
2118   Create padding resource node.
2119 
2120   @param PciDev     Pci device instance.
2121   @param IoNode     Resource info node for IO.
2122   @param Mem32Node  Resource info node for 32-bit memory.
2123   @param PMem32Node Resource info node for 32-bit Prefetchable Memory.
2124   @param Mem64Node  Resource info node for 64-bit memory.
2125   @param PMem64Node Resource info node for 64-bit Prefetchable Memory.
2126 
2127 **/
2128 VOID
ApplyResourcePadding(IN PCI_IO_DEVICE * PciDev,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node)2129 ApplyResourcePadding (
2130   IN PCI_IO_DEVICE         *PciDev,
2131   IN PCI_RESOURCE_NODE     *IoNode,
2132   IN PCI_RESOURCE_NODE     *Mem32Node,
2133   IN PCI_RESOURCE_NODE     *PMem32Node,
2134   IN PCI_RESOURCE_NODE     *Mem64Node,
2135   IN PCI_RESOURCE_NODE     *PMem64Node
2136   )
2137 {
2138   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
2139   PCI_RESOURCE_NODE                 *Node;
2140   UINT8                             DummyBarIndex;
2141 
2142   DummyBarIndex = 0;
2143   Ptr           = PciDev->ResourcePaddingDescriptors;
2144 
2145   while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) {
2146 
2147     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) {
2148       if (Ptr->AddrLen != 0) {
2149 
2150         Node = CreateResourceNode (
2151                 PciDev,
2152                 Ptr->AddrLen,
2153                 Ptr->AddrRangeMax,
2154                 DummyBarIndex,
2155                 PciBarTypeIo16,
2156                 PciResUsagePadding
2157                 );
2158         InsertResourceNode (
2159           IoNode,
2160           Node
2161           );
2162       }
2163 
2164       Ptr++;
2165       continue;
2166     }
2167 
2168     if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
2169 
2170       if (Ptr->AddrSpaceGranularity == 32) {
2171 
2172         //
2173         // prefetchable
2174         //
2175         if (Ptr->SpecificFlag == 0x6) {
2176           if (Ptr->AddrLen != 0) {
2177             Node = CreateResourceNode (
2178                     PciDev,
2179                     Ptr->AddrLen,
2180                     Ptr->AddrRangeMax,
2181                     DummyBarIndex,
2182                     PciBarTypePMem32,
2183                     PciResUsagePadding
2184                     );
2185             InsertResourceNode (
2186               PMem32Node,
2187               Node
2188               );
2189           }
2190 
2191           Ptr++;
2192           continue;
2193         }
2194 
2195         //
2196         // Non-prefetchable
2197         //
2198         if (Ptr->SpecificFlag == 0) {
2199           if (Ptr->AddrLen != 0) {
2200             Node = CreateResourceNode (
2201                     PciDev,
2202                     Ptr->AddrLen,
2203                     Ptr->AddrRangeMax,
2204                     DummyBarIndex,
2205                     PciBarTypeMem32,
2206                     PciResUsagePadding
2207                     );
2208             InsertResourceNode (
2209               Mem32Node,
2210               Node
2211               );
2212           }
2213 
2214           Ptr++;
2215           continue;
2216         }
2217       }
2218 
2219       if (Ptr->AddrSpaceGranularity == 64) {
2220 
2221         //
2222         // prefetchable
2223         //
2224         if (Ptr->SpecificFlag == 0x6) {
2225           if (Ptr->AddrLen != 0) {
2226             Node = CreateResourceNode (
2227                     PciDev,
2228                     Ptr->AddrLen,
2229                     Ptr->AddrRangeMax,
2230                     DummyBarIndex,
2231                     PciBarTypePMem64,
2232                     PciResUsagePadding
2233                     );
2234             InsertResourceNode (
2235               PMem64Node,
2236               Node
2237               );
2238           }
2239 
2240           Ptr++;
2241           continue;
2242         }
2243 
2244         //
2245         // Non-prefetchable
2246         //
2247         if (Ptr->SpecificFlag == 0) {
2248           if (Ptr->AddrLen != 0) {
2249             Node = CreateResourceNode (
2250                     PciDev,
2251                     Ptr->AddrLen,
2252                     Ptr->AddrRangeMax,
2253                     DummyBarIndex,
2254                     PciBarTypeMem64,
2255                     PciResUsagePadding
2256                     );
2257             InsertResourceNode (
2258               Mem64Node,
2259               Node
2260               );
2261           }
2262 
2263           Ptr++;
2264           continue;
2265         }
2266       }
2267     }
2268 
2269     Ptr++;
2270   }
2271 }
2272 
2273 /**
2274   Get padding resource for PCI-PCI bridge.
2275 
2276   @param  PciIoDevice     PCI-PCI bridge device instance.
2277 
2278   @note   Feature flag PcdPciBusHotplugDeviceSupport determines
2279           whether need to pad resource for them.
2280 **/
2281 VOID
GetResourcePaddingPpb(IN PCI_IO_DEVICE * PciIoDevice)2282 GetResourcePaddingPpb (
2283   IN  PCI_IO_DEVICE                  *PciIoDevice
2284   )
2285 {
2286   if (gPciHotPlugInit != NULL && FeaturePcdGet (PcdPciBusHotplugDeviceSupport)) {
2287     if (PciIoDevice->ResourcePaddingDescriptors == NULL) {
2288       GetResourcePaddingForHpb (PciIoDevice);
2289     }
2290   }
2291 }
2292 
2293