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