TianoCore EDK2 master
Loading...
Searching...
No Matches
PciEnumerator.c
Go to the documentation of this file.
1
10#include "PciBus.h"
11
25 IN EFI_HANDLE Controller,
26 IN EFI_HANDLE HostBridgeHandle
27 )
28{
29 EFI_STATUS Status;
31
32 //
33 // Get the pci host bridge resource allocation protocol
34 //
35 Status = gBS->OpenProtocol (
36 HostBridgeHandle,
37 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
38 (VOID **)&PciResAlloc,
39 gPciBusDriverBinding.DriverBindingHandle,
40 Controller,
41 EFI_OPEN_PROTOCOL_GET_PROTOCOL
42 );
43
44 if (EFI_ERROR (Status)) {
45 return Status;
46 }
47
48 //
49 // Notify the pci bus enumeration is about to begin
50 //
51 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration);
52
53 if (EFI_ERROR (Status)) {
54 return Status;
55 }
56
57 //
58 // Start the bus allocation phase
59 //
60 Status = PciHostBridgeEnumerator (PciResAlloc);
61
62 if (EFI_ERROR (Status)) {
63 return Status;
64 }
65
66 //
67 // Submit the resource request
68 //
69 Status = PciHostBridgeResourceAllocator (PciResAlloc);
70
71 if (EFI_ERROR (Status)) {
72 return Status;
73 }
74
75 //
76 // Notify the pci bus enumeration is about to complete
77 //
78 Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeEndEnumeration);
79
80 if (EFI_ERROR (Status)) {
81 return Status;
82 }
83
84 //
85 // Process P2C
86 //
87 Status = PciHostBridgeP2CProcess (PciResAlloc);
88
89 if (EFI_ERROR (Status)) {
90 return Status;
91 }
92
93 //
94 // Process attributes for devices on this host bridge
95 //
96 Status = PciHostBridgeDeviceAttribute (PciResAlloc);
97 if (EFI_ERROR (Status)) {
98 return Status;
99 }
100
101 return EFI_SUCCESS;
102}
103
117 IN PCI_IO_DEVICE *RootBridgeDev
118 )
119{
120 EFI_STATUS Status;
122 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration1;
123 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration2;
124 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration3;
125 UINT8 SubBusNumber;
126 UINT8 StartBusNumber;
127 UINT8 PaddedBusRange;
128 EFI_HANDLE RootBridgeHandle;
129 UINT8 Desc;
130 UINT64 AddrLen;
131 UINT64 AddrRangeMin;
132
133 SubBusNumber = 0;
134 StartBusNumber = 0;
135 PaddedBusRange = 0;
136
137 //
138 // Get the root bridge handle
139 //
140 RootBridgeHandle = RootBridgeDev->Handle;
141
144 EFI_IO_BUS_PCI | EFI_IOB_PCI_BUS_ENUM,
145 RootBridgeDev->DevicePath
146 );
147
148 //
149 // Get the Bus information
150 //
151 Status = PciResAlloc->StartBusEnumeration (
152 PciResAlloc,
153 RootBridgeHandle,
154 (VOID **)&Configuration
155 );
156
157 if (EFI_ERROR (Status)) {
158 return Status;
159 }
160
161 if ((Configuration == NULL) || (Configuration->Desc == ACPI_END_TAG_DESCRIPTOR)) {
162 return EFI_INVALID_PARAMETER;
163 }
164
165 RootBridgeDev->BusNumberRanges = Configuration;
166
167 //
168 // Sort the descriptors in ascending order
169 //
170 for (Configuration1 = Configuration; Configuration1->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration1++) {
171 Configuration2 = Configuration1;
172 for (Configuration3 = Configuration1 + 1; Configuration3->Desc != ACPI_END_TAG_DESCRIPTOR; Configuration3++) {
173 if (Configuration2->AddrRangeMin > Configuration3->AddrRangeMin) {
174 Configuration2 = Configuration3;
175 }
176 }
177
178 //
179 // All other fields other than AddrRangeMin and AddrLen are ignored in a descriptor,
180 // so only need to swap these two fields.
181 //
182 if (Configuration2 != Configuration1) {
183 AddrRangeMin = Configuration1->AddrRangeMin;
184 Configuration1->AddrRangeMin = Configuration2->AddrRangeMin;
185 Configuration2->AddrRangeMin = AddrRangeMin;
186
187 AddrLen = Configuration1->AddrLen;
188 Configuration1->AddrLen = Configuration2->AddrLen;
189 Configuration2->AddrLen = AddrLen;
190 }
191 }
192
193 //
194 // Get the bus number to start with
195 //
196 StartBusNumber = (UINT8)(Configuration->AddrRangeMin);
197
198 //
199 // Initialize the subordinate bus number
200 //
201 SubBusNumber = StartBusNumber;
202
203 //
204 // Reset all assigned PCI bus number
205 //
207 RootBridgeDev,
208 StartBusNumber
209 );
210
211 //
212 // Assign bus number
213 //
214 Status = PciScanBus (
215 RootBridgeDev,
216 StartBusNumber,
217 &SubBusNumber,
218 &PaddedBusRange
219 );
220
221 if (EFI_ERROR (Status)) {
222 return Status;
223 }
224
225 //
226 // Assign max bus number scanned
227 //
228
229 Status = PciAllocateBusNumber (RootBridgeDev, SubBusNumber, PaddedBusRange, &SubBusNumber);
230 if (EFI_ERROR (Status)) {
231 return Status;
232 }
233
234 //
235 // Find the bus range which contains the higest bus number, then returns the number of buses
236 // that should be decoded.
237 //
238 while (Configuration->AddrRangeMin + Configuration->AddrLen - 1 < SubBusNumber) {
239 Configuration++;
240 }
241
242 AddrLen = Configuration->AddrLen;
243 Configuration->AddrLen = SubBusNumber - Configuration->AddrRangeMin + 1;
244
245 //
246 // Save the Desc field of the next descriptor. Mark the next descriptor as an END descriptor.
247 //
248 Configuration++;
249 Desc = Configuration->Desc;
250 Configuration->Desc = ACPI_END_TAG_DESCRIPTOR;
251
252 //
253 // Set bus number
254 //
255 Status = PciResAlloc->SetBusNumbers (
256 PciResAlloc,
257 RootBridgeHandle,
258 RootBridgeDev->BusNumberRanges
259 );
260
261 //
262 // Restore changed fields
263 //
264 Configuration->Desc = Desc;
265 (Configuration - 1)->AddrLen = AddrLen;
266
267 return Status;
268}
269
279VOID
281 IN PCI_IO_DEVICE *Bridge,
282 IN UINT64 RomBase,
283 IN UINT64 MaxLength
284 )
285{
286 LIST_ENTRY *CurrentLink;
287 PCI_IO_DEVICE *Temp;
288
289 //
290 // Go through bridges to reach all devices
291 //
292 CurrentLink = Bridge->ChildList.ForwardLink;
293 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
294 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
295 if (!IsListEmpty (&Temp->ChildList)) {
296 //
297 // Go further to process the option rom under this bridge
298 //
299 ProcessOptionRom (Temp, RomBase, MaxLength);
300 }
301
302 if ((Temp->RomSize != 0) && (Temp->RomSize <= MaxLength)) {
303 //
304 // Load and process the option rom
305 //
306 LoadOpRomImage (Temp, RomBase);
307 }
308
309 CurrentLink = CurrentLink->ForwardLink;
310 }
311}
312
326 IN PCI_IO_DEVICE *Bridge,
327 IN UINT8 StartBusNumber,
328 OUT UINT8 *SubBusNumber
329 )
330{
331 EFI_STATUS Status;
332 PCI_TYPE00 Pci;
333 UINT8 Device;
334 UINT8 Func;
335 UINT64 Address;
336 UINTN SecondBus;
337 UINT16 Register;
338 UINT8 Register8;
339 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
340
341 PciRootBridgeIo = Bridge->PciRootBridgeIo;
342
343 SecondBus = 0;
344 Register = 0;
345
346 *SubBusNumber = StartBusNumber;
347
348 //
349 // First check to see whether the parent is ppb
350 //
351 for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
352 for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
353 //
354 // Check to see whether a pci device is present
355 //
356 Status = PciDevicePresent (
357 PciRootBridgeIo,
358 &Pci,
359 StartBusNumber,
360 Device,
361 Func
362 );
363
364 if (EFI_ERROR (Status) && (Func == 0)) {
365 //
366 // go to next device if there is no Function 0
367 //
368 break;
369 }
370
371 if (!EFI_ERROR (Status) &&
372 (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)))
373 {
374 //
375 // Reserved one bus for cardbus bridge
376 //
377 Status = PciAllocateBusNumber (Bridge, *SubBusNumber, 1, SubBusNumber);
378 if (EFI_ERROR (Status)) {
379 return Status;
380 }
381
382 SecondBus = *SubBusNumber;
383
384 Register = (UINT16)((SecondBus << 8) | (UINT16)StartBusNumber);
385
386 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18);
387
388 Status = PciRootBridgeIo->Pci.Write (
389 PciRootBridgeIo,
390 EfiPciWidthUint16,
391 Address,
392 1,
393 &Register
394 );
395
396 //
397 // Initialize SubBusNumber to SecondBus
398 //
399 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
400 Status = PciRootBridgeIo->Pci.Write (
401 PciRootBridgeIo,
402 EfiPciWidthUint8,
403 Address,
404 1,
405 SubBusNumber
406 );
407 //
408 // If it is PPB, resursively search down this bridge
409 //
410 if (IS_PCI_BRIDGE (&Pci)) {
411 Register8 = 0xFF;
412 Status = PciRootBridgeIo->Pci.Write (
413 PciRootBridgeIo,
414 EfiPciWidthUint8,
415 Address,
416 1,
417 &Register8
418 );
419
420 Status = PciAssignBusNumber (
421 Bridge,
422 (UINT8)(SecondBus),
423 SubBusNumber
424 );
425
426 if (EFI_ERROR (Status)) {
427 return EFI_DEVICE_ERROR;
428 }
429 }
430
431 //
432 // Set the current maximum bus number under the PPB
433 //
434 Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A);
435
436 Status = PciRootBridgeIo->Pci.Write (
437 PciRootBridgeIo,
438 EfiPciWidthUint8,
439 Address,
440 1,
441 SubBusNumber
442 );
443 }
444
445 if ((Func == 0) && !IS_PCI_MULTI_FUNC (&Pci)) {
446 //
447 // Skip sub functions, this is not a multi function device
448 //
449 Func = PCI_MAX_FUNC;
450 }
451 }
452 }
453
454 return EFI_SUCCESS;
455}
456
471 IN PCI_IO_DEVICE *RootBridgeDev
472 )
473{
474 UINT64 Attributes;
475 EFI_STATUS Status;
476 EFI_HANDLE RootBridgeHandle;
477
478 Attributes = 0;
479 RootBridgeHandle = RootBridgeDev->Handle;
480
481 //
482 // Get root bridge attribute by calling into pci host bridge resource allocation protocol
483 //
484 Status = PciResAlloc->GetAllocAttributes (
485 PciResAlloc,
486 RootBridgeHandle,
487 &Attributes
488 );
489
490 if (EFI_ERROR (Status)) {
491 return Status;
492 }
493
494 //
495 // Here is the point where PCI bus driver calls HOST bridge allocation protocol
496 // Currently we hardcoded for ea815
497 //
498 if ((Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) {
499 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED;
500 }
501
502 if ((Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) != 0) {
503 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM64_DECODE_SUPPORTED;
504 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED;
505 }
506
507 RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED;
508 RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED;
509 RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED;
510
511 return EFI_SUCCESS;
512}
513
522UINT32
524 IN PCI_IO_DEVICE *Bridge
525 )
526{
527 LIST_ENTRY *CurrentLink;
528 PCI_IO_DEVICE *Temp;
529 UINT32 MaxOptionRomSize;
530 UINT32 TempOptionRomSize;
531
532 MaxOptionRomSize = 0;
533
534 //
535 // Go through bridges to reach all devices
536 //
537 CurrentLink = Bridge->ChildList.ForwardLink;
538 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
539 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
540 if (!IsListEmpty (&Temp->ChildList)) {
541 //
542 // Get max option rom size under this bridge
543 //
544 TempOptionRomSize = GetMaxOptionRomSize (Temp);
545
546 //
547 // Compare with the option rom size of the bridge
548 // Get the larger one
549 //
550 if (Temp->RomSize > TempOptionRomSize) {
551 TempOptionRomSize = Temp->RomSize;
552 }
553 } else {
554 //
555 // For devices get the rom size directly
556 //
557 TempOptionRomSize = Temp->RomSize;
558 }
559
560 //
561 // Get the largest rom size on this bridge
562 //
563 if (TempOptionRomSize > MaxOptionRomSize) {
564 MaxOptionRomSize = TempOptionRomSize;
565 }
566
567 CurrentLink = CurrentLink->ForwardLink;
568 }
569
570 return MaxOptionRomSize;
571}
572
586 )
587{
588 EFI_HANDLE RootBridgeHandle;
589 PCI_IO_DEVICE *RootBridgeDev;
590 EFI_STATUS Status;
591
592 RootBridgeHandle = NULL;
593
594 while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) {
595 //
596 // Get RootBridg Device by handle
597 //
598 RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle);
599
600 if (RootBridgeDev == NULL) {
601 return EFI_NOT_FOUND;
602 }
603
604 //
605 // Set the attributes for devcies behind the Root Bridge
606 //
607 Status = DetermineDeviceAttribute (RootBridgeDev);
608 if (EFI_ERROR (Status)) {
609 return Status;
610 }
611 }
612
613 return EFI_SUCCESS;
614}
615
627VOID
629 VOID *AcpiConfig,
630 OUT UINT64 *IoResStatus,
631 OUT UINT64 *Mem32ResStatus,
632 OUT UINT64 *PMem32ResStatus,
633 OUT UINT64 *Mem64ResStatus,
634 OUT UINT64 *PMem64ResStatus
635 )
636{
637 UINT8 *Temp;
638 UINT64 ResStatus;
639 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ACPIAddressDesc;
640
641 Temp = (UINT8 *)AcpiConfig;
642
643 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
644 ACPIAddressDesc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp;
645 ResStatus = ACPIAddressDesc->AddrTranslationOffset;
646
647 switch (ACPIAddressDesc->ResType) {
648 case 0:
649 if (ACPIAddressDesc->AddrSpaceGranularity == 32) {
650 if (ACPIAddressDesc->SpecificFlag == 0x06) {
651 //
652 // Pmem32
653 //
654 *PMem32ResStatus = ResStatus;
655 } else {
656 //
657 // Mem32
658 //
659 *Mem32ResStatus = ResStatus;
660 }
661 }
662
663 if (ACPIAddressDesc->AddrSpaceGranularity == 64) {
664 if (ACPIAddressDesc->SpecificFlag == 0x06) {
665 //
666 // PMem64
667 //
668 *PMem64ResStatus = ResStatus;
669 } else {
670 //
671 // Mem64
672 //
673 *Mem64ResStatus = ResStatus;
674 }
675 }
676
677 break;
678
679 case 1:
680 //
681 // Io
682 //
683 *IoResStatus = ResStatus;
684 break;
685
686 default:
687 break;
688 }
689
690 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
691 }
692}
693
705 IN PCI_IO_DEVICE *PciDevice
706 )
707{
708 PCI_IO_DEVICE *Bridge;
709 PCI_IO_DEVICE *Temp;
710 LIST_ENTRY *CurrentLink;
711
712 //
713 // Remove the padding resource from a bridge
714 //
715 if ( IS_PCI_BRIDGE (&PciDevice->Pci) &&
716 (PciDevice->ResourcePaddingDescriptors != NULL))
717 {
718 FreePool (PciDevice->ResourcePaddingDescriptors);
719 PciDevice->ResourcePaddingDescriptors = NULL;
720 return EFI_SUCCESS;
721 }
722
723 //
724 // Skip RB and PPB
725 //
726 if (IS_PCI_BRIDGE (&PciDevice->Pci) || (PciDevice->Parent == NULL)) {
727 return EFI_ABORTED;
728 }
729
730 if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) {
731 //
732 // Get the root bridge device
733 //
734 Bridge = PciDevice;
735 while (Bridge->Parent != NULL) {
736 Bridge = Bridge->Parent;
737 }
738
739 RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice);
740
741 //
742 // Mark its bar
743 //
744 InitializeP2C (PciDevice);
745 }
746
747 //
748 // Remove the device
749 //
750 Bridge = PciDevice->Parent;
751 CurrentLink = Bridge->ChildList.ForwardLink;
752 while (CurrentLink != NULL && CurrentLink != &Bridge->ChildList) {
753 Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink);
754 if (Temp == PciDevice) {
755 InitializePciDevice (Temp);
756 RemoveEntryList (CurrentLink);
757 return EFI_SUCCESS;
758 }
759
760 CurrentLink = CurrentLink->ForwardLink;
761 }
762
763 return EFI_ABORTED;
764}
765
775BOOLEAN
777 IN PCI_RESOURCE_NODE *PciResNode
778 )
779{
780 PCI_IO_DEVICE *Temp;
781
782 Temp = PciResNode->PciDev;
783
784 //
785 // Ensure the device is present
786 //
787 if (Temp == NULL) {
788 return FALSE;
789 }
790
791 //
792 // PPB and RB should go ahead
793 //
794 if (IS_PCI_BRIDGE (&Temp->Pci) || (Temp->Parent == NULL)) {
795 return TRUE;
796 }
797
798 //
799 // Skip device on Bus0
800 //
801 if ((Temp->Parent != NULL) && (Temp->BusNumber == 0)) {
802 return FALSE;
803 }
804
805 //
806 // Skip VGA
807 //
808 if (IS_PCI_VGA (&Temp->Pci)) {
809 return FALSE;
810 }
811
812 return TRUE;
813}
814
826 IN PCI_RESOURCE_NODE *PciResNode1,
827 IN PCI_RESOURCE_NODE *PciResNode2
828 )
829{
830 if (PciResNode2 == NULL) {
831 return PciResNode1;
832 }
833
834 if ( (IS_PCI_BRIDGE (&(PciResNode2->PciDev->Pci)) || (PciResNode2->PciDev->Parent == NULL)) \
835 && (PciResNode2->ResourceUsage != PciResUsagePadding))
836 {
837 return PciResNode1;
838 }
839
840 if (PciResNode1 == NULL) {
841 return PciResNode2;
842 }
843
844 if ((PciResNode1->Length) > (PciResNode2->Length)) {
845 return PciResNode1;
846 }
847
848 return PciResNode2;
849}
850
861 IN PCI_RESOURCE_NODE *ResPool
862 )
863{
864 PCI_RESOURCE_NODE *Temp;
865 LIST_ENTRY *CurrentLink;
866 PCI_RESOURCE_NODE *PciResNode;
867 PCI_RESOURCE_NODE *PPBResNode;
868
869 PciResNode = NULL;
870
871 CurrentLink = ResPool->ChildList.ForwardLink;
872 while (CurrentLink != NULL && CurrentLink != &ResPool->ChildList) {
873 Temp = RESOURCE_NODE_FROM_LINK (CurrentLink);
874
875 if (!IsRejectiveDevice (Temp)) {
876 CurrentLink = CurrentLink->ForwardLink;
877 continue;
878 }
879
880 if ( (IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (Temp->PciDev->Parent == NULL)) \
881 && (Temp->ResourceUsage != PciResUsagePadding))
882 {
883 PPBResNode = GetMaxResourceConsumerDevice (Temp);
884 PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode);
885 } else {
886 PciResNode = GetLargerConsumerDevice (PciResNode, Temp);
887 }
888
889 CurrentLink = CurrentLink->ForwardLink;
890 }
891
892 return PciResNode;
893}
894
915 IN PCI_RESOURCE_NODE *IoPool,
916 IN PCI_RESOURCE_NODE *Mem32Pool,
917 IN PCI_RESOURCE_NODE *PMem32Pool,
918 IN PCI_RESOURCE_NODE *Mem64Pool,
919 IN PCI_RESOURCE_NODE *PMem64Pool,
920 IN UINT64 IoResStatus,
921 IN UINT64 Mem32ResStatus,
922 IN UINT64 PMem32ResStatus,
923 IN UINT64 Mem64ResStatus,
924 IN UINT64 PMem64ResStatus
925 )
926{
927 BOOLEAN AllocationAjusted;
928 PCI_RESOURCE_NODE *PciResNode;
929 PCI_RESOURCE_NODE *ResPool[5];
930 PCI_IO_DEVICE *RemovedPciDev[5];
931 UINT64 ResStatus[5];
932 UINTN RemovedPciDevNum;
933 UINTN DevIndex;
934 UINTN ResType;
935 EFI_STATUS Status;
937
938 PciResNode = NULL;
939 ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *));
940 RemovedPciDevNum = 0;
941
942 ResPool[0] = IoPool;
943 ResPool[1] = Mem32Pool;
944 ResPool[2] = PMem32Pool;
945 ResPool[3] = Mem64Pool;
946 ResPool[4] = PMem64Pool;
947
948 ResStatus[0] = IoResStatus;
949 ResStatus[1] = Mem32ResStatus;
950 ResStatus[2] = PMem32ResStatus;
951 ResStatus[3] = Mem64ResStatus;
952 ResStatus[4] = PMem64ResStatus;
953
954 AllocationAjusted = FALSE;
955
956 for (ResType = 0; ResType < 5; ResType++) {
957 if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) {
958 continue;
959 }
960
961 if (ResStatus[ResType] == EFI_RESOURCE_NOT_SATISFIED) {
962 //
963 // Host bridge hasn't this resource type
964 //
965 return EFI_ABORTED;
966 }
967
968 //
969 // Hostbridge hasn't enough resource
970 //
971 PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]);
972 if (PciResNode == NULL) {
973 continue;
974 }
975
976 //
977 // Check if the device has been removed before
978 //
979 for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) {
980 if (PciResNode->PciDev == RemovedPciDev[DevIndex]) {
981 break;
982 }
983 }
984
985 if (DevIndex != RemovedPciDevNum) {
986 continue;
987 }
988
989 //
990 // Remove the device if it isn't in the array
991 //
992 Status = RejectPciDevice (PciResNode->PciDev);
993 if (Status == EFI_SUCCESS) {
994 DEBUG ((
995 DEBUG_ERROR,
996 "PciBus: [%02x|%02x|%02x] was rejected due to resource confliction.\n",
997 PciResNode->PciDev->BusNumber,
998 PciResNode->PciDev->DeviceNumber,
999 PciResNode->PciDev->FunctionNumber
1000 ));
1001
1002 //
1003 // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code
1004 //
1005 //
1006 // Have no way to get ReqRes, AllocRes & Bar here
1007 //
1008 ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData));
1009 AllocFailExtendedData.DevicePathSize = (UINT16)sizeof (EFI_DEVICE_PATH_PROTOCOL);
1010 AllocFailExtendedData.DevicePath = (UINT8 *)PciResNode->PciDev->DevicePath;
1011 AllocFailExtendedData.Bar = PciResNode->Bar;
1012
1015 EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT,
1016 (VOID *)&AllocFailExtendedData,
1017 sizeof (AllocFailExtendedData)
1018 );
1019
1020 //
1021 // Add it to the array and indicate at least a device has been rejected
1022 //
1023 RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev;
1024 AllocationAjusted = TRUE;
1025 }
1026 }
1027
1028 //
1029 // End for
1030 //
1031
1032 if (AllocationAjusted) {
1033 return EFI_SUCCESS;
1034 } else {
1035 return EFI_ABORTED;
1036 }
1037}
1038
1057 IN PCI_IO_DEVICE *Bridge,
1058 IN PCI_RESOURCE_NODE *IoNode,
1059 IN PCI_RESOURCE_NODE *Mem32Node,
1060 IN PCI_RESOURCE_NODE *PMem32Node,
1061 IN PCI_RESOURCE_NODE *Mem64Node,
1062 IN PCI_RESOURCE_NODE *PMem64Node,
1063 OUT VOID **Config
1064 )
1065{
1066 UINT8 NumConfig;
1067 UINT8 Aperture;
1068 UINT8 *Configuration;
1071
1072 NumConfig = 0;
1073 Aperture = 0;
1074
1075 *Config = NULL;
1076
1077 //
1078 // if there is io request, add to the io aperture
1079 //
1080 if (ResourceRequestExisted (IoNode)) {
1081 NumConfig++;
1082 Aperture |= 0x01;
1083 }
1084
1085 //
1086 // if there is mem32 request, add to the mem32 aperture
1087 //
1088 if (ResourceRequestExisted (Mem32Node)) {
1089 NumConfig++;
1090 Aperture |= 0x02;
1091 }
1092
1093 //
1094 // if there is pmem32 request, add to the pmem32 aperture
1095 //
1096 if (ResourceRequestExisted (PMem32Node)) {
1097 NumConfig++;
1098 Aperture |= 0x04;
1099 }
1100
1101 //
1102 // if there is mem64 request, add to the mem64 aperture
1103 //
1104 if (ResourceRequestExisted (Mem64Node)) {
1105 NumConfig++;
1106 Aperture |= 0x08;
1107 }
1108
1109 //
1110 // if there is pmem64 request, add to the pmem64 aperture
1111 //
1112 if (ResourceRequestExisted (PMem64Node)) {
1113 NumConfig++;
1114 Aperture |= 0x10;
1115 }
1116
1117 if (NumConfig != 0) {
1118 //
1119 // If there is at least one type of resource request,
1120 // allocate a acpi resource node
1121 //
1122 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1123 if (Configuration == NULL) {
1124 return EFI_OUT_OF_RESOURCES;
1125 }
1126
1127 Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
1128
1129 //
1130 // Deal with io aperture
1131 //
1132 if ((Aperture & 0x01) != 0) {
1133 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1134 Ptr->Len = (UINT16)(sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1135 //
1136 // Io
1137 //
1138 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1139 //
1140 // non ISA range
1141 //
1142 Ptr->SpecificFlag = 1;
1143 Ptr->AddrLen = IoNode->Length;
1144 Ptr->AddrRangeMax = IoNode->Alignment;
1145
1146 Ptr++;
1147 }
1148
1149 //
1150 // Deal with mem32 aperture
1151 //
1152 if ((Aperture & 0x02) != 0) {
1153 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1154 Ptr->Len = (UINT16)(sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1155 //
1156 // Mem
1157 //
1158 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1159 //
1160 // Nonprefechable
1161 //
1162 Ptr->SpecificFlag = 0;
1163 //
1164 // 32 bit
1165 //
1166 Ptr->AddrSpaceGranularity = 32;
1167 Ptr->AddrLen = Mem32Node->Length;
1168 Ptr->AddrRangeMax = Mem32Node->Alignment;
1169
1170 Ptr++;
1171 }
1172
1173 //
1174 // Deal with Pmem32 aperture
1175 //
1176 if ((Aperture & 0x04) != 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 // prefechable
1185 //
1186 Ptr->SpecificFlag = 0x6;
1187 //
1188 // 32 bit
1189 //
1190 Ptr->AddrSpaceGranularity = 32;
1191 Ptr->AddrLen = PMem32Node->Length;
1192 Ptr->AddrRangeMax = PMem32Node->Alignment;
1193
1194 Ptr++;
1195 }
1196
1197 //
1198 // Deal with mem64 aperture
1199 //
1200 if ((Aperture & 0x08) != 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 // nonprefechable
1209 //
1210 Ptr->SpecificFlag = 0;
1211 //
1212 // 64 bit
1213 //
1214 Ptr->AddrSpaceGranularity = 64;
1215 Ptr->AddrLen = Mem64Node->Length;
1216 Ptr->AddrRangeMax = Mem64Node->Alignment;
1217
1218 Ptr++;
1219 }
1220
1221 //
1222 // Deal with Pmem64 aperture
1223 //
1224 if ((Aperture & 0x10) != 0) {
1225 Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1226 Ptr->Len = (UINT16)(sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3);
1227 //
1228 // Mem
1229 //
1230 Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1231 //
1232 // prefechable
1233 //
1234 Ptr->SpecificFlag = 0x06;
1235 //
1236 // 64 bit
1237 //
1238 Ptr->AddrSpaceGranularity = 64;
1239 Ptr->AddrLen = PMem64Node->Length;
1240 Ptr->AddrRangeMax = PMem64Node->Alignment;
1241
1242 Ptr++;
1243 }
1244
1245 //
1246 // put the checksum
1247 //
1248 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr;
1249
1250 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1251 PtrEnd->Checksum = 0;
1252 } else {
1253 //
1254 // If there is no resource request
1255 //
1256 Configuration = AllocateZeroPool (sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1257 if (Configuration == NULL) {
1258 return EFI_OUT_OF_RESOURCES;
1259 }
1260
1261 PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Configuration);
1262 PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR;
1263 PtrEnd->Checksum = 0;
1264 }
1265
1266 *Config = Configuration;
1267
1268 return EFI_SUCCESS;
1269}
1270
1282VOID
1284 IN VOID *Config,
1285 OUT UINT64 *IoBase,
1286 OUT UINT64 *Mem32Base,
1287 OUT UINT64 *PMem32Base,
1288 OUT UINT64 *Mem64Base,
1289 OUT UINT64 *PMem64Base
1290 )
1291{
1292 UINT8 *Temp;
1294 UINT64 ResStatus;
1295
1296 ASSERT (Config != NULL);
1297
1298 *IoBase = 0xFFFFFFFFFFFFFFFFULL;
1299 *Mem32Base = 0xFFFFFFFFFFFFFFFFULL;
1300 *PMem32Base = 0xFFFFFFFFFFFFFFFFULL;
1301 *Mem64Base = 0xFFFFFFFFFFFFFFFFULL;
1302 *PMem64Base = 0xFFFFFFFFFFFFFFFFULL;
1303
1304 Temp = (UINT8 *)Config;
1305
1306 while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1308 ResStatus = Ptr->AddrTranslationOffset;
1309
1310 if (ResStatus == EFI_RESOURCE_SATISFIED) {
1311 switch (Ptr->ResType) {
1312 //
1313 // Memory type aperture
1314 //
1315 case 0:
1316
1317 //
1318 // Check to see the granularity
1319 //
1320 if (Ptr->AddrSpaceGranularity == 32) {
1321 if ((Ptr->SpecificFlag & 0x06) != 0) {
1322 *PMem32Base = Ptr->AddrRangeMin;
1323 } else {
1324 *Mem32Base = Ptr->AddrRangeMin;
1325 }
1326 }
1327
1328 if (Ptr->AddrSpaceGranularity == 64) {
1329 if ((Ptr->SpecificFlag & 0x06) != 0) {
1330 *PMem64Base = Ptr->AddrRangeMin;
1331 } else {
1332 *Mem64Base = Ptr->AddrRangeMin;
1333 }
1334 }
1335
1336 break;
1337
1338 case 1:
1339
1340 //
1341 // Io type aperture
1342 //
1343 *IoBase = Ptr->AddrRangeMin;
1344 break;
1345
1346 default:
1347 break;
1348 }
1349
1350 //
1351 // End switch
1352 //
1353 }
1354
1355 //
1356 // End for
1357 //
1358 Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1359 }
1360}
1361
1374 IN PCI_IO_DEVICE *BridgeDev
1375 )
1376{
1377 UINT8 SubBusNumber;
1378 UINT8 StartBusNumber;
1379 EFI_PCI_IO_PROTOCOL *PciIo;
1380 EFI_STATUS Status;
1381
1382 SubBusNumber = 0;
1383 StartBusNumber = 0;
1384 PciIo = &(BridgeDev->PciIo);
1385 Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber);
1386
1387 if (EFI_ERROR (Status)) {
1388 return Status;
1389 }
1390
1391 Status = PciAssignBusNumber (
1392 BridgeDev,
1393 StartBusNumber,
1394 &SubBusNumber
1395 );
1396
1397 if (EFI_ERROR (Status)) {
1398 return Status;
1399 }
1400
1401 Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber);
1402
1403 if (EFI_ERROR (Status)) {
1404 return Status;
1405 }
1406
1407 Status = PciBridgeResourceAllocator (BridgeDev);
1408
1409 if (EFI_ERROR (Status)) {
1410 return Status;
1411 }
1412
1413 Status = DetermineDeviceAttribute (BridgeDev);
1414
1415 if (EFI_ERROR (Status)) {
1416 return Status;
1417 }
1418
1419 return EFI_SUCCESS;
1420}
1421
1433 IN PCI_IO_DEVICE *Bridge
1434 )
1435{
1436 PCI_RESOURCE_NODE *IoBridge;
1437 PCI_RESOURCE_NODE *Mem32Bridge;
1438 PCI_RESOURCE_NODE *PMem32Bridge;
1439 PCI_RESOURCE_NODE *Mem64Bridge;
1440 PCI_RESOURCE_NODE *PMem64Bridge;
1441 UINT64 IoBase;
1442 UINT64 Mem32Base;
1443 UINT64 PMem32Base;
1444 UINT64 Mem64Base;
1445 UINT64 PMem64Base;
1446 EFI_STATUS Status;
1447
1448 IoBridge = CreateResourceNode (
1449 Bridge,
1450 0,
1451 Bridge->BridgeIoAlignment,
1452 0,
1453 PciBarTypeIo16,
1454 PciResUsageTypical
1455 );
1456
1457 Mem32Bridge = CreateResourceNode (
1458 Bridge,
1459 0,
1460 0xFFFFF,
1461 0,
1462 PciBarTypeMem32,
1463 PciResUsageTypical
1464 );
1465
1466 PMem32Bridge = CreateResourceNode (
1467 Bridge,
1468 0,
1469 0xFFFFF,
1470 0,
1471 PciBarTypePMem32,
1472 PciResUsageTypical
1473 );
1474
1475 Mem64Bridge = CreateResourceNode (
1476 Bridge,
1477 0,
1478 0xFFFFF,
1479 0,
1480 PciBarTypeMem64,
1481 PciResUsageTypical
1482 );
1483
1484 PMem64Bridge = CreateResourceNode (
1485 Bridge,
1486 0,
1487 0xFFFFF,
1488 0,
1489 PciBarTypePMem64,
1490 PciResUsageTypical
1491 );
1492
1493 //
1494 // Create resourcemap by going through all the devices subject to this root bridge
1495 //
1497 Bridge,
1498 IoBridge,
1499 Mem32Bridge,
1500 PMem32Bridge,
1501 Mem64Bridge,
1502 PMem64Bridge
1503 );
1504
1505 Status = GetResourceBaseFromBridge (
1506 Bridge,
1507 &IoBase,
1508 &Mem32Base,
1509 &PMem32Base,
1510 &Mem64Base,
1511 &PMem64Base
1512 );
1513
1514 if (EFI_ERROR (Status)) {
1515 return Status;
1516 }
1517
1518 //
1519 // Program IO resources
1520 //
1522 IoBase,
1523 IoBridge
1524 );
1525
1526 //
1527 // Program Mem32 resources
1528 //
1530 Mem32Base,
1531 Mem32Bridge
1532 );
1533
1534 //
1535 // Program PMem32 resources
1536 //
1538 PMem32Base,
1539 PMem32Bridge
1540 );
1541
1542 //
1543 // Program Mem64 resources
1544 //
1546 Mem64Base,
1547 Mem64Bridge
1548 );
1549
1550 //
1551 // Program PMem64 resources
1552 //
1554 PMem64Base,
1555 PMem64Bridge
1556 );
1557
1558 DestroyResourceTree (IoBridge);
1559 DestroyResourceTree (Mem32Bridge);
1560 DestroyResourceTree (PMem32Bridge);
1561 DestroyResourceTree (PMem64Bridge);
1562 DestroyResourceTree (Mem64Bridge);
1563
1564 gBS->FreePool (IoBridge);
1565 gBS->FreePool (Mem32Bridge);
1566 gBS->FreePool (PMem32Bridge);
1567 gBS->FreePool (PMem64Bridge);
1568 gBS->FreePool (Mem64Bridge);
1569
1570 return EFI_SUCCESS;
1571}
1572
1589 IN PCI_IO_DEVICE *Bridge,
1590 OUT UINT64 *IoBase,
1591 OUT UINT64 *Mem32Base,
1592 OUT UINT64 *PMem32Base,
1593 OUT UINT64 *Mem64Base,
1594 OUT UINT64 *PMem64Base
1595 )
1596{
1597 if (!Bridge->Allocated) {
1598 return EFI_OUT_OF_RESOURCES;
1599 }
1600
1601 *IoBase = gAllOne;
1602 *Mem32Base = gAllOne;
1603 *PMem32Base = gAllOne;
1604 *Mem64Base = gAllOne;
1605 *PMem64Base = gAllOne;
1606
1607 if (IS_PCI_BRIDGE (&Bridge->Pci)) {
1608 if (Bridge->PciBar[PPB_IO_RANGE].Length > 0) {
1609 *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress;
1610 }
1611
1612 if (Bridge->PciBar[PPB_MEM32_RANGE].Length > 0) {
1613 *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress;
1614 }
1615
1616 if (Bridge->PciBar[PPB_PMEM32_RANGE].Length > 0) {
1617 *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress;
1618 }
1619
1620 if (Bridge->PciBar[PPB_PMEM64_RANGE].Length > 0) {
1621 *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress;
1622 } else {
1623 *PMem64Base = gAllOne;
1624 }
1625 }
1626
1627 if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) {
1628 if (Bridge->PciBar[P2C_IO_1].Length > 0) {
1629 *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress;
1630 } else {
1631 if (Bridge->PciBar[P2C_IO_2].Length > 0) {
1632 *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress;
1633 }
1634 }
1635
1636 if (Bridge->PciBar[P2C_MEM_1].Length > 0) {
1637 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) {
1638 *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1639 }
1640
1641 if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) {
1642 *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress;
1643 }
1644 }
1645
1646 if (Bridge->PciBar[P2C_MEM_2].Length > 0) {
1647 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) {
1648 *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1649 }
1650
1651 if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) {
1652 *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress;
1653 }
1654 }
1655 }
1656
1657 return EFI_SUCCESS;
1658}
1659
1728 )
1729{
1730 EFI_HANDLE HostBridgeHandle;
1731 EFI_HANDLE RootBridgeHandle;
1732 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
1733 EFI_STATUS Status;
1734
1735 HostBridgeHandle = NULL;
1736 RootBridgeHandle = NULL;
1737 if (gPciPlatformProtocol != NULL) {
1738 //
1739 // Get Host Bridge Handle.
1740 //
1741 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1742
1743 //
1744 // Get the rootbridge Io protocol to find the host bridge handle
1745 //
1746 Status = gBS->HandleProtocol (
1747 RootBridgeHandle,
1748 &gEfiPciRootBridgeIoProtocolGuid,
1749 (VOID **)&PciRootBridgeIo
1750 );
1751
1752 if (EFI_ERROR (Status)) {
1753 return EFI_NOT_FOUND;
1754 }
1755
1756 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1757
1758 //
1759 // Call PlatformPci::PlatformNotify() if the protocol is present.
1760 //
1761 gPciPlatformProtocol->PlatformNotify (
1762 gPciPlatformProtocol,
1763 HostBridgeHandle,
1764 Phase,
1766 );
1767 } else if (gPciOverrideProtocol != NULL) {
1768 //
1769 // Get Host Bridge Handle.
1770 //
1771 PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle);
1772
1773 //
1774 // Get the rootbridge Io protocol to find the host bridge handle
1775 //
1776 Status = gBS->HandleProtocol (
1777 RootBridgeHandle,
1778 &gEfiPciRootBridgeIoProtocolGuid,
1779 (VOID **)&PciRootBridgeIo
1780 );
1781
1782 if (EFI_ERROR (Status)) {
1783 return EFI_NOT_FOUND;
1784 }
1785
1786 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
1787
1788 //
1789 // Call PlatformPci::PhaseNotify() if the protocol is present.
1790 //
1791 gPciOverrideProtocol->PlatformNotify (
1792 gPciOverrideProtocol,
1793 HostBridgeHandle,
1794 Phase,
1796 );
1797 }
1798
1799 Status = PciResAlloc->NotifyPhase (
1800 PciResAlloc,
1801 Phase
1802 );
1803
1804 if (gPciPlatformProtocol != NULL) {
1805 //
1806 // Call PlatformPci::PlatformNotify() if the protocol is present.
1807 //
1808 gPciPlatformProtocol->PlatformNotify (
1809 gPciPlatformProtocol,
1810 HostBridgeHandle,
1811 Phase,
1813 );
1814 } else if (gPciOverrideProtocol != NULL) {
1815 //
1816 // Call PlatformPci::PhaseNotify() if the protocol is present.
1817 //
1818 gPciOverrideProtocol->PlatformNotify (
1819 gPciOverrideProtocol,
1820 HostBridgeHandle,
1821 Phase,
1823 );
1824 }
1825
1826 return Status;
1827}
1828
1855 IN PCI_IO_DEVICE *Bridge,
1856 IN UINT8 Bus,
1857 IN UINT8 Device,
1858 IN UINT8 Func,
1860 )
1861{
1864 EFI_HANDLE RootBridgeHandle;
1865 EFI_HANDLE HostBridgeHandle;
1866 EFI_STATUS Status;
1867
1868 //
1869 // Get the host bridge handle
1870 //
1871 HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle;
1872
1873 //
1874 // Get the pci host bridge resource allocation protocol
1875 //
1876 Status = gBS->OpenProtocol (
1877 HostBridgeHandle,
1878 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
1879 (VOID **)&PciResAlloc,
1880 NULL,
1881 NULL,
1882 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1883 );
1884
1885 if (EFI_ERROR (Status)) {
1886 return EFI_UNSUPPORTED;
1887 }
1888
1889 //
1890 // Get Root Brige Handle
1891 //
1892 while (Bridge->Parent != NULL) {
1893 Bridge = Bridge->Parent;
1894 }
1895
1896 RootBridgeHandle = Bridge->Handle;
1897
1898 RootBridgePciAddress.Register = 0;
1899 RootBridgePciAddress.Function = Func;
1900 RootBridgePciAddress.Device = Device;
1901 RootBridgePciAddress.Bus = Bus;
1902 RootBridgePciAddress.ExtendedRegister = 0;
1903
1904 if (gPciPlatformProtocol != NULL) {
1905 //
1906 // Call PlatformPci::PrepController() if the protocol is present.
1907 //
1908 gPciPlatformProtocol->PlatformPrepController (
1909 gPciPlatformProtocol,
1910 HostBridgeHandle,
1911 RootBridgeHandle,
1912 RootBridgePciAddress,
1913 Phase,
1915 );
1916 } else if (gPciOverrideProtocol != NULL) {
1917 //
1918 // Call PlatformPci::PrepController() if the protocol is present.
1919 //
1920 gPciOverrideProtocol->PlatformPrepController (
1921 gPciOverrideProtocol,
1922 HostBridgeHandle,
1923 RootBridgeHandle,
1924 RootBridgePciAddress,
1925 Phase,
1927 );
1928 }
1929
1930 Status = PciResAlloc->PreprocessController (
1931 PciResAlloc,
1932 RootBridgeHandle,
1933 RootBridgePciAddress,
1934 Phase
1935 );
1936
1937 if (gPciPlatformProtocol != NULL) {
1938 //
1939 // Call PlatformPci::PrepController() if the protocol is present.
1940 //
1941 gPciPlatformProtocol->PlatformPrepController (
1942 gPciPlatformProtocol,
1943 HostBridgeHandle,
1944 RootBridgeHandle,
1945 RootBridgePciAddress,
1946 Phase,
1948 );
1949 } else if (gPciOverrideProtocol != NULL) {
1950 //
1951 // Call PlatformPci::PrepController() if the protocol is present.
1952 //
1953 gPciOverrideProtocol->PlatformPrepController (
1954 gPciOverrideProtocol,
1955 HostBridgeHandle,
1956 RootBridgeHandle,
1957 RootBridgePciAddress,
1958 Phase,
1960 );
1961 }
1962
1963 return EFI_SUCCESS;
1964}
1965
1990EFIAPI
1993 IN EFI_PCI_HOTPLUG_OPERATION Operation,
1994 IN EFI_HANDLE Controller,
1995 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,
1996 IN OUT UINT8 *NumberOfChildren,
1997 IN OUT EFI_HANDLE *ChildHandleBuffer
1998 )
1999{
2000 PCI_IO_DEVICE *Bridge;
2001 PCI_IO_DEVICE *Temp;
2002 EFI_PCI_IO_PROTOCOL *PciIo;
2003 UINTN Index;
2004 EFI_HANDLE RootBridgeHandle;
2005 EFI_STATUS Status;
2006
2007 //
2008 // Check input parameter validity
2009 //
2010 if ((Controller == NULL) || (NumberOfChildren == NULL)) {
2011 return EFI_INVALID_PARAMETER;
2012 }
2013
2014 if ((Operation != EfiPciHotPlugRequestAdd) && (Operation != EfiPciHotplugRequestRemove)) {
2015 return EFI_INVALID_PARAMETER;
2016 }
2017
2018 if (Operation == EfiPciHotPlugRequestAdd) {
2019 if (ChildHandleBuffer == NULL) {
2020 return EFI_INVALID_PARAMETER;
2021 }
2022 } else if ((Operation == EfiPciHotplugRequestRemove) && (*NumberOfChildren != 0)) {
2023 if (ChildHandleBuffer == NULL) {
2024 return EFI_INVALID_PARAMETER;
2025 }
2026 }
2027
2028 Status = gBS->OpenProtocol (
2029 Controller,
2030 &gEfiPciIoProtocolGuid,
2031 (VOID **)&PciIo,
2032 gPciBusDriverBinding.DriverBindingHandle,
2033 Controller,
2034 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2035 );
2036
2037 if (EFI_ERROR (Status)) {
2038 return EFI_NOT_FOUND;
2039 }
2040
2041 Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo);
2042
2043 //
2044 // Get root bridge handle
2045 //
2046 Temp = Bridge;
2047 while (Temp->Parent != NULL) {
2048 Temp = Temp->Parent;
2049 }
2050
2051 RootBridgeHandle = Temp->Handle;
2052
2053 if (Operation == EfiPciHotPlugRequestAdd) {
2054 //
2055 // Report Status Code to indicate hot plug happens
2056 //
2059 (EFI_IO_BUS_PCI | EFI_IOB_PC_HOTPLUG),
2060 Temp->DevicePath
2061 );
2062
2063 if (NumberOfChildren != NULL) {
2064 *NumberOfChildren = 0;
2065 }
2066
2067 if (IsListEmpty (&Bridge->ChildList)) {
2068 Status = PciBridgeEnumerator (Bridge);
2069
2070 if (EFI_ERROR (Status)) {
2071 return Status;
2072 }
2073 }
2074
2075 Status = StartPciDevicesOnBridge (
2076 RootBridgeHandle,
2077 Bridge,
2078 RemainingDevicePath,
2079 NumberOfChildren,
2080 ChildHandleBuffer
2081 );
2082
2083 return Status;
2084 }
2085
2086 if (Operation == EfiPciHotplugRequestRemove) {
2087 if (*NumberOfChildren == 0) {
2088 //
2089 // Remove all devices on the bridge
2090 //
2091 RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge);
2092 return EFI_SUCCESS;
2093 }
2094
2095 for (Index = 0; Index < *NumberOfChildren; Index++) {
2096 //
2097 // De register all the pci device
2098 //
2099 Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]);
2100
2101 if (EFI_ERROR (Status)) {
2102 return Status;
2103 }
2104 }
2105
2106 //
2107 // End for
2108 //
2109 return EFI_SUCCESS;
2110 }
2111
2112 return EFI_SUCCESS;
2113}
2114
2124BOOLEAN
2126 IN EFI_HANDLE RootBridgeHandle
2127 )
2128{
2129 EFI_HANDLE HostBridgeHandle;
2130 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
2131 UINTN Index;
2132 EFI_STATUS Status;
2133
2134 //
2135 // Get the rootbridge Io protocol to find the host bridge handle
2136 //
2137 Status = gBS->OpenProtocol (
2138 RootBridgeHandle,
2139 &gEfiPciRootBridgeIoProtocolGuid,
2140 (VOID **)&PciRootBridgeIo,
2141 gPciBusDriverBinding.DriverBindingHandle,
2142 RootBridgeHandle,
2143 EFI_OPEN_PROTOCOL_GET_PROTOCOL
2144 );
2145
2146 if (EFI_ERROR (Status)) {
2147 return FALSE;
2148 }
2149
2150 HostBridgeHandle = PciRootBridgeIo->ParentHandle;
2151 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2152 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2153 return TRUE;
2154 }
2155 }
2156
2157 return FALSE;
2158}
2159
2172 IN EFI_HANDLE HostBridgeHandle
2173 )
2174{
2175 UINTN Index;
2176
2177 if (HostBridgeHandle == NULL) {
2178 return EFI_ABORTED;
2179 }
2180
2181 for (Index = 0; Index < gPciHostBridgeNumber; Index++) {
2182 if (HostBridgeHandle == gPciHostBrigeHandles[Index]) {
2183 return EFI_ABORTED;
2184 }
2185 }
2186
2187 if (Index < PCI_MAX_HOST_BRIDGE_NUM) {
2188 gPciHostBrigeHandles[Index] = HostBridgeHandle;
2189 gPciHostBridgeNumber++;
2190 }
2191
2192 return EFI_SUCCESS;
2193}
UINT64 UINTN
PACKED struct @89 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
LIST_ENTRY *EFIAPI RemoveEntryList(IN CONST LIST_ENTRY *Entry)
Definition: LinkedList.c:590
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
EFI_STATUS PciHostBridgeEnumerator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc)
Definition: PciLib.c:1543
EFI_STATUS PciHostBridgeResourceAllocator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc)
Definition: PciLib.c:469
EFI_STATUS PciScanBus(IN PCI_IO_DEVICE *Bridge, IN UINT8 StartBusNumber, OUT UINT8 *SubBusNumber, OUT UINT8 *PaddedBusRange)
Definition: PciLib.c:1082
EFI_STATUS PciAllocateBusNumber(IN PCI_IO_DEVICE *Bridge, IN UINT8 StartBusNumber, IN UINT8 NumberOfBuses, OUT UINT8 *NextBusNumber)
Definition: PciLib.c:1019
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type, Value, DevicePathParameter)
#define REPORT_STATUS_CODE_WITH_EXTENDED_DATA(Type, Value, ExtendedData, ExtendedDataSize)
#define IS_PCI_BRIDGE(_p)
Definition: Pci22.h:504
#define IS_PCI_VGA(_p)
Definition: Pci22.h:360
#define IS_PCI_MULTI_FUNC(_p)
Definition: Pci22.h:526
#define IS_CARDBUS_BRIDGE(_p)
Definition: Pci22.h:515
EFI_STATUS DeRegisterPciDevice(IN EFI_HANDLE Controller, IN EFI_HANDLE Handle)
EFI_STATUS StartPciDevicesOnBridge(IN EFI_HANDLE Controller, IN PCI_IO_DEVICE *RootBridge, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, IN OUT UINT8 *NumberOfChildren, IN OUT EFI_HANDLE *ChildHandleBuffer)
PCI_IO_DEVICE * GetRootBridgeByHandle(EFI_HANDLE RootBridgeHandle)
VOID RemoveAllPciDeviceOnBridge(EFI_HANDLE RootBridgeHandle, PCI_IO_DEVICE *Bridge)
VOID GetResourceBase(IN VOID *Config, OUT UINT64 *IoBase, OUT UINT64 *Mem32Base, OUT UINT64 *PMem32Base, OUT UINT64 *Mem64Base, OUT UINT64 *PMem64Base)
EFI_STATUS PciRootBridgeEnumerator(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, IN PCI_IO_DEVICE *RootBridgeDev)
EFI_STATUS EFIAPI PciHotPlugRequestNotify(IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL *This, IN EFI_PCI_HOTPLUG_OPERATION Operation, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, IN OUT UINT8 *NumberOfChildren, IN OUT EFI_HANDLE *ChildHandleBuffer)
EFI_STATUS RejectPciDevice(IN PCI_IO_DEVICE *PciDevice)
VOID ProcessOptionRom(IN PCI_IO_DEVICE *Bridge, IN UINT64 RomBase, IN UINT64 MaxLength)
EFI_STATUS PciBridgeResourceAllocator(IN PCI_IO_DEVICE *Bridge)
EFI_STATUS AddHostBridgeEnumerator(IN EFI_HANDLE HostBridgeHandle)
BOOLEAN SearchHostBridgeHandle(IN EFI_HANDLE RootBridgeHandle)
EFI_STATUS GetResourceBaseFromBridge(IN PCI_IO_DEVICE *Bridge, OUT UINT64 *IoBase, OUT UINT64 *Mem32Base, OUT UINT64 *PMem32Base, OUT UINT64 *Mem64Base, OUT UINT64 *PMem64Base)
PCI_RESOURCE_NODE * GetLargerConsumerDevice(IN PCI_RESOURCE_NODE *PciResNode1, IN PCI_RESOURCE_NODE *PciResNode2)
EFI_STATUS PciHostBridgeDeviceAttribute(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc)
PCI_RESOURCE_NODE * GetMaxResourceConsumerDevice(IN PCI_RESOURCE_NODE *ResPool)
EFI_STATUS DetermineRootBridgeAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, IN PCI_IO_DEVICE *RootBridgeDev)
BOOLEAN IsRejectiveDevice(IN PCI_RESOURCE_NODE *PciResNode)
VOID GetResourceAllocationStatus(VOID *AcpiConfig, OUT UINT64 *IoResStatus, OUT UINT64 *Mem32ResStatus, OUT UINT64 *PMem32ResStatus, OUT UINT64 *Mem64ResStatus, OUT UINT64 *PMem64ResStatus)
EFI_STATUS PreprocessController(IN PCI_IO_DEVICE *Bridge, IN UINT8 Bus, IN UINT8 Device, IN UINT8 Func, IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)
UINT32 GetMaxOptionRomSize(IN PCI_IO_DEVICE *Bridge)
EFI_STATUS PciBridgeEnumerator(IN PCI_IO_DEVICE *BridgeDev)
EFI_STATUS PciHostBridgeAdjustAllocation(IN PCI_RESOURCE_NODE *IoPool, IN PCI_RESOURCE_NODE *Mem32Pool, IN PCI_RESOURCE_NODE *PMem32Pool, IN PCI_RESOURCE_NODE *Mem64Pool, IN PCI_RESOURCE_NODE *PMem64Pool, IN UINT64 IoResStatus, IN UINT64 Mem32ResStatus, IN UINT64 PMem32ResStatus, IN UINT64 Mem64ResStatus, IN UINT64 PMem64ResStatus)
EFI_STATUS ConstructAcpiResourceRequestor(IN PCI_IO_DEVICE *Bridge, IN PCI_RESOURCE_NODE *IoNode, IN PCI_RESOURCE_NODE *Mem32Node, IN PCI_RESOURCE_NODE *PMem32Node, IN PCI_RESOURCE_NODE *Mem64Node, IN PCI_RESOURCE_NODE *PMem64Node, OUT VOID **Config)
EFI_STATUS PciAssignBusNumber(IN PCI_IO_DEVICE *Bridge, IN UINT8 StartBusNumber, OUT UINT8 *SubBusNumber)
EFI_STATUS PciEnumerator(IN EFI_HANDLE Controller, IN EFI_HANDLE HostBridgeHandle)
Definition: PciEnumerator.c:24
EFI_STATUS NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)
EFI_STATUS PciHostBridgeP2CProcess(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc)
Definition: PciLib.c:1498
EFI_STATUS PciPciDeviceInfoCollector(IN PCI_IO_DEVICE *Bridge, IN UINT8 StartBusNumber)
EFI_STATUS PciDevicePresent(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, OUT PCI_TYPE00 *Pci, IN UINT8 Bus, IN UINT8 Device, IN UINT8 Func)
VOID InitializeP2C(IN PCI_IO_DEVICE *PciIoDevice)
EFI_STATUS DetermineDeviceAttribute(IN PCI_IO_DEVICE *PciIoDevice)
VOID InitializePciDevice(IN PCI_IO_DEVICE *PciIoDevice)
VOID ResetAllPpbBusNumber(IN PCI_IO_DEVICE *Bridge, IN UINT8 StartBusNumber)
#define EFI_RESOURCE_SATISFIED
#define EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
#define EFI_PCI_HOST_BRIDGE_MEM64_DECODE
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
@ EfiPciHostBridgeBeginEnumeration
EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
#define EFI_RESOURCE_NOT_SATISFIED
EFI_PCI_HOTPLUG_OPERATION
@ EfiPciHotplugRequestRemove
@ EfiPciHotPlugRequestAdd
EFI_STATUS LoadOpRomImage(IN PCI_IO_DEVICE *PciDevice, IN UINT64 RomBase)
@ ChipsetExit
Definition: PciPlatform.h:175
@ ChipsetEntry
Definition: PciPlatform.h:161
BOOLEAN ResourceRequestExisted(IN PCI_RESOURCE_NODE *Bridge)
EFI_STATUS ProgramResource(IN UINT64 Base, IN PCI_RESOURCE_NODE *Bridge)
VOID CreateResourceMap(IN PCI_IO_DEVICE *Bridge, IN OUT PCI_RESOURCE_NODE *IoNode, IN OUT PCI_RESOURCE_NODE *Mem32Node, IN OUT PCI_RESOURCE_NODE *PMem32Node, IN OUT PCI_RESOURCE_NODE *Mem64Node, IN OUT PCI_RESOURCE_NODE *PMem64Node)
PCI_RESOURCE_NODE * CreateResourceNode(IN PCI_IO_DEVICE *PciDev, IN UINT64 Length, IN UINT64 Alignment, IN UINT8 Bar, IN PCI_BAR_TYPE ResType, IN PCI_RESOURCE_USAGE ResUsage)
VOID DestroyResourceTree(IN PCI_RESOURCE_NODE *Bridge)
#define EFI_IOB_PCI_BUS_ENUM
Definition: PiStatusCode.h:566
#define EFI_PROGRESS_CODE
Definition: PiStatusCode.h:43
EFI_STATUS EFIAPI Register(IN EFI_PEI_RSC_HANDLER_CALLBACK Callback)
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER PreprocessController
EFI_PCI_PLATFORM_PHASE_NOTIFY PlatformNotify
Definition: PciPlatform.h:320
EFI_PCI_PLATFORM_PREPROCESS_CONTROLLER PlatformPrepController
Definition: PciPlatform.h:325
EFI_PCI_IO_PROTOCOL_CONFIG Read
Definition: PciIo.h:232
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Write