]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciBusDxe / PciEnumerator.c
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
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
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
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
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
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
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
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
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
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
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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