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