TianoCore EDK2 master
Loading...
Searching...
No Matches
PciHostBridge.c
Go to the documentation of this file.
1
10#include "PciHostBridge.h"
11#include "PciRootBridge.h"
12#include "PciHostResource.h"
13
15
16GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
17 L"Mem", L"I/O", L"Bus"
18};
19GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
20 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
21};
22
24EFI_EVENT mIoMmuEvent;
25VOID *mIoMmuRegistration;
26
35UINT64
37 IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge,
38 IN PCI_RESOURCE_TYPE ResourceType
39 )
40{
41 switch (ResourceType) {
42 case TypeIo:
43 return RootBridge->Io.Translation;
44 case TypeMem32:
45 return RootBridge->Mem.Translation;
46 case TypePMem32:
47 return RootBridge->PMem.Translation;
48 case TypeMem64:
49 return RootBridge->MemAbove4G.Translation;
50 case TypePMem64:
51 return RootBridge->PMemAbove4G.Translation;
52 case TypeBus:
53 return RootBridge->Bus.Translation;
54 default:
55 ASSERT (FALSE);
56 return 0;
57 }
58}
59
95 IN UINT64 Base,
96 IN UINT64 Length,
98 )
99{
100 UINT64 IntersectionBase;
101 UINT64 IntersectionEnd;
102 EFI_STATUS Status;
103
104 if (Descriptor->GcdIoType == EfiGcdIoTypeIo) {
105 return EFI_SUCCESS;
106 }
107
108 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
109 IntersectionEnd = MIN (
110 Base + Length,
111 Descriptor->BaseAddress + Descriptor->Length
112 );
113 if (IntersectionBase >= IntersectionEnd) {
114 //
115 // The descriptor and the aperture don't overlap.
116 //
117 return EFI_SUCCESS;
118 }
119
120 if (Descriptor->GcdIoType == EfiGcdIoTypeNonExistent) {
121 Status = gDS->AddIoSpace (
123 IntersectionBase,
124 IntersectionEnd - IntersectionBase
125 );
126
127 DEBUG ((
128 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
129 "%a: %a: add [%Lx, %Lx): %r\n",
130 gEfiCallerBaseName,
131 __func__,
132 IntersectionBase,
133 IntersectionEnd,
134 Status
135 ));
136 return Status;
137 }
138
139 DEBUG ((
140 DEBUG_ERROR,
141 "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
142 "aperture [%Lx, %Lx)\n",
143 gEfiCallerBaseName,
144 __func__,
145 Descriptor->BaseAddress,
146 Descriptor->BaseAddress + Descriptor->Length,
147 (UINT32)Descriptor->GcdIoType,
148 Base,
149 Base + Length
150 ));
151 return EFI_INVALID_PARAMETER;
152}
153
166 IN UINT64 Base,
167 IN UINT64 Length
168 )
169{
170 EFI_STATUS Status;
171 UINTN Index;
172 UINTN NumberOfDescriptors;
173 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
174
175 Status = gDS->GetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);
176 if (EFI_ERROR (Status)) {
177 DEBUG ((
178 DEBUG_ERROR,
179 "%a: %a: GetIoSpaceMap(): %r\n",
180 gEfiCallerBaseName,
181 __func__,
182 Status
183 ));
184 return Status;
185 }
186
187 for (Index = 0; Index < NumberOfDescriptors; Index++) {
188 Status = IntersectIoDescriptor (Base, Length, &IoSpaceMap[Index]);
189 if (EFI_ERROR (Status)) {
190 goto FreeIoSpaceMap;
191 }
192 }
193
195 //
196 // Make sure there are adjacent descriptors covering [Base, Base + Length).
197 // It is possible that they have not been merged; merging can be prevented
198 // by allocation.
199 //
200 UINT64 CheckBase;
201 EFI_STATUS CheckStatus;
203
204 for (CheckBase = Base;
205 CheckBase < Base + Length;
206 CheckBase = Descriptor.BaseAddress + Descriptor.Length)
207 {
208 CheckStatus = gDS->GetIoSpaceDescriptor (CheckBase, &Descriptor);
209 ASSERT_EFI_ERROR (CheckStatus);
210 ASSERT (Descriptor.GcdIoType == EfiGcdIoTypeIo);
211 }
212
214
215FreeIoSpaceMap:
216 FreePool (IoSpaceMap);
217
218 return Status;
219}
220
262 IN UINT64 Base,
263 IN UINT64 Length,
264 IN UINT64 Capabilities,
266 )
267{
268 UINT64 IntersectionBase;
269 UINT64 IntersectionEnd;
270 EFI_STATUS Status;
271
272 if ((Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) &&
273 ((Descriptor->Capabilities & Capabilities) == Capabilities))
274 {
275 return EFI_SUCCESS;
276 }
277
278 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
279 IntersectionEnd = MIN (
280 Base + Length,
281 Descriptor->BaseAddress + Descriptor->Length
282 );
283 if (IntersectionBase >= IntersectionEnd) {
284 //
285 // The descriptor and the aperture don't overlap.
286 //
287 return EFI_SUCCESS;
288 }
289
290 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
291 Status = gDS->AddMemorySpace (
293 IntersectionBase,
294 IntersectionEnd - IntersectionBase,
295 Capabilities
296 );
297
298 DEBUG ((
299 EFI_ERROR (Status) ? DEBUG_ERROR : DEBUG_VERBOSE,
300 "%a: %a: add [%Lx, %Lx): %r\n",
301 gEfiCallerBaseName,
302 __func__,
303 IntersectionBase,
304 IntersectionEnd,
305 Status
306 ));
307 return Status;
308 }
309
310 DEBUG ((
311 DEBUG_ERROR,
312 "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
313 "with aperture [%Lx, %Lx) cap %Lx\n",
314 gEfiCallerBaseName,
315 __func__,
316 Descriptor->BaseAddress,
317 Descriptor->BaseAddress + Descriptor->Length,
318 (UINT32)Descriptor->GcdMemoryType,
319 Descriptor->Capabilities,
320 Base,
321 Base + Length,
322 Capabilities
323 ));
324 return EFI_INVALID_PARAMETER;
325}
326
340 IN UINT64 Base,
341 IN UINT64 Length,
342 IN UINT64 Capabilities
343 )
344{
345 EFI_STATUS Status;
346 UINTN Index;
347 UINTN NumberOfDescriptors;
348 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
349
350 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
351 if (EFI_ERROR (Status)) {
352 DEBUG ((
353 DEBUG_ERROR,
354 "%a: %a: GetMemorySpaceMap(): %r\n",
355 gEfiCallerBaseName,
356 __func__,
357 Status
358 ));
359 return Status;
360 }
361
362 for (Index = 0; Index < NumberOfDescriptors; Index++) {
364 Base,
365 Length,
366 Capabilities,
367 &MemorySpaceMap[Index]
368 );
369 if (EFI_ERROR (Status)) {
370 goto FreeMemorySpaceMap;
371 }
372 }
373
375 //
376 // Make sure there are adjacent descriptors covering [Base, Base + Length).
377 // It is possible that they have not been merged; merging can be prevented
378 // by allocation and different capabilities.
379 //
380 UINT64 CheckBase;
381 EFI_STATUS CheckStatus;
383
384 for (CheckBase = Base;
385 CheckBase < Base + Length;
386 CheckBase = Descriptor.BaseAddress + Descriptor.Length)
387 {
388 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);
389 ASSERT_EFI_ERROR (CheckStatus);
390 ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);
391 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);
392 }
393
395
396FreeMemorySpaceMap:
397 FreePool (MemorySpaceMap);
398
399 return Status;
400}
401
409VOID
410EFIAPI
412 IN EFI_EVENT Event,
413 IN VOID *Context
414 )
415{
416 EFI_STATUS Status;
417
418 Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmu);
419 if (!EFI_ERROR (Status)) {
420 gBS->CloseEvent (mIoMmuEvent);
421 }
422}
423
436EFIAPI
438 IN EFI_HANDLE ImageHandle,
439 IN EFI_SYSTEM_TABLE *SystemTable
440 )
441{
442 EFI_STATUS Status;
443 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
444 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
445 PCI_ROOT_BRIDGE *RootBridges;
446 UINTN RootBridgeCount;
447 UINTN Index;
448 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];
449 UINTN MemApertureIndex;
450 BOOLEAN ResourceAssigned;
451 LIST_ENTRY *Link;
452 UINT64 HostAddress;
453
454 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
455 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
456 return EFI_UNSUPPORTED;
457 }
458
459 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **)&mCpuIo);
460 ASSERT_EFI_ERROR (Status);
461
462 //
463 // Most systems in the world including complex servers have only one Host Bridge.
464 //
465 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
466 ASSERT (HostBridge != NULL);
467
468 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
469 HostBridge->CanRestarted = TRUE;
470 InitializeListHead (&HostBridge->RootBridges);
471 ResourceAssigned = FALSE;
472
473 //
474 // Create Root Bridge Device Handle in this Host Bridge
475 //
476 for (Index = 0; Index < RootBridgeCount; Index++) {
477 //
478 // Create Root Bridge Handle Instance
479 //
480 RootBridge = CreateRootBridge (&RootBridges[Index]);
481 ASSERT (RootBridge != NULL);
482 if (RootBridge == NULL) {
483 continue;
484 }
485
486 //
487 // Make sure all root bridges share the same ResourceAssigned value.
488 //
489 if (Index == 0) {
490 ResourceAssigned = RootBridges[Index].ResourceAssigned;
491 } else {
492 ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
493 }
494
495 if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
496 //
497 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
498 // For GCD resource manipulation, we need to use host address.
499 //
500 HostAddress = TO_HOST_ADDRESS (
501 RootBridges[Index].Io.Base,
502 RootBridges[Index].Io.Translation
503 );
504
505 Status = AddIoSpace (
506 HostAddress,
507 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
508 );
509 ASSERT_EFI_ERROR (Status);
510 if (ResourceAssigned) {
511 Status = gDS->AllocateIoSpace (
514 0,
515 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
516 &HostAddress,
518 NULL
519 );
520 ASSERT_EFI_ERROR (Status);
521 }
522 }
523
524 //
525 // Add all the Mem/PMem aperture to GCD
526 // Mem/PMem shouldn't overlap with each other
527 // Root bridge which needs to combine MEM and PMEM should only report
528 // the MEM aperture in Mem
529 //
530 MemApertures[0] = &RootBridges[Index].Mem;
531 MemApertures[1] = &RootBridges[Index].MemAbove4G;
532 MemApertures[2] = &RootBridges[Index].PMem;
533 MemApertures[3] = &RootBridges[Index].PMemAbove4G;
534
535 for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
536 if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
537 //
538 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
539 // For GCD resource manipulation, we need to use host address.
540 //
541 HostAddress = TO_HOST_ADDRESS (
542 MemApertures[MemApertureIndex]->Base,
543 MemApertures[MemApertureIndex]->Translation
544 );
545 Status = AddMemoryMappedIoSpace (
546 HostAddress,
547 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
548 EFI_MEMORY_UC
549 );
550 ASSERT_EFI_ERROR (Status);
551 Status = gDS->SetMemorySpaceAttributes (
552 HostAddress,
553 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
554 EFI_MEMORY_UC
555 );
556 if (EFI_ERROR (Status)) {
557 DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
558 }
559
560 if (ResourceAssigned) {
561 Status = gDS->AllocateMemorySpace (
564 0,
565 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
566 &HostAddress,
568 NULL
569 );
570 ASSERT_EFI_ERROR (Status);
571 }
572 }
573 }
574
575 //
576 // Insert Root Bridge Handle Instance
577 //
578 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
579 }
580
581 //
582 // When resources were assigned, it's not needed to expose
583 // PciHostBridgeResourceAllocation protocol.
584 //
585 if (!ResourceAssigned) {
586 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
587 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
588 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
589 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
590 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
591 HostBridge->ResAlloc.SubmitResources = SubmitResources;
592 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
593 HostBridge->ResAlloc.PreprocessController = PreprocessController;
594
595 Status = gBS->InstallMultipleProtocolInterfaces (
596 &HostBridge->Handle,
597 &gEfiPciHostBridgeResourceAllocationProtocolGuid,
598 &HostBridge->ResAlloc,
599 NULL
600 );
601 ASSERT_EFI_ERROR (Status);
602 }
603
604 for (Link = GetFirstNode (&HostBridge->RootBridges)
605 ; !IsNull (&HostBridge->RootBridges, Link)
606 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
607 )
608 {
609 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
610 RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
611
612 Status = gBS->InstallMultipleProtocolInterfaces (
613 &RootBridge->Handle,
614 &gEfiDevicePathProtocolGuid,
615 RootBridge->DevicePath,
616 &gEfiPciRootBridgeIoProtocolGuid,
617 &RootBridge->RootBridgeIo,
618 NULL
619 );
620 ASSERT_EFI_ERROR (Status);
621 }
622
623 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
624
625 if (!EFI_ERROR (Status)) {
626 mIoMmuEvent = EfiCreateProtocolNotifyEvent (
628 TPL_CALLBACK,
630 NULL,
631 &mIoMmuRegistration
632 );
633 }
634
635 return Status;
636}
637
643VOID
645 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
646 )
647{
651 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
652 LIST_ENTRY *Link;
653 UINTN RootBridgeCount;
654 PCI_RESOURCE_TYPE Index;
655 PCI_RES_NODE *ResAllocNode;
656
657 RootBridgeCount = 0;
658 for (Link = GetFirstNode (&HostBridge->RootBridges)
659 ; !IsNull (&HostBridge->RootBridges, Link)
660 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
661 )
662 {
663 RootBridgeCount++;
664 }
665
666 Resources = AllocatePool (
667 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +
669 );
670 ASSERT (Resources != NULL);
671
672 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
673 ; !IsNull (&HostBridge->RootBridges, Link)
674 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
675 )
676 {
677 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
678 for (Index = TypeIo; Index < TypeMax; Index++) {
679 ResAllocNode = &RootBridge->ResAllocNode[Index];
680
681 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
682 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
683 Descriptor->AddrRangeMin = ResAllocNode->Base;
684 Descriptor->AddrRangeMax = ResAllocNode->Alignment;
685 Descriptor->AddrLen = ResAllocNode->Length;
686 Descriptor->SpecificFlag = 0;
687 switch (ResAllocNode->Type) {
688 case TypeIo:
689 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
690 break;
691
692 case TypePMem32:
693 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
694 case TypeMem32:
695 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
696 Descriptor->AddrSpaceGranularity = 32;
697 break;
698
699 case TypePMem64:
700 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
701 case TypeMem64:
702 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
703 Descriptor->AddrSpaceGranularity = 64;
704 break;
705
706 case TypeBus:
707 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
708 break;
709
710 default:
711 break;
712 }
713
714 Descriptor++;
715 }
716
717 //
718 // Terminate the root bridge resources.
719 //
720 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;
721 End->Desc = ACPI_END_TAG_DESCRIPTOR;
722 End->Checksum = 0x0;
723
724 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(End + 1);
725 }
726
727 //
728 // Terminate the host bridge resources.
729 //
730 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;
731 End->Desc = ACPI_END_TAG_DESCRIPTOR;
732 End->Checksum = 0x0;
733
734 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
735 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
736 FreePool (Resources);
737}
738
752UINT64
754 BOOLEAN Mmio,
755 UINT64 Length,
756 UINTN BitsOfAlignment,
757 UINT64 BaseAddress,
758 UINT64 Limit
759 )
760{
761 EFI_STATUS Status;
762
763 if (BaseAddress < Limit) {
764 //
765 // Have to make sure Aligment is handled since we are doing direct address allocation
766 // Strictly speaking, alignment requirement should be applied to device
767 // address instead of host address which is used in GCD manipulation below,
768 // but as we restrict the alignment of Translation to be larger than any BAR
769 // alignment in the root bridge, we can simplify the situation and consider
770 // the same alignment requirement is also applied to host address.
771 //
772 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
773
774 while (BaseAddress + Length <= Limit + 1) {
775 if (Mmio) {
776 Status = gDS->AllocateMemorySpace (
779 BitsOfAlignment,
780 Length,
781 &BaseAddress,
783 NULL
784 );
785 } else {
786 Status = gDS->AllocateIoSpace (
789 BitsOfAlignment,
790 Length,
791 &BaseAddress,
793 NULL
794 );
795 }
796
797 if (!EFI_ERROR (Status)) {
798 return BaseAddress;
799 }
800
801 BaseAddress += LShiftU64 (1, BitsOfAlignment);
802 }
803 }
804
805 return MAX_UINT64;
806}
807
821EFIAPI
825 )
826{
827 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
828 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
829 LIST_ENTRY *Link;
830 EFI_PHYSICAL_ADDRESS BaseAddress;
831 UINTN BitsOfAlignment;
832 UINT64 Alignment;
833 EFI_STATUS Status;
834 EFI_STATUS ReturnStatus;
835 PCI_RESOURCE_TYPE Index;
836 PCI_RESOURCE_TYPE Index1;
837 PCI_RESOURCE_TYPE Index2;
838 BOOLEAN ResNodeHandled[TypeMax];
839 UINT64 MaxAlignment;
840 UINT64 Translation;
841
842 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
843
844 switch (Phase) {
846 if (!HostBridge->CanRestarted) {
847 return EFI_NOT_READY;
848 }
849
850 //
851 // Reset Root Bridge
852 //
853 for (Link = GetFirstNode (&HostBridge->RootBridges)
854 ; !IsNull (&HostBridge->RootBridges, Link)
855 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
856 )
857 {
858 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
859 for (Index = TypeIo; Index < TypeMax; Index++) {
860 RootBridge->ResAllocNode[Index].Type = Index;
861 RootBridge->ResAllocNode[Index].Base = 0;
862 RootBridge->ResAllocNode[Index].Length = 0;
863 RootBridge->ResAllocNode[Index].Status = ResNone;
864
865 RootBridge->ResourceSubmitted = FALSE;
866 }
867 }
868
869 HostBridge->CanRestarted = TRUE;
870 break;
871
873 //
874 // No specific action is required here, can perform any chipset specific programing
875 //
876 HostBridge->CanRestarted = FALSE;
877 break;
878
880 //
881 // No specific action is required here, can perform any chipset specific programing
882 //
883 break;
884
886 //
887 // No specific action is required here, can perform any chipset specific programing
888 //
889 break;
890
892 ReturnStatus = EFI_SUCCESS;
893
894 //
895 // Make sure the resource for all root bridges has been submitted.
896 //
897 for (Link = GetFirstNode (&HostBridge->RootBridges)
898 ; !IsNull (&HostBridge->RootBridges, Link)
899 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
900 )
901 {
902 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
903 if (!RootBridge->ResourceSubmitted) {
904 return EFI_NOT_READY;
905 }
906 }
907
908 DEBUG ((DEBUG_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
909 for (Link = GetFirstNode (&HostBridge->RootBridges)
910 ; !IsNull (&HostBridge->RootBridges, Link)
911 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
912 )
913 {
914 for (Index = TypeIo; Index < TypeBus; Index++) {
915 ResNodeHandled[Index] = FALSE;
916 }
917
918 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
919 DEBUG ((DEBUG_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
920
921 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
922 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
923 ResNodeHandled[Index1] = TRUE;
924 } else {
925 //
926 // Allocate the resource node with max alignment at first
927 //
928 MaxAlignment = 0;
929 Index = TypeMax;
930 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
931 if (ResNodeHandled[Index2]) {
932 continue;
933 }
934
935 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
936 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
937 Index = Index2;
938 }
939 }
940
941 ASSERT (Index < TypeMax);
942 ResNodeHandled[Index] = TRUE;
943 Alignment = RootBridge->ResAllocNode[Index].Alignment;
944 BitsOfAlignment = LowBitSet64 (Alignment + 1);
945 BaseAddress = MAX_UINT64;
946
947 //
948 // RESTRICTION: To simplify the situation, we require the alignment of
949 // Translation must be larger than any BAR alignment in the same root
950 // bridge, so that resource allocation alignment can be applied to
951 // both device address and host address.
952 //
953 Translation = GetTranslationByResourceType (RootBridge, Index);
954 if ((Translation & Alignment) != 0) {
955 DEBUG ((
956 DEBUG_ERROR,
957 "[%a:%d] Translation %lx is not aligned to %lx!\n",
958 __func__,
959 DEBUG_LINE_NUMBER,
960 Translation,
961 Alignment
962 ));
963 ASSERT ((Translation & Alignment) == 0);
964 //
965 // This may be caused by too large alignment or too small
966 // Translation; pick the 1st possibility and return out of resource,
967 // which can also go thru the same process for out of resource
968 // outside the loop.
969 //
970 ReturnStatus = EFI_OUT_OF_RESOURCES;
971 continue;
972 }
973
974 switch (Index) {
975 case TypeIo:
976 //
977 // Base and Limit in PCI_ROOT_BRIDGE_APERTURE are device address.
978 // For AllocateResource is manipulating GCD resource, we need to use
979 // host address here.
980 //
981 BaseAddress = AllocateResource (
982 FALSE,
983 RootBridge->ResAllocNode[Index].Length,
984 MIN (15, BitsOfAlignment),
985 TO_HOST_ADDRESS (
986 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
987 RootBridge->Io.Translation
988 ),
989 TO_HOST_ADDRESS (
990 RootBridge->Io.Limit,
991 RootBridge->Io.Translation
992 )
993 );
994 break;
995
996 case TypeMem64:
997 BaseAddress = AllocateResource (
998 TRUE,
999 RootBridge->ResAllocNode[Index].Length,
1000 MIN (63, BitsOfAlignment),
1001 TO_HOST_ADDRESS (
1002 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
1003 RootBridge->MemAbove4G.Translation
1004 ),
1005 TO_HOST_ADDRESS (
1006 RootBridge->MemAbove4G.Limit,
1007 RootBridge->MemAbove4G.Translation
1008 )
1009 );
1010 if (BaseAddress != MAX_UINT64) {
1011 break;
1012 }
1013
1014 //
1015 // If memory above 4GB is not available, try memory below 4GB
1016 //
1017
1018 case TypeMem32:
1019 BaseAddress = AllocateResource (
1020 TRUE,
1021 RootBridge->ResAllocNode[Index].Length,
1022 MIN (31, BitsOfAlignment),
1023 TO_HOST_ADDRESS (
1024 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
1025 RootBridge->Mem.Translation
1026 ),
1027 TO_HOST_ADDRESS (
1028 RootBridge->Mem.Limit,
1029 RootBridge->Mem.Translation
1030 )
1031 );
1032 break;
1033
1034 case TypePMem64:
1035 BaseAddress = AllocateResource (
1036 TRUE,
1037 RootBridge->ResAllocNode[Index].Length,
1038 MIN (63, BitsOfAlignment),
1039 TO_HOST_ADDRESS (
1040 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
1041 RootBridge->PMemAbove4G.Translation
1042 ),
1043 TO_HOST_ADDRESS (
1044 RootBridge->PMemAbove4G.Limit,
1045 RootBridge->PMemAbove4G.Translation
1046 )
1047 );
1048 if (BaseAddress != MAX_UINT64) {
1049 break;
1050 }
1051
1052 //
1053 // If memory above 4GB is not available, try memory below 4GB
1054 //
1055 case TypePMem32:
1056 BaseAddress = AllocateResource (
1057 TRUE,
1058 RootBridge->ResAllocNode[Index].Length,
1059 MIN (31, BitsOfAlignment),
1060 TO_HOST_ADDRESS (
1061 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
1062 RootBridge->PMem.Translation
1063 ),
1064 TO_HOST_ADDRESS (
1065 RootBridge->PMem.Limit,
1066 RootBridge->PMem.Translation
1067 )
1068 );
1069 break;
1070
1071 default:
1072 ASSERT (FALSE);
1073 break;
1074 }
1075
1076 DEBUG ((
1077 DEBUG_INFO,
1078 " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
1079 mPciResourceTypeStr[Index],
1080 BaseAddress,
1081 RootBridge->ResAllocNode[Index].Length,
1082 Alignment
1083 ));
1084 if (BaseAddress != MAX_UINT64) {
1085 RootBridge->ResAllocNode[Index].Base = BaseAddress;
1086 RootBridge->ResAllocNode[Index].Status = ResAllocated;
1087 DEBUG ((DEBUG_INFO, "Success\n"));
1088 } else {
1089 ReturnStatus = EFI_OUT_OF_RESOURCES;
1090 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
1091 }
1092 }
1093 }
1094 }
1095
1096 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
1097 ResourceConflict (HostBridge);
1098 }
1099
1100 //
1101 // Set resource to zero for nodes where allocation fails
1102 //
1103 for (Link = GetFirstNode (&HostBridge->RootBridges)
1104 ; !IsNull (&HostBridge->RootBridges, Link)
1105 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1106 )
1107 {
1108 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1109 for (Index = TypeIo; Index < TypeBus; Index++) {
1110 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
1111 RootBridge->ResAllocNode[Index].Length = 0;
1112 }
1113 }
1114 }
1115
1116 return ReturnStatus;
1117
1119 //
1120 // HostBridgeInstance->CanRestarted = FALSE;
1121 //
1122 break;
1123
1125 //
1126 // HostBridgeInstance->CanRestarted = FALSE;
1127 //
1128 ReturnStatus = EFI_SUCCESS;
1129 for (Link = GetFirstNode (&HostBridge->RootBridges)
1130 ; !IsNull (&HostBridge->RootBridges, Link)
1131 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1132 )
1133 {
1134 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1135 for (Index = TypeIo; Index < TypeBus; Index++) {
1136 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
1137 switch (Index) {
1138 case TypeIo:
1139 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
1140 if (EFI_ERROR (Status)) {
1141 ReturnStatus = Status;
1142 }
1143
1144 break;
1145
1146 case TypeMem32:
1147 case TypePMem32:
1148 case TypeMem64:
1149 case TypePMem64:
1150 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
1151 if (EFI_ERROR (Status)) {
1152 ReturnStatus = Status;
1153 }
1154
1155 break;
1156
1157 default:
1158 ASSERT (FALSE);
1159 break;
1160 }
1161
1162 RootBridge->ResAllocNode[Index].Type = Index;
1163 RootBridge->ResAllocNode[Index].Base = 0;
1164 RootBridge->ResAllocNode[Index].Length = 0;
1165 RootBridge->ResAllocNode[Index].Status = ResNone;
1166 }
1167 }
1168
1169 RootBridge->ResourceSubmitted = FALSE;
1170 }
1171
1172 HostBridge->CanRestarted = TRUE;
1173 return ReturnStatus;
1174
1176 //
1177 // The resource allocation phase is completed. No specific action is required
1178 // here. This notification can be used to perform any chipset specific programming.
1179 //
1180 break;
1181
1183 //
1184 // The Host Bridge Enumeration is completed. No specific action is required here.
1185 // This notification can be used to perform any chipset specific programming.
1186 //
1187 break;
1188
1189 default:
1190 return EFI_INVALID_PARAMETER;
1191 }
1192
1193 return EFI_SUCCESS;
1194}
1195
1213EFIAPI
1216 IN OUT EFI_HANDLE *RootBridgeHandle
1217 )
1218{
1219 BOOLEAN ReturnNext;
1220 LIST_ENTRY *Link;
1221 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1222 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1223
1224 if (RootBridgeHandle == NULL) {
1225 return EFI_INVALID_PARAMETER;
1226 }
1227
1228 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1229 ReturnNext = (BOOLEAN)(*RootBridgeHandle == NULL);
1230
1231 for (Link = GetFirstNode (&HostBridge->RootBridges)
1232 ; !IsNull (&HostBridge->RootBridges, Link)
1233 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1234 )
1235 {
1236 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1237 if (ReturnNext) {
1238 *RootBridgeHandle = RootBridge->Handle;
1239 return EFI_SUCCESS;
1240 }
1241
1242 ReturnNext = (BOOLEAN)(*RootBridgeHandle == RootBridge->Handle);
1243 }
1244
1245 if (ReturnNext) {
1246 ASSERT (IsNull (&HostBridge->RootBridges, Link));
1247 return EFI_NOT_FOUND;
1248 } else {
1249 return EFI_INVALID_PARAMETER;
1250 }
1251}
1252
1270EFIAPI
1273 IN EFI_HANDLE RootBridgeHandle,
1274 OUT UINT64 *Attributes
1275 )
1276{
1277 LIST_ENTRY *Link;
1278 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1279 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1280
1281 if (Attributes == NULL) {
1282 return EFI_INVALID_PARAMETER;
1283 }
1284
1285 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1286 for (Link = GetFirstNode (&HostBridge->RootBridges)
1287 ; !IsNull (&HostBridge->RootBridges, Link)
1288 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1289 )
1290 {
1291 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1292 if (RootBridgeHandle == RootBridge->Handle) {
1293 *Attributes = RootBridge->AllocationAttributes;
1294 return EFI_SUCCESS;
1295 }
1296 }
1297
1298 return EFI_INVALID_PARAMETER;
1299}
1300
1316EFIAPI
1319 IN EFI_HANDLE RootBridgeHandle,
1320 OUT VOID **Configuration
1321 )
1322{
1323 LIST_ENTRY *Link;
1324 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1325 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1328
1329 if (Configuration == NULL) {
1330 return EFI_INVALID_PARAMETER;
1331 }
1332
1333 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1334 for (Link = GetFirstNode (&HostBridge->RootBridges)
1335 ; !IsNull (&HostBridge->RootBridges, Link)
1336 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1337 )
1338 {
1339 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1340 if (RootBridgeHandle == RootBridge->Handle) {
1341 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1342 if (*Configuration == NULL) {
1343 return EFI_OUT_OF_RESOURCES;
1344 }
1345
1346 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)*Configuration;
1347 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1348 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1349 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
1350 Descriptor->GenFlag = 0;
1351 Descriptor->SpecificFlag = 0;
1352 Descriptor->AddrSpaceGranularity = 0;
1353 Descriptor->AddrRangeMin = RootBridge->Bus.Base;
1354 Descriptor->AddrRangeMax = 0;
1355 Descriptor->AddrTranslationOffset = 0;
1356 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
1357
1358 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Descriptor + 1);
1359 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1360 End->Checksum = 0x0;
1361
1362 return EFI_SUCCESS;
1363 }
1364 }
1365
1366 return EFI_INVALID_PARAMETER;
1367}
1368
1383EFIAPI
1386 IN EFI_HANDLE RootBridgeHandle,
1387 IN VOID *Configuration
1388 )
1389{
1390 LIST_ENTRY *Link;
1391 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1392 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1395
1396 if (Configuration == NULL) {
1397 return EFI_INVALID_PARAMETER;
1398 }
1399
1400 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration;
1401 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)(Descriptor + 1);
1402
1403 //
1404 // Check the Configuration is valid
1405 //
1406 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
1407 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
1408 (End->Desc != ACPI_END_TAG_DESCRIPTOR)
1409 )
1410 {
1411 return EFI_INVALID_PARAMETER;
1412 }
1413
1414 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1415 for (Link = GetFirstNode (&HostBridge->RootBridges)
1416 ; !IsNull (&HostBridge->RootBridges, Link)
1417 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1418 )
1419 {
1420 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1421 if (RootBridgeHandle == RootBridge->Handle) {
1422 if (Descriptor->AddrLen == 0) {
1423 return EFI_INVALID_PARAMETER;
1424 }
1425
1426 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
1427 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
1428 )
1429 {
1430 return EFI_INVALID_PARAMETER;
1431 }
1432
1433 //
1434 // Update the Bus Range
1435 //
1436 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;
1437 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;
1438 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;
1439 return EFI_SUCCESS;
1440 }
1441 }
1442
1443 return EFI_INVALID_PARAMETER;
1444}
1445
1459EFIAPI
1462 IN EFI_HANDLE RootBridgeHandle,
1463 IN VOID *Configuration
1464 )
1465{
1466 LIST_ENTRY *Link;
1467 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1468 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1470 PCI_RESOURCE_TYPE Type;
1471
1472 //
1473 // Check the input parameter: Configuration
1474 //
1475 if (Configuration == NULL) {
1476 return EFI_INVALID_PARAMETER;
1477 }
1478
1479 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1480 for (Link = GetFirstNode (&HostBridge->RootBridges)
1481 ; !IsNull (&HostBridge->RootBridges, Link)
1482 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1483 )
1484 {
1485 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1486 if (RootBridgeHandle == RootBridge->Handle) {
1487 DEBUG ((DEBUG_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
1488 //
1489 // Check the resource descriptors.
1490 // If the Configuration includes one or more invalid resource descriptors, all the resource
1491 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1492 //
1493 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1494 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {
1495 return EFI_INVALID_PARAMETER;
1496 }
1497
1498 DEBUG ((
1499 DEBUG_INFO,
1500 " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1501 mAcpiAddressSpaceTypeStr[Descriptor->ResType],
1502 Descriptor->AddrSpaceGranularity,
1503 Descriptor->SpecificFlag,
1504 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""
1505 ));
1506 DEBUG ((DEBUG_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));
1507 switch (Descriptor->ResType) {
1508 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1509 if ((Descriptor->AddrSpaceGranularity != 32) && (Descriptor->AddrSpaceGranularity != 64)) {
1510 return EFI_INVALID_PARAMETER;
1511 }
1512
1513 if ((Descriptor->AddrSpaceGranularity == 32) && (Descriptor->AddrLen >= SIZE_4GB)) {
1514 return EFI_INVALID_PARAMETER;
1515 }
1516
1517 //
1518 // If the PCI root bridge does not support separate windows for nonprefetchable and
1519 // prefetchable memory, then the PCI bus driver needs to include requests for
1520 // prefetchable memory in the nonprefetchable memory pool.
1521 //
1522 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
1523 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
1524 )
1525 {
1526 return EFI_INVALID_PARAMETER;
1527 }
1528
1529 case ACPI_ADDRESS_SPACE_TYPE_IO:
1530 //
1531 // Check aligment, it should be of the form 2^n-1
1532 //
1533 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
1534 return EFI_INVALID_PARAMETER;
1535 }
1536
1537 break;
1538 default:
1539 ASSERT (FALSE);
1540 break;
1541 }
1542 }
1543
1544 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
1545 return EFI_INVALID_PARAMETER;
1546 }
1547
1548 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1549 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
1550 if (Descriptor->AddrSpaceGranularity == 32) {
1551 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1552 Type = TypePMem32;
1553 } else {
1554 Type = TypeMem32;
1555 }
1556 } else {
1557 ASSERT (Descriptor->AddrSpaceGranularity == 64);
1558 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1559 Type = TypePMem64;
1560 } else {
1561 Type = TypeMem64;
1562 }
1563 }
1564 } else {
1565 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
1566 Type = TypeIo;
1567 }
1568
1569 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;
1570 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
1571 RootBridge->ResAllocNode[Type].Status = ResSubmitted;
1572 }
1573
1574 RootBridge->ResourceSubmitted = TRUE;
1575 return EFI_SUCCESS;
1576 }
1577 }
1578
1579 return EFI_INVALID_PARAMETER;
1580}
1581
1598EFIAPI
1601 IN EFI_HANDLE RootBridgeHandle,
1602 OUT VOID **Configuration
1603 )
1604{
1605 LIST_ENTRY *Link;
1606 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1607 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1608 UINTN Index;
1609 UINTN Number;
1610 VOID *Buffer;
1613 UINT64 ResStatus;
1614
1615 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1616 for (Link = GetFirstNode (&HostBridge->RootBridges)
1617 ; !IsNull (&HostBridge->RootBridges, Link)
1618 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1619 )
1620 {
1621 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1622 if (RootBridgeHandle == RootBridge->Handle) {
1623 for (Index = 0, Number = 0; Index < TypeBus; Index++) {
1624 if (RootBridge->ResAllocNode[Index].Status != ResNone) {
1625 Number++;
1626 }
1627 }
1628
1630 if (Buffer == NULL) {
1631 return EFI_OUT_OF_RESOURCES;
1632 }
1633
1634 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Buffer;
1635 for (Index = 0; Index < TypeBus; Index++) {
1636 ResStatus = RootBridge->ResAllocNode[Index].Status;
1637 if (ResStatus != ResNone) {
1638 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1639 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1640 Descriptor->GenFlag = 0;
1641 //
1642 // AddrRangeMin in Resource Descriptor here should be device address
1643 // instead of host address, or else PCI bus driver cannot set correct
1644 // address into PCI BAR registers.
1645 // Base in ResAllocNode is a host address, so conversion is needed.
1646 //
1647 Descriptor->AddrRangeMin = TO_DEVICE_ADDRESS (
1648 RootBridge->ResAllocNode[Index].Base,
1649 GetTranslationByResourceType (RootBridge, Index)
1650 );
1651 Descriptor->AddrRangeMax = 0;
1652 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
1653 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;
1654
1655 switch (Index) {
1656 case TypeIo:
1657 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1658 break;
1659
1660 case TypePMem32:
1661 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1662 case TypeMem32:
1663 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1664 Descriptor->AddrSpaceGranularity = 32;
1665 break;
1666
1667 case TypePMem64:
1668 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1669 case TypeMem64:
1670 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1671 Descriptor->AddrSpaceGranularity = 64;
1672 break;
1673 }
1674
1675 Descriptor++;
1676 }
1677 }
1678
1679 End = (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor;
1680 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1681 End->Checksum = 0;
1682
1683 *Configuration = Buffer;
1684
1685 return EFI_SUCCESS;
1686 }
1687 }
1688
1689 return EFI_INVALID_PARAMETER;
1690}
1691
1707EFIAPI
1710 IN EFI_HANDLE RootBridgeHandle,
1713 )
1714{
1715 LIST_ENTRY *Link;
1716 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1717 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1718
1719 if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
1720 return EFI_INVALID_PARAMETER;
1721 }
1722
1723 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1724 for (Link = GetFirstNode (&HostBridge->RootBridges)
1725 ; !IsNull (&HostBridge->RootBridges, Link)
1726 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1727 )
1728 {
1729 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1730 if (RootBridgeHandle == RootBridge->Handle) {
1731 return EFI_SUCCESS;
1732 }
1733 }
1734
1735 return EFI_INVALID_PARAMETER;
1736}
UINT64 UINTN
PACKED struct @89 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
BOOLEAN EFIAPI IsNull(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:443
LIST_ENTRY *EFIAPI GetNextNode(IN CONST LIST_ENTRY *List, IN CONST LIST_ENTRY *Node)
Definition: LinkedList.c:333
LIST_ENTRY *EFIAPI GetFirstNode(IN CONST LIST_ENTRY *List)
Definition: LinkedList.c:298
UINT64 EFIAPI GetPowerOfTwo64(IN UINT64 Operand)
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
INTN EFIAPI LowBitSet64(IN UINT64 Operand)
Definition: LowBitSet64.c:27
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
LIST_ENTRY *EFIAPI InsertTailList(IN OUT LIST_ENTRY *ListHead, IN OUT LIST_ENTRY *Entry)
Definition: LinkedList.c:259
EFI_DXE_SERVICES * gDS
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#define MIN(a, b)
Definition: Base.h:1007
#define ALIGN_VALUE(Value, Alignment)
Definition: Base.h:948
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define ARRAY_SIZE(Array)
Definition: Base.h:1393
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define MAX(a, b)
Definition: Base.h:992
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG_CODE_BEGIN()
Definition: DebugLib.h:564
#define DEBUG(Expression)
Definition: DebugLib.h:434
#define DEBUG_CODE_END()
Definition: DebugLib.h:578
PCI_IO_DEVICE * CreateRootBridge(IN EFI_HANDLE RootBridgeHandle)
EFI_STATUS EFIAPI GetNextRootBridge(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN OUT EFI_HANDLE *RootBridgeHandle)
EFI_STATUS EFIAPI NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)
EFI_STATUS EFIAPI PreprocessController(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)
EFI_STATUS EFIAPI StartBusEnumeration(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, OUT VOID **Configuration)
EFI_STATUS EFIAPI InitializePciHostBridge(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
EFI_STATUS IntersectIoDescriptor(IN UINT64 Base, IN UINT64 Length, IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor)
Definition: PciHostBridge.c:94
UINT64 AllocateResource(BOOLEAN Mmio, UINT64 Length, UINTN BitsOfAlignment, UINT64 BaseAddress, UINT64 Limit)
EFI_STATUS EFIAPI GetAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, OUT UINT64 *Attributes)
EFI_STATUS EFIAPI SetBusNumbers(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, IN VOID *Configuration)
VOID ResourceConflict(IN PCI_HOST_BRIDGE_INSTANCE *HostBridge)
VOID EFIAPI IoMmuProtocolCallback(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS AddIoSpace(IN UINT64 Base, IN UINT64 Length)
UINT64 GetTranslationByResourceType(IN PCI_ROOT_BRIDGE_INSTANCE *RootBridge, IN PCI_RESOURCE_TYPE ResourceType)
Definition: PciHostBridge.c:36
EFI_STATUS EFIAPI GetProposedResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, OUT VOID **Configuration)
EFI_STATUS EFIAPI SubmitResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, IN EFI_HANDLE RootBridgeHandle, IN VOID *Configuration)
EFI_STATUS AddMemoryMappedIoSpace(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities)
EFI_STATUS IntersectMemoryDescriptor(IN UINT64 Base, IN UINT64 Length, IN UINT64 Capabilities, IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor)
PCI_ROOT_BRIDGE *EFIAPI PciHostBridgeGetRootBridges(UINTN *Count)
VOID EFIAPI PciHostBridgeFreeRootBridges(PCI_ROOT_BRIDGE *Bridges, UINTN Count)
VOID EFIAPI PciHostBridgeResourceConflict(EFI_HANDLE HostBridgeHandle, VOID *Configuration)
#define EFI_RESOURCE_SATISFIED
#define EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE
@ EfiPciHostBridgeBeginEnumeration
@ EfiPciHostBridgeBeginResourceAllocation
@ EfiPciHostBridgeAllocateResources
@ EfiPciHostBridgeBeginBusAllocation
@ EfiPciHostBridgeEndResourceAllocation
@ EfiPciHostBridgeEndBusAllocation
EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE
@ EfiGcdMemoryTypeNonExistent
Definition: PiDxeCis.h:26
@ EfiGcdMemoryTypeMemoryMappedIo
Definition: PiDxeCis.h:44
@ EfiGcdAllocateAddress
Definition: PiDxeCis.h:107
@ EfiGcdIoTypeNonExistent
Definition: PiDxeCis.h:75
@ EfiGcdIoTypeIo
Definition: PiDxeCis.h:85
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
EFI_GUID gEdkiiIoMmuProtocolGuid
UINT64 EFI_PHYSICAL_ADDRESS
Definition: UefiBaseType.h:50
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_HANDLE gImageHandle
EFI_BOOT_SERVICES * gBS
EFI_EVENT EFIAPI EfiCreateProtocolNotifyEvent(IN EFI_GUID *ProtocolGuid, IN EFI_TPL NotifyTpl, IN EFI_EVENT_NOTIFY NotifyFunction, IN VOID *NotifyContext OPTIONAL, OUT VOID **Registration)
Definition: UefiLib.c:134
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES SubmitResources
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION StartBusEnumeration
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES GetAllocAttributes
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS SetBusNumbers
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE NotifyPhase
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER PreprocessController
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES GetProposedResources
EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE GetNextRootBridge
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:181
EFI_GCD_IO_TYPE GcdIoType
Definition: PiDxeCis.h:192
EFI_GCD_MEMORY_TYPE GcdMemoryType
Definition: PiDxeCis.h:152
EFI_PHYSICAL_ADDRESS BaseAddress
Definition: PiDxeCis.h:130
PCI_ROOT_BRIDGE_APERTURE Io
IO aperture which can be used by the root bridge.
BOOLEAN ResourceAssigned
PCI_ROOT_BRIDGE_APERTURE PMem
Prefetchable MMIO aperture below 4GB which can be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE Mem
MMIO aperture below 4GB which can be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE PMemAbove4G
Prefetchable MMIO aperture above 4GB which can be used by the root bridge.
PCI_ROOT_BRIDGE_APERTURE MemAbove4G
MMIO aperture above 4GB which can be used by the root bridge.