1 /** @file
2   PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
3 
4 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution.  The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10 
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #include "PciBus.h"
17 
18 /**
19   This routine is used to enumerate entire pci bus system
20   in a given platform.
21 
22   @param Controller  Parent controller handle.
23 
24   @retval EFI_SUCCESS    PCI enumeration finished successfully.
25   @retval other          Some error occurred when enumerating the pci bus system.
26 
27 **/
28 EFI_STATUS
PciEnumerator(IN EFI_HANDLE Controller)29 PciEnumerator (
30   IN EFI_HANDLE                    Controller
31   )
32 {
33   EFI_HANDLE                                        HostBridgeHandle;
34   EFI_STATUS                                        Status;
35   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
36   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL                   *PciRootBridgeIo;
37 
38   //
39   // If PCI bus has already done the full enumeration, never do it again
40   //
41   if (!gFullEnumeration) {
42     return PciEnumeratorLight (Controller);
43   }
44 
45   //
46   // Get the rootbridge Io protocol to find the host bridge handle
47   //
48   Status = gBS->OpenProtocol (
49                   Controller,
50                   &gEfiPciRootBridgeIoProtocolGuid,
51                   (VOID **) &PciRootBridgeIo,
52                   gPciBusDriverBinding.DriverBindingHandle,
53                   Controller,
54                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
55                   );
56 
57   if (EFI_ERROR (Status)) {
58     return Status;
59   }
60 
61   //
62   // Get the host bridge handle
63   //
64   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
65 
66   //
67   // Get the pci host bridge resource allocation protocol
68   //
69   Status = gBS->OpenProtocol (
70                   HostBridgeHandle,
71                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
72                   (VOID **) &PciResAlloc,
73                   gPciBusDriverBinding.DriverBindingHandle,
74                   Controller,
75                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
76                   );
77 
78   if (EFI_ERROR (Status)) {
79     return Status;
80   }
81 
82   //
83   // Notify the pci bus enumeration is about to begin
84   //
85   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
86 
87   if (EFI_ERROR (Status)) {
88     return Status;
89   }
90 
91   //
92   // Start the bus allocation phase
93   //
94   Status = PciHostBridgeEnumerator (PciResAlloc);
95 
96   if (EFI_ERROR (Status)) {
97     return Status;
98   }
99 
100   //
101   // Submit the resource request
102   //
103   Status = PciHostBridgeResourceAllocator (PciResAlloc);
104 
105   if (EFI_ERROR (Status)) {
106     return Status;
107   }
108 
109   //
110   // Notify the pci bus enumeration is about to complete
111   //
112   Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
113 
114   if (EFI_ERROR (Status)) {
115     return Status;
116   }
117 
118   //
119   // Process P2C
120   //
121   Status = PciHostBridgeP2CProcess (PciResAlloc);
122 
123   if (EFI_ERROR (Status)) {
124     return Status;
125   }
126 
127   //
128   // Process attributes for devices on this host bridge
129   //
130   Status = PciHostBridgeDeviceAttribute (PciResAlloc);
131   if (EFI_ERROR (Status)) {
132     return Status;
133   }
134 
135   gFullEnumeration = FALSE;
136 
137   Status = gBS->InstallProtocolInterface (
138                   &HostBridgeHandle,
139                   &gEfiPciEnumerationCompleteProtocolGuid,
140                   EFI_NATIVE_INTERFACE,
141                   NULL
142                   );
143   if (EFI_ERROR (Status)) {
144     return Status;
145   }
146 
147   return EFI_SUCCESS;
148 }
149 
150 /**
151   Enumerate PCI root bridge.
152 
153   @param PciResAlloc   Pointer to protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
154   @param RootBridgeDev Instance of root bridge device.
155 
156   @retval EFI_SUCCESS  Successfully enumerated root bridge.
157   @retval other        Failed to enumerate root bridge.
158 
159 **/
160 EFI_STATUS
PciRootBridgeEnumerator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc,IN PCI_IO_DEVICE * RootBridgeDev)161 PciRootBridgeEnumerator (
162   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc,
163   IN PCI_IO_DEVICE                                     *RootBridgeDev
164   )
165 {
166   EFI_STATUS                        Status;
167   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
168   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;
169   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;
170   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;
171   UINT8                             SubBusNumber;
172   UINT8                             StartBusNumber;
173   UINT8                             PaddedBusRange;
174   EFI_HANDLE                        RootBridgeHandle;
175   UINT8                             Desc;
176   UINT64                            AddrLen;
177   UINT64                            AddrRangeMin;
178 
179   SubBusNumber    = 0;
180   StartBusNumber  = 0;
181   PaddedBusRange  = 0;
182 
183   //
184   // Get the root bridge handle
185   //
186   RootBridgeHandle = RootBridgeDev->Handle;
187 
188   REPORT_STATUS_CODE_WITH_DEVICE_PATH (
189     EFI_PROGRESS_CODE,
190     EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,
191     RootBridgeDev->DevicePath
192     );
193 
194   //
195   // Get the Bus information
196   //
197   Status = PciResAlloc->StartBusEnumeration (
198                           PciResAlloc,
199                           RootBridgeHandle,
200                           (VOID **) &Configuration
201                           );
202 
203   if (EFI_ERROR (Status)) {
204     return Status;
205   }
206 
207   if (Configuration == NULL || Configuration->Desc == ACPI_END_TAG_DESCRIPTOR) {
208     return EFI_INVALID_PARAMETER;
209   }
210   RootBridgeDev->BusNumberRanges = Configuration;
211 
212   //
213   // Sort the descriptors in ascending order
214   //
215   for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {
216     Configuration2 = Configuration1;
217     for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {
218       if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {
219         Configuration2 = Configuration3;
220       }
221     }
222     //
223     // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
224     // so only need to swap these two fields.
225     //
226     if (Configuration2 != Configuration1) {
227       AddrRangeMin = Configuration1->AddrRangeMin;
228       Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;
229       Configuration2->AddrRangeMin = AddrRangeMin;
230 
231       AddrLen = Configuration1->AddrLen;
232       Configuration1->AddrLen = Configuration2->AddrLen;
233       Configuration2->AddrLen = AddrLen;
234     }
235   }
236 
237   //
238   // Get the bus number to start with
239   //
240   StartBusNumber = (UINT8) (Configuration->AddrRangeMin);
241 
242   //
243   // Initialize the subordinate bus number
244   //
245   SubBusNumber = StartBusNumber;
246 
247   //
248   // Reset all assigned PCI bus number
249   //
250   ResetAllPpbBusNumber (
251     RootBridgeDev,
252     StartBusNumber
253   );
254 
255   //
256   // Assign bus number
257   //
258   Status = PciScanBus (
259             RootBridgeDev,
260             StartBusNumber,
261             &SubBusNumber,
262             &PaddedBusRange
263             );
264 
265   if (EFI_ERROR (Status)) {
266     return Status;
267   }
268 
269 
270   //
271   // Assign max bus number scanned
272   //
273 
274   Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);
275   if (EFI_ERROR (Status)) {
276     return Status;
277   }
278 
279   //
280   // Find the bus range which contains the higest bus number, then returns the number of buses
281   // that should be decoded.
282   //
283   while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {
284     Configuration++;
285   }
286   AddrLen = Configuration->AddrLen;
287   Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;
288 
289   //
290   // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
291   //
292   Configuration++;
293   Desc = Configuration->Desc;
294   Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;
295 
296   //
297   // Set bus number
298   //
299   Status = PciResAlloc->SetBusNumbers (
300                           PciResAlloc,
301                           RootBridgeHandle,
302                           RootBridgeDev->BusNumberRanges
303                           );
304 
305   //
306   // Restore changed fields
307   //
308   Configuration->Desc = Desc;
309   (Configuration - 1)->AddrLen = AddrLen;
310 
311   return Status;
312 }
313 
314 /**
315   This routine is used to process all PCI devices' Option Rom
316   on a certain root bridge.
317 
318   @param Bridge     Given parent's root bridge.
319   @param RomBase    Base address of ROM driver loaded from.
320   @param MaxLength  Maximum rom size.
321 
322 **/
323 VOID
ProcessOptionRom(IN PCI_IO_DEVICE * Bridge,IN UINT64 RomBase,IN UINT64 MaxLength)324 ProcessOptionRom (
325   IN PCI_IO_DEVICE *Bridge,
326   IN UINT64        RomBase,
327   IN UINT64        MaxLength
328   )
329 {
330   LIST_ENTRY      *CurrentLink;
331   PCI_IO_DEVICE   *Temp;
332 
333   //
334   // Go through bridges to reach all devices
335   //
336   CurrentLink = Bridge->ChildList.ForwardLink;
337   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
338     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
339     if (!IsListEmpty (&Temp->ChildList)) {
340 
341       //
342       // Go further to process the option rom under this bridge
343       //
344       ProcessOptionRom (Temp, RomBase, MaxLength);
345     }
346 
347     if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) {
348 
349       //
350       // Load and process the option rom
351       //
352       LoadOpRomImage (Temp, RomBase);
353     }
354 
355     CurrentLink = CurrentLink->ForwardLink;
356   }
357 }
358 
359 /**
360   This routine is used to assign bus number to the given PCI bus system
361 
362   @param Bridge             Parent root bridge instance.
363   @param StartBusNumber     Number of beginning.
364   @param SubBusNumber       The number of sub bus.
365 
366   @retval EFI_SUCCESS       Successfully assigned bus number.
367   @retval EFI_DEVICE_ERROR  Failed to assign bus number.
368 
369 **/
370 EFI_STATUS
PciAssignBusNumber(IN PCI_IO_DEVICE * Bridge,IN UINT8 StartBusNumber,OUT UINT8 * SubBusNumber)371 PciAssignBusNumber (
372   IN PCI_IO_DEVICE                      *Bridge,
373   IN UINT8                              StartBusNumber,
374   OUT UINT8                             *SubBusNumber
375   )
376 {
377   EFI_STATUS                      Status;
378   PCI_TYPE00                      Pci;
379   UINT8                           Device;
380   UINT8                           Func;
381   UINT64                          Address;
382   UINTN                           SecondBus;
383   UINT16                          Register;
384   UINT8                           Register8;
385   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
386 
387   PciRootBridgeIo = Bridge->PciRootBridgeIo;
388 
389   SecondBus       = 0;
390   Register        = 0;
391 
392   *SubBusNumber = StartBusNumber;
393 
394   //
395   // First check to see whether the parent is ppb
396   //
397   for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
398     for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
399 
400       //
401       // Check to see whether a pci device is present
402       //
403       Status = PciDevicePresent (
404                 PciRootBridgeIo,
405                 &Pci,
406                 StartBusNumber,
407                 Device,
408                 Func
409                 );
410 
411       if (EFI_ERROR (Status) && Func == 0) {
412         //
413         // go to next device if there is no Function 0
414         //
415         break;
416       }
417 
418       if (!EFI_ERROR (Status)   &&
419           (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) {
420 
421         //
422         // Reserved one bus for cardbus bridge
423         //
424         Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
425         if (EFI_ERROR (Status)) {
426           return Status;
427         }
428         SecondBus = *SubBusNumber;
429 
430         Register  = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber);
431 
432         Address   = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
433 
434         Status = PciRootBridgeIo->Pci.Write (
435                                         PciRootBridgeIo,
436                                         EfiPciWidthUint16,
437                                         Address,
438                                         1,
439                                         &Register
440                                         );
441 
442         //
443         // Initialize SubBusNumber to SecondBus
444         //
445         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
446         Status = PciRootBridgeIo->Pci.Write (
447                                         PciRootBridgeIo,
448                                         EfiPciWidthUint8,
449                                         Address,
450                                         1,
451                                         SubBusNumber
452                                         );
453         //
454         // If it is PPB, resursively search down this bridge
455         //
456         if (IS_PCI_BRIDGE (&Pci)) {
457 
458           Register8 = 0xFF;
459           Status = PciRootBridgeIo->Pci.Write (
460                                           PciRootBridgeIo,
461                                           EfiPciWidthUint8,
462                                           Address,
463                                           1,
464                                           &Register8
465                                           );
466 
467           Status = PciAssignBusNumber (
468                     Bridge,
469                     (UINT8) (SecondBus),
470                     SubBusNumber
471                     );
472 
473           if (EFI_ERROR (Status)) {
474             return EFI_DEVICE_ERROR;
475           }
476         }
477 
478         //
479         // Set the current maximum bus number under the PPB
480         //
481         Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
482 
483         Status = PciRootBridgeIo->Pci.Write (
484                                         PciRootBridgeIo,
485                                         EfiPciWidthUint8,
486                                         Address,
487                                         1,
488                                         SubBusNumber
489                                         );
490 
491       }
492 
493       if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) {
494 
495         //
496         // Skip sub functions, this is not a multi function device
497         //
498         Func = PCI_MAX_FUNC;
499       }
500     }
501   }
502 
503   return EFI_SUCCESS;
504 }
505 
506 /**
507   This routine is used to determine the root bridge attribute by interfacing
508   the host bridge resource allocation protocol.
509 
510   @param PciResAlloc    Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
511   @param RootBridgeDev  Root bridge instance
512 
513   @retval EFI_SUCCESS  Successfully got root bridge's attribute.
514   @retval other        Failed to get attribute.
515 
516 **/
517 EFI_STATUS
DetermineRootBridgeAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc,IN PCI_IO_DEVICE * RootBridgeDev)518 DetermineRootBridgeAttributes (
519   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
520   IN PCI_IO_DEVICE                                    *RootBridgeDev
521   )
522 {
523   UINT64      Attributes;
524   EFI_STATUS  Status;
525   EFI_HANDLE  RootBridgeHandle;
526 
527   Attributes        = 0;
528   RootBridgeHandle  = RootBridgeDev->Handle;
529 
530   //
531   // Get root bridge attribute by calling into pci host bridge resource allocation protocol
532   //
533   Status = PciResAlloc->GetAllocAttributes (
534                           PciResAlloc,
535                           RootBridgeHandle,
536                           &Attributes
537                           );
538 
539   if (EFI_ERROR (Status)) {
540     return Status;
541   }
542 
543   //
544   // Here is the point where PCI bus driver calls HOST bridge allocation protocol
545   // Currently we hardcoded for ea815
546   //
547   if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {
548     RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
549   }
550 
551   if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {
552     RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;
553     RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
554   }
555 
556   RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
557   RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
558   RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
559 
560   return EFI_SUCCESS;
561 }
562 
563 /**
564   Get Max Option Rom size on specified bridge.
565 
566   @param Bridge    Given bridge device instance.
567 
568   @return Max size of option rom needed.
569 
570 **/
571 UINT64
GetMaxOptionRomSize(IN PCI_IO_DEVICE * Bridge)572 GetMaxOptionRomSize (
573   IN PCI_IO_DEVICE   *Bridge
574   )
575 {
576   LIST_ENTRY      *CurrentLink;
577   PCI_IO_DEVICE   *Temp;
578   UINT64          MaxOptionRomSize;
579   UINT64          TempOptionRomSize;
580 
581   MaxOptionRomSize = 0;
582 
583   //
584   // Go through bridges to reach all devices
585   //
586   CurrentLink = Bridge->ChildList.ForwardLink;
587   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
588     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
589     if (!IsListEmpty (&Temp->ChildList)) {
590 
591       //
592       // Get max option rom size under this bridge
593       //
594       TempOptionRomSize = GetMaxOptionRomSize (Temp);
595 
596       //
597       // Compare with the option rom size of the bridge
598       // Get the larger one
599       //
600       if (Temp->RomSize > TempOptionRomSize) {
601         TempOptionRomSize = Temp->RomSize;
602       }
603 
604     } else {
605 
606       //
607       // For devices get the rom size directly
608       //
609       TempOptionRomSize = Temp->RomSize;
610     }
611 
612     //
613     // Get the largest rom size on this bridge
614     //
615     if (TempOptionRomSize > MaxOptionRomSize) {
616       MaxOptionRomSize = TempOptionRomSize;
617     }
618 
619     CurrentLink = CurrentLink->ForwardLink;
620   }
621 
622   return MaxOptionRomSize;
623 }
624 
625 /**
626   Process attributes of devices on this host bridge
627 
628   @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
629 
630   @retval EFI_SUCCESS   Successfully process attribute.
631   @retval EFI_NOT_FOUND Can not find the specific root bridge device.
632   @retval other         Failed to determine the root bridge device's attribute.
633 
634 **/
635 EFI_STATUS
PciHostBridgeDeviceAttribute(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc)636 PciHostBridgeDeviceAttribute (
637   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
638   )
639 {
640   EFI_HANDLE    RootBridgeHandle;
641   PCI_IO_DEVICE *RootBridgeDev;
642   EFI_STATUS    Status;
643 
644   RootBridgeHandle = NULL;
645 
646   while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
647 
648     //
649     // Get RootBridg Device by handle
650     //
651     RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
652 
653     if (RootBridgeDev == NULL) {
654       return EFI_NOT_FOUND;
655     }
656 
657     //
658     // Set the attributes for devcies behind the Root Bridge
659     //
660     Status = DetermineDeviceAttribute (RootBridgeDev);
661     if (EFI_ERROR (Status)) {
662       return Status;
663     }
664 
665   }
666 
667   return EFI_SUCCESS;
668 }
669 
670 /**
671   Get resource allocation status from the ACPI resource descriptor.
672 
673   @param AcpiConfig       Point to Acpi configuration table.
674   @param IoResStatus      Return the status of I/O resource.
675   @param Mem32ResStatus   Return the status of 32-bit Memory resource.
676   @param PMem32ResStatus  Return the status of 32-bit Prefetchable Memory resource.
677   @param Mem64ResStatus   Return the status of 64-bit Memory resource.
678   @param PMem64ResStatus  Return the status of 64-bit Prefetchable Memory resource.
679 
680 **/
681 VOID
GetResourceAllocationStatus(VOID * AcpiConfig,OUT UINT64 * IoResStatus,OUT UINT64 * Mem32ResStatus,OUT UINT64 * PMem32ResStatus,OUT UINT64 * Mem64ResStatus,OUT UINT64 * PMem64ResStatus)682 GetResourceAllocationStatus (
683   VOID        *AcpiConfig,
684   OUT UINT64  *IoResStatus,
685   OUT UINT64  *Mem32ResStatus,
686   OUT UINT64  *PMem32ResStatus,
687   OUT UINT64  *Mem64ResStatus,
688   OUT UINT64  *PMem64ResStatus
689   )
690 {
691   UINT8                             *Temp;
692   UINT64                            ResStatus;
693   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;
694 
695   Temp = (UINT8 *) AcpiConfig;
696 
697   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
698 
699     ACPIAddressDesc       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
700     ResStatus = ACPIAddressDesc->AddrTranslationOffset;
701 
702     switch (ACPIAddressDesc->ResType) {
703     case 0:
704       if (ACPIAddressDesc->AddrSpaceGranularity == 32) {
705         if (ACPIAddressDesc->SpecificFlag == 0x06) {
706           //
707           // Pmem32
708           //
709           *PMem32ResStatus = ResStatus;
710         } else {
711           //
712           // Mem32
713           //
714           *Mem32ResStatus = ResStatus;
715         }
716       }
717 
718       if (ACPIAddressDesc->AddrSpaceGranularity == 64) {
719         if (ACPIAddressDesc->SpecificFlag == 0x06) {
720           //
721           // PMem64
722           //
723           *PMem64ResStatus = ResStatus;
724         } else {
725           //
726           // Mem64
727           //
728           *Mem64ResStatus = ResStatus;
729         }
730       }
731 
732       break;
733 
734     case 1:
735       //
736       // Io
737       //
738       *IoResStatus = ResStatus;
739       break;
740 
741     default:
742       break;
743     }
744 
745     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
746   }
747 }
748 
749 /**
750   Remove a PCI device from device pool and mark its bar.
751 
752   @param PciDevice Instance of Pci device.
753 
754   @retval EFI_SUCCESS Successfully remove the PCI device.
755   @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
756 
757 **/
758 EFI_STATUS
RejectPciDevice(IN PCI_IO_DEVICE * PciDevice)759 RejectPciDevice (
760   IN PCI_IO_DEVICE       *PciDevice
761   )
762 {
763   PCI_IO_DEVICE   *Bridge;
764   PCI_IO_DEVICE   *Temp;
765   LIST_ENTRY      *CurrentLink;
766 
767   //
768   // Remove the padding resource from a bridge
769   //
770   if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&
771        PciDevice->ResourcePaddingDescriptors != NULL ) {
772     FreePool (PciDevice->ResourcePaddingDescriptors);
773     PciDevice->ResourcePaddingDescriptors = NULL;
774     return EFI_SUCCESS;
775   }
776 
777   //
778   // Skip RB and PPB
779   //
780   if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {
781     return EFI_ABORTED;
782   }
783 
784   if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
785     //
786     // Get the root bridge device
787     //
788     Bridge = PciDevice;
789     while (Bridge->Parent != NULL) {
790       Bridge = Bridge->Parent;
791     }
792 
793     RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
794 
795     //
796     // Mark its bar
797     //
798     InitializeP2C (PciDevice);
799   }
800 
801   //
802   // Remove the device
803   //
804   Bridge      = PciDevice->Parent;
805   CurrentLink = Bridge->ChildList.ForwardLink;
806   while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
807     Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
808     if (Temp == PciDevice) {
809       InitializePciDevice (Temp);
810       RemoveEntryList (CurrentLink);
811       return EFI_SUCCESS;
812     }
813 
814     CurrentLink = CurrentLink->ForwardLink;
815   }
816 
817   return EFI_ABORTED;
818 }
819 
820 /**
821   Determine whethter a PCI device can be rejected.
822 
823   @param  PciResNode Pointer to Pci resource node instance.
824 
825   @retval TRUE  The PCI device can be rejected.
826   @retval TRUE  The PCI device cannot be rejected.
827 
828 **/
829 BOOLEAN
IsRejectiveDevice(IN PCI_RESOURCE_NODE * PciResNode)830 IsRejectiveDevice (
831   IN  PCI_RESOURCE_NODE   *PciResNode
832   )
833 {
834   PCI_IO_DEVICE *Temp;
835 
836   Temp = PciResNode->PciDev;
837 
838   //
839   // Ensure the device is present
840   //
841   if (Temp == NULL) {
842     return FALSE;
843   }
844 
845   //
846   // PPB and RB should go ahead
847   //
848   if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {
849     return TRUE;
850   }
851 
852   //
853   // Skip device on Bus0
854   //
855   if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {
856     return FALSE;
857   }
858 
859   //
860   // Skip VGA
861   //
862   if (IS_PCI_VGA (&Temp->Pci)) {
863     return FALSE;
864   }
865 
866   return TRUE;
867 }
868 
869 /**
870   Compare two resource nodes and get the larger resource consumer.
871 
872   @param PciResNode1  resource node 1 want to be compared
873   @param PciResNode2  resource node 2 want to be compared
874 
875   @return Larger resource node.
876 
877 **/
878 PCI_RESOURCE_NODE *
GetLargerConsumerDevice(IN PCI_RESOURCE_NODE * PciResNode1,IN PCI_RESOURCE_NODE * PciResNode2)879 GetLargerConsumerDevice (
880   IN  PCI_RESOURCE_NODE   *PciResNode1,
881   IN  PCI_RESOURCE_NODE   *PciResNode2
882   )
883 {
884   if (PciResNode2 == NULL) {
885     return PciResNode1;
886   }
887 
888   if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \
889        && (PciResNode2->ResourceUsage != PciResUsagePadding) )
890   {
891     return PciResNode1;
892   }
893 
894   if (PciResNode1 == NULL) {
895     return PciResNode2;
896   }
897 
898   if ((PciResNode1->Length) > (PciResNode2->Length)) {
899     return PciResNode1;
900   }
901 
902   return PciResNode2;
903 }
904 
905 
906 /**
907   Get the max resource consumer in the host resource pool.
908 
909   @param ResPool  Pointer to resource pool node.
910 
911   @return The max resource consumer in the host resource pool.
912 
913 **/
914 PCI_RESOURCE_NODE *
GetMaxResourceConsumerDevice(IN PCI_RESOURCE_NODE * ResPool)915 GetMaxResourceConsumerDevice (
916   IN  PCI_RESOURCE_NODE   *ResPool
917   )
918 {
919   PCI_RESOURCE_NODE *Temp;
920   LIST_ENTRY        *CurrentLink;
921   PCI_RESOURCE_NODE *PciResNode;
922   PCI_RESOURCE_NODE *PPBResNode;
923 
924   PciResNode  = NULL;
925 
926   CurrentLink = ResPool->ChildList.ForwardLink;
927   while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {
928 
929     Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
930 
931     if (!IsRejectiveDevice (Temp)) {
932       CurrentLink = CurrentLink->ForwardLink;
933       continue;
934     }
935 
936     if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \
937           && (Temp->ResourceUsage != PciResUsagePadding))
938     {
939       PPBResNode  = GetMaxResourceConsumerDevice (Temp);
940       PciResNode  = GetLargerConsumerDevice (PciResNode, PPBResNode);
941     } else {
942       PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
943     }
944 
945     CurrentLink = CurrentLink->ForwardLink;
946   }
947 
948   return PciResNode;
949 }
950 
951 /**
952   Adjust host bridge allocation so as to reduce resource requirement
953 
954   @param IoPool           Pointer to instance of I/O resource Node.
955   @param Mem32Pool        Pointer to instance of 32-bit memory resource Node.
956   @param PMem32Pool       Pointer to instance of 32-bit Prefetchable memory resource node.
957   @param Mem64Pool        Pointer to instance of 64-bit memory resource node.
958   @param PMem64Pool       Pointer to instance of 64-bit Prefetchable memory resource node.
959   @param IoResStatus      Status of I/O resource Node.
960   @param Mem32ResStatus   Status of 32-bit memory resource Node.
961   @param PMem32ResStatus  Status of 32-bit Prefetchable memory resource node.
962   @param Mem64ResStatus   Status of 64-bit memory resource node.
963   @param PMem64ResStatus  Status of 64-bit Prefetchable memory resource node.
964 
965   @retval EFI_SUCCESS     Successfully adjusted resoruce on host bridge.
966   @retval EFI_ABORTED     Host bridge hasn't this resource type or no resource be adjusted.
967 
968 **/
969 EFI_STATUS
PciHostBridgeAdjustAllocation(IN PCI_RESOURCE_NODE * IoPool,IN PCI_RESOURCE_NODE * Mem32Pool,IN PCI_RESOURCE_NODE * PMem32Pool,IN PCI_RESOURCE_NODE * Mem64Pool,IN PCI_RESOURCE_NODE * PMem64Pool,IN UINT64 IoResStatus,IN UINT64 Mem32ResStatus,IN UINT64 PMem32ResStatus,IN UINT64 Mem64ResStatus,IN UINT64 PMem64ResStatus)970 PciHostBridgeAdjustAllocation (
971   IN  PCI_RESOURCE_NODE   *IoPool,
972   IN  PCI_RESOURCE_NODE   *Mem32Pool,
973   IN  PCI_RESOURCE_NODE   *PMem32Pool,
974   IN  PCI_RESOURCE_NODE   *Mem64Pool,
975   IN  PCI_RESOURCE_NODE   *PMem64Pool,
976   IN  UINT64              IoResStatus,
977   IN  UINT64              Mem32ResStatus,
978   IN  UINT64              PMem32ResStatus,
979   IN  UINT64              Mem64ResStatus,
980   IN  UINT64              PMem64ResStatus
981   )
982 {
983   BOOLEAN                               AllocationAjusted;
984   PCI_RESOURCE_NODE                     *PciResNode;
985   PCI_RESOURCE_NODE                     *ResPool[5];
986   PCI_IO_DEVICE                         *RemovedPciDev[5];
987   UINT64                                ResStatus[5];
988   UINTN                                 RemovedPciDevNum;
989   UINTN                                 DevIndex;
990   UINTN                                 ResType;
991   EFI_STATUS                            Status;
992   EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
993 
994   PciResNode = NULL;
995   ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
996   RemovedPciDevNum  = 0;
997 
998   ResPool[0]        = IoPool;
999   ResPool[1]        = Mem32Pool;
1000   ResPool[2]        = PMem32Pool;
1001   ResPool[3]        = Mem64Pool;
1002   ResPool[4]        = PMem64Pool;
1003 
1004   ResStatus[0]      = IoResStatus;
1005   ResStatus[1]      = Mem32ResStatus;
1006   ResStatus[2]      = PMem32ResStatus;
1007   ResStatus[3]      = Mem64ResStatus;
1008   ResStatus[4]      = PMem64ResStatus;
1009 
1010   AllocationAjusted = FALSE;
1011 
1012   for (ResType = 0; ResType < 5; ResType++) {
1013 
1014     if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
1015       continue;
1016     }
1017 
1018     if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {
1019       //
1020       // Host bridge hasn't this resource type
1021       //
1022       return EFI_ABORTED;
1023     }
1024 
1025     //
1026     // Hostbridge hasn't enough resource
1027     //
1028     PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
1029     if (PciResNode == NULL) {
1030       continue;
1031     }
1032 
1033     //
1034     // Check if the device has been removed before
1035     //
1036     for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
1037       if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
1038         break;
1039       }
1040     }
1041 
1042     if (DevIndex != RemovedPciDevNum) {
1043       continue;
1044     }
1045 
1046     //
1047     // Remove the device if it isn't in the array
1048     //
1049     Status = RejectPciDevice (PciResNode->PciDev);
1050     if (Status == EFI_SUCCESS) {
1051       DEBUG ((
1052         EFI_D_ERROR,
1053         "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
1054         PciResNode->PciDev->BusNumber, PciResNode->PciDev->DeviceNumber, PciResNode->PciDev->FunctionNumber
1055         ));
1056 
1057       //
1058       // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1059       //
1060       //
1061       // Have no way to get ReqRes, AllocRes & Bar here
1062       //
1063       ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
1064       AllocFailExtendedData.DevicePathSize = (UINT16) sizeof (EFI_DEVICE_PATH_PROTOCOL);
1065       AllocFailExtendedData.DevicePath     = (UINT8 *) PciResNode->PciDev->DevicePath;
1066       AllocFailExtendedData.Bar            = PciResNode->Bar;
1067 
1068       REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
1069             EFI_PROGRESS_CODE,
1070             EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
1071             (VOID *) &AllocFailExtendedData,
1072             sizeof (AllocFailExtendedData)
1073             );
1074 
1075       //
1076       // Add it to the array and indicate at least a device has been rejected
1077       //
1078       RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
1079       AllocationAjusted                 = TRUE;
1080     }
1081   }
1082   //
1083   // End for
1084   //
1085 
1086   if (AllocationAjusted) {
1087     return EFI_SUCCESS;
1088   } else {
1089     return EFI_ABORTED;
1090   }
1091 }
1092 
1093 /**
1094   Summary requests for all resource type, and contruct ACPI resource
1095   requestor instance.
1096 
1097   @param Bridge           detecting bridge
1098   @param IoNode           Pointer to instance of I/O resource Node
1099   @param Mem32Node        Pointer to instance of 32-bit memory resource Node
1100   @param PMem32Node       Pointer to instance of 32-bit Pmemory resource node
1101   @param Mem64Node        Pointer to instance of 64-bit memory resource node
1102   @param PMem64Node       Pointer to instance of 64-bit Pmemory resource node
1103   @param Config           Output buffer holding new constructed APCI resource requestor
1104 
1105   @retval EFI_SUCCESS           Successfully constructed ACPI resource.
1106   @retval EFI_OUT_OF_RESOURCES  No memory availabe.
1107 
1108 **/
1109 EFI_STATUS
ConstructAcpiResourceRequestor(IN PCI_IO_DEVICE * Bridge,IN PCI_RESOURCE_NODE * IoNode,IN PCI_RESOURCE_NODE * Mem32Node,IN PCI_RESOURCE_NODE * PMem32Node,IN PCI_RESOURCE_NODE * Mem64Node,IN PCI_RESOURCE_NODE * PMem64Node,OUT VOID ** Config)1110 ConstructAcpiResourceRequestor (
1111   IN PCI_IO_DEVICE      *Bridge,
1112   IN PCI_RESOURCE_NODE  *IoNode,
1113   IN PCI_RESOURCE_NODE  *Mem32Node,
1114   IN PCI_RESOURCE_NODE  *PMem32Node,
1115   IN PCI_RESOURCE_NODE  *Mem64Node,
1116   IN PCI_RESOURCE_NODE  *PMem64Node,
1117   OUT VOID              **Config
1118   )
1119 {
1120   UINT8                             NumConfig;
1121   UINT8                             Aperture;
1122   UINT8                             *Configuration;
1123   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1124   EFI_ACPI_END_TAG_DESCRIPTOR       *PtrEnd;
1125 
1126   NumConfig = 0;
1127   Aperture  = 0;
1128 
1129   *Config  = NULL;
1130 
1131   //
1132   // if there is io request, add to the io aperture
1133   //
1134   if (ResourceRequestExisted (IoNode)) {
1135     NumConfig++;
1136     Aperture |= 0x01;
1137   }
1138 
1139   //
1140   // if there is mem32 request, add to the mem32 aperture
1141   //
1142   if (ResourceRequestExisted (Mem32Node)) {
1143     NumConfig++;
1144     Aperture |= 0x02;
1145   }
1146 
1147   //
1148   // if there is pmem32 request, add to the pmem32 aperture
1149   //
1150   if (ResourceRequestExisted (PMem32Node)) {
1151     NumConfig++;
1152     Aperture |= 0x04;
1153   }
1154 
1155   //
1156   // if there is mem64 request, add to the mem64 aperture
1157   //
1158   if (ResourceRequestExisted (Mem64Node)) {
1159     NumConfig++;
1160     Aperture |= 0x08;
1161   }
1162 
1163   //
1164   // if there is pmem64 request, add to the pmem64 aperture
1165   //
1166   if (ResourceRequestExisted (PMem64Node)) {
1167     NumConfig++;
1168     Aperture |= 0x10;
1169   }
1170 
1171   if (NumConfig != 0) {
1172 
1173     //
1174     // If there is at least one type of resource request,
1175     // allocate a acpi resource node
1176     //
1177     Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1178     if (Configuration == NULL) {
1179       return EFI_OUT_OF_RESOURCES;
1180     }
1181 
1182     Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1183 
1184     //
1185     // Deal with io aperture
1186     //
1187     if ((Aperture & 0x01) != 0) {
1188       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1189       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1190       //
1191       // Io
1192       //
1193       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_IO;
1194       //
1195       // non ISA range
1196       //
1197       Ptr->SpecificFlag = 1;
1198       Ptr->AddrLen      = IoNode->Length;
1199       Ptr->AddrRangeMax = IoNode->Alignment;
1200 
1201       Ptr++;
1202     }
1203     //
1204     // Deal with mem32 aperture
1205     //
1206     if ((Aperture & 0x02) != 0) {
1207       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1208       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1209       //
1210       // Mem
1211       //
1212       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
1213       //
1214       // Nonprefechable
1215       //
1216       Ptr->SpecificFlag = 0;
1217       //
1218       // 32 bit
1219       //
1220       Ptr->AddrSpaceGranularity = 32;
1221       Ptr->AddrLen      = Mem32Node->Length;
1222       Ptr->AddrRangeMax = Mem32Node->Alignment;
1223 
1224       Ptr++;
1225     }
1226 
1227     //
1228     // Deal with Pmem32 aperture
1229     //
1230     if ((Aperture & 0x04) != 0) {
1231       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1232       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1233       //
1234       // Mem
1235       //
1236       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
1237       //
1238       // prefechable
1239       //
1240       Ptr->SpecificFlag = 0x6;
1241       //
1242       // 32 bit
1243       //
1244       Ptr->AddrSpaceGranularity = 32;
1245       Ptr->AddrLen      = PMem32Node->Length;
1246       Ptr->AddrRangeMax = PMem32Node->Alignment;
1247 
1248       Ptr++;
1249     }
1250     //
1251     // Deal with mem64 aperture
1252     //
1253     if ((Aperture & 0x08) != 0) {
1254       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1255       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1256       //
1257       // Mem
1258       //
1259       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
1260       //
1261       // nonprefechable
1262       //
1263       Ptr->SpecificFlag = 0;
1264       //
1265       // 64 bit
1266       //
1267       Ptr->AddrSpaceGranularity = 64;
1268       Ptr->AddrLen      = Mem64Node->Length;
1269       Ptr->AddrRangeMax = Mem64Node->Alignment;
1270 
1271       Ptr++;
1272     }
1273     //
1274     // Deal with Pmem64 aperture
1275     //
1276     if ((Aperture & 0x10) != 0) {
1277       Ptr->Desc     = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1278       Ptr->Len      = (UINT16) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1279       //
1280       // Mem
1281       //
1282       Ptr->ResType  = ACPI_ADDRESS_SPACE_TYPE_MEM;
1283       //
1284       // prefechable
1285       //
1286       Ptr->SpecificFlag = 0x06;
1287       //
1288       // 64 bit
1289       //
1290       Ptr->AddrSpaceGranularity = 64;
1291       Ptr->AddrLen      = PMem64Node->Length;
1292       Ptr->AddrRangeMax = PMem64Node->Alignment;
1293 
1294       Ptr++;
1295     }
1296 
1297     //
1298     // put the checksum
1299     //
1300     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;
1301 
1302     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
1303     PtrEnd->Checksum  = 0;
1304 
1305   } else {
1306 
1307     //
1308     // If there is no resource request
1309     //
1310     Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1311     if (Configuration == NULL) {
1312       return EFI_OUT_OF_RESOURCES;
1313     }
1314 
1315     Ptr               = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
1316     Ptr->Desc         = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1317 
1318     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);
1319     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
1320     PtrEnd->Checksum  = 0;
1321   }
1322 
1323   *Config = Configuration;
1324 
1325   return EFI_SUCCESS;
1326 }
1327 
1328 /**
1329   Get resource base from an acpi configuration descriptor.
1330 
1331   @param Config       An acpi configuration descriptor.
1332   @param IoBase       Output of I/O resource base address.
1333   @param Mem32Base    Output of 32-bit memory base address.
1334   @param PMem32Base   Output of 32-bit prefetchable memory base address.
1335   @param Mem64Base    Output of 64-bit memory base address.
1336   @param PMem64Base   Output of 64-bit prefetchable memory base address.
1337 
1338 **/
1339 VOID
GetResourceBase(IN VOID * Config,OUT UINT64 * IoBase,OUT UINT64 * Mem32Base,OUT UINT64 * PMem32Base,OUT UINT64 * Mem64Base,OUT UINT64 * PMem64Base)1340 GetResourceBase (
1341   IN VOID     *Config,
1342   OUT UINT64  *IoBase,
1343   OUT UINT64  *Mem32Base,
1344   OUT UINT64  *PMem32Base,
1345   OUT UINT64  *Mem64Base,
1346   OUT UINT64  *PMem64Base
1347   )
1348 {
1349   UINT8                             *Temp;
1350   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1351   UINT64                            ResStatus;
1352 
1353   ASSERT (Config != NULL);
1354 
1355   *IoBase     = 0xFFFFFFFFFFFFFFFFULL;
1356   *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;
1357   *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1358   *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;
1359   *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1360 
1361   Temp        = (UINT8 *) Config;
1362 
1363   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1364 
1365     Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1366     ResStatus = Ptr->AddrTranslationOffset;
1367 
1368     if (ResStatus == EFI_RESOURCE_SATISFIED) {
1369 
1370       switch (Ptr->ResType) {
1371 
1372       //
1373       // Memory type aperture
1374       //
1375       case 0:
1376 
1377         //
1378         // Check to see the granularity
1379         //
1380         if (Ptr->AddrSpaceGranularity == 32) {
1381           if ((Ptr->SpecificFlag & 0x06) != 0) {
1382             *PMem32Base = Ptr->AddrRangeMin;
1383           } else {
1384             *Mem32Base = Ptr->AddrRangeMin;
1385           }
1386         }
1387 
1388         if (Ptr->AddrSpaceGranularity == 64) {
1389           if ((Ptr->SpecificFlag & 0x06) != 0) {
1390             *PMem64Base = Ptr->AddrRangeMin;
1391           } else {
1392             *Mem64Base = Ptr->AddrRangeMin;
1393           }
1394         }
1395         break;
1396 
1397       case 1:
1398 
1399         //
1400         // Io type aperture
1401         //
1402         *IoBase = Ptr->AddrRangeMin;
1403         break;
1404 
1405       default:
1406         break;
1407 
1408       }
1409       //
1410       // End switch
1411       //
1412     }
1413     //
1414     // End for
1415     //
1416     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1417   }
1418 }
1419 
1420 /**
1421   Enumerate pci bridge, allocate resource and determine attribute
1422   for devices on this bridge.
1423 
1424   @param BridgeDev    Pointer to instance of bridge device.
1425 
1426   @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1427   @retval other       Failed to enumerate.
1428 
1429 **/
1430 EFI_STATUS
PciBridgeEnumerator(IN PCI_IO_DEVICE * BridgeDev)1431 PciBridgeEnumerator (
1432   IN PCI_IO_DEVICE                                     *BridgeDev
1433   )
1434 {
1435   UINT8               SubBusNumber;
1436   UINT8               StartBusNumber;
1437   EFI_PCI_IO_PROTOCOL *PciIo;
1438   EFI_STATUS          Status;
1439 
1440   SubBusNumber    = 0;
1441   StartBusNumber  = 0;
1442   PciIo           = &(BridgeDev->PciIo);
1443   Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1444 
1445   if (EFI_ERROR (Status)) {
1446     return Status;
1447   }
1448 
1449   Status = PciAssignBusNumber (
1450             BridgeDev,
1451             StartBusNumber,
1452             &SubBusNumber
1453             );
1454 
1455   if (EFI_ERROR (Status)) {
1456     return Status;
1457   }
1458 
1459   Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1460 
1461   if (EFI_ERROR (Status)) {
1462     return Status;
1463   }
1464 
1465   Status = PciBridgeResourceAllocator (BridgeDev);
1466 
1467   if (EFI_ERROR (Status)) {
1468     return Status;
1469   }
1470 
1471   Status = DetermineDeviceAttribute (BridgeDev);
1472 
1473   if (EFI_ERROR (Status)) {
1474     return Status;
1475   }
1476 
1477   return EFI_SUCCESS;
1478 
1479 }
1480 
1481 /**
1482   Allocate all kinds of resource for PCI bridge.
1483 
1484   @param  Bridge      Pointer to bridge instance.
1485 
1486   @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1487   @retval other       Failed to allocate resource for bridge.
1488 
1489 **/
1490 EFI_STATUS
PciBridgeResourceAllocator(IN PCI_IO_DEVICE * Bridge)1491 PciBridgeResourceAllocator (
1492   IN PCI_IO_DEVICE  *Bridge
1493   )
1494 {
1495   PCI_RESOURCE_NODE *IoBridge;
1496   PCI_RESOURCE_NODE *Mem32Bridge;
1497   PCI_RESOURCE_NODE *PMem32Bridge;
1498   PCI_RESOURCE_NODE *Mem64Bridge;
1499   PCI_RESOURCE_NODE *PMem64Bridge;
1500   UINT64            IoBase;
1501   UINT64            Mem32Base;
1502   UINT64            PMem32Base;
1503   UINT64            Mem64Base;
1504   UINT64            PMem64Base;
1505   EFI_STATUS        Status;
1506 
1507   IoBridge = CreateResourceNode (
1508                Bridge,
1509                0,
1510                Bridge->BridgeIoAlignment,
1511                0,
1512                PciBarTypeIo16,
1513                PciResUsageTypical
1514                );
1515 
1516   Mem32Bridge = CreateResourceNode (
1517                   Bridge,
1518                   0,
1519                   0xFFFFF,
1520                   0,
1521                   PciBarTypeMem32,
1522                   PciResUsageTypical
1523                   );
1524 
1525   PMem32Bridge = CreateResourceNode (
1526                    Bridge,
1527                    0,
1528                    0xFFFFF,
1529                    0,
1530                    PciBarTypePMem32,
1531                    PciResUsageTypical
1532                    );
1533 
1534   Mem64Bridge = CreateResourceNode (
1535                   Bridge,
1536                   0,
1537                   0xFFFFF,
1538                   0,
1539                   PciBarTypeMem64,
1540                   PciResUsageTypical
1541                   );
1542 
1543   PMem64Bridge = CreateResourceNode (
1544                    Bridge,
1545                    0,
1546                    0xFFFFF,
1547                    0,
1548                    PciBarTypePMem64,
1549                    PciResUsageTypical
1550                    );
1551 
1552   //
1553   // Create resourcemap by going through all the devices subject to this root bridge
1554   //
1555   CreateResourceMap (
1556     Bridge,
1557     IoBridge,
1558     Mem32Bridge,
1559     PMem32Bridge,
1560     Mem64Bridge,
1561     PMem64Bridge
1562     );
1563 
1564   Status = GetResourceBaseFromBridge (
1565              Bridge,
1566              &IoBase,
1567              &Mem32Base,
1568              &PMem32Base,
1569              &Mem64Base,
1570              &PMem64Base
1571              );
1572 
1573   if (EFI_ERROR (Status)) {
1574     return Status;
1575   }
1576 
1577   //
1578   // Program IO resources
1579   //
1580   ProgramResource (
1581     IoBase,
1582     IoBridge
1583     );
1584 
1585   //
1586   // Program Mem32 resources
1587   //
1588   ProgramResource (
1589     Mem32Base,
1590     Mem32Bridge
1591     );
1592 
1593   //
1594   // Program PMem32 resources
1595   //
1596   ProgramResource (
1597     PMem32Base,
1598     PMem32Bridge
1599     );
1600 
1601   //
1602   // Program Mem64 resources
1603   //
1604   ProgramResource (
1605     Mem64Base,
1606     Mem64Bridge
1607     );
1608 
1609   //
1610   // Program PMem64 resources
1611   //
1612   ProgramResource (
1613     PMem64Base,
1614     PMem64Bridge
1615     );
1616 
1617   DestroyResourceTree (IoBridge);
1618   DestroyResourceTree (Mem32Bridge);
1619   DestroyResourceTree (PMem32Bridge);
1620   DestroyResourceTree (PMem64Bridge);
1621   DestroyResourceTree (Mem64Bridge);
1622 
1623   gBS->FreePool (IoBridge);
1624   gBS->FreePool (Mem32Bridge);
1625   gBS->FreePool (PMem32Bridge);
1626   gBS->FreePool (PMem64Bridge);
1627   gBS->FreePool (Mem64Bridge);
1628 
1629   return EFI_SUCCESS;
1630 }
1631 
1632 /**
1633   Get resource base address for a pci bridge device.
1634 
1635   @param Bridge     Given Pci driver instance.
1636   @param IoBase     Output for base address of I/O type resource.
1637   @param Mem32Base  Output for base address of 32-bit memory type resource.
1638   @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1639   @param Mem64Base  Output for base address of 64-bit memory type resource.
1640   @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1641 
1642   @retval EFI_SUCCESS           Successfully got resource base address.
1643   @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
1644 
1645 **/
1646 EFI_STATUS
GetResourceBaseFromBridge(IN PCI_IO_DEVICE * Bridge,OUT UINT64 * IoBase,OUT UINT64 * Mem32Base,OUT UINT64 * PMem32Base,OUT UINT64 * Mem64Base,OUT UINT64 * PMem64Base)1647 GetResourceBaseFromBridge (
1648   IN  PCI_IO_DEVICE *Bridge,
1649   OUT UINT64        *IoBase,
1650   OUT UINT64        *Mem32Base,
1651   OUT UINT64        *PMem32Base,
1652   OUT UINT64        *Mem64Base,
1653   OUT UINT64        *PMem64Base
1654   )
1655 {
1656   if (!Bridge->Allocated) {
1657     return EFI_OUT_OF_RESOURCES;
1658   }
1659 
1660   *IoBase     = gAllOne;
1661   *Mem32Base  = gAllOne;
1662   *PMem32Base = gAllOne;
1663   *Mem64Base  = gAllOne;
1664   *PMem64Base = gAllOne;
1665 
1666   if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1667 
1668     if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
1669       *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1670     }
1671 
1672     if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
1673       *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1674     }
1675 
1676     if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
1677       *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1678     }
1679 
1680     if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
1681       *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1682     } else {
1683       *PMem64Base = gAllOne;
1684     }
1685 
1686   }
1687 
1688   if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1689     if (Bridge->PciBar[P2C_IO_1].Length > 0) {
1690       *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1691     } else {
1692       if (Bridge->PciBar[P2C_IO_2].Length > 0) {
1693         *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1694       }
1695     }
1696 
1697     if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
1698       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1699         *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1700       }
1701 
1702       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1703         *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1704       }
1705     }
1706 
1707     if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
1708       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1709         *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1710       }
1711 
1712       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1713         *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1714       }
1715     }
1716   }
1717 
1718   return EFI_SUCCESS;
1719 }
1720 
1721 /**
1722    These are the notifications from the PCI bus driver that it is about to enter a certain
1723    phase of the PCI enumeration process.
1724 
1725    This member function can be used to notify the host bridge driver to perform specific actions,
1726    including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1727    Eight notification points are defined at this time. See belows:
1728    EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
1729                                           structures. The PCI enumerator should issue this notification
1730                                           before starting a fresh enumeration process. Enumeration cannot
1731                                           be restarted after sending any other notification such as
1732                                           EfiPciHostBridgeBeginBusAllocation.
1733    EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
1734                                           required here. This notification can be used to perform any
1735                                           chipset-specific programming.
1736    EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
1737                                           specific action is required here. This notification can be used to
1738                                           perform any chipset-specific programming.
1739    EfiPciHostBridgeBeginResourceAllocation
1740                                           The resource allocation phase is about to begin. No specific
1741                                           action is required here. This notification can be used to perform
1742                                           any chipset-specific programming.
1743    EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
1744                                           root bridges. These resource settings are returned on the next call to
1745                                           GetProposedResources(). Before calling NotifyPhase() with a Phase of
1746                                           EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1747                                           for gathering I/O and memory requests for
1748                                           all the PCI root bridges and submitting these requests using
1749                                           SubmitResources(). This function pads the resource amount
1750                                           to suit the root bridge hardware, takes care of dependencies between
1751                                           the PCI root bridges, and calls the Global Coherency Domain (GCD)
1752                                           with the allocation request. In the case of padding, the allocated range
1753                                           could be bigger than what was requested.
1754    EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
1755                                           resources (proposed resources) for all the PCI root bridges. After the
1756                                           hardware is programmed, reassigning resources will not be supported.
1757                                           The bus settings are not affected.
1758    EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
1759                                           root bridges and resets the I/O and memory apertures to their initial
1760                                           state. The bus settings are not affected. If the request to allocate
1761                                           resources fails, the PCI enumerator can use this notification to
1762                                           deallocate previous resources, adjust the requests, and retry
1763                                           allocation.
1764    EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
1765                                           required here. This notification can be used to perform any chipsetspecific
1766                                           programming.
1767 
1768    @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1769    @param[in] Phase               The phase during enumeration
1770 
1771    @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
1772                                   is valid for a Phase of EfiPciHostBridgeAllocateResources if
1773                                   SubmitResources() has not been called for one or more
1774                                   PCI root bridges before this call
1775    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
1776                                   for a Phase of EfiPciHostBridgeSetResources.
1777    @retval EFI_INVALID_PARAMETER  Invalid phase parameter
1778    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1779                                   This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1780                                   previously submitted resource requests cannot be fulfilled or
1781                                   were only partially fulfilled.
1782    @retval EFI_SUCCESS            The notification was accepted without any errors.
1783 
1784 **/
1785 EFI_STATUS
NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc,EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)1786 NotifyPhase (
1787   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
1788   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
1789   )
1790 {
1791   EFI_HANDLE                      HostBridgeHandle;
1792   EFI_HANDLE                      RootBridgeHandle;
1793   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1794   EFI_STATUS                      Status;
1795 
1796   HostBridgeHandle  = NULL;
1797   RootBridgeHandle  = NULL;
1798   if (gPciPlatformProtocol != NULL) {
1799     //
1800     // Get Host Bridge Handle.
1801     //
1802     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1803 
1804     //
1805     // Get the rootbridge Io protocol to find the host bridge handle
1806     //
1807     Status = gBS->HandleProtocol (
1808                     RootBridgeHandle,
1809                     &gEfiPciRootBridgeIoProtocolGuid,
1810                     (VOID **) &PciRootBridgeIo
1811                     );
1812 
1813     if (EFI_ERROR (Status)) {
1814       return EFI_NOT_FOUND;
1815     }
1816 
1817     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1818 
1819     //
1820     // Call PlatformPci::PlatformNotify() if the protocol is present.
1821     //
1822     gPciPlatformProtocol->PlatformNotify (
1823                             gPciPlatformProtocol,
1824                             HostBridgeHandle,
1825                             Phase,
1826                             ChipsetEntry
1827                             );
1828   } else if (gPciOverrideProtocol != NULL){
1829     //
1830     // Get Host Bridge Handle.
1831     //
1832     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1833 
1834     //
1835     // Get the rootbridge Io protocol to find the host bridge handle
1836     //
1837     Status = gBS->HandleProtocol (
1838                     RootBridgeHandle,
1839                     &gEfiPciRootBridgeIoProtocolGuid,
1840                     (VOID **) &PciRootBridgeIo
1841                     );
1842 
1843     if (EFI_ERROR (Status)) {
1844       return EFI_NOT_FOUND;
1845     }
1846 
1847     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1848 
1849     //
1850     // Call PlatformPci::PhaseNotify() if the protocol is present.
1851     //
1852     gPciOverrideProtocol->PlatformNotify (
1853                             gPciOverrideProtocol,
1854                             HostBridgeHandle,
1855                             Phase,
1856                             ChipsetEntry
1857                             );
1858   }
1859 
1860   Status = PciResAlloc->NotifyPhase (
1861                           PciResAlloc,
1862                           Phase
1863                           );
1864 
1865   if (gPciPlatformProtocol != NULL) {
1866     //
1867     // Call PlatformPci::PlatformNotify() if the protocol is present.
1868     //
1869     gPciPlatformProtocol->PlatformNotify (
1870                             gPciPlatformProtocol,
1871                             HostBridgeHandle,
1872                             Phase,
1873                             ChipsetExit
1874                             );
1875 
1876   } else if (gPciOverrideProtocol != NULL) {
1877     //
1878     // Call PlatformPci::PhaseNotify() if the protocol is present.
1879     //
1880     gPciOverrideProtocol->PlatformNotify (
1881                             gPciOverrideProtocol,
1882                             HostBridgeHandle,
1883                             Phase,
1884                             ChipsetExit
1885                             );
1886   }
1887 
1888   return Status;
1889 }
1890 
1891 /**
1892   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1893   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1894   PCI controllers before enumeration.
1895 
1896   This function is called during the PCI enumeration process. No specific action is expected from this
1897   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1898   enumeration.
1899 
1900   @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1901   @param Bus               The bus number of the pci device.
1902   @param Device            The device number of the pci device.
1903   @param Func              The function number of the pci device.
1904   @param Phase             The phase of the PCI device enumeration.
1905 
1906   @retval EFI_SUCCESS              The requested parameters were returned.
1907   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
1908   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
1909                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1910   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
1911                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
1912                                    bridge.
1913 
1914 **/
1915 EFI_STATUS
PreprocessController(IN PCI_IO_DEVICE * Bridge,IN UINT8 Bus,IN UINT8 Device,IN UINT8 Func,IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)1916 PreprocessController (
1917   IN PCI_IO_DEVICE                                    *Bridge,
1918   IN UINT8                                            Bus,
1919   IN UINT8                                            Device,
1920   IN UINT8                                            Func,
1921   IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase
1922   )
1923 {
1924   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;
1925   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
1926   EFI_HANDLE                                        RootBridgeHandle;
1927   EFI_HANDLE                                        HostBridgeHandle;
1928   EFI_STATUS                                        Status;
1929 
1930   //
1931   // Get the host bridge handle
1932   //
1933   HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1934 
1935   //
1936   // Get the pci host bridge resource allocation protocol
1937   //
1938   Status = gBS->OpenProtocol (
1939                   HostBridgeHandle,
1940                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1941                   (VOID **) &PciResAlloc,
1942                   NULL,
1943                   NULL,
1944                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1945                   );
1946 
1947   if (EFI_ERROR (Status)) {
1948     return EFI_UNSUPPORTED;
1949   }
1950 
1951   //
1952   // Get Root Brige Handle
1953   //
1954   while (Bridge->Parent != NULL) {
1955     Bridge = Bridge->Parent;
1956   }
1957 
1958   RootBridgeHandle                      = Bridge->Handle;
1959 
1960   RootBridgePciAddress.Register         = 0;
1961   RootBridgePciAddress.Function         = Func;
1962   RootBridgePciAddress.Device           = Device;
1963   RootBridgePciAddress.Bus              = Bus;
1964   RootBridgePciAddress.ExtendedRegister = 0;
1965 
1966   if (gPciPlatformProtocol != NULL) {
1967     //
1968     // Call PlatformPci::PrepController() if the protocol is present.
1969     //
1970     gPciPlatformProtocol->PlatformPrepController (
1971                             gPciPlatformProtocol,
1972                             HostBridgeHandle,
1973                             RootBridgeHandle,
1974                             RootBridgePciAddress,
1975                             Phase,
1976                             ChipsetEntry
1977                             );
1978   } else if (gPciOverrideProtocol != NULL) {
1979     //
1980     // Call PlatformPci::PrepController() if the protocol is present.
1981     //
1982     gPciOverrideProtocol->PlatformPrepController (
1983                             gPciOverrideProtocol,
1984                             HostBridgeHandle,
1985                             RootBridgeHandle,
1986                             RootBridgePciAddress,
1987                             Phase,
1988                             ChipsetEntry
1989                             );
1990   }
1991 
1992   Status = PciResAlloc->PreprocessController (
1993                           PciResAlloc,
1994                           RootBridgeHandle,
1995                           RootBridgePciAddress,
1996                           Phase
1997                           );
1998 
1999   if (gPciPlatformProtocol != NULL) {
2000     //
2001     // Call PlatformPci::PrepController() if the protocol is present.
2002     //
2003     gPciPlatformProtocol->PlatformPrepController (
2004                             gPciPlatformProtocol,
2005                             HostBridgeHandle,
2006                             RootBridgeHandle,
2007                             RootBridgePciAddress,
2008                             Phase,
2009                             ChipsetExit
2010                             );
2011   } else if (gPciOverrideProtocol != NULL) {
2012     //
2013     // Call PlatformPci::PrepController() if the protocol is present.
2014     //
2015     gPciOverrideProtocol->PlatformPrepController (
2016                             gPciOverrideProtocol,
2017                             HostBridgeHandle,
2018                             RootBridgeHandle,
2019                             RootBridgePciAddress,
2020                             Phase,
2021                             ChipsetExit
2022                             );
2023   }
2024 
2025   return EFI_SUCCESS;
2026 }
2027 
2028 /**
2029   This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
2030   happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
2031 
2032   @param This                 A pointer to the hot plug request protocol.
2033   @param Operation            The operation the PCI bus driver is requested to make.
2034   @param Controller           The handle of the hot-plug controller.
2035   @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
2036   @param NumberOfChildren     The number of child handles.
2037                               For a add operation, it is an output parameter.
2038                               For a remove operation, it's an input parameter.
2039   @param ChildHandleBuffer    The buffer which contains the child handles.
2040 
2041   @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
2042                                  Controller is NULL or not a valid handle.
2043                                  NumberOfChildren is NULL.
2044                                  ChildHandleBuffer is NULL while Operation is add.
2045   @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
2046   @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
2047   @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
2048                                  as requested, and for an add operation, the new handles are
2049                                  returned in ChildHandleBuffer.
2050 **/
2051 EFI_STATUS
2052 EFIAPI
PciHotPlugRequestNotify(IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,IN EFI_PCI_HOTPLUG_OPERATION Operation,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN OUT UINT8 * NumberOfChildren,IN OUT EFI_HANDLE * ChildHandleBuffer)2053 PciHotPlugRequestNotify (
2054   IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
2055   IN EFI_PCI_HOTPLUG_OPERATION        Operation,
2056   IN EFI_HANDLE                       Controller,
2057   IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
2058   IN OUT UINT8                        *NumberOfChildren,
2059   IN OUT EFI_HANDLE                   * ChildHandleBuffer
2060   )
2061 {
2062   PCI_IO_DEVICE       *Bridge;
2063   PCI_IO_DEVICE       *Temp;
2064   EFI_PCI_IO_PROTOCOL *PciIo;
2065   UINTN               Index;
2066   EFI_HANDLE          RootBridgeHandle;
2067   EFI_STATUS          Status;
2068 
2069   //
2070   // Check input parameter validity
2071   //
2072   if ((Controller == NULL) || (NumberOfChildren == NULL)){
2073     return EFI_INVALID_PARAMETER;
2074   }
2075 
2076   if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
2077     return EFI_INVALID_PARAMETER;
2078   }
2079 
2080   if (Operation == EfiPciHotPlugRequestAdd){
2081     if (ChildHandleBuffer == NULL) {
2082       return EFI_INVALID_PARAMETER;
2083     }
2084   } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
2085     if (ChildHandleBuffer == NULL) {
2086       return EFI_INVALID_PARAMETER;
2087     }
2088   }
2089 
2090   Status = gBS->OpenProtocol (
2091                   Controller,
2092                   &gEfiPciIoProtocolGuid,
2093                   (VOID **) &PciIo,
2094                   gPciBusDriverBinding.DriverBindingHandle,
2095                   Controller,
2096                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2097                   );
2098 
2099   if (EFI_ERROR (Status)) {
2100     return EFI_NOT_FOUND;
2101   }
2102 
2103   Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2104 
2105   //
2106   // Get root bridge handle
2107   //
2108   Temp = Bridge;
2109   while (Temp->Parent != NULL) {
2110     Temp = Temp->Parent;
2111   }
2112 
2113   RootBridgeHandle = Temp->Handle;
2114 
2115   if (Operation == EfiPciHotPlugRequestAdd) {
2116     //
2117     // Report Status Code to indicate hot plug happens
2118     //
2119     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2120       EFI_PROGRESS_CODE,
2121       (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
2122       Temp->DevicePath
2123       );
2124 
2125     if (NumberOfChildren != NULL) {
2126       *NumberOfChildren = 0;
2127     }
2128 
2129     if (IsListEmpty (&Bridge->ChildList)) {
2130 
2131       Status = PciBridgeEnumerator (Bridge);
2132 
2133       if (EFI_ERROR (Status)) {
2134         return Status;
2135       }
2136     }
2137 
2138     Status = StartPciDevicesOnBridge (
2139               RootBridgeHandle,
2140               Bridge,
2141               RemainingDevicePath,
2142               NumberOfChildren,
2143               ChildHandleBuffer
2144               );
2145 
2146     return Status;
2147   }
2148 
2149   if (Operation == EfiPciHotplugRequestRemove) {
2150 
2151     if (*NumberOfChildren == 0) {
2152       //
2153       // Remove all devices on the bridge
2154       //
2155       RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2156       return EFI_SUCCESS;
2157 
2158     }
2159 
2160     for (Index = 0; Index < *NumberOfChildren; Index++) {
2161       //
2162       // De register all the pci device
2163       //
2164       Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2165 
2166       if (EFI_ERROR (Status)) {
2167         return Status;
2168       }
2169 
2170     }
2171     //
2172     // End for
2173     //
2174     return EFI_SUCCESS;
2175   }
2176 
2177   return EFI_SUCCESS;
2178 }
2179 
2180 /**
2181   Search hostbridge according to given handle
2182 
2183   @param RootBridgeHandle  Host bridge handle.
2184 
2185   @retval TRUE             Found host bridge handle.
2186   @retval FALSE            Not found hot bridge handle.
2187 
2188 **/
2189 BOOLEAN
SearchHostBridgeHandle(IN EFI_HANDLE RootBridgeHandle)2190 SearchHostBridgeHandle (
2191   IN EFI_HANDLE RootBridgeHandle
2192   )
2193 {
2194   EFI_HANDLE                      HostBridgeHandle;
2195   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2196   UINTN                           Index;
2197   EFI_STATUS                      Status;
2198 
2199   //
2200   // Get the rootbridge Io protocol to find the host bridge handle
2201   //
2202   Status = gBS->OpenProtocol (
2203                   RootBridgeHandle,
2204                   &gEfiPciRootBridgeIoProtocolGuid,
2205                   (VOID **) &PciRootBridgeIo,
2206                   gPciBusDriverBinding.DriverBindingHandle,
2207                   RootBridgeHandle,
2208                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2209                   );
2210 
2211   if (EFI_ERROR (Status)) {
2212     return FALSE;
2213   }
2214 
2215   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2216   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2217     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2218       return TRUE;
2219     }
2220   }
2221 
2222   return FALSE;
2223 }
2224 
2225 /**
2226   Add host bridge handle to global variable for enumerating.
2227 
2228   @param HostBridgeHandle   Host bridge handle.
2229 
2230   @retval EFI_SUCCESS       Successfully added host bridge.
2231   @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
2232                             has been in host bridge list.
2233 
2234 **/
2235 EFI_STATUS
AddHostBridgeEnumerator(IN EFI_HANDLE HostBridgeHandle)2236 AddHostBridgeEnumerator (
2237   IN EFI_HANDLE HostBridgeHandle
2238   )
2239 {
2240   UINTN Index;
2241 
2242   if (HostBridgeHandle == NULL) {
2243     return EFI_ABORTED;
2244   }
2245 
2246   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2247     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2248       return EFI_ABORTED;
2249     }
2250   }
2251 
2252   if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2253     gPciHostBrigeHandles[Index] = HostBridgeHandle;
2254     gPciHostBridgeNumber++;
2255   }
2256 
2257   return EFI_SUCCESS;
2258 }
2259 
2260