]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg/Include: Add IOMMU protocol definition.
[mirror_edk2.git] / MdeModulePkg / Bus / Pci / PciHostBridgeDxe / PciHostBridge.c
1 /** @file
2
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
4
5 Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "PciHostBridge.h"
17 #include "PciRootBridge.h"
18 #include "PciHostResource.h"
19
20
21 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
22 EFI_CPU_IO2_PROTOCOL *mCpuIo;
23
24 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mAcpiAddressSpaceTypeStr[] = {
25 L"Mem", L"I/O", L"Bus"
26 };
27 GLOBAL_REMOVE_IF_UNREFERENCED CHAR16 *mPciResourceTypeStr[] = {
28 L"I/O", L"Mem", L"PMem", L"Mem64", L"PMem64", L"Bus"
29 };
30
31 /**
32 Ensure the compatibility of an IO space descriptor with the IO aperture.
33
34 The IO space descriptor can come from the GCD IO space map, or it can
35 represent a gap between two neighboring IO space descriptors. In the latter
36 case, the GcdIoType field is expected to be EfiGcdIoTypeNonExistent.
37
38 If the IO space descriptor already has type EfiGcdIoTypeIo, then no action is
39 taken -- it is by definition compatible with the aperture.
40
41 Otherwise, the intersection of the IO space descriptor is calculated with the
42 aperture. If the intersection is the empty set (no overlap), no action is
43 taken; the IO space descriptor is compatible with the aperture.
44
45 Otherwise, the type of the descriptor is investigated again. If the type is
46 EfiGcdIoTypeNonExistent (representing a gap, or a genuine descriptor with
47 such a type), then an attempt is made to add the intersection as IO space to
48 the GCD IO space map. This ensures continuity for the aperture, and the
49 descriptor is deemed compatible with the aperture.
50
51 Otherwise, the IO space descriptor is incompatible with the IO aperture.
52
53 @param[in] Base Base address of the aperture.
54 @param[in] Length Length of the aperture.
55 @param[in] Descriptor The descriptor to ensure compatibility with the
56 aperture for.
57
58 @retval EFI_SUCCESS The descriptor is compatible. The GCD IO space
59 map may have been updated, for continuity
60 within the aperture.
61 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
62 @return Error codes from gDS->AddIoSpace().
63 **/
64 EFI_STATUS
65 IntersectIoDescriptor (
66 IN UINT64 Base,
67 IN UINT64 Length,
68 IN CONST EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor
69 )
70 {
71 UINT64 IntersectionBase;
72 UINT64 IntersectionEnd;
73 EFI_STATUS Status;
74
75 if (Descriptor->GcdIoType == EfiGcdIoTypeIo) {
76 return EFI_SUCCESS;
77 }
78
79 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
80 IntersectionEnd = MIN (Base + Length,
81 Descriptor->BaseAddress + Descriptor->Length);
82 if (IntersectionBase >= IntersectionEnd) {
83 //
84 // The descriptor and the aperture don't overlap.
85 //
86 return EFI_SUCCESS;
87 }
88
89 if (Descriptor->GcdIoType == EfiGcdIoTypeNonExistent) {
90 Status = gDS->AddIoSpace (EfiGcdIoTypeIo, IntersectionBase,
91 IntersectionEnd - IntersectionBase);
92
93 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,
94 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,
95 IntersectionBase, IntersectionEnd, Status));
96 return Status;
97 }
98
99 DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u conflicts with "
100 "aperture [%Lx, %Lx)\n", gEfiCallerBaseName, __FUNCTION__,
101 Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,
102 (UINT32)Descriptor->GcdIoType, Base, Base + Length));
103 return EFI_INVALID_PARAMETER;
104 }
105
106 /**
107 Add IO space to GCD.
108 The routine checks the GCD database and only adds those which are
109 not added in the specified range to GCD.
110
111 @param Base Base address of the IO space.
112 @param Length Length of the IO space.
113
114 @retval EFI_SUCCES The IO space was added successfully.
115 **/
116 EFI_STATUS
117 AddIoSpace (
118 IN UINT64 Base,
119 IN UINT64 Length
120 )
121 {
122 EFI_STATUS Status;
123 UINTN Index;
124 UINTN NumberOfDescriptors;
125 EFI_GCD_IO_SPACE_DESCRIPTOR *IoSpaceMap;
126
127 Status = gDS->GetIoSpaceMap (&NumberOfDescriptors, &IoSpaceMap);
128 if (EFI_ERROR (Status)) {
129 DEBUG ((EFI_D_ERROR, "%a: %a: GetIoSpaceMap(): %r\n",
130 gEfiCallerBaseName, __FUNCTION__, Status));
131 return Status;
132 }
133
134 for (Index = 0; Index < NumberOfDescriptors; Index++) {
135 Status = IntersectIoDescriptor (Base, Length, &IoSpaceMap[Index]);
136 if (EFI_ERROR (Status)) {
137 goto FreeIoSpaceMap;
138 }
139 }
140
141 DEBUG_CODE (
142 //
143 // Make sure there are adjacent descriptors covering [Base, Base + Length).
144 // It is possible that they have not been merged; merging can be prevented
145 // by allocation.
146 //
147 UINT64 CheckBase;
148 EFI_STATUS CheckStatus;
149 EFI_GCD_IO_SPACE_DESCRIPTOR Descriptor;
150
151 for (CheckBase = Base;
152 CheckBase < Base + Length;
153 CheckBase = Descriptor.BaseAddress + Descriptor.Length) {
154 CheckStatus = gDS->GetIoSpaceDescriptor (CheckBase, &Descriptor);
155 ASSERT_EFI_ERROR (CheckStatus);
156 ASSERT (Descriptor.GcdIoType == EfiGcdIoTypeIo);
157 }
158 );
159
160 FreeIoSpaceMap:
161 FreePool (IoSpaceMap);
162
163 return Status;
164 }
165
166 /**
167 Ensure the compatibility of a memory space descriptor with the MMIO aperture.
168
169 The memory space descriptor can come from the GCD memory space map, or it can
170 represent a gap between two neighboring memory space descriptors. In the
171 latter case, the GcdMemoryType field is expected to be
172 EfiGcdMemoryTypeNonExistent.
173
174 If the memory space descriptor already has type
175 EfiGcdMemoryTypeMemoryMappedIo, and its capabilities are a superset of the
176 required capabilities, then no action is taken -- it is by definition
177 compatible with the aperture.
178
179 Otherwise, the intersection of the memory space descriptor is calculated with
180 the aperture. If the intersection is the empty set (no overlap), no action is
181 taken; the memory space descriptor is compatible with the aperture.
182
183 Otherwise, the type of the descriptor is investigated again. If the type is
184 EfiGcdMemoryTypeNonExistent (representing a gap, or a genuine descriptor with
185 such a type), then an attempt is made to add the intersection as MMIO space
186 to the GCD memory space map, with the specified capabilities. This ensures
187 continuity for the aperture, and the descriptor is deemed compatible with the
188 aperture.
189
190 Otherwise, the memory space descriptor is incompatible with the MMIO
191 aperture.
192
193 @param[in] Base Base address of the aperture.
194 @param[in] Length Length of the aperture.
195 @param[in] Capabilities Capabilities required by the aperture.
196 @param[in] Descriptor The descriptor to ensure compatibility with the
197 aperture for.
198
199 @retval EFI_SUCCESS The descriptor is compatible. The GCD memory
200 space map may have been updated, for
201 continuity within the aperture.
202 @retval EFI_INVALID_PARAMETER The descriptor is incompatible.
203 @return Error codes from gDS->AddMemorySpace().
204 **/
205 EFI_STATUS
206 IntersectMemoryDescriptor (
207 IN UINT64 Base,
208 IN UINT64 Length,
209 IN UINT64 Capabilities,
210 IN CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor
211 )
212 {
213 UINT64 IntersectionBase;
214 UINT64 IntersectionEnd;
215 EFI_STATUS Status;
216
217 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo &&
218 (Descriptor->Capabilities & Capabilities) == Capabilities) {
219 return EFI_SUCCESS;
220 }
221
222 IntersectionBase = MAX (Base, Descriptor->BaseAddress);
223 IntersectionEnd = MIN (Base + Length,
224 Descriptor->BaseAddress + Descriptor->Length);
225 if (IntersectionBase >= IntersectionEnd) {
226 //
227 // The descriptor and the aperture don't overlap.
228 //
229 return EFI_SUCCESS;
230 }
231
232 if (Descriptor->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
233 Status = gDS->AddMemorySpace (EfiGcdMemoryTypeMemoryMappedIo,
234 IntersectionBase, IntersectionEnd - IntersectionBase,
235 Capabilities);
236
237 DEBUG ((EFI_ERROR (Status) ? EFI_D_ERROR : EFI_D_VERBOSE,
238 "%a: %a: add [%Lx, %Lx): %r\n", gEfiCallerBaseName, __FUNCTION__,
239 IntersectionBase, IntersectionEnd, Status));
240 return Status;
241 }
242
243 DEBUG ((EFI_D_ERROR, "%a: %a: desc [%Lx, %Lx) type %u cap %Lx conflicts "
244 "with aperture [%Lx, %Lx) cap %Lx\n", gEfiCallerBaseName, __FUNCTION__,
245 Descriptor->BaseAddress, Descriptor->BaseAddress + Descriptor->Length,
246 (UINT32)Descriptor->GcdMemoryType, Descriptor->Capabilities,
247 Base, Base + Length, Capabilities));
248 return EFI_INVALID_PARAMETER;
249 }
250
251 /**
252 Add MMIO space to GCD.
253 The routine checks the GCD database and only adds those which are
254 not added in the specified range to GCD.
255
256 @param Base Base address of the MMIO space.
257 @param Length Length of the MMIO space.
258 @param Capabilities Capabilities of the MMIO space.
259
260 @retval EFI_SUCCES The MMIO space was added successfully.
261 **/
262 EFI_STATUS
263 AddMemoryMappedIoSpace (
264 IN UINT64 Base,
265 IN UINT64 Length,
266 IN UINT64 Capabilities
267 )
268 {
269 EFI_STATUS Status;
270 UINTN Index;
271 UINTN NumberOfDescriptors;
272 EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap;
273
274 Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap);
275 if (EFI_ERROR (Status)) {
276 DEBUG ((EFI_D_ERROR, "%a: %a: GetMemorySpaceMap(): %r\n",
277 gEfiCallerBaseName, __FUNCTION__, Status));
278 return Status;
279 }
280
281 for (Index = 0; Index < NumberOfDescriptors; Index++) {
282 Status = IntersectMemoryDescriptor (Base, Length, Capabilities,
283 &MemorySpaceMap[Index]);
284 if (EFI_ERROR (Status)) {
285 goto FreeMemorySpaceMap;
286 }
287 }
288
289 DEBUG_CODE (
290 //
291 // Make sure there are adjacent descriptors covering [Base, Base + Length).
292 // It is possible that they have not been merged; merging can be prevented
293 // by allocation and different capabilities.
294 //
295 UINT64 CheckBase;
296 EFI_STATUS CheckStatus;
297 EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor;
298
299 for (CheckBase = Base;
300 CheckBase < Base + Length;
301 CheckBase = Descriptor.BaseAddress + Descriptor.Length) {
302 CheckStatus = gDS->GetMemorySpaceDescriptor (CheckBase, &Descriptor);
303 ASSERT_EFI_ERROR (CheckStatus);
304 ASSERT (Descriptor.GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo);
305 ASSERT ((Descriptor.Capabilities & Capabilities) == Capabilities);
306 }
307 );
308
309 FreeMemorySpaceMap:
310 FreePool (MemorySpaceMap);
311
312 return Status;
313 }
314
315 /**
316
317 Entry point of this driver.
318
319 @param ImageHandle Image handle of this driver.
320 @param SystemTable Pointer to standard EFI system table.
321
322 @retval EFI_SUCCESS Succeed.
323 @retval EFI_DEVICE_ERROR Fail to install PCI_ROOT_BRIDGE_IO protocol.
324
325 **/
326 EFI_STATUS
327 EFIAPI
328 InitializePciHostBridge (
329 IN EFI_HANDLE ImageHandle,
330 IN EFI_SYSTEM_TABLE *SystemTable
331 )
332 {
333 EFI_STATUS Status;
334 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
335 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
336 PCI_ROOT_BRIDGE *RootBridges;
337 UINTN RootBridgeCount;
338 UINTN Index;
339 PCI_ROOT_BRIDGE_APERTURE *MemApertures[4];
340 UINTN MemApertureIndex;
341 BOOLEAN ResourceAssigned;
342 LIST_ENTRY *Link;
343
344 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
345 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
346 return EFI_UNSUPPORTED;
347 }
348
349 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
350 ASSERT_EFI_ERROR (Status);
351 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);
352 ASSERT_EFI_ERROR (Status);
353
354 //
355 // Most systems in the world including complex servers have only one Host Bridge.
356 //
357 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
358 ASSERT (HostBridge != NULL);
359
360 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
361 HostBridge->CanRestarted = TRUE;
362 InitializeListHead (&HostBridge->RootBridges);
363 ResourceAssigned = FALSE;
364
365 //
366 // Create Root Bridge Device Handle in this Host Bridge
367 //
368 for (Index = 0; Index < RootBridgeCount; Index++) {
369 //
370 // Create Root Bridge Handle Instance
371 //
372 RootBridge = CreateRootBridge (&RootBridges[Index]);
373 ASSERT (RootBridge != NULL);
374 if (RootBridge == NULL) {
375 continue;
376 }
377
378 //
379 // Make sure all root bridges share the same ResourceAssigned value.
380 //
381 if (Index == 0) {
382 ResourceAssigned = RootBridges[Index].ResourceAssigned;
383 } else {
384 ASSERT (ResourceAssigned == RootBridges[Index].ResourceAssigned);
385 }
386
387 if (RootBridges[Index].Io.Base <= RootBridges[Index].Io.Limit) {
388 Status = AddIoSpace (
389 RootBridges[Index].Io.Base,
390 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
391 );
392 ASSERT_EFI_ERROR (Status);
393 if (ResourceAssigned) {
394 Status = gDS->AllocateIoSpace (
395 EfiGcdAllocateAddress,
396 EfiGcdIoTypeIo,
397 0,
398 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1,
399 &RootBridges[Index].Io.Base,
400 gImageHandle,
401 NULL
402 );
403 ASSERT_EFI_ERROR (Status);
404 }
405 }
406
407 //
408 // Add all the Mem/PMem aperture to GCD
409 // Mem/PMem shouldn't overlap with each other
410 // Root bridge which needs to combine MEM and PMEM should only report
411 // the MEM aperture in Mem
412 //
413 MemApertures[0] = &RootBridges[Index].Mem;
414 MemApertures[1] = &RootBridges[Index].MemAbove4G;
415 MemApertures[2] = &RootBridges[Index].PMem;
416 MemApertures[3] = &RootBridges[Index].PMemAbove4G;
417
418 for (MemApertureIndex = 0; MemApertureIndex < ARRAY_SIZE (MemApertures); MemApertureIndex++) {
419 if (MemApertures[MemApertureIndex]->Base <= MemApertures[MemApertureIndex]->Limit) {
420 Status = AddMemoryMappedIoSpace (
421 MemApertures[MemApertureIndex]->Base,
422 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
423 EFI_MEMORY_UC
424 );
425 ASSERT_EFI_ERROR (Status);
426 Status = gDS->SetMemorySpaceAttributes (
427 MemApertures[MemApertureIndex]->Base,
428 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
429 EFI_MEMORY_UC
430 );
431 if (EFI_ERROR (Status)) {
432 DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
433 }
434 if (ResourceAssigned) {
435 Status = gDS->AllocateMemorySpace (
436 EfiGcdAllocateAddress,
437 EfiGcdMemoryTypeMemoryMappedIo,
438 0,
439 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
440 &MemApertures[MemApertureIndex]->Base,
441 gImageHandle,
442 NULL
443 );
444 ASSERT_EFI_ERROR (Status);
445 }
446 }
447 }
448 //
449 // Insert Root Bridge Handle Instance
450 //
451 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
452 }
453
454 //
455 // When resources were assigned, it's not needed to expose
456 // PciHostBridgeResourceAllocation protocol.
457 //
458 if (!ResourceAssigned) {
459 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
460 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
461 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
462 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
463 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
464 HostBridge->ResAlloc.SubmitResources = SubmitResources;
465 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
466 HostBridge->ResAlloc.PreprocessController = PreprocessController;
467
468 Status = gBS->InstallMultipleProtocolInterfaces (
469 &HostBridge->Handle,
470 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
471 NULL
472 );
473 ASSERT_EFI_ERROR (Status);
474 }
475
476 for (Link = GetFirstNode (&HostBridge->RootBridges)
477 ; !IsNull (&HostBridge->RootBridges, Link)
478 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
479 ) {
480 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
481 RootBridge->RootBridgeIo.ParentHandle = HostBridge->Handle;
482
483 Status = gBS->InstallMultipleProtocolInterfaces (
484 &RootBridge->Handle,
485 &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,
486 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,
487 NULL
488 );
489 ASSERT_EFI_ERROR (Status);
490 }
491 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
492 return Status;
493 }
494
495 /**
496 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
497
498 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
499 **/
500 VOID
501 ResourceConflict (
502 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
503 )
504 {
505 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
506 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
507 EFI_ACPI_END_TAG_DESCRIPTOR *End;
508 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
509 LIST_ENTRY *Link;
510 UINTN RootBridgeCount;
511 PCI_RESOURCE_TYPE Index;
512 PCI_RES_NODE *ResAllocNode;
513
514 RootBridgeCount = 0;
515 for (Link = GetFirstNode (&HostBridge->RootBridges)
516 ; !IsNull (&HostBridge->RootBridges, Link)
517 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
518 ) {
519 RootBridgeCount++;
520 }
521
522 Resources = AllocatePool (
523 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +
524 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
525 );
526 ASSERT (Resources != NULL);
527
528 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
529 ; !IsNull (&HostBridge->RootBridges, Link)
530 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
531 ) {
532 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
533 for (Index = TypeIo; Index < TypeMax; Index++) {
534 ResAllocNode = &RootBridge->ResAllocNode[Index];
535
536 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
537 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
538 Descriptor->AddrRangeMin = ResAllocNode->Base;
539 Descriptor->AddrRangeMax = ResAllocNode->Alignment;
540 Descriptor->AddrLen = ResAllocNode->Length;
541 switch (ResAllocNode->Type) {
542
543 case TypeIo:
544 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
545 break;
546
547 case TypePMem32:
548 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
549 case TypeMem32:
550 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
551 Descriptor->AddrSpaceGranularity = 32;
552 break;
553
554 case TypePMem64:
555 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
556 case TypeMem64:
557 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
558 Descriptor->AddrSpaceGranularity = 64;
559 break;
560
561 case TypeBus:
562 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
563 break;
564
565 default:
566 break;
567 }
568
569 Descriptor++;
570 }
571 //
572 // Terminate the root bridge resources.
573 //
574 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
575 End->Desc = ACPI_END_TAG_DESCRIPTOR;
576 End->Checksum = 0x0;
577
578 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);
579 }
580 //
581 // Terminate the host bridge resources.
582 //
583 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
584 End->Desc = ACPI_END_TAG_DESCRIPTOR;
585 End->Checksum = 0x0;
586
587 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
588 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
589 FreePool (Resources);
590 }
591
592 /**
593 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
594 from GCD range [BaseAddress, Limit).
595
596 @param Mmio TRUE for MMIO and FALSE for IO.
597 @param Length Length of the resource to allocate.
598 @param BitsOfAlignment Alignment of the resource to allocate.
599 @param BaseAddress The starting address the allocation is from.
600 @param Limit The ending address the allocation is to.
601
602 @retval The base address of the allocated resource or MAX_UINT64 if allocation
603 fails.
604 **/
605 UINT64
606 AllocateResource (
607 BOOLEAN Mmio,
608 UINT64 Length,
609 UINTN BitsOfAlignment,
610 UINT64 BaseAddress,
611 UINT64 Limit
612 )
613 {
614 EFI_STATUS Status;
615
616 if (BaseAddress < Limit) {
617 //
618 // Have to make sure Aligment is handled since we are doing direct address allocation
619 //
620 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
621
622 while (BaseAddress + Length <= Limit + 1) {
623 if (Mmio) {
624 Status = gDS->AllocateMemorySpace (
625 EfiGcdAllocateAddress,
626 EfiGcdMemoryTypeMemoryMappedIo,
627 BitsOfAlignment,
628 Length,
629 &BaseAddress,
630 gImageHandle,
631 NULL
632 );
633 } else {
634 Status = gDS->AllocateIoSpace (
635 EfiGcdAllocateAddress,
636 EfiGcdIoTypeIo,
637 BitsOfAlignment,
638 Length,
639 &BaseAddress,
640 gImageHandle,
641 NULL
642 );
643 }
644
645 if (!EFI_ERROR (Status)) {
646 return BaseAddress;
647 }
648 BaseAddress += LShiftU64 (1, BitsOfAlignment);
649 }
650 }
651 return MAX_UINT64;
652 }
653
654 /**
655
656 Enter a certain phase of the PCI enumeration process.
657
658 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
659 @param Phase The phase during enumeration.
660
661 @retval EFI_SUCCESS Succeed.
662 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
663 @retval EFI_NOT_READY Resources have not been submitted yet.
664
665 **/
666 EFI_STATUS
667 EFIAPI
668 NotifyPhase (
669 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
670 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
671 )
672 {
673 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
674 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
675 LIST_ENTRY *Link;
676 EFI_PHYSICAL_ADDRESS BaseAddress;
677 UINTN BitsOfAlignment;
678 UINT64 Alignment;
679 EFI_STATUS Status;
680 EFI_STATUS ReturnStatus;
681 PCI_RESOURCE_TYPE Index;
682 PCI_RESOURCE_TYPE Index1;
683 PCI_RESOURCE_TYPE Index2;
684 BOOLEAN ResNodeHandled[TypeMax];
685 UINT64 MaxAlignment;
686
687 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
688
689 switch (Phase) {
690 case EfiPciHostBridgeBeginEnumeration:
691 if (!HostBridge->CanRestarted) {
692 return EFI_NOT_READY;
693 }
694 //
695 // Reset Root Bridge
696 //
697 for (Link = GetFirstNode (&HostBridge->RootBridges)
698 ; !IsNull (&HostBridge->RootBridges, Link)
699 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
700 ) {
701 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
702 for (Index = TypeIo; Index < TypeMax; Index++) {
703 RootBridge->ResAllocNode[Index].Type = Index;
704 RootBridge->ResAllocNode[Index].Base = 0;
705 RootBridge->ResAllocNode[Index].Length = 0;
706 RootBridge->ResAllocNode[Index].Status = ResNone;
707
708 RootBridge->ResourceSubmitted = FALSE;
709 }
710 }
711
712 HostBridge->CanRestarted = TRUE;
713 break;
714
715 case EfiPciHostBridgeBeginBusAllocation:
716 //
717 // No specific action is required here, can perform any chipset specific programing
718 //
719 HostBridge->CanRestarted = FALSE;
720 break;
721
722 case EfiPciHostBridgeEndBusAllocation:
723 //
724 // No specific action is required here, can perform any chipset specific programing
725 //
726 break;
727
728 case EfiPciHostBridgeBeginResourceAllocation:
729 //
730 // No specific action is required here, can perform any chipset specific programing
731 //
732 break;
733
734 case EfiPciHostBridgeAllocateResources:
735 ReturnStatus = EFI_SUCCESS;
736
737 //
738 // Make sure the resource for all root bridges has been submitted.
739 //
740 for (Link = GetFirstNode (&HostBridge->RootBridges)
741 ; !IsNull (&HostBridge->RootBridges, Link)
742 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
743 ) {
744 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
745 if (!RootBridge->ResourceSubmitted) {
746 return EFI_NOT_READY;
747 }
748 }
749
750 DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
751 for (Link = GetFirstNode (&HostBridge->RootBridges)
752 ; !IsNull (&HostBridge->RootBridges, Link)
753 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
754 ) {
755 for (Index = TypeIo; Index < TypeBus; Index++) {
756 ResNodeHandled[Index] = FALSE;
757 }
758
759 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
760 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
761
762 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
763 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
764 ResNodeHandled[Index1] = TRUE;
765 } else {
766 //
767 // Allocate the resource node with max alignment at first
768 //
769 MaxAlignment = 0;
770 Index = TypeMax;
771 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
772 if (ResNodeHandled[Index2]) {
773 continue;
774 }
775 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
776 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
777 Index = Index2;
778 }
779 }
780
781 ASSERT (Index < TypeMax);
782 ResNodeHandled[Index] = TRUE;
783 Alignment = RootBridge->ResAllocNode[Index].Alignment;
784 BitsOfAlignment = LowBitSet64 (Alignment + 1);
785 BaseAddress = MAX_UINT64;
786
787 switch (Index) {
788 case TypeIo:
789 BaseAddress = AllocateResource (
790 FALSE,
791 RootBridge->ResAllocNode[Index].Length,
792 MIN (15, BitsOfAlignment),
793 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
794 RootBridge->Io.Limit
795 );
796 break;
797
798 case TypeMem64:
799 BaseAddress = AllocateResource (
800 TRUE,
801 RootBridge->ResAllocNode[Index].Length,
802 MIN (63, BitsOfAlignment),
803 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
804 RootBridge->MemAbove4G.Limit
805 );
806 if (BaseAddress != MAX_UINT64) {
807 break;
808 }
809 //
810 // If memory above 4GB is not available, try memory below 4GB
811 //
812
813 case TypeMem32:
814 BaseAddress = AllocateResource (
815 TRUE,
816 RootBridge->ResAllocNode[Index].Length,
817 MIN (31, BitsOfAlignment),
818 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
819 RootBridge->Mem.Limit
820 );
821 break;
822
823 case TypePMem64:
824 BaseAddress = AllocateResource (
825 TRUE,
826 RootBridge->ResAllocNode[Index].Length,
827 MIN (63, BitsOfAlignment),
828 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
829 RootBridge->PMemAbove4G.Limit
830 );
831 if (BaseAddress != MAX_UINT64) {
832 break;
833 }
834 //
835 // If memory above 4GB is not available, try memory below 4GB
836 //
837 case TypePMem32:
838 BaseAddress = AllocateResource (
839 TRUE,
840 RootBridge->ResAllocNode[Index].Length,
841 MIN (31, BitsOfAlignment),
842 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
843 RootBridge->PMem.Limit
844 );
845 break;
846
847 default:
848 ASSERT (FALSE);
849 break;
850 }
851
852 DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
853 mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));
854 if (BaseAddress != MAX_UINT64) {
855 RootBridge->ResAllocNode[Index].Base = BaseAddress;
856 RootBridge->ResAllocNode[Index].Status = ResAllocated;
857 DEBUG ((DEBUG_INFO, "Success\n"));
858 } else {
859 ReturnStatus = EFI_OUT_OF_RESOURCES;
860 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
861 }
862 }
863 }
864 }
865
866 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
867 ResourceConflict (HostBridge);
868 }
869
870 //
871 // Set resource to zero for nodes where allocation fails
872 //
873 for (Link = GetFirstNode (&HostBridge->RootBridges)
874 ; !IsNull (&HostBridge->RootBridges, Link)
875 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
876 ) {
877 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
878 for (Index = TypeIo; Index < TypeBus; Index++) {
879 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
880 RootBridge->ResAllocNode[Index].Length = 0;
881 }
882 }
883 }
884 return ReturnStatus;
885
886 case EfiPciHostBridgeSetResources:
887 //
888 // HostBridgeInstance->CanRestarted = FALSE;
889 //
890 break;
891
892 case EfiPciHostBridgeFreeResources:
893 //
894 // HostBridgeInstance->CanRestarted = FALSE;
895 //
896 ReturnStatus = EFI_SUCCESS;
897 for (Link = GetFirstNode (&HostBridge->RootBridges)
898 ; !IsNull (&HostBridge->RootBridges, Link)
899 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
900 ) {
901 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
902 for (Index = TypeIo; Index < TypeBus; Index++) {
903 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
904 switch (Index) {
905 case TypeIo:
906 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
907 if (EFI_ERROR (Status)) {
908 ReturnStatus = Status;
909 }
910 break;
911
912 case TypeMem32:
913 case TypePMem32:
914 case TypeMem64:
915 case TypePMem64:
916 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
917 if (EFI_ERROR (Status)) {
918 ReturnStatus = Status;
919 }
920 break;
921
922 default:
923 ASSERT (FALSE);
924 break;
925 }
926
927 RootBridge->ResAllocNode[Index].Type = Index;
928 RootBridge->ResAllocNode[Index].Base = 0;
929 RootBridge->ResAllocNode[Index].Length = 0;
930 RootBridge->ResAllocNode[Index].Status = ResNone;
931 }
932 }
933
934 RootBridge->ResourceSubmitted = FALSE;
935 }
936
937 HostBridge->CanRestarted = TRUE;
938 return ReturnStatus;
939
940 case EfiPciHostBridgeEndResourceAllocation:
941 //
942 // The resource allocation phase is completed. No specific action is required
943 // here. This notification can be used to perform any chipset specific programming.
944 //
945 break;
946
947 case EfiPciHostBridgeEndEnumeration:
948 //
949 // The Host Bridge Enumeration is completed. No specific action is required here.
950 // This notification can be used to perform any chipset specific programming.
951 //
952 break;
953
954 default:
955 return EFI_INVALID_PARAMETER;
956 }
957
958 return EFI_SUCCESS;
959 }
960
961 /**
962
963 Return the device handle of the next PCI root bridge that is associated with
964 this Host Bridge.
965
966 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
967 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
968 On input, it holds the RootBridgeHandle returned by the most
969 recent call to GetNextRootBridge().The handle for the first
970 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
971
972 @retval EFI_SUCCESS Succeed.
973 @retval EFI_NOT_FOUND Next PCI root bridge not found.
974 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
975
976 **/
977 EFI_STATUS
978 EFIAPI
979 GetNextRootBridge (
980 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
981 IN OUT EFI_HANDLE *RootBridgeHandle
982 )
983 {
984 BOOLEAN ReturnNext;
985 LIST_ENTRY *Link;
986 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
987 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
988
989 if (RootBridgeHandle == NULL) {
990 return EFI_INVALID_PARAMETER;
991 }
992
993 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
994 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);
995
996 for (Link = GetFirstNode (&HostBridge->RootBridges)
997 ; !IsNull (&HostBridge->RootBridges, Link)
998 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
999 ) {
1000 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1001 if (ReturnNext) {
1002 *RootBridgeHandle = RootBridge->Handle;
1003 return EFI_SUCCESS;
1004 }
1005
1006 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);
1007 }
1008
1009 if (ReturnNext) {
1010 ASSERT (IsNull (&HostBridge->RootBridges, Link));
1011 return EFI_NOT_FOUND;
1012 } else {
1013 return EFI_INVALID_PARAMETER;
1014 }
1015 }
1016
1017 /**
1018
1019 Returns the attributes of a PCI Root Bridge.
1020
1021 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1022 @param RootBridgeHandle The device handle of the PCI Root Bridge
1023 that the caller is interested in.
1024 @param Attributes The pointer to attributes of the PCI Root Bridge.
1025
1026 @retval EFI_SUCCESS Succeed.
1027 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
1028 RootBridgeHandle is not an EFI_HANDLE
1029 that was returned on a previous call to
1030 GetNextRootBridge().
1031
1032 **/
1033 EFI_STATUS
1034 EFIAPI
1035 GetAttributes (
1036 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1037 IN EFI_HANDLE RootBridgeHandle,
1038 OUT UINT64 *Attributes
1039 )
1040 {
1041 LIST_ENTRY *Link;
1042 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1043 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1044
1045 if (Attributes == NULL) {
1046 return EFI_INVALID_PARAMETER;
1047 }
1048
1049 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1050 for (Link = GetFirstNode (&HostBridge->RootBridges)
1051 ; !IsNull (&HostBridge->RootBridges, Link)
1052 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1053 ) {
1054 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1055 if (RootBridgeHandle == RootBridge->Handle) {
1056 *Attributes = RootBridge->AllocationAttributes;
1057 return EFI_SUCCESS;
1058 }
1059 }
1060
1061 return EFI_INVALID_PARAMETER;
1062 }
1063
1064 /**
1065
1066 This is the request from the PCI enumerator to set up
1067 the specified PCI Root Bridge for bus enumeration process.
1068
1069 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1070 @param RootBridgeHandle The PCI Root Bridge to be set up.
1071 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1072
1073 @retval EFI_SUCCESS Succeed.
1074 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1075 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1076
1077 **/
1078 EFI_STATUS
1079 EFIAPI
1080 StartBusEnumeration (
1081 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1082 IN EFI_HANDLE RootBridgeHandle,
1083 OUT VOID **Configuration
1084 )
1085 {
1086 LIST_ENTRY *Link;
1087 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1088 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1089 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1090 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1091
1092 if (Configuration == NULL) {
1093 return EFI_INVALID_PARAMETER;
1094 }
1095
1096 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1097 for (Link = GetFirstNode (&HostBridge->RootBridges)
1098 ; !IsNull (&HostBridge->RootBridges, Link)
1099 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1100 ) {
1101 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1102 if (RootBridgeHandle == RootBridge->Handle) {
1103 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1104 if (*Configuration == NULL) {
1105 return EFI_OUT_OF_RESOURCES;
1106 }
1107
1108 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;
1109 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1110 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1111 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
1112 Descriptor->GenFlag = 0;
1113 Descriptor->SpecificFlag = 0;
1114 Descriptor->AddrSpaceGranularity = 0;
1115 Descriptor->AddrRangeMin = RootBridge->Bus.Base;
1116 Descriptor->AddrRangeMax = 0;
1117 Descriptor->AddrTranslationOffset = 0;
1118 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
1119
1120 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
1121 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1122 End->Checksum = 0x0;
1123
1124 return EFI_SUCCESS;
1125 }
1126 }
1127
1128 return EFI_INVALID_PARAMETER;
1129 }
1130
1131 /**
1132
1133 This function programs the PCI Root Bridge hardware so that
1134 it decodes the specified PCI bus range.
1135
1136 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1137 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1138 @param Configuration The pointer to the PCI bus resource descriptor.
1139
1140 @retval EFI_SUCCESS Succeed.
1141 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1142
1143 **/
1144 EFI_STATUS
1145 EFIAPI
1146 SetBusNumbers (
1147 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1148 IN EFI_HANDLE RootBridgeHandle,
1149 IN VOID *Configuration
1150 )
1151 {
1152 LIST_ENTRY *Link;
1153 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1154 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1155 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1156 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1157
1158 if (Configuration == NULL) {
1159 return EFI_INVALID_PARAMETER;
1160 }
1161
1162 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1163 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
1164
1165 //
1166 // Check the Configuration is valid
1167 //
1168 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
1169 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
1170 (End->Desc != ACPI_END_TAG_DESCRIPTOR)
1171 ) {
1172 return EFI_INVALID_PARAMETER;
1173 }
1174
1175 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1176 for (Link = GetFirstNode (&HostBridge->RootBridges)
1177 ; !IsNull (&HostBridge->RootBridges, Link)
1178 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1179 ) {
1180 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1181 if (RootBridgeHandle == RootBridge->Handle) {
1182
1183 if (Descriptor->AddrLen == 0) {
1184 return EFI_INVALID_PARAMETER;
1185 }
1186
1187 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
1188 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
1189 ) {
1190 return EFI_INVALID_PARAMETER;
1191 }
1192 //
1193 // Update the Bus Range
1194 //
1195 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;
1196 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;
1197 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;
1198 return EFI_SUCCESS;
1199 }
1200 }
1201
1202 return EFI_INVALID_PARAMETER;
1203 }
1204
1205 /**
1206
1207 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1208
1209 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1210 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1211 are being submitted.
1212 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1213
1214 @retval EFI_SUCCESS Succeed.
1215 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1216 **/
1217 EFI_STATUS
1218 EFIAPI
1219 SubmitResources (
1220 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1221 IN EFI_HANDLE RootBridgeHandle,
1222 IN VOID *Configuration
1223 )
1224 {
1225 LIST_ENTRY *Link;
1226 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1227 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1228 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1229 PCI_RESOURCE_TYPE Type;
1230
1231 //
1232 // Check the input parameter: Configuration
1233 //
1234 if (Configuration == NULL) {
1235 return EFI_INVALID_PARAMETER;
1236 }
1237
1238 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1239 for (Link = GetFirstNode (&HostBridge->RootBridges)
1240 ; !IsNull (&HostBridge->RootBridges, Link)
1241 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1242 ) {
1243 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1244 if (RootBridgeHandle == RootBridge->Handle) {
1245 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
1246 //
1247 // Check the resource descriptors.
1248 // If the Configuration includes one or more invalid resource descriptors, all the resource
1249 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1250 //
1251 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1252 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {
1253 return EFI_INVALID_PARAMETER;
1254 }
1255
1256 DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1257 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
1258 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""
1259 ));
1260 DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));
1261 switch (Descriptor->ResType) {
1262 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1263 if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {
1264 return EFI_INVALID_PARAMETER;
1265 }
1266 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {
1267 return EFI_INVALID_PARAMETER;
1268 }
1269 //
1270 // If the PCI root bridge does not support separate windows for nonprefetchable and
1271 // prefetchable memory, then the PCI bus driver needs to include requests for
1272 // prefetchable memory in the nonprefetchable memory pool.
1273 //
1274 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
1275 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
1276 ) {
1277 return EFI_INVALID_PARAMETER;
1278 }
1279 case ACPI_ADDRESS_SPACE_TYPE_IO:
1280 //
1281 // Check aligment, it should be of the form 2^n-1
1282 //
1283 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
1284 return EFI_INVALID_PARAMETER;
1285 }
1286 break;
1287 default:
1288 ASSERT (FALSE);
1289 break;
1290 }
1291 }
1292 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
1293 return EFI_INVALID_PARAMETER;
1294 }
1295
1296 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1297 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
1298 if (Descriptor->AddrSpaceGranularity == 32) {
1299 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1300 Type = TypePMem32;
1301 } else {
1302 Type = TypeMem32;
1303 }
1304 } else {
1305 ASSERT (Descriptor->AddrSpaceGranularity == 64);
1306 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1307 Type = TypePMem64;
1308 } else {
1309 Type = TypeMem64;
1310 }
1311 }
1312 } else {
1313 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
1314 Type = TypeIo;
1315 }
1316 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;
1317 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
1318 RootBridge->ResAllocNode[Type].Status = ResSubmitted;
1319 }
1320 RootBridge->ResourceSubmitted = TRUE;
1321 return EFI_SUCCESS;
1322 }
1323 }
1324
1325 return EFI_INVALID_PARAMETER;
1326 }
1327
1328 /**
1329
1330 This function returns the proposed resource settings for the specified
1331 PCI Root Bridge.
1332
1333 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1334 @param RootBridgeHandle The PCI Root Bridge handle.
1335 @param Configuration The pointer to the pointer to the PCI I/O
1336 and memory resource descriptor.
1337
1338 @retval EFI_SUCCESS Succeed.
1339 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1340 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1341
1342 **/
1343 EFI_STATUS
1344 EFIAPI
1345 GetProposedResources (
1346 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1347 IN EFI_HANDLE RootBridgeHandle,
1348 OUT VOID **Configuration
1349 )
1350 {
1351 LIST_ENTRY *Link;
1352 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1353 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1354 UINTN Index;
1355 UINTN Number;
1356 VOID *Buffer;
1357 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1358 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1359 UINT64 ResStatus;
1360
1361 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1362 for (Link = GetFirstNode (&HostBridge->RootBridges)
1363 ; !IsNull (&HostBridge->RootBridges, Link)
1364 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1365 ) {
1366 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1367 if (RootBridgeHandle == RootBridge->Handle) {
1368 for (Index = 0, Number = 0; Index < TypeBus; Index++) {
1369 if (RootBridge->ResAllocNode[Index].Status != ResNone) {
1370 Number++;
1371 }
1372 }
1373
1374 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1375 if (Buffer == NULL) {
1376 return EFI_OUT_OF_RESOURCES;
1377 }
1378
1379 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;
1380 for (Index = 0; Index < TypeBus; Index++) {
1381 ResStatus = RootBridge->ResAllocNode[Index].Status;
1382 if (ResStatus != ResNone) {
1383 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1384 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
1385 Descriptor->GenFlag = 0;
1386 Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;
1387 Descriptor->AddrRangeMax = 0;
1388 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
1389 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;
1390
1391 switch (Index) {
1392
1393 case TypeIo:
1394 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1395 break;
1396
1397 case TypePMem32:
1398 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1399 case TypeMem32:
1400 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1401 Descriptor->AddrSpaceGranularity = 32;
1402 break;
1403
1404 case TypePMem64:
1405 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1406 case TypeMem64:
1407 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1408 Descriptor->AddrSpaceGranularity = 64;
1409 break;
1410 }
1411
1412 Descriptor++;
1413 }
1414 }
1415 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
1416 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1417 End->Checksum = 0;
1418
1419 *Configuration = Buffer;
1420
1421 return EFI_SUCCESS;
1422 }
1423 }
1424
1425 return EFI_INVALID_PARAMETER;
1426 }
1427
1428 /**
1429
1430 This function is called for all the PCI controllers that the PCI
1431 bus driver finds. Can be used to Preprogram the controller.
1432
1433 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1434 @param RootBridgeHandle The PCI Root Bridge handle.
1435 @param PciAddress Address of the controller on the PCI bus.
1436 @param Phase The Phase during resource allocation.
1437
1438 @retval EFI_SUCCESS Succeed.
1439 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1440
1441 **/
1442 EFI_STATUS
1443 EFIAPI
1444 PreprocessController (
1445 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1446 IN EFI_HANDLE RootBridgeHandle,
1447 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1448 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1449 )
1450 {
1451 LIST_ENTRY *Link;
1452 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1453 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1454
1455 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {
1456 return EFI_INVALID_PARAMETER;
1457 }
1458
1459 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1460 for (Link = GetFirstNode (&HostBridge->RootBridges)
1461 ; !IsNull (&HostBridge->RootBridges, Link)
1462 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1463 ) {
1464 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1465 if (RootBridgeHandle == RootBridge->Handle) {
1466 return EFI_SUCCESS;
1467 }
1468 }
1469
1470 return EFI_INVALID_PARAMETER;
1471 }