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