]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridge.c
MdeModulePkg/PciHostBridgeDxe: remove unused but set variables
[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
342 RootBridges = PciHostBridgeGetRootBridges (&RootBridgeCount);
343 if ((RootBridges == NULL) || (RootBridgeCount == 0)) {
344 return EFI_UNSUPPORTED;
345 }
346
347 Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **) &mMetronome);
348 ASSERT_EFI_ERROR (Status);
349 Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) &mCpuIo);
350 ASSERT_EFI_ERROR (Status);
351
352 //
353 // Most systems in the world including complex servers have only one Host Bridge.
354 //
355 HostBridge = AllocateZeroPool (sizeof (PCI_HOST_BRIDGE_INSTANCE));
356 ASSERT (HostBridge != NULL);
357
358 HostBridge->Signature = PCI_HOST_BRIDGE_SIGNATURE;
359 HostBridge->CanRestarted = TRUE;
360 InitializeListHead (&HostBridge->RootBridges);
361
362 HostBridge->ResAlloc.NotifyPhase = NotifyPhase;
363 HostBridge->ResAlloc.GetNextRootBridge = GetNextRootBridge;
364 HostBridge->ResAlloc.GetAllocAttributes = GetAttributes;
365 HostBridge->ResAlloc.StartBusEnumeration = StartBusEnumeration;
366 HostBridge->ResAlloc.SetBusNumbers = SetBusNumbers;
367 HostBridge->ResAlloc.SubmitResources = SubmitResources;
368 HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
369 HostBridge->ResAlloc.PreprocessController = PreprocessController;
370
371 Status = gBS->InstallMultipleProtocolInterfaces (
372 &HostBridge->Handle,
373 &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge->ResAlloc,
374 NULL
375 );
376 ASSERT_EFI_ERROR (Status);
377 if (EFI_ERROR (Status)) {
378 FreePool (HostBridge);
379 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
380 return Status;
381 }
382
383 //
384 // Create Root Bridge Device Handle in this Host Bridge
385 //
386 for (Index = 0; Index < RootBridgeCount; Index++) {
387 //
388 // Create Root Bridge Handle Instance
389 //
390 RootBridge = CreateRootBridge (&RootBridges[Index], HostBridge->Handle);
391 ASSERT (RootBridge != NULL);
392 if (RootBridge == NULL) {
393 continue;
394 }
395
396 if (RootBridges[Index].Io.Limit > RootBridges[Index].Io.Base) {
397 Status = AddIoSpace (
398 RootBridges[Index].Io.Base,
399 RootBridges[Index].Io.Limit - RootBridges[Index].Io.Base + 1
400 );
401 ASSERT_EFI_ERROR (Status);
402 }
403
404 //
405 // Add all the Mem/PMem aperture to GCD
406 // Mem/PMem shouldn't overlap with each other
407 // Root bridge which needs to combine MEM and PMEM should only report
408 // the MEM aperture in Mem
409 //
410 MemApertures[0] = &RootBridges[Index].Mem;
411 MemApertures[1] = &RootBridges[Index].MemAbove4G;
412 MemApertures[2] = &RootBridges[Index].PMem;
413 MemApertures[3] = &RootBridges[Index].PMemAbove4G;
414
415 for (MemApertureIndex = 0; MemApertureIndex < sizeof (MemApertures) / sizeof (MemApertures[0]); MemApertureIndex++) {
416 if (MemApertures[MemApertureIndex]->Limit > MemApertures[MemApertureIndex]->Base) {
417 Status = AddMemoryMappedIoSpace (
418 MemApertures[MemApertureIndex]->Base,
419 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
420 EFI_MEMORY_UC
421 );
422 ASSERT_EFI_ERROR (Status);
423 Status = gDS->SetMemorySpaceAttributes (
424 MemApertures[MemApertureIndex]->Base,
425 MemApertures[MemApertureIndex]->Limit - MemApertures[MemApertureIndex]->Base + 1,
426 EFI_MEMORY_UC
427 );
428 if (EFI_ERROR (Status)) {
429 DEBUG ((DEBUG_WARN, "PciHostBridge driver failed to set EFI_MEMORY_UC to MMIO aperture - %r.\n", Status));
430 }
431 }
432 }
433 //
434 // Insert Root Bridge Handle Instance
435 //
436 Status = gBS->InstallMultipleProtocolInterfaces (
437 &RootBridge->Handle,
438 &gEfiDevicePathProtocolGuid, RootBridge->DevicePath,
439 &gEfiPciRootBridgeIoProtocolGuid, &RootBridge->RootBridgeIo,
440 NULL
441 );
442 ASSERT_EFI_ERROR (Status);
443 InsertTailList (&HostBridge->RootBridges, &RootBridge->Link);
444 }
445 PciHostBridgeFreeRootBridges (RootBridges, RootBridgeCount);
446 return Status;
447 }
448
449 /**
450 This routine constructs the resource descriptors for all root bridges and call PciHostBridgeResourceConflict().
451
452 @param HostBridge The Host Bridge Instance where the resource adjustment happens.
453 **/
454 VOID
455 ResourceConflict (
456 IN PCI_HOST_BRIDGE_INSTANCE *HostBridge
457 )
458 {
459 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Resources;
460 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
461 EFI_ACPI_END_TAG_DESCRIPTOR *End;
462 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
463 LIST_ENTRY *Link;
464 UINTN RootBridgeCount;
465 PCI_RESOURCE_TYPE Index;
466 PCI_RES_NODE *ResAllocNode;
467
468 RootBridgeCount = 0;
469 for (Link = GetFirstNode (&HostBridge->RootBridges)
470 ; !IsNull (&HostBridge->RootBridges, Link)
471 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
472 ) {
473 RootBridgeCount++;
474 }
475
476 Resources = AllocatePool (
477 RootBridgeCount * (TypeMax * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)) +
478 sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)
479 );
480 ASSERT (Resources != NULL);
481
482 for (Link = GetFirstNode (&HostBridge->RootBridges), Descriptor = Resources
483 ; !IsNull (&HostBridge->RootBridges, Link)
484 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
485 ) {
486 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
487 for (Index = TypeIo; Index < TypeMax; Index++) {
488 ResAllocNode = &RootBridge->ResAllocNode[Index];
489
490 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
491 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
492 Descriptor->AddrRangeMin = ResAllocNode->Base;
493 Descriptor->AddrRangeMax = ResAllocNode->Alignment;
494 Descriptor->AddrLen = ResAllocNode->Length;
495 switch (ResAllocNode->Type) {
496
497 case TypeIo:
498 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
499 break;
500
501 case TypePMem32:
502 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
503 case TypeMem32:
504 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
505 Descriptor->AddrSpaceGranularity = 32;
506 break;
507
508 case TypePMem64:
509 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
510 case TypeMem64:
511 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
512 Descriptor->AddrSpaceGranularity = 64;
513 break;
514
515 case TypeBus:
516 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
517 break;
518
519 default:
520 break;
521 }
522
523 Descriptor++;
524 }
525 //
526 // Terminate the root bridge resources.
527 //
528 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
529 End->Desc = ACPI_END_TAG_DESCRIPTOR;
530 End->Checksum = 0x0;
531
532 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (End + 1);
533 }
534 //
535 // Terminate the host bridge resources.
536 //
537 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
538 End->Desc = ACPI_END_TAG_DESCRIPTOR;
539 End->Checksum = 0x0;
540
541 DEBUG ((DEBUG_ERROR, "Call PciHostBridgeResourceConflict().\n"));
542 PciHostBridgeResourceConflict (HostBridge->Handle, Resources);
543 FreePool (Resources);
544 }
545
546 /**
547 Allocate Length of MMIO or IO resource with alignment BitsOfAlignment
548 from GCD range [BaseAddress, Limit).
549
550 @param Mmio TRUE for MMIO and FALSE for IO.
551 @param Length Length of the resource to allocate.
552 @param BitsOfAlignment Alignment of the resource to allocate.
553 @param BaseAddress The starting address the allocation is from.
554 @param Limit The ending address the allocation is to.
555
556 @retval The base address of the allocated resource or MAX_UINT64 if allocation
557 fails.
558 **/
559 UINT64
560 AllocateResource (
561 BOOLEAN Mmio,
562 UINT64 Length,
563 UINTN BitsOfAlignment,
564 UINT64 BaseAddress,
565 UINT64 Limit
566 )
567 {
568 EFI_STATUS Status;
569
570 if (BaseAddress < Limit) {
571 //
572 // Have to make sure Aligment is handled since we are doing direct address allocation
573 //
574 BaseAddress = ALIGN_VALUE (BaseAddress, LShiftU64 (1, BitsOfAlignment));
575
576 while (BaseAddress + Length <= Limit + 1) {
577 if (Mmio) {
578 Status = gDS->AllocateMemorySpace (
579 EfiGcdAllocateAddress,
580 EfiGcdMemoryTypeMemoryMappedIo,
581 BitsOfAlignment,
582 Length,
583 &BaseAddress,
584 gImageHandle,
585 NULL
586 );
587 } else {
588 Status = gDS->AllocateIoSpace (
589 EfiGcdAllocateAddress,
590 EfiGcdIoTypeIo,
591 BitsOfAlignment,
592 Length,
593 &BaseAddress,
594 gImageHandle,
595 NULL
596 );
597 }
598
599 if (!EFI_ERROR (Status)) {
600 return BaseAddress;
601 }
602 BaseAddress += LShiftU64 (1, BitsOfAlignment);
603 }
604 }
605 return MAX_UINT64;
606 }
607
608 /**
609
610 Enter a certain phase of the PCI enumeration process.
611
612 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
613 @param Phase The phase during enumeration.
614
615 @retval EFI_SUCCESS Succeed.
616 @retval EFI_INVALID_PARAMETER Wrong phase parameter passed in.
617 @retval EFI_NOT_READY Resources have not been submitted yet.
618
619 **/
620 EFI_STATUS
621 EFIAPI
622 NotifyPhase (
623 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
624 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
625 )
626 {
627 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
628 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
629 LIST_ENTRY *Link;
630 EFI_PHYSICAL_ADDRESS BaseAddress;
631 UINTN BitsOfAlignment;
632 UINT64 Alignment;
633 EFI_STATUS Status;
634 EFI_STATUS ReturnStatus;
635 PCI_RESOURCE_TYPE Index;
636 PCI_RESOURCE_TYPE Index1;
637 PCI_RESOURCE_TYPE Index2;
638 BOOLEAN ResNodeHandled[TypeMax];
639 UINT64 MaxAlignment;
640
641 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
642
643 switch (Phase) {
644 case EfiPciHostBridgeBeginEnumeration:
645 if (!HostBridge->CanRestarted) {
646 return EFI_NOT_READY;
647 }
648 //
649 // Reset Root Bridge
650 //
651 for (Link = GetFirstNode (&HostBridge->RootBridges)
652 ; !IsNull (&HostBridge->RootBridges, Link)
653 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
654 ) {
655 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
656 for (Index = TypeIo; Index < TypeMax; Index++) {
657 RootBridge->ResAllocNode[Index].Type = Index;
658 RootBridge->ResAllocNode[Index].Base = 0;
659 RootBridge->ResAllocNode[Index].Length = 0;
660 RootBridge->ResAllocNode[Index].Status = ResNone;
661
662 RootBridge->ResourceSubmitted = FALSE;
663 }
664 }
665
666 HostBridge->CanRestarted = TRUE;
667 break;
668
669 case EfiPciHostBridgeBeginBusAllocation:
670 //
671 // No specific action is required here, can perform any chipset specific programing
672 //
673 HostBridge->CanRestarted = FALSE;
674 break;
675
676 case EfiPciHostBridgeEndBusAllocation:
677 //
678 // No specific action is required here, can perform any chipset specific programing
679 //
680 break;
681
682 case EfiPciHostBridgeBeginResourceAllocation:
683 //
684 // No specific action is required here, can perform any chipset specific programing
685 //
686 break;
687
688 case EfiPciHostBridgeAllocateResources:
689 ReturnStatus = EFI_SUCCESS;
690
691 //
692 // Make sure the resource for all root bridges has been submitted.
693 //
694 for (Link = GetFirstNode (&HostBridge->RootBridges)
695 ; !IsNull (&HostBridge->RootBridges, Link)
696 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
697 ) {
698 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
699 if (!RootBridge->ResourceSubmitted) {
700 return EFI_NOT_READY;
701 }
702 }
703
704 DEBUG ((EFI_D_INFO, "PciHostBridge: NotifyPhase (AllocateResources)\n"));
705 for (Link = GetFirstNode (&HostBridge->RootBridges)
706 ; !IsNull (&HostBridge->RootBridges, Link)
707 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
708 ) {
709 for (Index = TypeIo; Index < TypeBus; Index++) {
710 ResNodeHandled[Index] = FALSE;
711 }
712
713 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
714 DEBUG ((EFI_D_INFO, " RootBridge: %s\n", RootBridge->DevicePathStr));
715
716 for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
717 if (RootBridge->ResAllocNode[Index1].Status == ResNone) {
718 ResNodeHandled[Index1] = TRUE;
719 } else {
720 //
721 // Allocate the resource node with max alignment at first
722 //
723 MaxAlignment = 0;
724 Index = TypeMax;
725 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
726 if (ResNodeHandled[Index2]) {
727 continue;
728 }
729 if (MaxAlignment <= RootBridge->ResAllocNode[Index2].Alignment) {
730 MaxAlignment = RootBridge->ResAllocNode[Index2].Alignment;
731 Index = Index2;
732 }
733 }
734
735 ASSERT (Index < TypeMax);
736 ResNodeHandled[Index] = TRUE;
737 Alignment = RootBridge->ResAllocNode[Index].Alignment;
738 BitsOfAlignment = LowBitSet64 (Alignment + 1);
739 BaseAddress = MAX_UINT64;
740
741 switch (Index) {
742 case TypeIo:
743 BaseAddress = AllocateResource (
744 FALSE,
745 RootBridge->ResAllocNode[Index].Length,
746 MIN (15, BitsOfAlignment),
747 ALIGN_VALUE (RootBridge->Io.Base, Alignment + 1),
748 RootBridge->Io.Limit
749 );
750 break;
751
752 case TypeMem64:
753 BaseAddress = AllocateResource (
754 TRUE,
755 RootBridge->ResAllocNode[Index].Length,
756 MIN (63, BitsOfAlignment),
757 ALIGN_VALUE (RootBridge->MemAbove4G.Base, Alignment + 1),
758 RootBridge->MemAbove4G.Limit
759 );
760 if (BaseAddress != MAX_UINT64) {
761 break;
762 }
763 //
764 // If memory above 4GB is not available, try memory below 4GB
765 //
766
767 case TypeMem32:
768 BaseAddress = AllocateResource (
769 TRUE,
770 RootBridge->ResAllocNode[Index].Length,
771 MIN (31, BitsOfAlignment),
772 ALIGN_VALUE (RootBridge->Mem.Base, Alignment + 1),
773 RootBridge->Mem.Limit
774 );
775 break;
776
777 case TypePMem64:
778 BaseAddress = AllocateResource (
779 TRUE,
780 RootBridge->ResAllocNode[Index].Length,
781 MIN (63, BitsOfAlignment),
782 ALIGN_VALUE (RootBridge->PMemAbove4G.Base, Alignment + 1),
783 RootBridge->PMemAbove4G.Limit
784 );
785 if (BaseAddress != MAX_UINT64) {
786 break;
787 }
788 //
789 // If memory above 4GB is not available, try memory below 4GB
790 //
791 case TypePMem32:
792 BaseAddress = AllocateResource (
793 TRUE,
794 RootBridge->ResAllocNode[Index].Length,
795 MIN (31, BitsOfAlignment),
796 ALIGN_VALUE (RootBridge->PMem.Base, Alignment + 1),
797 RootBridge->PMem.Limit
798 );
799 break;
800
801 default:
802 ASSERT (FALSE);
803 break;
804 }
805
806 DEBUG ((DEBUG_INFO, " %s: Base/Length/Alignment = %lx/%lx/%lx - ",
807 mPciResourceTypeStr[Index], BaseAddress, RootBridge->ResAllocNode[Index].Length, Alignment));
808 if (BaseAddress != MAX_UINT64) {
809 RootBridge->ResAllocNode[Index].Base = BaseAddress;
810 RootBridge->ResAllocNode[Index].Status = ResAllocated;
811 DEBUG ((DEBUG_INFO, "Success\n"));
812 } else {
813 ReturnStatus = EFI_OUT_OF_RESOURCES;
814 DEBUG ((DEBUG_ERROR, "Out Of Resource!\n"));
815 }
816 }
817 }
818 }
819
820 if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
821 ResourceConflict (HostBridge);
822 }
823
824 //
825 // Set resource to zero for nodes where allocation fails
826 //
827 for (Link = GetFirstNode (&HostBridge->RootBridges)
828 ; !IsNull (&HostBridge->RootBridges, Link)
829 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
830 ) {
831 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
832 for (Index = TypeIo; Index < TypeBus; Index++) {
833 if (RootBridge->ResAllocNode[Index].Status != ResAllocated) {
834 RootBridge->ResAllocNode[Index].Length = 0;
835 }
836 }
837 }
838 return ReturnStatus;
839
840 case EfiPciHostBridgeSetResources:
841 //
842 // HostBridgeInstance->CanRestarted = FALSE;
843 //
844 break;
845
846 case EfiPciHostBridgeFreeResources:
847 //
848 // HostBridgeInstance->CanRestarted = FALSE;
849 //
850 ReturnStatus = EFI_SUCCESS;
851 for (Link = GetFirstNode (&HostBridge->RootBridges)
852 ; !IsNull (&HostBridge->RootBridges, Link)
853 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
854 ) {
855 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
856 for (Index = TypeIo; Index < TypeBus; Index++) {
857 if (RootBridge->ResAllocNode[Index].Status == ResAllocated) {
858 switch (Index) {
859 case TypeIo:
860 Status = gDS->FreeIoSpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
861 if (EFI_ERROR (Status)) {
862 ReturnStatus = Status;
863 }
864 break;
865
866 case TypeMem32:
867 case TypePMem32:
868 case TypeMem64:
869 case TypePMem64:
870 Status = gDS->FreeMemorySpace (RootBridge->ResAllocNode[Index].Base, RootBridge->ResAllocNode[Index].Length);
871 if (EFI_ERROR (Status)) {
872 ReturnStatus = Status;
873 }
874 break;
875
876 default:
877 ASSERT (FALSE);
878 break;
879 }
880
881 RootBridge->ResAllocNode[Index].Type = Index;
882 RootBridge->ResAllocNode[Index].Base = 0;
883 RootBridge->ResAllocNode[Index].Length = 0;
884 RootBridge->ResAllocNode[Index].Status = ResNone;
885 }
886 }
887
888 RootBridge->ResourceSubmitted = FALSE;
889 }
890
891 HostBridge->CanRestarted = TRUE;
892 return ReturnStatus;
893
894 case EfiPciHostBridgeEndResourceAllocation:
895 //
896 // The resource allocation phase is completed. No specific action is required
897 // here. This notification can be used to perform any chipset specific programming.
898 //
899 break;
900
901 case EfiPciHostBridgeEndEnumeration:
902 //
903 // The Host Bridge Enumeration is completed. No specific action is required here.
904 // This notification can be used to perform any chipset specific programming.
905 //
906 break;
907
908 default:
909 return EFI_INVALID_PARAMETER;
910 }
911
912 return EFI_SUCCESS;
913 }
914
915 /**
916
917 Return the device handle of the next PCI root bridge that is associated with
918 this Host Bridge.
919
920 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
921 @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge.
922 On input, it holds the RootBridgeHandle returned by the most
923 recent call to GetNextRootBridge().The handle for the first
924 PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
925
926 @retval EFI_SUCCESS Succeed.
927 @retval EFI_NOT_FOUND Next PCI root bridge not found.
928 @retval EFI_INVALID_PARAMETER Wrong parameter passed in.
929
930 **/
931 EFI_STATUS
932 EFIAPI
933 GetNextRootBridge (
934 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
935 IN OUT EFI_HANDLE *RootBridgeHandle
936 )
937 {
938 BOOLEAN ReturnNext;
939 LIST_ENTRY *Link;
940 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
941 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
942
943 if (RootBridgeHandle == NULL) {
944 return EFI_INVALID_PARAMETER;
945 }
946
947 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
948 ReturnNext = (BOOLEAN) (*RootBridgeHandle == NULL);
949
950 for (Link = GetFirstNode (&HostBridge->RootBridges)
951 ; !IsNull (&HostBridge->RootBridges, Link)
952 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
953 ) {
954 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
955 if (ReturnNext) {
956 *RootBridgeHandle = RootBridge->Handle;
957 return EFI_SUCCESS;
958 }
959
960 ReturnNext = (BOOLEAN) (*RootBridgeHandle == RootBridge->Handle);
961 }
962
963 if (ReturnNext) {
964 ASSERT (IsNull (&HostBridge->RootBridges, Link));
965 return EFI_NOT_FOUND;
966 } else {
967 return EFI_INVALID_PARAMETER;
968 }
969 }
970
971 /**
972
973 Returns the attributes of a PCI Root Bridge.
974
975 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
976 @param RootBridgeHandle The device handle of the PCI Root Bridge
977 that the caller is interested in.
978 @param Attributes The pointer to attributes of the PCI Root Bridge.
979
980 @retval EFI_SUCCESS Succeed.
981 @retval EFI_INVALID_PARAMETER Attributes parameter passed in is NULL or
982 RootBridgeHandle is not an EFI_HANDLE
983 that was returned on a previous call to
984 GetNextRootBridge().
985
986 **/
987 EFI_STATUS
988 EFIAPI
989 GetAttributes (
990 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
991 IN EFI_HANDLE RootBridgeHandle,
992 OUT UINT64 *Attributes
993 )
994 {
995 LIST_ENTRY *Link;
996 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
997 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
998
999 if (Attributes == NULL) {
1000 return EFI_INVALID_PARAMETER;
1001 }
1002
1003 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1004 for (Link = GetFirstNode (&HostBridge->RootBridges)
1005 ; !IsNull (&HostBridge->RootBridges, Link)
1006 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1007 ) {
1008 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1009 if (RootBridgeHandle == RootBridge->Handle) {
1010 *Attributes = RootBridge->AllocationAttributes;
1011 return EFI_SUCCESS;
1012 }
1013 }
1014
1015 return EFI_INVALID_PARAMETER;
1016 }
1017
1018 /**
1019
1020 This is the request from the PCI enumerator to set up
1021 the specified PCI Root Bridge for bus enumeration process.
1022
1023 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1024 @param RootBridgeHandle The PCI Root Bridge to be set up.
1025 @param Configuration Pointer to the pointer to the PCI bus resource descriptor.
1026
1027 @retval EFI_SUCCESS Succeed.
1028 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1029 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1030
1031 **/
1032 EFI_STATUS
1033 EFIAPI
1034 StartBusEnumeration (
1035 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1036 IN EFI_HANDLE RootBridgeHandle,
1037 OUT VOID **Configuration
1038 )
1039 {
1040 LIST_ENTRY *Link;
1041 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1042 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1043 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1044 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1045
1046 if (Configuration == NULL) {
1047 return EFI_INVALID_PARAMETER;
1048 }
1049
1050 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1051 for (Link = GetFirstNode (&HostBridge->RootBridges)
1052 ; !IsNull (&HostBridge->RootBridges, Link)
1053 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1054 ) {
1055 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1056 if (RootBridgeHandle == RootBridge->Handle) {
1057 *Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1058 if (*Configuration == NULL) {
1059 return EFI_OUT_OF_RESOURCES;
1060 }
1061
1062 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) *Configuration;
1063 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1064 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
1065 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;
1066 Descriptor->GenFlag = 0;
1067 Descriptor->SpecificFlag = 0;
1068 Descriptor->AddrSpaceGranularity = 0;
1069 Descriptor->AddrRangeMin = RootBridge->Bus.Base;
1070 Descriptor->AddrRangeMax = 0;
1071 Descriptor->AddrTranslationOffset = 0;
1072 Descriptor->AddrLen = RootBridge->Bus.Limit - RootBridge->Bus.Base + 1;
1073
1074 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
1075 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1076 End->Checksum = 0x0;
1077
1078 return EFI_SUCCESS;
1079 }
1080 }
1081
1082 return EFI_INVALID_PARAMETER;
1083 }
1084
1085 /**
1086
1087 This function programs the PCI Root Bridge hardware so that
1088 it decodes the specified PCI bus range.
1089
1090 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1091 @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed.
1092 @param Configuration The pointer to the PCI bus resource descriptor.
1093
1094 @retval EFI_SUCCESS Succeed.
1095 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1096
1097 **/
1098 EFI_STATUS
1099 EFIAPI
1100 SetBusNumbers (
1101 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1102 IN EFI_HANDLE RootBridgeHandle,
1103 IN VOID *Configuration
1104 )
1105 {
1106 LIST_ENTRY *Link;
1107 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1108 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1109 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1110 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1111
1112 if (Configuration == NULL) {
1113 return EFI_INVALID_PARAMETER;
1114 }
1115
1116 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
1117 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Descriptor + 1);
1118
1119 //
1120 // Check the Configuration is valid
1121 //
1122 if ((Descriptor->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) ||
1123 (Descriptor->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) ||
1124 (End->Desc != ACPI_END_TAG_DESCRIPTOR)
1125 ) {
1126 return EFI_INVALID_PARAMETER;
1127 }
1128
1129 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1130 for (Link = GetFirstNode (&HostBridge->RootBridges)
1131 ; !IsNull (&HostBridge->RootBridges, Link)
1132 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1133 ) {
1134 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1135 if (RootBridgeHandle == RootBridge->Handle) {
1136
1137 if (Descriptor->AddrLen == 0) {
1138 return EFI_INVALID_PARAMETER;
1139 }
1140
1141 if ((Descriptor->AddrRangeMin < RootBridge->Bus.Base) ||
1142 (Descriptor->AddrRangeMin + Descriptor->AddrLen - 1 > RootBridge->Bus.Limit)
1143 ) {
1144 return EFI_INVALID_PARAMETER;
1145 }
1146 //
1147 // Update the Bus Range
1148 //
1149 RootBridge->ResAllocNode[TypeBus].Base = Descriptor->AddrRangeMin;
1150 RootBridge->ResAllocNode[TypeBus].Length = Descriptor->AddrLen;
1151 RootBridge->ResAllocNode[TypeBus].Status = ResAllocated;
1152 return EFI_SUCCESS;
1153 }
1154 }
1155
1156 return EFI_INVALID_PARAMETER;
1157 }
1158
1159 /**
1160
1161 Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
1162
1163 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1164 @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements.
1165 are being submitted.
1166 @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
1167
1168 @retval EFI_SUCCESS Succeed.
1169 @retval EFI_INVALID_PARAMETER Wrong parameters passed in.
1170 **/
1171 EFI_STATUS
1172 EFIAPI
1173 SubmitResources (
1174 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1175 IN EFI_HANDLE RootBridgeHandle,
1176 IN VOID *Configuration
1177 )
1178 {
1179 LIST_ENTRY *Link;
1180 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1181 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1182 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1183 PCI_RESOURCE_TYPE Type;
1184
1185 //
1186 // Check the input parameter: Configuration
1187 //
1188 if (Configuration == NULL) {
1189 return EFI_INVALID_PARAMETER;
1190 }
1191
1192 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1193 for (Link = GetFirstNode (&HostBridge->RootBridges)
1194 ; !IsNull (&HostBridge->RootBridges, Link)
1195 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1196 ) {
1197 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1198 if (RootBridgeHandle == RootBridge->Handle) {
1199 DEBUG ((EFI_D_INFO, "PciHostBridge: SubmitResources for %s\n", RootBridge->DevicePathStr));
1200 //
1201 // Check the resource descriptors.
1202 // If the Configuration includes one or more invalid resource descriptors, all the resource
1203 // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1204 //
1205 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1206 if (Descriptor->ResType > ACPI_ADDRESS_SPACE_TYPE_BUS) {
1207 return EFI_INVALID_PARAMETER;
1208 }
1209
1210 DEBUG ((EFI_D_INFO, " %s: Granularity/SpecificFlag = %ld / %02x%s\n",
1211 mAcpiAddressSpaceTypeStr[Descriptor->ResType], Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
1212 (Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0 ? L" (Prefetchable)" : L""
1213 ));
1214 DEBUG ((EFI_D_INFO, " Length/Alignment = 0x%lx / 0x%lx\n", Descriptor->AddrLen, Descriptor->AddrRangeMax));
1215 switch (Descriptor->ResType) {
1216 case ACPI_ADDRESS_SPACE_TYPE_MEM:
1217 if (Descriptor->AddrSpaceGranularity != 32 && Descriptor->AddrSpaceGranularity != 64) {
1218 return EFI_INVALID_PARAMETER;
1219 }
1220 if (Descriptor->AddrSpaceGranularity == 32 && Descriptor->AddrLen >= SIZE_4GB) {
1221 return EFI_INVALID_PARAMETER;
1222 }
1223 //
1224 // If the PCI root bridge does not support separate windows for nonprefetchable and
1225 // prefetchable memory, then the PCI bus driver needs to include requests for
1226 // prefetchable memory in the nonprefetchable memory pool.
1227 //
1228 if (((RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0) &&
1229 ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0)
1230 ) {
1231 return EFI_INVALID_PARAMETER;
1232 }
1233 case ACPI_ADDRESS_SPACE_TYPE_IO:
1234 //
1235 // Check aligment, it should be of the form 2^n-1
1236 //
1237 if (GetPowerOfTwo64 (Descriptor->AddrRangeMax + 1) != (Descriptor->AddrRangeMax + 1)) {
1238 return EFI_INVALID_PARAMETER;
1239 }
1240 break;
1241 default:
1242 ASSERT (FALSE);
1243 break;
1244 }
1245 }
1246 if (Descriptor->Desc != ACPI_END_TAG_DESCRIPTOR) {
1247 return EFI_INVALID_PARAMETER;
1248 }
1249
1250 for (Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
1251 if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
1252 if (Descriptor->AddrSpaceGranularity == 32) {
1253 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1254 Type = TypePMem32;
1255 } else {
1256 Type = TypeMem32;
1257 }
1258 } else {
1259 ASSERT (Descriptor->AddrSpaceGranularity == 64);
1260 if ((Descriptor->SpecificFlag & EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE) != 0) {
1261 Type = TypePMem64;
1262 } else {
1263 Type = TypeMem64;
1264 }
1265 }
1266 } else {
1267 ASSERT (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_IO);
1268 Type = TypeIo;
1269 }
1270 RootBridge->ResAllocNode[Type].Length = Descriptor->AddrLen;
1271 RootBridge->ResAllocNode[Type].Alignment = Descriptor->AddrRangeMax;
1272 RootBridge->ResAllocNode[Type].Status = ResSubmitted;
1273 }
1274 RootBridge->ResourceSubmitted = TRUE;
1275 return EFI_SUCCESS;
1276 }
1277 }
1278
1279 return EFI_INVALID_PARAMETER;
1280 }
1281
1282 /**
1283
1284 This function returns the proposed resource settings for the specified
1285 PCI Root Bridge.
1286
1287 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1288 @param RootBridgeHandle The PCI Root Bridge handle.
1289 @param Configuration The pointer to the pointer to the PCI I/O
1290 and memory resource descriptor.
1291
1292 @retval EFI_SUCCESS Succeed.
1293 @retval EFI_OUT_OF_RESOURCES Not enough pool to be allocated.
1294 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1295
1296 **/
1297 EFI_STATUS
1298 EFIAPI
1299 GetProposedResources (
1300 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1301 IN EFI_HANDLE RootBridgeHandle,
1302 OUT VOID **Configuration
1303 )
1304 {
1305 LIST_ENTRY *Link;
1306 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1307 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1308 UINTN Index;
1309 UINTN Number;
1310 VOID *Buffer;
1311 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
1312 EFI_ACPI_END_TAG_DESCRIPTOR *End;
1313 UINT64 ResStatus;
1314
1315 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1316 for (Link = GetFirstNode (&HostBridge->RootBridges)
1317 ; !IsNull (&HostBridge->RootBridges, Link)
1318 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1319 ) {
1320 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1321 if (RootBridgeHandle == RootBridge->Handle) {
1322 for (Index = 0, Number = 0; Index < TypeBus; Index++) {
1323 if (RootBridge->ResAllocNode[Index].Status != ResNone) {
1324 Number++;
1325 }
1326 }
1327
1328 Buffer = AllocateZeroPool (Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1329 if (Buffer == NULL) {
1330 return EFI_OUT_OF_RESOURCES;
1331 }
1332
1333 Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Buffer;
1334 for (Index = 0; Index < TypeBus; Index++) {
1335 ResStatus = RootBridge->ResAllocNode[Index].Status;
1336 if (ResStatus != ResNone) {
1337 Descriptor->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
1338 Descriptor->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;;
1339 Descriptor->GenFlag = 0;
1340 Descriptor->AddrRangeMin = RootBridge->ResAllocNode[Index].Base;
1341 Descriptor->AddrRangeMax = 0;
1342 Descriptor->AddrTranslationOffset = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : PCI_RESOURCE_LESS;
1343 Descriptor->AddrLen = RootBridge->ResAllocNode[Index].Length;
1344
1345 switch (Index) {
1346
1347 case TypeIo:
1348 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
1349 break;
1350
1351 case TypePMem32:
1352 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1353 case TypeMem32:
1354 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1355 Descriptor->AddrSpaceGranularity = 32;
1356 break;
1357
1358 case TypePMem64:
1359 Descriptor->SpecificFlag = EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE;
1360 case TypeMem64:
1361 Descriptor->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
1362 Descriptor->AddrSpaceGranularity = 64;
1363 break;
1364 }
1365
1366 Descriptor++;
1367 }
1368 }
1369 End = (EFI_ACPI_END_TAG_DESCRIPTOR *) Descriptor;
1370 End->Desc = ACPI_END_TAG_DESCRIPTOR;
1371 End->Checksum = 0;
1372
1373 *Configuration = Buffer;
1374
1375 return EFI_SUCCESS;
1376 }
1377 }
1378
1379 return EFI_INVALID_PARAMETER;
1380 }
1381
1382 /**
1383
1384 This function is called for all the PCI controllers that the PCI
1385 bus driver finds. Can be used to Preprogram the controller.
1386
1387 @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1388 @param RootBridgeHandle The PCI Root Bridge handle.
1389 @param PciAddress Address of the controller on the PCI bus.
1390 @param Phase The Phase during resource allocation.
1391
1392 @retval EFI_SUCCESS Succeed.
1393 @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid handle.
1394
1395 **/
1396 EFI_STATUS
1397 EFIAPI
1398 PreprocessController (
1399 IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1400 IN EFI_HANDLE RootBridgeHandle,
1401 IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
1402 IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
1403 )
1404 {
1405 LIST_ENTRY *Link;
1406 PCI_HOST_BRIDGE_INSTANCE *HostBridge;
1407 PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
1408
1409 if ((UINT32) Phase > EfiPciBeforeResourceCollection) {
1410 return EFI_INVALID_PARAMETER;
1411 }
1412
1413 HostBridge = PCI_HOST_BRIDGE_FROM_THIS (This);
1414 for (Link = GetFirstNode (&HostBridge->RootBridges)
1415 ; !IsNull (&HostBridge->RootBridges, Link)
1416 ; Link = GetNextNode (&HostBridge->RootBridges, Link)
1417 ) {
1418 RootBridge = ROOT_BRIDGE_FROM_LINK (Link);
1419 if (RootBridgeHandle == RootBridge->Handle) {
1420 return EFI_SUCCESS;
1421 }
1422 }
1423
1424 return EFI_INVALID_PARAMETER;
1425 }