]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciBusDxe/PciEnumerator.c
bd256cfc8564e334bc338419a6429d59a03397b4
[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 - 2009, Intel Corporation
5 All rights reserved. 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_PC_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_PMEM64_DECODE_SUPPORTED;
479 }
480
481 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
482 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
483 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
484
485 return EFI_SUCCESS;
486 }
487
488 /**
489 Get Max Option Rom size on specified bridge.
490
491 @param Bridge Given bridge device instance.
492
493 @return Max size of option rom needed.
494
495 **/
496 UINT64
497 GetMaxOptionRomSize (
498 IN PCI_IO_DEVICE *Bridge
499 )
500 {
501 LIST_ENTRY *CurrentLink;
502 PCI_IO_DEVICE *Temp;
503 UINT64 MaxOptionRomSize;
504 UINT64 TempOptionRomSize;
505
506 MaxOptionRomSize = 0;
507
508 //
509 // Go through bridges to reach all devices
510 //
511 CurrentLink = Bridge->ChildList.ForwardLink;
512 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
513 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
514 if (!IsListEmpty (&Temp->ChildList)) {
515
516 //
517 // Get max option rom size under this bridge
518 //
519 TempOptionRomSize = GetMaxOptionRomSize (Temp);
520
521 //
522 // Compare with the option rom size of the bridge
523 // Get the larger one
524 //
525 if (Temp->RomSize > TempOptionRomSize) {
526 TempOptionRomSize = Temp->RomSize;
527 }
528
529 } else {
530
531 //
532 // For devices get the rom size directly
533 //
534 TempOptionRomSize = Temp->RomSize;
535 }
536
537 //
538 // Get the largest rom size on this bridge
539 //
540 if (TempOptionRomSize > MaxOptionRomSize) {
541 MaxOptionRomSize = TempOptionRomSize;
542 }
543
544 CurrentLink = CurrentLink->ForwardLink;
545 }
546
547 return MaxOptionRomSize;
548 }
549
550 /**
551 Process attributes of devices on this host bridge
552
553 @param PciResAlloc Protocol instance of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL.
554
555 @retval EFI_SUCCESS Successfully process attribute.
556 @retval EFI_NOT_FOUND Can not find the specific root bridge device.
557 @retval other Failed to determine the root bridge device's attribute.
558
559 **/
560 EFI_STATUS
561 PciHostBridgeDeviceAttribute (
562 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc
563 )
564 {
565 EFI_HANDLE RootBridgeHandle;
566 PCI_IO_DEVICE *RootBridgeDev;
567 EFI_STATUS Status;
568
569 RootBridgeHandle = NULL;
570
571 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
572
573 //
574 // Get RootBridg Device by handle
575 //
576 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
577
578 if (RootBridgeDev == NULL) {
579 return EFI_NOT_FOUND;
580 }
581
582 //
583 // Set the attributes for devcies behind the Root Bridge
584 //
585 Status = DetermineDeviceAttribute (RootBridgeDev);
586 if (EFI_ERROR (Status)) {
587 return Status;
588 }
589
590 }
591
592 return EFI_SUCCESS;
593 }
594
595 /**
596 Get resource allocation status from the ACPI resource descriptor.
597
598 @param AcpiConfig Point to Acpi configuration table.
599 @param IoResStatus Return the status of I/O resource.
600 @param Mem32ResStatus Return the status of 32-bit Memory resource.
601 @param PMem32ResStatus Return the status of 32-bit Prefetchable Memory resource.
602 @param Mem64ResStatus Return the status of 64-bit Memory resource.
603 @param PMem64ResStatus Return the status of 64-bit Prefetchable Memory resource.
604
605 **/
606 VOID
607 GetResourceAllocationStatus (
608 VOID *AcpiConfig,
609 OUT UINT64 *IoResStatus,
610 OUT UINT64 *Mem32ResStatus,
611 OUT UINT64 *PMem32ResStatus,
612 OUT UINT64 *Mem64ResStatus,
613 OUT UINT64 *PMem64ResStatus
614 )
615 {
616 UINT8 *Temp;
617 UINT64 ResStatus;
618 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;
619
620 Temp = (UINT8 *) AcpiConfig;
621
622 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
623
624 ACPIAddressDesc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
625 ResStatus = ACPIAddressDesc->AddrTranslationOffset;
626
627 switch (ACPIAddressDesc->ResType) {
628 case 0:
629 if (ACPIAddressDesc->AddrSpaceGranularity == 32) {
630 if (ACPIAddressDesc->SpecificFlag == 0x06) {
631 //
632 // Pmem32
633 //
634 *PMem32ResStatus = ResStatus;
635 } else {
636 //
637 // Mem32
638 //
639 *Mem32ResStatus = ResStatus;
640 }
641 }
642
643 if (ACPIAddressDesc->AddrSpaceGranularity == 64) {
644 if (ACPIAddressDesc->SpecificFlag == 0x06) {
645 //
646 // PMem64
647 //
648 *PMem64ResStatus = ResStatus;
649 } else {
650 //
651 // Mem64
652 //
653 *Mem64ResStatus = ResStatus;
654 }
655 }
656
657 break;
658
659 case 1:
660 //
661 // Io
662 //
663 *IoResStatus = ResStatus;
664 break;
665
666 default:
667 break;
668 }
669
670 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
671 }
672 }
673
674 /**
675 Remove a PCI device from device pool and mark its bar.
676
677 @param PciDevice Instance of Pci device.
678
679 @retval EFI_SUCCESS Successfully remove the PCI device.
680 @retval EFI_ABORTED Pci device is a root bridge or a PCI-PCI bridge.
681
682 **/
683 EFI_STATUS
684 RejectPciDevice (
685 IN PCI_IO_DEVICE *PciDevice
686 )
687 {
688 PCI_IO_DEVICE *Bridge;
689 PCI_IO_DEVICE *Temp;
690 LIST_ENTRY *CurrentLink;
691
692 //
693 // Remove the padding resource from a bridge
694 //
695 if ( IS_PCI_BRIDGE(&PciDevice->Pci) &&
696 PciDevice->ResourcePaddingDescriptors != NULL ) {
697 FreePool (PciDevice->ResourcePaddingDescriptors);
698 PciDevice->ResourcePaddingDescriptors = NULL;
699 return EFI_SUCCESS;
700 }
701
702 //
703 // Skip RB and PPB
704 //
705 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {
706 return EFI_ABORTED;
707 }
708
709 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
710 //
711 // Get the root bridge device
712 //
713 Bridge = PciDevice;
714 while (Bridge->Parent != NULL) {
715 Bridge = Bridge->Parent;
716 }
717
718 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
719
720 //
721 // Mark its bar
722 //
723 InitializeP2C (PciDevice);
724 }
725
726 //
727 // Remove the device
728 //
729 Bridge = PciDevice->Parent;
730 CurrentLink = Bridge->ChildList.ForwardLink;
731 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
732 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
733 if (Temp == PciDevice) {
734 InitializePciDevice (Temp);
735 RemoveEntryList (CurrentLink);
736 FreePciDevice (Temp);
737 return EFI_SUCCESS;
738 }
739
740 CurrentLink = CurrentLink->ForwardLink;
741 }
742
743 return EFI_ABORTED;
744 }
745
746 /**
747 Determine whethter a PCI device can be rejected.
748
749 @param PciResNode Pointer to Pci resource node instance.
750
751 @retval TRUE The PCI device can be rejected.
752 @retval TRUE The PCI device cannot be rejected.
753
754 **/
755 BOOLEAN
756 IsRejectiveDevice (
757 IN PCI_RESOURCE_NODE *PciResNode
758 )
759 {
760 PCI_IO_DEVICE *Temp;
761
762 Temp = PciResNode->PciDev;
763
764 //
765 // Ensure the device is present
766 //
767 if (Temp == NULL) {
768 return FALSE;
769 }
770
771 //
772 // PPB and RB should go ahead
773 //
774 if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {
775 return TRUE;
776 }
777
778 //
779 // Skip device on Bus0
780 //
781 if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {
782 return FALSE;
783 }
784
785 //
786 // Skip VGA
787 //
788 if (IS_PCI_VGA (&Temp->Pci)) {
789 return FALSE;
790 }
791
792 return TRUE;
793 }
794
795 /**
796 Compare two resource nodes and get the larger resource consumer.
797
798 @param PciResNode1 resource node 1 want to be compared
799 @param PciResNode2 resource node 2 want to be compared
800
801 @return Larger resource node.
802
803 **/
804 PCI_RESOURCE_NODE *
805 GetLargerConsumerDevice (
806 IN PCI_RESOURCE_NODE *PciResNode1,
807 IN PCI_RESOURCE_NODE *PciResNode2
808 )
809 {
810 if (PciResNode2 == NULL) {
811 return PciResNode1;
812 }
813
814 if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \
815 && (PciResNode2->ResourceUsage != PciResUsagePadding) )
816 {
817 return PciResNode1;
818 }
819
820 if (PciResNode1 == NULL) {
821 return PciResNode2;
822 }
823
824 if ((PciResNode1->Length) > (PciResNode2->Length)) {
825 return PciResNode1;
826 }
827
828 return PciResNode2;
829 }
830
831
832 /**
833 Get the max resource consumer in the host resource pool.
834
835 @param ResPool Pointer to resource pool node.
836
837 @return The max resource consumer in the host resource pool.
838
839 **/
840 PCI_RESOURCE_NODE *
841 GetMaxResourceConsumerDevice (
842 IN PCI_RESOURCE_NODE *ResPool
843 )
844 {
845 PCI_RESOURCE_NODE *Temp;
846 LIST_ENTRY *CurrentLink;
847 PCI_RESOURCE_NODE *PciResNode;
848 PCI_RESOURCE_NODE *PPBResNode;
849
850 PciResNode = NULL;
851
852 CurrentLink = ResPool->ChildList.ForwardLink;
853 while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {
854
855 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
856
857 if (!IsRejectiveDevice (Temp)) {
858 CurrentLink = CurrentLink->ForwardLink;
859 continue;
860 }
861
862 if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \
863 && (Temp->ResourceUsage != PciResUsagePadding))
864 {
865 PPBResNode = GetMaxResourceConsumerDevice (Temp);
866 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
867 } else {
868 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
869 }
870
871 CurrentLink = CurrentLink->ForwardLink;
872 }
873
874 return PciResNode;
875 }
876
877 /**
878 Adjust host bridge allocation so as to reduce resource requirement
879
880 @param IoPool Pointer to instance of I/O resource Node.
881 @param Mem32Pool Pointer to instance of 32-bit memory resource Node.
882 @param PMem32Pool Pointer to instance of 32-bit Prefetchable memory resource node.
883 @param Mem64Pool Pointer to instance of 64-bit memory resource node.
884 @param PMem64Pool Pointer to instance of 64-bit Prefetchable memory resource node.
885 @param IoResStatus Status of I/O resource Node.
886 @param Mem32ResStatus Status of 32-bit memory resource Node.
887 @param PMem32ResStatus Status of 32-bit Prefetchable memory resource node.
888 @param Mem64ResStatus Status of 64-bit memory resource node.
889 @param PMem64ResStatus Status of 64-bit Prefetchable memory resource node.
890
891 @retval EFI_SUCCESS Successfully adjusted resoruce on host bridge.
892 @retval EFI_ABORTED Host bridge hasn't this resource type or no resource be adjusted.
893
894 **/
895 EFI_STATUS
896 PciHostBridgeAdjustAllocation (
897 IN PCI_RESOURCE_NODE *IoPool,
898 IN PCI_RESOURCE_NODE *Mem32Pool,
899 IN PCI_RESOURCE_NODE *PMem32Pool,
900 IN PCI_RESOURCE_NODE *Mem64Pool,
901 IN PCI_RESOURCE_NODE *PMem64Pool,
902 IN UINT64 IoResStatus,
903 IN UINT64 Mem32ResStatus,
904 IN UINT64 PMem32ResStatus,
905 IN UINT64 Mem64ResStatus,
906 IN UINT64 PMem64ResStatus
907 )
908 {
909 BOOLEAN AllocationAjusted;
910 PCI_RESOURCE_NODE *PciResNode;
911 PCI_RESOURCE_NODE *ResPool[5];
912 PCI_IO_DEVICE *RemovedPciDev[5];
913 UINT64 ResStatus[5];
914 UINTN RemovedPciDevNum;
915 UINTN DevIndex;
916 UINTN ResType;
917 EFI_STATUS Status;
918 EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA_PAYLOAD AllocFailExtendedData;
919
920 PciResNode = NULL;
921 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
922 RemovedPciDevNum = 0;
923
924 ResPool[0] = IoPool;
925 ResPool[1] = Mem32Pool;
926 ResPool[2] = PMem32Pool;
927 ResPool[3] = Mem64Pool;
928 ResPool[4] = PMem64Pool;
929
930 ResStatus[0] = IoResStatus;
931 ResStatus[1] = Mem32ResStatus;
932 ResStatus[2] = PMem32ResStatus;
933 ResStatus[3] = Mem64ResStatus;
934 ResStatus[4] = PMem64ResStatus;
935
936 AllocationAjusted = FALSE;
937
938 for (ResType = 0; ResType < 5; ResType++) {
939
940 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
941 continue;
942 }
943
944 if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {
945 //
946 // Host bridge hasn't this resource type
947 //
948 return EFI_ABORTED;
949 }
950
951 //
952 // Hostbridge hasn't enough resource
953 //
954 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
955 if (PciResNode == NULL) {
956 continue;
957 }
958
959 //
960 // Check if the device has been removed before
961 //
962 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
963 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
964 break;
965 }
966 }
967
968 if (DevIndex != RemovedPciDevNum) {
969 continue;
970 }
971
972 //
973 // Remove the device if it isn't in the array
974 //
975 Status = RejectPciDevice (PciResNode->PciDev);
976 if (Status == EFI_SUCCESS) {
977
978 //
979 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
980 //
981 //
982 // Have no way to get ReqRes, AllocRes & Bar here
983 //
984 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
985 AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL);
986 AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath;
987 AllocFailExtendedData.Bar = PciResNode->Bar;
988
989 REPORT_STATUS_CODE_WITH_EXTENDED_DATA (
990 EFI_PROGRESS_CODE,
991 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
992 (VOID *) &AllocFailExtendedData,
993 sizeof (AllocFailExtendedData)
994 );
995
996 //
997 // Add it to the array and indicate at least a device has been rejected
998 //
999 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
1000 AllocationAjusted = TRUE;
1001 }
1002 }
1003 //
1004 // End for
1005 //
1006
1007 if (AllocationAjusted) {
1008 return EFI_SUCCESS;
1009 } else {
1010 return EFI_ABORTED;
1011 }
1012 }
1013
1014 /**
1015 Summary requests for all resource type, and contruct ACPI resource
1016 requestor instance.
1017
1018 @param Bridge detecting bridge
1019 @param IoNode Pointer to instance of I/O resource Node
1020 @param Mem32Node Pointer to instance of 32-bit memory resource Node
1021 @param PMem32Node Pointer to instance of 32-bit Pmemory resource node
1022 @param Mem64Node Pointer to instance of 64-bit memory resource node
1023 @param PMem64Node Pointer to instance of 64-bit Pmemory resource node
1024 @param Config Output buffer holding new constructed APCI resource requestor
1025
1026 @retval EFI_SUCCESS Successfully constructed ACPI resource.
1027 @retval EFI_OUT_OF_RESOURCES No memory availabe.
1028
1029 **/
1030 EFI_STATUS
1031 ConstructAcpiResourceRequestor (
1032 IN PCI_IO_DEVICE *Bridge,
1033 IN PCI_RESOURCE_NODE *IoNode,
1034 IN PCI_RESOURCE_NODE *Mem32Node,
1035 IN PCI_RESOURCE_NODE *PMem32Node,
1036 IN PCI_RESOURCE_NODE *Mem64Node,
1037 IN PCI_RESOURCE_NODE *PMem64Node,
1038 OUT VOID **Config
1039 )
1040 {
1041 UINT8 NumConfig;
1042 UINT8 Aperture;
1043 UINT8 *Configuration;
1044 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1045 EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd;
1046
1047 NumConfig = 0;
1048 Aperture = 0;
1049
1050 *Config = NULL;
1051
1052 //
1053 // if there is io request, add to the io aperture
1054 //
1055 if (ResourceRequestExisted (IoNode)) {
1056 NumConfig++;
1057 Aperture |= 0x01;
1058 }
1059
1060 //
1061 // if there is mem32 request, add to the mem32 aperture
1062 //
1063 if (ResourceRequestExisted (Mem32Node)) {
1064 NumConfig++;
1065 Aperture |= 0x02;
1066 }
1067
1068 //
1069 // if there is pmem32 request, add to the pmem32 aperture
1070 //
1071 if (ResourceRequestExisted (PMem32Node)) {
1072 NumConfig++;
1073 Aperture |= 0x04;
1074 }
1075
1076 //
1077 // if there is mem64 request, add to the mem64 aperture
1078 //
1079 if (ResourceRequestExisted (Mem64Node)) {
1080 NumConfig++;
1081 Aperture |= 0x08;
1082 }
1083
1084 //
1085 // if there is pmem64 request, add to the pmem64 aperture
1086 //
1087 if (ResourceRequestExisted (PMem64Node)) {
1088 NumConfig++;
1089 Aperture |= 0x10;
1090 }
1091
1092 if (NumConfig != 0) {
1093
1094 //
1095 // If there is at least one type of resource request,
1096 // allocate a acpi resource node
1097 //
1098 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1099 if (Configuration == NULL) {
1100 return EFI_OUT_OF_RESOURCES;
1101 }
1102
1103 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1104
1105 //
1106 // Deal with io aperture
1107 //
1108 if ((Aperture & 0x01) != 0) {
1109 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1110 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1111 //
1112 // Io
1113 //
1114 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1115 //
1116 // non ISA range
1117 //
1118 Ptr->SpecificFlag = 1;
1119 Ptr->AddrLen = IoNode->Length;
1120 Ptr->AddrRangeMax = IoNode->Alignment;
1121
1122 Ptr++;
1123 }
1124 //
1125 // Deal with mem32 aperture
1126 //
1127 if ((Aperture & 0x02) != 0) {
1128 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1129 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1130 //
1131 // Mem
1132 //
1133 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1134 //
1135 // Nonprefechable
1136 //
1137 Ptr->SpecificFlag = 0;
1138 //
1139 // 32 bit
1140 //
1141 Ptr->AddrSpaceGranularity = 32;
1142 Ptr->AddrLen = Mem32Node->Length;
1143 Ptr->AddrRangeMax = Mem32Node->Alignment;
1144
1145 Ptr++;
1146 }
1147
1148 //
1149 // Deal with Pmem32 aperture
1150 //
1151 if ((Aperture & 0x04) != 0) {
1152 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1153 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1154 //
1155 // Mem
1156 //
1157 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1158 //
1159 // prefechable
1160 //
1161 Ptr->SpecificFlag = 0x6;
1162 //
1163 // 32 bit
1164 //
1165 Ptr->AddrSpaceGranularity = 32;
1166 Ptr->AddrLen = PMem32Node->Length;
1167 Ptr->AddrRangeMax = PMem32Node->Alignment;
1168
1169 Ptr++;
1170 }
1171 //
1172 // Deal with mem64 aperture
1173 //
1174 if ((Aperture & 0x08) != 0) {
1175 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1176 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1177 //
1178 // Mem
1179 //
1180 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1181 //
1182 // nonprefechable
1183 //
1184 Ptr->SpecificFlag = 0;
1185 //
1186 // 64 bit
1187 //
1188 Ptr->AddrSpaceGranularity = 64;
1189 Ptr->AddrLen = Mem64Node->Length;
1190 Ptr->AddrRangeMax = Mem64Node->Alignment;
1191
1192 Ptr++;
1193 }
1194 //
1195 // Deal with Pmem64 aperture
1196 //
1197 if ((Aperture & 0x10) != 0) {
1198 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1199 Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1200 //
1201 // Mem
1202 //
1203 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1204 //
1205 // prefechable
1206 //
1207 Ptr->SpecificFlag = 0x06;
1208 //
1209 // 64 bit
1210 //
1211 Ptr->AddrSpaceGranularity = 64;
1212 Ptr->AddrLen = PMem64Node->Length;
1213 Ptr->AddrRangeMax = PMem64Node->Alignment;
1214
1215 Ptr++;
1216 }
1217
1218 //
1219 // put the checksum
1220 //
1221 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr;
1222
1223 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1224 PtrEnd->Checksum = 0;
1225
1226 } else {
1227
1228 //
1229 // If there is no resource request
1230 //
1231 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1232 if (Configuration == NULL) {
1233 return EFI_OUT_OF_RESOURCES;
1234 }
1235
1236 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration);
1237 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1238
1239 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Ptr + 1);
1240 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1241 PtrEnd->Checksum = 0;
1242 }
1243
1244 *Config = Configuration;
1245
1246 return EFI_SUCCESS;
1247 }
1248
1249 /**
1250 Get resource base from an acpi configuration descriptor.
1251
1252 @param Config An acpi configuration descriptor.
1253 @param IoBase Output of I/O resource base address.
1254 @param Mem32Base Output of 32-bit memory base address.
1255 @param PMem32Base Output of 32-bit prefetchable memory base address.
1256 @param Mem64Base Output of 64-bit memory base address.
1257 @param PMem64Base Output of 64-bit prefetchable memory base address.
1258
1259 **/
1260 VOID
1261 GetResourceBase (
1262 IN VOID *Config,
1263 OUT UINT64 *IoBase,
1264 OUT UINT64 *Mem32Base,
1265 OUT UINT64 *PMem32Base,
1266 OUT UINT64 *Mem64Base,
1267 OUT UINT64 *PMem64Base
1268 )
1269 {
1270 UINT8 *Temp;
1271 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr;
1272 UINT64 ResStatus;
1273
1274 ASSERT (Config != NULL);
1275
1276 *IoBase = 0xFFFFFFFFFFFFFFFFULL;
1277 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
1278 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1279 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
1280 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1281
1282 Temp = (UINT8 *) Config;
1283
1284 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1285
1286 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1287 ResStatus = Ptr->AddrTranslationOffset;
1288
1289 if (ResStatus == EFI_RESOURCE_SATISFIED) {
1290
1291 switch (Ptr->ResType) {
1292
1293 //
1294 // Memory type aperture
1295 //
1296 case 0:
1297
1298 //
1299 // Check to see the granularity
1300 //
1301 if (Ptr->AddrSpaceGranularity == 32) {
1302 if ((Ptr->SpecificFlag & 0x06) != 0) {
1303 *PMem32Base = Ptr->AddrRangeMin;
1304 } else {
1305 *Mem32Base = Ptr->AddrRangeMin;
1306 }
1307 }
1308
1309 if (Ptr->AddrSpaceGranularity == 64) {
1310 if ((Ptr->SpecificFlag & 0x06) != 0) {
1311 *PMem64Base = Ptr->AddrRangeMin;
1312 } else {
1313 *Mem64Base = Ptr->AddrRangeMin;
1314 }
1315 }
1316 break;
1317
1318 case 1:
1319
1320 //
1321 // Io type aperture
1322 //
1323 *IoBase = Ptr->AddrRangeMin;
1324 break;
1325
1326 default:
1327 break;
1328
1329 }
1330 //
1331 // End switch
1332 //
1333 }
1334 //
1335 // End for
1336 //
1337 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1338 }
1339 }
1340
1341 /**
1342 Enumerate pci bridge, allocate resource and determine attribute
1343 for devices on this bridge.
1344
1345 @param BridgeDev Pointer to instance of bridge device.
1346
1347 @retval EFI_SUCCESS Successfully enumerated PCI bridge.
1348 @retval other Failed to enumerate.
1349
1350 **/
1351 EFI_STATUS
1352 PciBridgeEnumerator (
1353 IN PCI_IO_DEVICE *BridgeDev
1354 )
1355 {
1356 UINT8 SubBusNumber;
1357 UINT8 StartBusNumber;
1358 EFI_PCI_IO_PROTOCOL *PciIo;
1359 EFI_STATUS Status;
1360
1361 SubBusNumber = 0;
1362 StartBusNumber = 0;
1363 PciIo = &(BridgeDev->PciIo);
1364 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1365
1366 if (EFI_ERROR (Status)) {
1367 return Status;
1368 }
1369
1370 Status = PciAssignBusNumber (
1371 BridgeDev,
1372 StartBusNumber,
1373 &SubBusNumber
1374 );
1375
1376 if (EFI_ERROR (Status)) {
1377 return Status;
1378 }
1379
1380 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1381
1382 if (EFI_ERROR (Status)) {
1383 return Status;
1384 }
1385
1386 Status = PciBridgeResourceAllocator (BridgeDev);
1387
1388 if (EFI_ERROR (Status)) {
1389 return Status;
1390 }
1391
1392 Status = DetermineDeviceAttribute (BridgeDev);
1393
1394 if (EFI_ERROR (Status)) {
1395 return Status;
1396 }
1397
1398 return EFI_SUCCESS;
1399
1400 }
1401
1402 /**
1403 Allocate all kinds of resource for PCI bridge.
1404
1405 @param Bridge Pointer to bridge instance.
1406
1407 @retval EFI_SUCCESS Successfully allocated resource for PCI bridge.
1408 @retval other Failed to allocate resource for bridge.
1409
1410 **/
1411 EFI_STATUS
1412 PciBridgeResourceAllocator (
1413 IN PCI_IO_DEVICE *Bridge
1414 )
1415 {
1416 PCI_RESOURCE_NODE *IoBridge;
1417 PCI_RESOURCE_NODE *Mem32Bridge;
1418 PCI_RESOURCE_NODE *PMem32Bridge;
1419 PCI_RESOURCE_NODE *Mem64Bridge;
1420 PCI_RESOURCE_NODE *PMem64Bridge;
1421 UINT64 IoBase;
1422 UINT64 Mem32Base;
1423 UINT64 PMem32Base;
1424 UINT64 Mem64Base;
1425 UINT64 PMem64Base;
1426 EFI_STATUS Status;
1427
1428 IoBridge = CreateResourceNode (
1429 Bridge,
1430 0,
1431 0xFFF,
1432 0,
1433 PciBarTypeIo16,
1434 PciResUsageTypical
1435 );
1436
1437 Mem32Bridge = CreateResourceNode (
1438 Bridge,
1439 0,
1440 0xFFFFF,
1441 0,
1442 PciBarTypeMem32,
1443 PciResUsageTypical
1444 );
1445
1446 PMem32Bridge = CreateResourceNode (
1447 Bridge,
1448 0,
1449 0xFFFFF,
1450 0,
1451 PciBarTypePMem32,
1452 PciResUsageTypical
1453 );
1454
1455 Mem64Bridge = CreateResourceNode (
1456 Bridge,
1457 0,
1458 0xFFFFF,
1459 0,
1460 PciBarTypeMem64,
1461 PciResUsageTypical
1462 );
1463
1464 PMem64Bridge = CreateResourceNode (
1465 Bridge,
1466 0,
1467 0xFFFFF,
1468 0,
1469 PciBarTypePMem64,
1470 PciResUsageTypical
1471 );
1472
1473 //
1474 // Create resourcemap by going through all the devices subject to this root bridge
1475 //
1476 CreateResourceMap (
1477 Bridge,
1478 IoBridge,
1479 Mem32Bridge,
1480 PMem32Bridge,
1481 Mem64Bridge,
1482 PMem64Bridge
1483 );
1484
1485 Status = GetResourceBaseFromBridge (
1486 Bridge,
1487 &IoBase,
1488 &Mem32Base,
1489 &PMem32Base,
1490 &Mem64Base,
1491 &PMem64Base
1492 );
1493
1494 if (EFI_ERROR (Status)) {
1495 return Status;
1496 }
1497
1498 //
1499 // Program IO resources
1500 //
1501 ProgramResource (
1502 IoBase,
1503 IoBridge
1504 );
1505
1506 //
1507 // Program Mem32 resources
1508 //
1509 ProgramResource (
1510 Mem32Base,
1511 Mem32Bridge
1512 );
1513
1514 //
1515 // Program PMem32 resources
1516 //
1517 ProgramResource (
1518 PMem32Base,
1519 PMem32Bridge
1520 );
1521
1522 //
1523 // Program Mem64 resources
1524 //
1525 ProgramResource (
1526 Mem64Base,
1527 Mem64Bridge
1528 );
1529
1530 //
1531 // Program PMem64 resources
1532 //
1533 ProgramResource (
1534 PMem64Base,
1535 PMem64Bridge
1536 );
1537
1538 DestroyResourceTree (IoBridge);
1539 DestroyResourceTree (Mem32Bridge);
1540 DestroyResourceTree (PMem32Bridge);
1541 DestroyResourceTree (PMem64Bridge);
1542 DestroyResourceTree (Mem64Bridge);
1543
1544 gBS->FreePool (IoBridge);
1545 gBS->FreePool (Mem32Bridge);
1546 gBS->FreePool (PMem32Bridge);
1547 gBS->FreePool (PMem64Bridge);
1548 gBS->FreePool (Mem64Bridge);
1549
1550 return EFI_SUCCESS;
1551 }
1552
1553 /**
1554 Get resource base address for a pci bridge device.
1555
1556 @param Bridge Given Pci driver instance.
1557 @param IoBase Output for base address of I/O type resource.
1558 @param Mem32Base Output for base address of 32-bit memory type resource.
1559 @param PMem32Base Ooutput for base address of 32-bit Pmemory type resource.
1560 @param Mem64Base Output for base address of 64-bit memory type resource.
1561 @param PMem64Base Output for base address of 64-bit Pmemory type resource.
1562
1563 @retval EFI_SUCCESS Successfully got resource base address.
1564 @retval EFI_OUT_OF_RESOURCES PCI bridge is not available.
1565
1566 **/
1567 EFI_STATUS
1568 GetResourceBaseFromBridge (
1569 IN PCI_IO_DEVICE *Bridge,
1570 OUT UINT64 *IoBase,
1571 OUT UINT64 *Mem32Base,
1572 OUT UINT64 *PMem32Base,
1573 OUT UINT64 *Mem64Base,
1574 OUT UINT64 *PMem64Base
1575 )
1576 {
1577 if (!Bridge->Allocated) {
1578 return EFI_OUT_OF_RESOURCES;
1579 }
1580
1581 *IoBase = gAllOne;
1582 *Mem32Base = gAllOne;
1583 *PMem32Base = gAllOne;
1584 *Mem64Base = gAllOne;
1585 *PMem64Base = gAllOne;
1586
1587 if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1588
1589 if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
1590 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1591 }
1592
1593 if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
1594 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1595 }
1596
1597 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
1598 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1599 }
1600
1601 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
1602 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1603 } else {
1604 *PMem64Base = gAllOne;
1605 }
1606
1607 }
1608
1609 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1610 if (Bridge->PciBar[P2C_IO_1].Length > 0) {
1611 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1612 } else {
1613 if (Bridge->PciBar[P2C_IO_2].Length > 0) {
1614 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1615 }
1616 }
1617
1618 if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
1619 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1620 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1621 }
1622
1623 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1624 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1625 }
1626 }
1627
1628 if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
1629 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1630 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1631 }
1632
1633 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1634 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1635 }
1636 }
1637 }
1638
1639 return EFI_SUCCESS;
1640 }
1641
1642 /**
1643 These are the notifications from the PCI bus driver that it is about to enter a certain
1644 phase of the PCI enumeration process.
1645
1646 This member function can be used to notify the host bridge driver to perform specific actions,
1647 including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
1648 Eight notification points are defined at this time. See belows:
1649 EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
1650 structures. The PCI enumerator should issue this notification
1651 before starting a fresh enumeration process. Enumeration cannot
1652 be restarted after sending any other notification such as
1653 EfiPciHostBridgeBeginBusAllocation.
1654 EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
1655 required here. This notification can be used to perform any
1656 chipset-specific programming.
1657 EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
1658 specific action is required here. This notification can be used to
1659 perform any chipset-specific programming.
1660 EfiPciHostBridgeBeginResourceAllocation
1661 The resource allocation phase is about to begin. No specific
1662 action is required here. This notification can be used to perform
1663 any chipset-specific programming.
1664 EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
1665 root bridges. These resource settings are returned on the next call to
1666 GetProposedResources(). Before calling NotifyPhase() with a Phase of
1667 EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
1668 for gathering I/O and memory requests for
1669 all the PCI root bridges and submitting these requests using
1670 SubmitResources(). This function pads the resource amount
1671 to suit the root bridge hardware, takes care of dependencies between
1672 the PCI root bridges, and calls the Global Coherency Domain (GCD)
1673 with the allocation request. In the case of padding, the allocated range
1674 could be bigger than what was requested.
1675 EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
1676 resources (proposed resources) for all the PCI root bridges. After the
1677 hardware is programmed, reassigning resources will not be supported.
1678 The bus settings are not affected.
1679 EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
1680 root bridges and resets the I/O and memory apertures to their initial
1681 state. The bus settings are not affected. If the request to allocate
1682 resources fails, the PCI enumerator can use this notification to
1683 deallocate previous resources, adjust the requests, and retry
1684 allocation.
1685 EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
1686 required here. This notification can be used to perform any chipsetspecific
1687 programming.
1688
1689 @param[in] PciResAlloc The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1690 @param[in] Phase The phase during enumeration
1691
1692 @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
1693 is valid for a Phase of EfiPciHostBridgeAllocateResources if
1694 SubmitResources() has not been called for one or more
1695 PCI root bridges before this call
1696 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
1697 for a Phase of EfiPciHostBridgeSetResources.
1698 @retval EFI_INVALID_PARAMETER Invalid phase parameter
1699 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
1700 This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
1701 previously submitted resource requests cannot be fulfilled or
1702 were only partially fulfilled.
1703 @retval EFI_SUCCESS The notification was accepted without any errors.
1704
1705 **/
1706 EFI_STATUS
1707 NotifyPhase (
1708 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc,
1709 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
1710 )
1711 {
1712 EFI_HANDLE HostBridgeHandle;
1713 EFI_HANDLE RootBridgeHandle;
1714 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1715 EFI_STATUS Status;
1716
1717 HostBridgeHandle = NULL;
1718 RootBridgeHandle = NULL;
1719 if (gPciPlatformProtocol != NULL) {
1720 //
1721 // Get Host Bridge Handle.
1722 //
1723 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1724
1725 //
1726 // Get the rootbridge Io protocol to find the host bridge handle
1727 //
1728 Status = gBS->HandleProtocol (
1729 RootBridgeHandle,
1730 &gEfiPciRootBridgeIoProtocolGuid,
1731 (VOID **) &PciRootBridgeIo
1732 );
1733
1734 if (EFI_ERROR (Status)) {
1735 return EFI_NOT_FOUND;
1736 }
1737
1738 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1739
1740 //
1741 // Call PlatformPci::PlatformNotify() if the protocol is present.
1742 //
1743 gPciPlatformProtocol->PlatformNotify (
1744 gPciPlatformProtocol,
1745 HostBridgeHandle,
1746 Phase,
1747 ChipsetEntry
1748 );
1749 } else if (gPciOverrideProtocol != 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::PhaseNotify() if the protocol is present.
1772 //
1773 gPciOverrideProtocol->PlatformNotify (
1774 gPciOverrideProtocol,
1775 HostBridgeHandle,
1776 Phase,
1777 ChipsetEntry
1778 );
1779 }
1780
1781 Status = PciResAlloc->NotifyPhase (
1782 PciResAlloc,
1783 Phase
1784 );
1785
1786 if (gPciPlatformProtocol != NULL) {
1787 //
1788 // Call PlatformPci::PlatformNotify() if the protocol is present.
1789 //
1790 gPciPlatformProtocol->PlatformNotify (
1791 gPciPlatformProtocol,
1792 HostBridgeHandle,
1793 Phase,
1794 ChipsetExit
1795 );
1796
1797 } else if (gPciOverrideProtocol != NULL) {
1798 //
1799 // Call PlatformPci::PhaseNotify() if the protocol is present.
1800 //
1801 gPciOverrideProtocol->PlatformNotify (
1802 gPciOverrideProtocol,
1803 HostBridgeHandle,
1804 Phase,
1805 ChipsetExit
1806 );
1807 }
1808
1809 return EFI_SUCCESS;
1810 }
1811
1812 /**
1813 Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
1814 stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
1815 PCI controllers before enumeration.
1816
1817 This function is called during the PCI enumeration process. No specific action is expected from this
1818 member function. It allows the host bridge driver to preinitialize individual PCI controllers before
1819 enumeration.
1820
1821 @param Bridge Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
1822 @param Bus The bus number of the pci device.
1823 @param Device The device number of the pci device.
1824 @param Func The function number of the pci device.
1825 @param Phase The phase of the PCI device enumeration.
1826
1827 @retval EFI_SUCCESS The requested parameters were returned.
1828 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
1829 @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
1830 EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1831 @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
1832 not enumerate this device, including its child devices if it is a PCI-to-PCI
1833 bridge.
1834
1835 **/
1836 EFI_STATUS
1837 PreprocessController (
1838 IN PCI_IO_DEVICE *Bridge,
1839 IN UINT8 Bus,
1840 IN UINT8 Device,
1841 IN UINT8 Func,
1842 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1843 )
1844 {
1845 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress;
1846 EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc;
1847 EFI_HANDLE RootBridgeHandle;
1848 EFI_HANDLE HostBridgeHandle;
1849 EFI_STATUS Status;
1850
1851 //
1852 // Get the host bridge handle
1853 //
1854 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1855
1856 //
1857 // Get the pci host bridge resource allocation protocol
1858 //
1859 Status = gBS->OpenProtocol (
1860 HostBridgeHandle,
1861 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1862 (VOID **) &PciResAlloc,
1863 NULL,
1864 NULL,
1865 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1866 );
1867
1868 if (EFI_ERROR (Status)) {
1869 return EFI_UNSUPPORTED;
1870 }
1871
1872 //
1873 // Get Root Brige Handle
1874 //
1875 while (Bridge->Parent != NULL) {
1876 Bridge = Bridge->Parent;
1877 }
1878
1879 RootBridgeHandle = Bridge->Handle;
1880
1881 RootBridgePciAddress.Register = 0;
1882 RootBridgePciAddress.Function = Func;
1883 RootBridgePciAddress.Device = Device;
1884 RootBridgePciAddress.Bus = Bus;
1885 RootBridgePciAddress.ExtendedRegister = 0;
1886
1887 if (gPciPlatformProtocol != NULL) {
1888 //
1889 // Call PlatformPci::PrepController() if the protocol is present.
1890 //
1891 gPciPlatformProtocol->PlatformPrepController (
1892 gPciPlatformProtocol,
1893 HostBridgeHandle,
1894 RootBridgeHandle,
1895 RootBridgePciAddress,
1896 Phase,
1897 ChipsetEntry
1898 );
1899 } else if (gPciOverrideProtocol != NULL) {
1900 //
1901 // Call PlatformPci::PrepController() if the protocol is present.
1902 //
1903 gPciOverrideProtocol->PlatformPrepController (
1904 gPciOverrideProtocol,
1905 HostBridgeHandle,
1906 RootBridgeHandle,
1907 RootBridgePciAddress,
1908 Phase,
1909 ChipsetEntry
1910 );
1911 }
1912
1913 Status = PciResAlloc->PreprocessController (
1914 PciResAlloc,
1915 RootBridgeHandle,
1916 RootBridgePciAddress,
1917 Phase
1918 );
1919
1920 if (gPciPlatformProtocol != NULL) {
1921 //
1922 // Call PlatformPci::PrepController() if the protocol is present.
1923 //
1924 gPciPlatformProtocol->PlatformPrepController (
1925 gPciPlatformProtocol,
1926 HostBridgeHandle,
1927 RootBridgeHandle,
1928 RootBridgePciAddress,
1929 Phase,
1930 ChipsetExit
1931 );
1932 } else if (gPciOverrideProtocol != NULL) {
1933 //
1934 // Call PlatformPci::PrepController() if the protocol is present.
1935 //
1936 gPciOverrideProtocol->PlatformPrepController (
1937 gPciOverrideProtocol,
1938 HostBridgeHandle,
1939 RootBridgeHandle,
1940 RootBridgePciAddress,
1941 Phase,
1942 ChipsetExit
1943 );
1944 }
1945
1946 return EFI_SUCCESS;
1947 }
1948
1949 /**
1950 This function allows the PCI bus driver to be notified to act as requested when a hot-plug event has
1951 happened on the hot-plug controller. Currently, the operations include add operation and remove operation..
1952
1953 @param This A pointer to the hot plug request protocol.
1954 @param Operation The operation the PCI bus driver is requested to make.
1955 @param Controller The handle of the hot-plug controller.
1956 @param RemainingDevicePath The remaining device path for the PCI-like hot-plug device.
1957 @param NumberOfChildren The number of child handles.
1958 For a add operation, it is an output parameter.
1959 For a remove operation, it's an input parameter.
1960 @param ChildHandleBuffer The buffer which contains the child handles.
1961
1962 @retval EFI_INVALID_PARAMETER Operation is not a legal value.
1963 Controller is NULL or not a valid handle.
1964 NumberOfChildren is NULL.
1965 ChildHandleBuffer is NULL while Operation is add.
1966 @retval EFI_OUT_OF_RESOURCES There are no enough resources to start the devices.
1967 @retval EFI_NOT_FOUND Can not find bridge according to controller handle.
1968 @retval EFI_SUCCESS The handles for the specified device have been created or destroyed
1969 as requested, and for an add operation, the new handles are
1970 returned in ChildHandleBuffer.
1971 **/
1972 EFI_STATUS
1973 EFIAPI
1974 PciHotPlugRequestNotify (
1975 IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This,
1976 IN EFI_PCI_HOTPLUG_OPERATION Operation,
1977 IN EFI_HANDLE Controller,
1978 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,
1979 IN OUT UINT8 *NumberOfChildren,
1980 IN OUT EFI_HANDLE * ChildHandleBuffer
1981 )
1982 {
1983 PCI_IO_DEVICE *Bridge;
1984 PCI_IO_DEVICE *Temp;
1985 EFI_PCI_IO_PROTOCOL *PciIo;
1986 UINTN Index;
1987 EFI_HANDLE RootBridgeHandle;
1988 EFI_STATUS Status;
1989
1990 //
1991 // Check input parameter validity
1992 //
1993 if ((Controller == NULL) || (NumberOfChildren == NULL)){
1994 return EFI_INVALID_PARAMETER;
1995 }
1996
1997 if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
1998 return EFI_INVALID_PARAMETER;
1999 }
2000
2001 if (Operation == EfiPciHotPlugRequestAdd){
2002 if (ChildHandleBuffer == NULL) {
2003 return EFI_INVALID_PARAMETER;
2004 }
2005 } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
2006 if (ChildHandleBuffer == NULL) {
2007 return EFI_INVALID_PARAMETER;
2008 }
2009 }
2010
2011 Status = gBS->OpenProtocol (
2012 Controller,
2013 &gEfiPciIoProtocolGuid,
2014 (VOID **) &PciIo,
2015 gPciBusDriverBinding.DriverBindingHandle,
2016 Controller,
2017 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2018 );
2019
2020 if (EFI_ERROR (Status)) {
2021 return EFI_NOT_FOUND;
2022 }
2023
2024 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2025
2026 //
2027 // Get root bridge handle
2028 //
2029 Temp = Bridge;
2030 while (Temp->Parent != NULL) {
2031 Temp = Temp->Parent;
2032 }
2033
2034 RootBridgeHandle = Temp->Handle;
2035
2036 if (Operation == EfiPciHotPlugRequestAdd) {
2037
2038 if (NumberOfChildren != NULL) {
2039 *NumberOfChildren = 0;
2040 }
2041
2042 if (IsListEmpty (&Bridge->ChildList)) {
2043
2044 Status = PciBridgeEnumerator (Bridge);
2045
2046 if (EFI_ERROR (Status)) {
2047 return Status;
2048 }
2049 }
2050
2051 Status = StartPciDevicesOnBridge (
2052 RootBridgeHandle,
2053 Bridge,
2054 RemainingDevicePath,
2055 NumberOfChildren,
2056 ChildHandleBuffer
2057 );
2058
2059 return Status;
2060 }
2061
2062 if (Operation == EfiPciHotplugRequestRemove) {
2063
2064 if (*NumberOfChildren == 0) {
2065 //
2066 // Remove all devices on the bridge
2067 //
2068 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2069 return EFI_SUCCESS;
2070
2071 }
2072
2073 for (Index = 0; Index < *NumberOfChildren; Index++) {
2074 //
2075 // De register all the pci device
2076 //
2077 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2078
2079 if (EFI_ERROR (Status)) {
2080 return Status;
2081 }
2082
2083 }
2084 //
2085 // End for
2086 //
2087 return EFI_SUCCESS;
2088 }
2089
2090 return EFI_SUCCESS;
2091 }
2092
2093 /**
2094 Search hostbridge according to given handle
2095
2096 @param RootBridgeHandle Host bridge handle.
2097
2098 @retval TRUE Found host bridge handle.
2099 @retval FALSE Not found hot bridge handle.
2100
2101 **/
2102 BOOLEAN
2103 SearchHostBridgeHandle (
2104 IN EFI_HANDLE RootBridgeHandle
2105 )
2106 {
2107 EFI_HANDLE HostBridgeHandle;
2108 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2109 UINTN Index;
2110 EFI_STATUS Status;
2111
2112 //
2113 // Get the rootbridge Io protocol to find the host bridge handle
2114 //
2115 Status = gBS->OpenProtocol (
2116 RootBridgeHandle,
2117 &gEfiPciRootBridgeIoProtocolGuid,
2118 (VOID **) &PciRootBridgeIo,
2119 gPciBusDriverBinding.DriverBindingHandle,
2120 RootBridgeHandle,
2121 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2122 );
2123
2124 if (EFI_ERROR (Status)) {
2125 return FALSE;
2126 }
2127
2128 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2129 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2130 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2131 return TRUE;
2132 }
2133 }
2134
2135 return FALSE;
2136 }
2137
2138 /**
2139 Add host bridge handle to global variable for enumerating.
2140
2141 @param HostBridgeHandle Host bridge handle.
2142
2143 @retval EFI_SUCCESS Successfully added host bridge.
2144 @retval EFI_ABORTED Host bridge is NULL, or given host bridge
2145 has been in host bridge list.
2146
2147 **/
2148 EFI_STATUS
2149 AddHostBridgeEnumerator (
2150 IN EFI_HANDLE HostBridgeHandle
2151 )
2152 {
2153 UINTN Index;
2154
2155 if (HostBridgeHandle == NULL) {
2156 return EFI_ABORTED;
2157 }
2158
2159 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2160 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2161 return EFI_ABORTED;
2162 }
2163 }
2164
2165 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2166 gPciHostBrigeHandles[Index] = HostBridgeHandle;
2167 gPciHostBridgeNumber++;
2168 }
2169
2170 return EFI_SUCCESS;
2171 }
2172