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