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