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