• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   PCI eunmeration implementation on entire PCI bus system for PCI Bus module.
3 
4 Copyright (c) 2006 - 2016, 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 resource 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 construct 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 available.
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_END_TAG_DESCRIPTOR));
1311     if (Configuration == NULL) {
1312       return EFI_OUT_OF_RESOURCES;
1313     }
1314 
1315     PtrEnd            = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration);
1316     PtrEnd->Desc      = ACPI_END_TAG_DESCRIPTOR;
1317     PtrEnd->Checksum  = 0;
1318   }
1319 
1320   *Config = Configuration;
1321 
1322   return EFI_SUCCESS;
1323 }
1324 
1325 /**
1326   Get resource base from an acpi configuration descriptor.
1327 
1328   @param Config       An acpi configuration descriptor.
1329   @param IoBase       Output of I/O resource base address.
1330   @param Mem32Base    Output of 32-bit memory base address.
1331   @param PMem32Base   Output of 32-bit prefetchable memory base address.
1332   @param Mem64Base    Output of 64-bit memory base address.
1333   @param PMem64Base   Output of 64-bit prefetchable memory base address.
1334 
1335 **/
1336 VOID
GetResourceBase(IN VOID * Config,OUT UINT64 * IoBase,OUT UINT64 * Mem32Base,OUT UINT64 * PMem32Base,OUT UINT64 * Mem64Base,OUT UINT64 * PMem64Base)1337 GetResourceBase (
1338   IN VOID     *Config,
1339   OUT UINT64  *IoBase,
1340   OUT UINT64  *Mem32Base,
1341   OUT UINT64  *PMem32Base,
1342   OUT UINT64  *Mem64Base,
1343   OUT UINT64  *PMem64Base
1344   )
1345 {
1346   UINT8                             *Temp;
1347   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1348   UINT64                            ResStatus;
1349 
1350   ASSERT (Config != NULL);
1351 
1352   *IoBase     = 0xFFFFFFFFFFFFFFFFULL;
1353   *Mem32Base  = 0xFFFFFFFFFFFFFFFFULL;
1354   *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1355   *Mem64Base  = 0xFFFFFFFFFFFFFFFFULL;
1356   *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1357 
1358   Temp        = (UINT8 *) Config;
1359 
1360   while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1361 
1362     Ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1363     ResStatus = Ptr->AddrTranslationOffset;
1364 
1365     if (ResStatus == EFI_RESOURCE_SATISFIED) {
1366 
1367       switch (Ptr->ResType) {
1368 
1369       //
1370       // Memory type aperture
1371       //
1372       case 0:
1373 
1374         //
1375         // Check to see the granularity
1376         //
1377         if (Ptr->AddrSpaceGranularity == 32) {
1378           if ((Ptr->SpecificFlag & 0x06) != 0) {
1379             *PMem32Base = Ptr->AddrRangeMin;
1380           } else {
1381             *Mem32Base = Ptr->AddrRangeMin;
1382           }
1383         }
1384 
1385         if (Ptr->AddrSpaceGranularity == 64) {
1386           if ((Ptr->SpecificFlag & 0x06) != 0) {
1387             *PMem64Base = Ptr->AddrRangeMin;
1388           } else {
1389             *Mem64Base = Ptr->AddrRangeMin;
1390           }
1391         }
1392         break;
1393 
1394       case 1:
1395 
1396         //
1397         // Io type aperture
1398         //
1399         *IoBase = Ptr->AddrRangeMin;
1400         break;
1401 
1402       default:
1403         break;
1404 
1405       }
1406       //
1407       // End switch
1408       //
1409     }
1410     //
1411     // End for
1412     //
1413     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1414   }
1415 }
1416 
1417 /**
1418   Enumerate pci bridge, allocate resource and determine attribute
1419   for devices on this bridge.
1420 
1421   @param BridgeDev    Pointer to instance of bridge device.
1422 
1423   @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1424   @retval other       Failed to enumerate.
1425 
1426 **/
1427 EFI_STATUS
PciBridgeEnumerator(IN PCI_IO_DEVICE * BridgeDev)1428 PciBridgeEnumerator (
1429   IN PCI_IO_DEVICE                                     *BridgeDev
1430   )
1431 {
1432   UINT8               SubBusNumber;
1433   UINT8               StartBusNumber;
1434   EFI_PCI_IO_PROTOCOL *PciIo;
1435   EFI_STATUS          Status;
1436 
1437   SubBusNumber    = 0;
1438   StartBusNumber  = 0;
1439   PciIo           = &(BridgeDev->PciIo);
1440   Status          = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1441 
1442   if (EFI_ERROR (Status)) {
1443     return Status;
1444   }
1445 
1446   Status = PciAssignBusNumber (
1447             BridgeDev,
1448             StartBusNumber,
1449             &SubBusNumber
1450             );
1451 
1452   if (EFI_ERROR (Status)) {
1453     return Status;
1454   }
1455 
1456   Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1457 
1458   if (EFI_ERROR (Status)) {
1459     return Status;
1460   }
1461 
1462   Status = PciBridgeResourceAllocator (BridgeDev);
1463 
1464   if (EFI_ERROR (Status)) {
1465     return Status;
1466   }
1467 
1468   Status = DetermineDeviceAttribute (BridgeDev);
1469 
1470   if (EFI_ERROR (Status)) {
1471     return Status;
1472   }
1473 
1474   return EFI_SUCCESS;
1475 
1476 }
1477 
1478 /**
1479   Allocate all kinds of resource for PCI bridge.
1480 
1481   @param  Bridge      Pointer to bridge instance.
1482 
1483   @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1484   @retval other       Failed to allocate resource for bridge.
1485 
1486 **/
1487 EFI_STATUS
PciBridgeResourceAllocator(IN PCI_IO_DEVICE * Bridge)1488 PciBridgeResourceAllocator (
1489   IN PCI_IO_DEVICE  *Bridge
1490   )
1491 {
1492   PCI_RESOURCE_NODE *IoBridge;
1493   PCI_RESOURCE_NODE *Mem32Bridge;
1494   PCI_RESOURCE_NODE *PMem32Bridge;
1495   PCI_RESOURCE_NODE *Mem64Bridge;
1496   PCI_RESOURCE_NODE *PMem64Bridge;
1497   UINT64            IoBase;
1498   UINT64            Mem32Base;
1499   UINT64            PMem32Base;
1500   UINT64            Mem64Base;
1501   UINT64            PMem64Base;
1502   EFI_STATUS        Status;
1503 
1504   IoBridge = CreateResourceNode (
1505                Bridge,
1506                0,
1507                Bridge->BridgeIoAlignment,
1508                0,
1509                PciBarTypeIo16,
1510                PciResUsageTypical
1511                );
1512 
1513   Mem32Bridge = CreateResourceNode (
1514                   Bridge,
1515                   0,
1516                   0xFFFFF,
1517                   0,
1518                   PciBarTypeMem32,
1519                   PciResUsageTypical
1520                   );
1521 
1522   PMem32Bridge = CreateResourceNode (
1523                    Bridge,
1524                    0,
1525                    0xFFFFF,
1526                    0,
1527                    PciBarTypePMem32,
1528                    PciResUsageTypical
1529                    );
1530 
1531   Mem64Bridge = CreateResourceNode (
1532                   Bridge,
1533                   0,
1534                   0xFFFFF,
1535                   0,
1536                   PciBarTypeMem64,
1537                   PciResUsageTypical
1538                   );
1539 
1540   PMem64Bridge = CreateResourceNode (
1541                    Bridge,
1542                    0,
1543                    0xFFFFF,
1544                    0,
1545                    PciBarTypePMem64,
1546                    PciResUsageTypical
1547                    );
1548 
1549   //
1550   // Create resourcemap by going through all the devices subject to this root bridge
1551   //
1552   CreateResourceMap (
1553     Bridge,
1554     IoBridge,
1555     Mem32Bridge,
1556     PMem32Bridge,
1557     Mem64Bridge,
1558     PMem64Bridge
1559     );
1560 
1561   Status = GetResourceBaseFromBridge (
1562              Bridge,
1563              &IoBase,
1564              &Mem32Base,
1565              &PMem32Base,
1566              &Mem64Base,
1567              &PMem64Base
1568              );
1569 
1570   if (EFI_ERROR (Status)) {
1571     return Status;
1572   }
1573 
1574   //
1575   // Program IO resources
1576   //
1577   ProgramResource (
1578     IoBase,
1579     IoBridge
1580     );
1581 
1582   //
1583   // Program Mem32 resources
1584   //
1585   ProgramResource (
1586     Mem32Base,
1587     Mem32Bridge
1588     );
1589 
1590   //
1591   // Program PMem32 resources
1592   //
1593   ProgramResource (
1594     PMem32Base,
1595     PMem32Bridge
1596     );
1597 
1598   //
1599   // Program Mem64 resources
1600   //
1601   ProgramResource (
1602     Mem64Base,
1603     Mem64Bridge
1604     );
1605 
1606   //
1607   // Program PMem64 resources
1608   //
1609   ProgramResource (
1610     PMem64Base,
1611     PMem64Bridge
1612     );
1613 
1614   DestroyResourceTree (IoBridge);
1615   DestroyResourceTree (Mem32Bridge);
1616   DestroyResourceTree (PMem32Bridge);
1617   DestroyResourceTree (PMem64Bridge);
1618   DestroyResourceTree (Mem64Bridge);
1619 
1620   gBS->FreePool (IoBridge);
1621   gBS->FreePool (Mem32Bridge);
1622   gBS->FreePool (PMem32Bridge);
1623   gBS->FreePool (PMem64Bridge);
1624   gBS->FreePool (Mem64Bridge);
1625 
1626   return EFI_SUCCESS;
1627 }
1628 
1629 /**
1630   Get resource base address for a pci bridge device.
1631 
1632   @param Bridge     Given Pci driver instance.
1633   @param IoBase     Output for base address of I/O type resource.
1634   @param Mem32Base  Output for base address of 32-bit memory type resource.
1635   @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1636   @param Mem64Base  Output for base address of 64-bit memory type resource.
1637   @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1638 
1639   @retval EFI_SUCCESS           Successfully got resource base address.
1640   @retval EFI_OUT_OF_RESOURCES  PCI bridge is not available.
1641 
1642 **/
1643 EFI_STATUS
GetResourceBaseFromBridge(IN PCI_IO_DEVICE * Bridge,OUT UINT64 * IoBase,OUT UINT64 * Mem32Base,OUT UINT64 * PMem32Base,OUT UINT64 * Mem64Base,OUT UINT64 * PMem64Base)1644 GetResourceBaseFromBridge (
1645   IN  PCI_IO_DEVICE *Bridge,
1646   OUT UINT64        *IoBase,
1647   OUT UINT64        *Mem32Base,
1648   OUT UINT64        *PMem32Base,
1649   OUT UINT64        *Mem64Base,
1650   OUT UINT64        *PMem64Base
1651   )
1652 {
1653   if (!Bridge->Allocated) {
1654     return EFI_OUT_OF_RESOURCES;
1655   }
1656 
1657   *IoBase     = gAllOne;
1658   *Mem32Base  = gAllOne;
1659   *PMem32Base = gAllOne;
1660   *Mem64Base  = gAllOne;
1661   *PMem64Base = gAllOne;
1662 
1663   if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1664 
1665     if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
1666       *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1667     }
1668 
1669     if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
1670       *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1671     }
1672 
1673     if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
1674       *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1675     }
1676 
1677     if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
1678       *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1679     } else {
1680       *PMem64Base = gAllOne;
1681     }
1682 
1683   }
1684 
1685   if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1686     if (Bridge->PciBar[P2C_IO_1].Length > 0) {
1687       *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1688     } else {
1689       if (Bridge->PciBar[P2C_IO_2].Length > 0) {
1690         *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1691       }
1692     }
1693 
1694     if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
1695       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1696         *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1697       }
1698 
1699       if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1700         *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1701       }
1702     }
1703 
1704     if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
1705       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1706         *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1707       }
1708 
1709       if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1710         *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1711       }
1712     }
1713   }
1714 
1715   return EFI_SUCCESS;
1716 }
1717 
1718 /**
1719    These are the notifications from the PCI bus driver that it is about to enter a certain
1720    phase of the PCI enumeration process.
1721 
1722    This member function can be used to notify the host bridge driver to perform specific actions,
1723    including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1724    Eight notification points are defined at this time. See belows:
1725    EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures and internal data
1726                                           structures. The PCI enumerator should issue this notification
1727                                           before starting a fresh enumeration process. Enumeration cannot
1728                                           be restarted after sending any other notification such as
1729                                           EfiPciHostBridgeBeginBusAllocation.
1730    EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to begin. No specific action is
1731                                           required here. This notification can be used to perform any
1732                                           chipset-specific programming.
1733    EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming phase is complete. No
1734                                           specific action is required here. This notification can be used to
1735                                           perform any chipset-specific programming.
1736    EfiPciHostBridgeBeginResourceAllocation
1737                                           The resource allocation phase is about to begin. No specific
1738                                           action is required here. This notification can be used to perform
1739                                           any chipset-specific programming.
1740    EfiPciHostBridgeAllocateResources      Allocates resources per previously submitted requests for all the PCI
1741                                           root bridges. These resource settings are returned on the next call to
1742                                           GetProposedResources(). Before calling NotifyPhase() with a Phase of
1743                                           EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1744                                           for gathering I/O and memory requests for
1745                                           all the PCI root bridges and submitting these requests using
1746                                           SubmitResources(). This function pads the resource amount
1747                                           to suit the root bridge hardware, takes care of dependencies between
1748                                           the PCI root bridges, and calls the Global Coherency Domain (GCD)
1749                                           with the allocation request. In the case of padding, the allocated range
1750                                           could be bigger than what was requested.
1751    EfiPciHostBridgeSetResources           Programs the host bridge hardware to decode previously allocated
1752                                           resources (proposed resources) for all the PCI root bridges. After the
1753                                           hardware is programmed, reassigning resources will not be supported.
1754                                           The bus settings are not affected.
1755    EfiPciHostBridgeFreeResources          Deallocates resources that were previously allocated for all the PCI
1756                                           root bridges and resets the I/O and memory apertures to their initial
1757                                           state. The bus settings are not affected. If the request to allocate
1758                                           resources fails, the PCI enumerator can use this notification to
1759                                           deallocate previous resources, adjust the requests, and retry
1760                                           allocation.
1761    EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is completed. No specific action is
1762                                           required here. This notification can be used to perform any chipsetspecific
1763                                           programming.
1764 
1765    @param[in] PciResAlloc         The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1766    @param[in] Phase               The phase during enumeration
1767 
1768    @retval EFI_NOT_READY          This phase cannot be entered at this time. For example, this error
1769                                   is valid for a Phase of EfiPciHostBridgeAllocateResources if
1770                                   SubmitResources() has not been called for one or more
1771                                   PCI root bridges before this call
1772    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error. This error is valid
1773                                   for a Phase of EfiPciHostBridgeSetResources.
1774    @retval EFI_INVALID_PARAMETER  Invalid phase parameter
1775    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1776                                   This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1777                                   previously submitted resource requests cannot be fulfilled or
1778                                   were only partially fulfilled.
1779    @retval EFI_SUCCESS            The notification was accepted without any errors.
1780 
1781 **/
1782 EFI_STATUS
NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * PciResAlloc,EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)1783 NotifyPhase (
1784   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
1785   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE       Phase
1786   )
1787 {
1788   EFI_HANDLE                      HostBridgeHandle;
1789   EFI_HANDLE                      RootBridgeHandle;
1790   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1791   EFI_STATUS                      Status;
1792 
1793   HostBridgeHandle  = NULL;
1794   RootBridgeHandle  = NULL;
1795   if (gPciPlatformProtocol != NULL) {
1796     //
1797     // Get Host Bridge Handle.
1798     //
1799     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1800 
1801     //
1802     // Get the rootbridge Io protocol to find the host bridge handle
1803     //
1804     Status = gBS->HandleProtocol (
1805                     RootBridgeHandle,
1806                     &gEfiPciRootBridgeIoProtocolGuid,
1807                     (VOID **) &PciRootBridgeIo
1808                     );
1809 
1810     if (EFI_ERROR (Status)) {
1811       return EFI_NOT_FOUND;
1812     }
1813 
1814     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1815 
1816     //
1817     // Call PlatformPci::PlatformNotify() if the protocol is present.
1818     //
1819     gPciPlatformProtocol->PlatformNotify (
1820                             gPciPlatformProtocol,
1821                             HostBridgeHandle,
1822                             Phase,
1823                             ChipsetEntry
1824                             );
1825   } else if (gPciOverrideProtocol != NULL){
1826     //
1827     // Get Host Bridge Handle.
1828     //
1829     PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1830 
1831     //
1832     // Get the rootbridge Io protocol to find the host bridge handle
1833     //
1834     Status = gBS->HandleProtocol (
1835                     RootBridgeHandle,
1836                     &gEfiPciRootBridgeIoProtocolGuid,
1837                     (VOID **) &PciRootBridgeIo
1838                     );
1839 
1840     if (EFI_ERROR (Status)) {
1841       return EFI_NOT_FOUND;
1842     }
1843 
1844     HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1845 
1846     //
1847     // Call PlatformPci::PhaseNotify() if the protocol is present.
1848     //
1849     gPciOverrideProtocol->PlatformNotify (
1850                             gPciOverrideProtocol,
1851                             HostBridgeHandle,
1852                             Phase,
1853                             ChipsetEntry
1854                             );
1855   }
1856 
1857   Status = PciResAlloc->NotifyPhase (
1858                           PciResAlloc,
1859                           Phase
1860                           );
1861 
1862   if (gPciPlatformProtocol != NULL) {
1863     //
1864     // Call PlatformPci::PlatformNotify() if the protocol is present.
1865     //
1866     gPciPlatformProtocol->PlatformNotify (
1867                             gPciPlatformProtocol,
1868                             HostBridgeHandle,
1869                             Phase,
1870                             ChipsetExit
1871                             );
1872 
1873   } else if (gPciOverrideProtocol != NULL) {
1874     //
1875     // Call PlatformPci::PhaseNotify() if the protocol is present.
1876     //
1877     gPciOverrideProtocol->PlatformNotify (
1878                             gPciOverrideProtocol,
1879                             HostBridgeHandle,
1880                             Phase,
1881                             ChipsetExit
1882                             );
1883   }
1884 
1885   return Status;
1886 }
1887 
1888 /**
1889   Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1890   stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1891   PCI controllers before enumeration.
1892 
1893   This function is called during the PCI enumeration process. No specific action is expected from this
1894   member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1895   enumeration.
1896 
1897   @param Bridge            Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1898   @param Bus               The bus number of the pci device.
1899   @param Device            The device number of the pci device.
1900   @param Func              The function number of the pci device.
1901   @param Phase             The phase of the PCI device enumeration.
1902 
1903   @retval EFI_SUCCESS              The requested parameters were returned.
1904   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge handle.
1905   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined in
1906                                    EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1907   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error. The PCI enumerator should
1908                                    not enumerate this device, including its child devices if it is a PCI-to-PCI
1909                                    bridge.
1910 
1911 **/
1912 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)1913 PreprocessController (
1914   IN PCI_IO_DEVICE                                    *Bridge,
1915   IN UINT8                                            Bus,
1916   IN UINT8                                            Device,
1917   IN UINT8                                            Func,
1918   IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE     Phase
1919   )
1920 {
1921   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       RootBridgePciAddress;
1922   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *PciResAlloc;
1923   EFI_HANDLE                                        RootBridgeHandle;
1924   EFI_HANDLE                                        HostBridgeHandle;
1925   EFI_STATUS                                        Status;
1926 
1927   //
1928   // Get the host bridge handle
1929   //
1930   HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1931 
1932   //
1933   // Get the pci host bridge resource allocation protocol
1934   //
1935   Status = gBS->OpenProtocol (
1936                   HostBridgeHandle,
1937                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1938                   (VOID **) &PciResAlloc,
1939                   NULL,
1940                   NULL,
1941                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1942                   );
1943 
1944   if (EFI_ERROR (Status)) {
1945     return EFI_UNSUPPORTED;
1946   }
1947 
1948   //
1949   // Get Root Brige Handle
1950   //
1951   while (Bridge->Parent != NULL) {
1952     Bridge = Bridge->Parent;
1953   }
1954 
1955   RootBridgeHandle                      = Bridge->Handle;
1956 
1957   RootBridgePciAddress.Register         = 0;
1958   RootBridgePciAddress.Function         = Func;
1959   RootBridgePciAddress.Device           = Device;
1960   RootBridgePciAddress.Bus              = Bus;
1961   RootBridgePciAddress.ExtendedRegister = 0;
1962 
1963   if (gPciPlatformProtocol != NULL) {
1964     //
1965     // Call PlatformPci::PrepController() if the protocol is present.
1966     //
1967     gPciPlatformProtocol->PlatformPrepController (
1968                             gPciPlatformProtocol,
1969                             HostBridgeHandle,
1970                             RootBridgeHandle,
1971                             RootBridgePciAddress,
1972                             Phase,
1973                             ChipsetEntry
1974                             );
1975   } else if (gPciOverrideProtocol != NULL) {
1976     //
1977     // Call PlatformPci::PrepController() if the protocol is present.
1978     //
1979     gPciOverrideProtocol->PlatformPrepController (
1980                             gPciOverrideProtocol,
1981                             HostBridgeHandle,
1982                             RootBridgeHandle,
1983                             RootBridgePciAddress,
1984                             Phase,
1985                             ChipsetEntry
1986                             );
1987   }
1988 
1989   Status = PciResAlloc->PreprocessController (
1990                           PciResAlloc,
1991                           RootBridgeHandle,
1992                           RootBridgePciAddress,
1993                           Phase
1994                           );
1995 
1996   if (gPciPlatformProtocol != NULL) {
1997     //
1998     // Call PlatformPci::PrepController() if the protocol is present.
1999     //
2000     gPciPlatformProtocol->PlatformPrepController (
2001                             gPciPlatformProtocol,
2002                             HostBridgeHandle,
2003                             RootBridgeHandle,
2004                             RootBridgePciAddress,
2005                             Phase,
2006                             ChipsetExit
2007                             );
2008   } else if (gPciOverrideProtocol != NULL) {
2009     //
2010     // Call PlatformPci::PrepController() if the protocol is present.
2011     //
2012     gPciOverrideProtocol->PlatformPrepController (
2013                             gPciOverrideProtocol,
2014                             HostBridgeHandle,
2015                             RootBridgeHandle,
2016                             RootBridgePciAddress,
2017                             Phase,
2018                             ChipsetExit
2019                             );
2020   }
2021 
2022   return EFI_SUCCESS;
2023 }
2024 
2025 /**
2026   This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
2027   happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
2028 
2029   @param This                 A pointer to the hot plug request protocol.
2030   @param Operation            The operation the PCI bus driver is requested to make.
2031   @param Controller           The handle of the hot-plug controller.
2032   @param RemainingDevicePath  The remaining device path for the PCI-like hot-plug device.
2033   @param NumberOfChildren     The number of child handles.
2034                               For a add operation, it is an output parameter.
2035                               For a remove operation, it's an input parameter.
2036   @param ChildHandleBuffer    The buffer which contains the child handles.
2037 
2038   @retval EFI_INVALID_PARAMETER  Operation is not a legal value.
2039                                  Controller is NULL or not a valid handle.
2040                                  NumberOfChildren is NULL.
2041                                  ChildHandleBuffer is NULL while Operation is add.
2042   @retval EFI_OUT_OF_RESOURCES   There are no enough resources to start the devices.
2043   @retval EFI_NOT_FOUND          Can not find bridge according to controller handle.
2044   @retval EFI_SUCCESS            The handles for the specified device have been created or destroyed
2045                                  as requested, and for an add operation, the new handles are
2046                                  returned in ChildHandleBuffer.
2047 **/
2048 EFI_STATUS
2049 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)2050 PciHotPlugRequestNotify (
2051   IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
2052   IN EFI_PCI_HOTPLUG_OPERATION        Operation,
2053   IN EFI_HANDLE                       Controller,
2054   IN EFI_DEVICE_PATH_PROTOCOL         * RemainingDevicePath OPTIONAL,
2055   IN OUT UINT8                        *NumberOfChildren,
2056   IN OUT EFI_HANDLE                   * ChildHandleBuffer
2057   )
2058 {
2059   PCI_IO_DEVICE       *Bridge;
2060   PCI_IO_DEVICE       *Temp;
2061   EFI_PCI_IO_PROTOCOL *PciIo;
2062   UINTN               Index;
2063   EFI_HANDLE          RootBridgeHandle;
2064   EFI_STATUS          Status;
2065 
2066   //
2067   // Check input parameter validity
2068   //
2069   if ((Controller == NULL) || (NumberOfChildren == NULL)){
2070     return EFI_INVALID_PARAMETER;
2071   }
2072 
2073   if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
2074     return EFI_INVALID_PARAMETER;
2075   }
2076 
2077   if (Operation == EfiPciHotPlugRequestAdd){
2078     if (ChildHandleBuffer == NULL) {
2079       return EFI_INVALID_PARAMETER;
2080     }
2081   } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
2082     if (ChildHandleBuffer == NULL) {
2083       return EFI_INVALID_PARAMETER;
2084     }
2085   }
2086 
2087   Status = gBS->OpenProtocol (
2088                   Controller,
2089                   &gEfiPciIoProtocolGuid,
2090                   (VOID **) &PciIo,
2091                   gPciBusDriverBinding.DriverBindingHandle,
2092                   Controller,
2093                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2094                   );
2095 
2096   if (EFI_ERROR (Status)) {
2097     return EFI_NOT_FOUND;
2098   }
2099 
2100   Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2101 
2102   //
2103   // Get root bridge handle
2104   //
2105   Temp = Bridge;
2106   while (Temp->Parent != NULL) {
2107     Temp = Temp->Parent;
2108   }
2109 
2110   RootBridgeHandle = Temp->Handle;
2111 
2112   if (Operation == EfiPciHotPlugRequestAdd) {
2113     //
2114     // Report Status Code to indicate hot plug happens
2115     //
2116     REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2117       EFI_PROGRESS_CODE,
2118       (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
2119       Temp->DevicePath
2120       );
2121 
2122     if (NumberOfChildren != NULL) {
2123       *NumberOfChildren = 0;
2124     }
2125 
2126     if (IsListEmpty (&Bridge->ChildList)) {
2127 
2128       Status = PciBridgeEnumerator (Bridge);
2129 
2130       if (EFI_ERROR (Status)) {
2131         return Status;
2132       }
2133     }
2134 
2135     Status = StartPciDevicesOnBridge (
2136               RootBridgeHandle,
2137               Bridge,
2138               RemainingDevicePath,
2139               NumberOfChildren,
2140               ChildHandleBuffer
2141               );
2142 
2143     return Status;
2144   }
2145 
2146   if (Operation == EfiPciHotplugRequestRemove) {
2147 
2148     if (*NumberOfChildren == 0) {
2149       //
2150       // Remove all devices on the bridge
2151       //
2152       RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2153       return EFI_SUCCESS;
2154 
2155     }
2156 
2157     for (Index = 0; Index < *NumberOfChildren; Index++) {
2158       //
2159       // De register all the pci device
2160       //
2161       Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2162 
2163       if (EFI_ERROR (Status)) {
2164         return Status;
2165       }
2166 
2167     }
2168     //
2169     // End for
2170     //
2171     return EFI_SUCCESS;
2172   }
2173 
2174   return EFI_SUCCESS;
2175 }
2176 
2177 /**
2178   Search hostbridge according to given handle
2179 
2180   @param RootBridgeHandle  Host bridge handle.
2181 
2182   @retval TRUE             Found host bridge handle.
2183   @retval FALSE            Not found hot bridge handle.
2184 
2185 **/
2186 BOOLEAN
SearchHostBridgeHandle(IN EFI_HANDLE RootBridgeHandle)2187 SearchHostBridgeHandle (
2188   IN EFI_HANDLE RootBridgeHandle
2189   )
2190 {
2191   EFI_HANDLE                      HostBridgeHandle;
2192   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2193   UINTN                           Index;
2194   EFI_STATUS                      Status;
2195 
2196   //
2197   // Get the rootbridge Io protocol to find the host bridge handle
2198   //
2199   Status = gBS->OpenProtocol (
2200                   RootBridgeHandle,
2201                   &gEfiPciRootBridgeIoProtocolGuid,
2202                   (VOID **) &PciRootBridgeIo,
2203                   gPciBusDriverBinding.DriverBindingHandle,
2204                   RootBridgeHandle,
2205                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
2206                   );
2207 
2208   if (EFI_ERROR (Status)) {
2209     return FALSE;
2210   }
2211 
2212   HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2213   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2214     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2215       return TRUE;
2216     }
2217   }
2218 
2219   return FALSE;
2220 }
2221 
2222 /**
2223   Add host bridge handle to global variable for enumerating.
2224 
2225   @param HostBridgeHandle   Host bridge handle.
2226 
2227   @retval EFI_SUCCESS       Successfully added host bridge.
2228   @retval EFI_ABORTED       Host bridge is NULL, or given host bridge
2229                             has been in host bridge list.
2230 
2231 **/
2232 EFI_STATUS
AddHostBridgeEnumerator(IN EFI_HANDLE HostBridgeHandle)2233 AddHostBridgeEnumerator (
2234   IN EFI_HANDLE HostBridgeHandle
2235   )
2236 {
2237   UINTN Index;
2238 
2239   if (HostBridgeHandle == NULL) {
2240     return EFI_ABORTED;
2241   }
2242 
2243   for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2244     if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2245       return EFI_ABORTED;
2246     }
2247   }
2248 
2249   if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2250     gPciHostBrigeHandles[Index] = HostBridgeHandle;
2251     gPciHostBridgeNumber++;
2252   }
2253 
2254   return EFI_SUCCESS;
2255 }
2256 
2257