• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 *  Implementation of the Pci Host Bridge Resource Allocation for the Xpress-RICH3 PCIe Root Complex
3 *
4 *  Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
5 *
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 
18 EFI_STATUS
PciHbRaNotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)19 PciHbRaNotifyPhase (
20   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
21   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE     Phase
22   )
23 {
24   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
25   PCI_ROOT_BRIDGE_INSTANCE    *RootBridgeInstance;
26   EFI_STATUS                  Status;
27   EFI_PHYSICAL_ADDRESS        BaseAddress;
28   UINT64                      AddrLen;
29   UINTN                       BitsOfAlignment;
30 
31   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
32 
33   PCI_TRACE ("PciHbRaNotifyPhase()");
34 
35   // Check RootBridge Signature
36   ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
37 
38   // The enumeration cannot be restarted after the process has been further than the first phase
39   if (Phase == EfiPciHostBridgeBeginEnumeration) {
40     if (!HostBridgeInstance->CanRestarted) {
41       return EFI_NOT_READY;
42     }
43   } else {
44     HostBridgeInstance->CanRestarted = FALSE;
45   }
46 
47   switch (Phase) {
48   case EfiPciHostBridgeBeginEnumeration:
49     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginEnumeration)");
50     // Resets the host bridge PCI apertures and internal data structures
51     Status = HWPciRbInit (HostBridgeInstance->CpuIo);
52     if (EFI_ERROR (Status)) {
53       return Status;
54     }
55     break;
56 
57   case EfiPciHostBridgeBeginBusAllocation:
58     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginBusAllocation)");
59     // The bus allocation phase is about to begin
60     break;
61 
62   case EfiPciHostBridgeEndBusAllocation:
63     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndBusAllocation)");
64     // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
65     // a bus number range into their configuration
66     break;
67 
68   case EfiPciHostBridgeBeginResourceAllocation:
69     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeBeginResourceAllocation)");
70     // The resource allocation phase is about to begin.
71     break;
72 
73   case EfiPciHostBridgeAllocateResources:
74     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeAllocateResources)");
75     // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
76     // PciHbRaSubmitResources() before.
77 
78     RootBridgeInstance = HostBridgeInstance->RootBridge;
79     if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
80       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1;     // Get the number of '1' in Alignment
81       AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
82 
83       Status = gDS->AllocateIoSpace (
84                   EfiGcdAllocateAnySearchBottomUp,
85                   EfiGcdIoTypeIo,
86                   BitsOfAlignment,
87                   AddrLen,
88                   &BaseAddress,
89                   HostBridgeInstance->ImageHandle,
90                   NULL
91                );
92       // If error then ResAlloc[n].Base ==0
93       if (!EFI_ERROR (Status)) {
94         RootBridgeInstance->ResAlloc[ResTypeIo].Base   = (UINTN)BaseAddress;
95       }
96     }
97 
98     if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
99       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1;  // Get the number of '1' in Alignment
100       AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
101 
102       // Top of the 32bit PCI Memory space
103       BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
104 
105       Status = gDS->AllocateMemorySpace (
106                   EfiGcdAllocateMaxAddressSearchTopDown,
107                   EfiGcdMemoryTypeMemoryMappedIo,
108                   BitsOfAlignment,
109                   AddrLen,
110                   &BaseAddress,
111                   HostBridgeInstance->ImageHandle,
112                   NULL
113                );
114 
115       // Ensure the allocation is in the 32bit PCI memory space
116       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
117         RootBridgeInstance->ResAlloc[ResTypeMem32].Base   = (UINTN)BaseAddress;
118       }
119     }
120     if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
121       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1;  // Get the number of '1' in Alignment
122       AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
123 
124       // Top of the 32bit PCI Memory space
125       BaseAddress = FixedPcdGet64 (PcdPciMmio32Base) + FixedPcdGet64 (PcdPciMmio32Size);
126 
127       Status = gDS->AllocateMemorySpace (
128                   EfiGcdAllocateMaxAddressSearchTopDown,
129                   EfiGcdMemoryTypeMemoryMappedIo,
130                   BitsOfAlignment,
131                   AddrLen,
132                   &BaseAddress,
133                   HostBridgeInstance->ImageHandle,
134                   NULL
135                );
136 
137       // Ensure the allocation is in the 32bit PCI memory space
138       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio32Base))) {
139         RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)BaseAddress;
140       }
141     }
142     if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
143       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1;  // Get the number of '1' in Alignment
144       AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
145 
146       // Top of the 64bit PCI Memory space
147       BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
148 
149       Status = gDS->AllocateMemorySpace (
150                   EfiGcdAllocateMaxAddressSearchTopDown,
151                   EfiGcdMemoryTypeMemoryMappedIo,
152                   BitsOfAlignment,
153                   AddrLen,
154                   &BaseAddress,
155                   HostBridgeInstance->ImageHandle,
156                   NULL
157                );
158 
159       // Ensure the allocation is in the 64bit PCI memory space
160       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
161         RootBridgeInstance->ResAlloc[ResTypeMem64].Base   = (UINTN)BaseAddress;
162       }
163     }
164     if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
165       BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1;  //Get the number of '1' in Alignment
166       AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
167 
168       // Top of the 64bit PCI Memory space
169       BaseAddress = FixedPcdGet64 (PcdPciMmio64Base) + FixedPcdGet64 (PcdPciMmio64Size);
170 
171       Status = gDS->AllocateMemorySpace (
172                   EfiGcdAllocateMaxAddressSearchTopDown,
173                   EfiGcdMemoryTypeMemoryMappedIo,
174                   BitsOfAlignment,
175                   AddrLen,
176                   &BaseAddress,
177                   HostBridgeInstance->ImageHandle,
178                   NULL
179                );
180 
181       // Ensure the allocation is in the 64bit PCI memory space
182       if (!EFI_ERROR (Status) && (BaseAddress >= FixedPcdGet64 (PcdPciMmio64Base))) {
183         RootBridgeInstance->ResAlloc[ResTypePMem64].Base   = (UINTN)BaseAddress;
184       }
185     }
186 
187     break;
188 
189   case EfiPciHostBridgeSetResources:
190     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeSetResources)");
191     // Programs the host bridge hardware to decode previously allocated resources (proposed resources)
192     // for all the PCI root bridges. The PCI bus driver will now program the resources
193     break;
194 
195   case EfiPciHostBridgeFreeResources:
196     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeFreeResources)");
197     // Deallocates resources that were previously allocated for all the PCI root bridges and resets the
198     // I/O and memory apertures to their initial state.*/
199     break;
200 
201   case EfiPciHostBridgeEndResourceAllocation:
202     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndResourceAllocation)");
203     break;
204 
205   case EfiPciHostBridgeEndEnumeration:
206     PCI_TRACE ("PciHbRaNotifyPhase(EfiPciHostBridgeEndEnumeration)");
207     break;
208 
209   default:
210     DEBUG ((EFI_D_INFO, "PciHbRaNotifyPhase(Phase:%d)\n", Phase));
211     ASSERT (0);
212   }
213 
214   return EFI_SUCCESS;
215 }
216 
217 /**
218  * PciHbRaGetNextRootBridge() returns the next root bridge attached to the 'This' PCI Host Bridge.
219  * As we have only got one PCI Root Bridge in this PCI interface, we return either this root bridge
220  * if it the first time we call this function (*RootBridgeHandle == NULL) or we return EFI_NOT_FOUND
221  **/
222 EFI_STATUS
PciHbRaGetNextRootBridge(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN OUT EFI_HANDLE * RootBridgeHandle)223 PciHbRaGetNextRootBridge (
224   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
225   IN OUT EFI_HANDLE                                    *RootBridgeHandle
226   )
227 {
228   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
229 
230   PCI_TRACE ("PciHbRaGetNextRootBridge()");
231 
232   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
233   ASSERT (HostBridgeInstance->RootBridge != NULL);
234 
235   //Check RootBridge Signature
236   ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
237 
238   if (*RootBridgeHandle == NULL) {
239     *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
240     return EFI_SUCCESS;
241   } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
242     return EFI_NOT_FOUND;
243   } else {
244     return EFI_INVALID_PARAMETER;
245   }
246 }
247 
248 /** PciHbRaGetAllocAttributes() returns the resource allocation attributes supported by this PCI Root Bridge.
249  *  A PCI Root bridge could support these types :
250  *      - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate windows for nonprefetchable and prefetchable memory.
251  *      - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
252  **/
253 EFI_STATUS
PciHbRaGetAllocAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT UINT64 * Attributes)254 PciHbRaGetAllocAttributes (
255   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
256   IN  EFI_HANDLE                                        RootBridgeHandle,
257   OUT UINT64                                           *Attributes
258   )
259 {
260   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
261 
262   PCI_TRACE ("PciHbRaGetAllocAttributes()");
263 
264   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
265 
266   // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
267   ASSERT (HostBridgeInstance->RootBridge != NULL);
268   if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
269     return EFI_INVALID_PARAMETER;
270   }
271 
272   *Attributes = HostBridgeInstance->RootBridge->MemAllocAttributes;
273   return EFI_SUCCESS;
274 }
275 
276 EFI_STATUS
PciHbRaStartBusEnumeration(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)277 PciHbRaStartBusEnumeration (
278   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
279   IN  EFI_HANDLE                                        RootBridgeHandle,
280   OUT VOID                                            **Configuration
281   )
282 {
283   VOID    *Buffer;
284   UINT8   *Ptr;
285   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
286 
287   // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
288   // to set bus numbers to PCI-to-PCI bridge.
289   PCI_TRACE ("PciHbRaStartBusEnumeration()");
290 
291   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
292 
293   Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
294   if (Buffer == NULL) {
295     return EFI_OUT_OF_RESOURCES;
296   }
297 
298   Ptr = (UINT8 *)Buffer;
299 
300   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;    // QWORD Address space Descriptor
301   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len  = 0x2B;    // Length of this descriptor in bytes not including the first two fields
302   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS;  // Resource Type Bus Number Range
303   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
304   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
305   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
306   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart;   // Bus Start
307   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0;    // Bus Max
308   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
309   ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
310 
311   Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
312   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
313   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
314 
315   *Configuration = Buffer;
316   return EFI_SUCCESS;
317 }
318 
319 EFI_STATUS
PciHbRaSetBusNumbers(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)320 PciHbRaSetBusNumbers (
321   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
322   IN EFI_HANDLE                                         RootBridgeHandle,
323   IN VOID                                              *Configuration
324   )
325 {
326   PCI_HOST_BRIDGE_INSTANCE    *HostBridgeInstance;
327   UINT8                       *Ptr;
328   UINTN                       BusStart;
329   UINTN                       BusEnd;
330   UINTN                       BusLen;
331 
332   PCI_TRACE ("PciHbRaSetBusNumbers()");
333 
334   Ptr = Configuration;
335   if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
336     return EFI_INVALID_PARAMETER;
337   }
338 
339   // Check if the passed ACPI descriptor table define a Bus Number Range
340   if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
341     return EFI_INVALID_PARAMETER;
342   }
343 
344   // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
345   if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
346     return EFI_INVALID_PARAMETER;
347   }
348 
349   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
350   ASSERT (HostBridgeInstance->RootBridge != NULL);
351   if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
352     return EFI_INVALID_PARAMETER;
353   }
354 
355   BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
356   BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
357   BusEnd = BusStart + BusLen - 1;
358 
359   ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
360   ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
361 
362   HostBridgeInstance->RootBridge->BusStart  = BusStart;
363   HostBridgeInstance->RootBridge->BusLength = BusLen;
364 
365   return EFI_SUCCESS;
366 }
367 
368 /**
369  * This function is used to submit all the I/O and memory resources that are required by the specified
370  * PCI root bridge.
371  **/
372 EFI_STATUS
PciHbRaSubmitResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)373 PciHbRaSubmitResources (
374   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
375   IN EFI_HANDLE                                         RootBridgeHandle,
376   IN VOID                                              *Configuration
377   )
378 {
379   PCI_HOST_BRIDGE_INSTANCE            *HostBridgeInstance;
380   PCI_ROOT_BRIDGE_INSTANCE            *RootBridgeInstance;
381   UINT8                               *Ptr;
382   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
383   PCI_RESOURCE_TYPE                   ResType;
384 
385   PCI_TRACE ("PciHbRaSubmitResources()");
386 
387   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
388 
389   if (Configuration == NULL) {
390     return EFI_INVALID_PARAMETER;
391   }
392 
393   // Check if the ACPI Descriptor tables is conformed
394   Ptr = (UINT8 *)Configuration;
395   while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
396     Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
397   }
398   if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
399     return EFI_INVALID_PARAMETER;
400   }
401 
402   // Check the RootBridgeHandle
403   RootBridgeInstance = HostBridgeInstance->RootBridge;
404   ASSERT (RootBridgeInstance != NULL);
405   if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
406     return EFI_INVALID_PARAMETER;
407   }
408 
409   Ptr = (UINT8 *)Configuration;
410   while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
411     Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
412 
413     // Check if the description is valid
414     if (Desc->AddrLen > 0xffffffff) {
415       return EFI_INVALID_PARAMETER;
416     }
417 
418     if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
419       return EFI_INVALID_PARAMETER;
420     }
421 
422     switch (Desc->ResType) {
423     case ACPI_ADDRESS_SPACE_TYPE_MEM:
424       // Check invalid Address Space Granularity
425       if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
426         return EFI_INVALID_PARAMETER;
427       }
428 
429       // check the memory resource request is supported by PCI root bridge
430       if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
431         return EFI_INVALID_PARAMETER;
432       }
433 
434       if (Desc->AddrSpaceGranularity == 32) {
435         if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
436           ResType = ResTypePMem32;
437         } else {
438           ResType = ResTypeMem32;
439         }
440       } else {
441         if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
442           ResType = ResTypePMem64;
443         } else {
444           ResType = ResTypeMem64;
445         }
446       }
447       RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
448       RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
449       RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
450       break;
451     case ACPI_ADDRESS_SPACE_TYPE_IO:
452       RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
453       RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
454       RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
455       break;
456     default:
457       ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
458       break;
459     }
460     Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
461   }
462 
463   return EFI_SUCCESS;
464 }
465 
466 /** Returns the proposed resource settings for the specified PCI root bridge. The resources have been submitted by
467   * PciHbRaSubmitResources() before
468   **/
469 EFI_STATUS
PciHbRaGetProposedResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)470 PciHbRaGetProposedResources (
471   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
472   IN  EFI_HANDLE                                        RootBridgeHandle,
473   OUT VOID                                            **Configuration
474   )
475 {
476   PCI_HOST_BRIDGE_INSTANCE            *HostBridgeInstance;
477   PCI_ROOT_BRIDGE_INSTANCE            *RootBridgeInstance;
478   UINT32                              i;
479   UINT32                              ResAllocCount;
480   VOID                                *Buffer;
481   UINT8                               *Ptr;
482   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR   *Desc;
483 
484   PCI_TRACE ("PciHbRaGetProposedResources()");
485 
486   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
487 
488   // Check the RootBridgeHandle
489   RootBridgeInstance = HostBridgeInstance->RootBridge;
490   ASSERT (RootBridgeInstance != NULL);
491   if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
492     return EFI_INVALID_PARAMETER;
493   }
494 
495   // Count the number of Resource Allocated for this Root Bridge
496   ResAllocCount = 0;
497   for (i = 0; i < ResTypeMax; i++) {
498     if (RootBridgeInstance->ResAlloc[i].Length != 0)  ResAllocCount++;
499   }
500 
501   if (ResAllocCount ==  0) {
502     return EFI_INVALID_PARAMETER;
503   }
504 
505   Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
506   if (Buffer == NULL) {
507     return EFI_OUT_OF_RESOURCES;
508   }
509 
510   Ptr = Buffer;
511   for (i = 0; i < ResTypeMax; i++) {
512     if (RootBridgeInstance->ResAlloc[i].Length != 0) {    // Base != 0 if the resource has been allocated
513       Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
514 
515       Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
516       Desc->Len  = 0x2B;
517       Desc->GenFlag = 0;
518       Desc->AddrRangeMax = 0;
519 
520       switch (i) {
521       case ResTypeIo:
522         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_IO;
523         Desc->SpecificFlag = 0;
524         Desc->AddrSpaceGranularity = 0;
525         break;
526       case ResTypeMem32:
527         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
528         Desc->SpecificFlag = 0;
529         Desc->AddrSpaceGranularity = 32;
530         break;
531       case ResTypePMem32:
532         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
533         Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
534         Desc->AddrSpaceGranularity = 32;
535         break;
536       case ResTypeMem64:
537         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
538         Desc->SpecificFlag = 0;
539         Desc->AddrSpaceGranularity = 64;
540         break;
541       case ResTypePMem64:
542         Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
543         Desc->SpecificFlag = ACPI_SPECFLAG_PREFETCHABLE;
544         Desc->AddrSpaceGranularity = 64;
545         break;
546       }
547       Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
548       Desc->AddrTranslationOffset = (RootBridgeInstance->ResAlloc[i].Base != 0) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
549       Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
550       Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
551     }
552   }
553 
554   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
555   ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
556 
557   *Configuration = Buffer;
558   return EFI_SUCCESS;
559 }
560 
561 EFI_STATUS
PciHbRaPreprocessController(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)562 PciHbRaPreprocessController (
563   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL  *This,
564   IN  EFI_HANDLE                                        RootBridgeHandle,
565   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS       PciAddress,
566   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE      Phase
567   )
568 {
569   PCI_HOST_BRIDGE_INSTANCE*   HostBridge;
570   PCI_ROOT_BRIDGE_INSTANCE*   RootBridge;
571   UINT32                      CapabilityPtr;
572   UINT32                      CapabilityEntry;
573   UINT16                      CapabilityID;
574   UINT32                      DeviceCapability;
575 
576   PCI_TRACE ("PciHbRaPreprocessController()");
577 
578   if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
579     // Do Max payload fixup for every devices
580     if (Phase == EfiPciBeforeResourceCollection) {
581       // Get RootBridge Instance from Host Bridge Instance
582       HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
583       RootBridge = HostBridge->RootBridge;
584 
585       // Get the first PCI Capability
586       CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
587       RootBridge->Io.Pci.Read (
588           &RootBridge->Io,
589           EfiPciWidthUint8,
590           EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
591           1,
592           &CapabilityPtr
593       );
594       CapabilityPtr &= 0x1FF;
595 
596       // Get Pci Express Capability
597       while (CapabilityPtr != 0) {
598         RootBridge->Io.Pci.Read (
599             &RootBridge->Io,
600             EfiPciWidthUint16,
601             EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
602             1,
603             &CapabilityEntry
604             );
605 
606         CapabilityID = (UINT8)CapabilityEntry;
607 
608         // Is PCIe capability ?
609         if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
610           // Get PCIe Device Capabilities
611           RootBridge->Io.Pci.Read (
612               &RootBridge->Io,
613               EfiPciWidthUint32,
614               EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
615               1,
616               &DeviceCapability
617               );
618 
619           // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
620           DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
621           // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
622           DeviceCapability &= ~ ((UINT32)(0x7 << 12));
623           // Enable all error reporting
624           DeviceCapability |= 0xF;
625 
626           RootBridge->Io.Pci.Write (
627               &RootBridge->Io,
628               EfiPciWidthUint32,
629               EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
630               1,
631               &DeviceCapability
632               );
633 
634           return EFI_SUCCESS;
635         }
636         CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
637       }
638     }
639   }
640 
641   return EFI_SUCCESS;
642 }
643