• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2 Pci Host Bridge driver for a simple IIO. There is only one PCI Root Bridge in the system.
3 Provides the basic interfaces to abstract a PCI Host Bridge Resource Allocation.
4 
5 Copyright (c) 2013-2015 Intel Corporation.
6 
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution.  The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
11 
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 
16 **/
17 
18 #include "PciHostBridge.h"
19 #include <IntelQNCRegs.h>
20 
21 //
22 // We can hardcode the following for a Simple IIO -
23 // Root Bridge Count within the host bridge
24 // Root Bridge's device path
25 // Root Bridge's resource appeture
26 //
27 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH    mEfiPciRootBridgeDevicePath[ROOT_BRIDGE_COUNT] = {
28   {
29     {
30       {
31         ACPI_DEVICE_PATH,
32         ACPI_DP,
33         {
34           (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
35           (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
36         }
37       },
38       EISA_PNP_ID (0x0A03),
39       0
40     },
41     {
42       END_DEVICE_PATH_TYPE,
43       END_ENTIRE_DEVICE_PATH_SUBTYPE,
44       {
45         END_DEVICE_PATH_LENGTH,
46         0
47       }
48     }
49   }
50 };
51 
52 EFI_HANDLE                         mDriverImageHandle;
53 PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *mResAperture;
54 
55 //
56 // Implementation
57 //
58 EFI_STATUS
59 EFIAPI
InitializePciHostBridge(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)60 InitializePciHostBridge (
61   IN EFI_HANDLE         ImageHandle,
62   IN EFI_SYSTEM_TABLE   *SystemTable
63   )
64 /*++
65 
66 Routine Description:
67 
68   Entry point of this driver.
69 
70 Arguments:
71 
72   ImageHandle  -  Image handle of this driver.
73   SystemTable  -  Pointer to standard EFI system table.
74 
75 Returns:
76 
77   EFI_SUCCESS       -  Succeed.
78   EFI_DEVICE_ERROR  -  Fail to install PCI_ROOT_BRIDGE_IO protocol.
79 
80 --*/
81 {
82   EFI_STATUS                  Status;
83   UINTN                       TotalRootBridgeFound;
84   PCI_HOST_BRIDGE_INSTANCE    *HostBridge;
85   PCI_ROOT_BRIDGE_INSTANCE    *PrivateData;
86   UINT64                      AllocAttributes;
87   EFI_PHYSICAL_ADDRESS        BaseAddress;
88 
89   PrivateData = NULL;
90 
91   mDriverImageHandle = ImageHandle;
92 
93   //
94   // Most systems in the world including complex servers
95   // have only one Host Bridge. Create Host Bridge Device Handle
96   //
97   Status = gBS->AllocatePool(EfiBootServicesData, sizeof(PCI_HOST_BRIDGE_INSTANCE), (VOID **) &HostBridge);
98   ASSERT_EFI_ERROR (Status);
99   ZeroMem (HostBridge, sizeof (PCI_HOST_BRIDGE_INSTANCE));
100 
101   HostBridge->Signature         = PCI_HOST_BRIDGE_SIGNATURE;
102   HostBridge->RootBridgeCount   = 1;
103   HostBridge->ResourceSubmited  = FALSE;
104   HostBridge->CanRestarted      = TRUE;
105   //
106   // InitializeListHead (&HostBridge->Head);
107   //
108   HostBridge->ResAlloc.NotifyPhase          = NotifyPhase;
109   HostBridge->ResAlloc.GetNextRootBridge    = GetNextRootBridge;
110   HostBridge->ResAlloc.GetAllocAttributes   = GetAttributes;
111   HostBridge->ResAlloc.StartBusEnumeration  = StartBusEnumeration;
112   HostBridge->ResAlloc.SetBusNumbers        = SetBusNumbers;
113   HostBridge->ResAlloc.SubmitResources      = SubmitResources;
114   HostBridge->ResAlloc.GetProposedResources = GetProposedResources;
115   HostBridge->ResAlloc.PreprocessController = PreprocessController;
116 
117   Status = gBS->InstallProtocolInterface (
118                     &HostBridge->HostBridgeHandle,
119                     &gEfiPciHostBridgeResourceAllocationProtocolGuid,
120                     EFI_NATIVE_INTERFACE,
121                     &HostBridge->ResAlloc
122                     );
123   if (EFI_ERROR (Status)) {
124     gBS->FreePool (HostBridge);
125     return EFI_DEVICE_ERROR;
126   }
127 
128   Status = gBS->AllocatePool (EfiBootServicesData,
129                 HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE),
130                 (VOID **) &mResAperture);
131   ASSERT_EFI_ERROR (Status);
132   ZeroMem (mResAperture, HostBridge->RootBridgeCount * sizeof(PCI_ROOT_BRIDGE_RESOURCE_APERTURE));
133 
134   DEBUG ((EFI_D_INFO, "Address of resource Aperture:  %x\n", mResAperture));
135 
136   //
137   // Create Root Bridge Device Handle in this Host Bridge
138   //
139   InitializeListHead (&HostBridge->Head);
140 
141   TotalRootBridgeFound = 0;
142 
143   Status = gBS->AllocatePool ( EfiBootServicesData,sizeof (PCI_ROOT_BRIDGE_INSTANCE), (VOID **) &PrivateData);
144   ASSERT_EFI_ERROR (Status);
145   ZeroMem (PrivateData, sizeof (PCI_ROOT_BRIDGE_INSTANCE));
146 
147   PrivateData->Signature  = PCI_ROOT_BRIDGE_SIGNATURE;
148   PrivateData->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &mEfiPciRootBridgeDevicePath[TotalRootBridgeFound];
149   AllocAttributes         = GetAllocAttributes (TotalRootBridgeFound);
150 
151   SimpleIioRootBridgeConstructor (
152       &PrivateData->Io,
153       HostBridge->HostBridgeHandle,
154       &(mResAperture[TotalRootBridgeFound]),
155       AllocAttributes
156       );
157   //
158   // Update Root Bridge with UDS resource information
159   //
160   PrivateData->Aperture.BusBase    = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE;
161   PrivateData->Aperture.BusLimit   = QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT;
162   PrivateData->Aperture.Mem32Base  = PcdGet32 (PcdPciHostBridgeMemory32Base);
163   PrivateData->Aperture.Mem32Limit = PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1);
164   PrivateData->Aperture.IoBase  = PcdGet16 (PcdPciHostBridgeIoBase);
165   PrivateData->Aperture.IoLimit = PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1);
166 
167   DEBUG ((EFI_D_INFO, "PCI Host Bridge BusBase:               %x\n",  QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSBASE));
168   DEBUG ((EFI_D_INFO, "PCI Host Bridge BusLimit:              %x\n",  QNC_PCI_HOST_BRIDGE_RESOURCE_APPETURE_BUSLIMIT));
169   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Base:  %x\n",  PcdGet32 (PcdPciHostBridgeMemory32Base)));
170   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem32Limit: %x\n",  PcdGet32 (PcdPciHostBridgeMemory32Base) + (PcdGet32 (PcdPciHostBridgeMemory32Size) - 1)));
171   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Base:  %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base)));
172   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceMem64Limit: %lX\n", PcdGet64 (PcdPciHostBridgeMemory64Base) + (PcdGet64 (PcdPciHostBridgeMemory64Size) - 1)));
173   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoBase:     %x\n",  PcdGet16 (PcdPciHostBridgeIoBase)));
174   DEBUG ((EFI_D_INFO, "PCI Host Bridge PciResourceIoLimit:    %x\n",  PcdGet16 (PcdPciHostBridgeIoBase) + (PcdGet16 (PcdPciHostBridgeIoSize) - 1)));
175 
176   PrivateData->Handle = NULL;
177   Status = gBS->InstallMultipleProtocolInterfaces (
178                   &PrivateData->Handle,
179                   &gEfiDevicePathProtocolGuid,
180                   PrivateData->DevicePath,
181                   &gEfiPciRootBridgeIoProtocolGuid,
182                   &PrivateData->Io,
183                   NULL
184                   );
185   ASSERT_EFI_ERROR (Status);
186 
187   InsertTailList (&HostBridge->Head, &PrivateData->Link);
188   TotalRootBridgeFound++;           // This is a valid rootbridge so imcrement total root bridges found
189 
190   //
191   // Add PCIE base into Runtime memory so that it can be reported in E820 table
192   //
193   Status = gDS->AddMemorySpace (
194                   EfiGcdMemoryTypeMemoryMappedIo,
195                   PcdGet64 (PcdPciExpressBaseAddress),
196                   PcdGet64 (PcdPciExpressSize),
197                   EFI_MEMORY_RUNTIME | EFI_MEMORY_UC
198                   );
199   ASSERT_EFI_ERROR(Status);
200 
201   BaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
202 
203   Status = gDS->AllocateMemorySpace (
204                   EfiGcdAllocateAddress,
205                   EfiGcdMemoryTypeMemoryMappedIo,
206                   0,
207                   PcdGet64 (PcdPciExpressSize),
208                   &BaseAddress,
209                   ImageHandle,
210                   NULL
211                   );
212   ASSERT_EFI_ERROR(Status);
213 
214   Status = gDS->SetMemorySpaceAttributes (
215                   PcdGet64 (PcdPciExpressBaseAddress),
216                   PcdGet64 (PcdPciExpressSize),
217                   EFI_MEMORY_RUNTIME
218                   );
219   ASSERT_EFI_ERROR (Status);
220 
221   if (PcdGet16 (PcdPciHostBridgeIoSize) > 0) {
222     //
223     // At present, we use up the first 4k for fixed ranges like
224     // ICH GPIO, ACPI and ISA devices. The first 4k is not
225     // tracked through GCD. It should be.
226     //
227     Status = gDS->AddIoSpace (
228                     EfiGcdIoTypeIo,
229                     PcdGet16(PcdPciHostBridgeIoBase),
230                     PcdGet16(PcdPciHostBridgeIoSize)
231                     );
232     ASSERT_EFI_ERROR (Status);
233   }
234 
235   if (PcdGet32(PcdPciHostBridgeMemory32Size) > 0) {
236     //
237     // Shouldn't the capabilities be UC?
238     //
239     Status = gDS->AddMemorySpace (
240                     EfiGcdMemoryTypeMemoryMappedIo,
241                     PcdGet32(PcdPciHostBridgeMemory32Base),
242                     PcdGet32(PcdPciHostBridgeMemory32Size),
243                     0
244                     );
245     ASSERT_EFI_ERROR (Status);
246   }
247 
248   return Status;
249 }
250 
251 EFI_STATUS
252 EFIAPI
NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)253 NotifyPhase (
254   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
255   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
256   )
257 /*++
258 
259 Routine Description:
260 
261   Enter a certain phase of the PCI enumeration process.
262 
263 Arguments:
264 
265   This   -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
266   Phase  -  The phase during enumeration.
267 
268 Returns:
269 
270   EFI_SUCCESS            -  Succeed.
271   EFI_INVALID_PARAMETER  -  Wrong phase parameter passed in.
272   EFI_NOT_READY          -  Resources have not been submitted yet.
273 
274 --*/
275 {
276   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
277   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
278   PCI_RESOURCE_TYPE                     Index;
279   EFI_LIST_ENTRY                        *List;
280   EFI_PHYSICAL_ADDRESS                  BaseAddress;
281   UINT64                                AddrLen;
282   UINTN                                 BitsOfAlignment;
283   UINT64                                Alignment;
284   EFI_STATUS                            Status;
285   EFI_STATUS                            ReturnStatus;
286   PCI_RESOURCE_TYPE                     Index1;
287   PCI_RESOURCE_TYPE                     Index2;
288   BOOLEAN                               ResNodeHandled[TypeMax];
289   UINT64                                MaxAlignment;
290 
291   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
292 
293   switch (Phase) {
294     case EfiPciHostBridgeBeginEnumeration:
295         if (HostBridgeInstance->CanRestarted) {
296           //
297           // Reset Root Bridge
298           //
299           List = HostBridgeInstance->Head.ForwardLink;
300 
301           while (List != &HostBridgeInstance->Head) {
302             RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
303             for (Index = TypeIo; Index < TypeMax; Index++) {
304               RootBridgeInstance->ResAllocNode[Index].Type    = Index;
305               RootBridgeInstance->ResAllocNode[Index].Base    = 0;
306               RootBridgeInstance->ResAllocNode[Index].Length  = 0;
307               RootBridgeInstance->ResAllocNode[Index].Status  = ResNone;
308             } // for
309 
310             List = List->ForwardLink;
311           } // while
312 
313           HostBridgeInstance->ResourceSubmited  = FALSE;
314           HostBridgeInstance->CanRestarted      = TRUE;
315         } else {
316           //
317           // Can not restart
318           //
319           return EFI_NOT_READY;
320         } // if
321         break;
322 
323     case EfiPciHostBridgeEndEnumeration:
324         return EFI_SUCCESS;
325         break;
326 
327     case EfiPciHostBridgeBeginBusAllocation:
328         //
329         // No specific action is required here, can perform any chipset specific programing
330         //
331         HostBridgeInstance->CanRestarted = FALSE;
332         return EFI_SUCCESS;
333         break;
334 
335     case EfiPciHostBridgeEndBusAllocation:
336         //
337         // No specific action is required here, can perform any chipset specific programing
338         //
339         // HostBridgeInstance->CanRestarted = FALSE;
340         //
341         return EFI_SUCCESS;
342         break;
343 
344     case EfiPciHostBridgeBeginResourceAllocation:
345         //
346         // No specific action is required here, can perform any chipset specific programing
347         //
348         // HostBridgeInstance->CanRestarted = FALSE;
349         //
350         return EFI_SUCCESS;
351         break;
352 
353     case EfiPciHostBridgeAllocateResources:
354         ReturnStatus = EFI_SUCCESS;
355         if (HostBridgeInstance->ResourceSubmited) {
356           List = HostBridgeInstance->Head.ForwardLink;
357           while (List != &HostBridgeInstance->Head) {
358             for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
359               ResNodeHandled[Index1] = FALSE;
360             }
361 
362             RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
363             DEBUG ((EFI_D_INFO, "Address of RootBridgeInstance:   %x)\n", RootBridgeInstance));
364             DEBUG ((EFI_D_INFO, "  Signature:              %x\n", RootBridgeInstance->Signature));
365             DEBUG ((EFI_D_INFO, "  Bus Number Assigned:    %x\n", RootBridgeInstance->BusNumberAssigned));
366             DEBUG ((EFI_D_INFO, "  Bus Scan Count:         %x\n", RootBridgeInstance->BusScanCount));
367 
368             for (Index1 = TypeIo; Index1 < TypeBus; Index1++) {
369               if (RootBridgeInstance->ResAllocNode[Index1].Status == ResNone) {
370                 ResNodeHandled[Index1] = TRUE;
371               } else {
372                 //
373                 // Allocate the resource node with max alignment at first
374                 //
375                 MaxAlignment = 0;
376                 Index        = TypeMax;
377                 for (Index2 = TypeIo; Index2 < TypeBus; Index2++) {
378                   if (ResNodeHandled[Index2]) {
379                     continue;
380                   }
381                   if (MaxAlignment <= RootBridgeInstance->ResAllocNode[Index2].Alignment) {
382                     MaxAlignment = RootBridgeInstance->ResAllocNode[Index2].Alignment;
383                     Index = Index2;
384                   }
385                 } // for
386 
387                 if (Index < TypeMax) {
388                   ResNodeHandled[Index] = TRUE;
389                 } else {
390                   ASSERT (FALSE);
391                 }
392 
393                 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
394 
395                 //
396                 // Get the number of '1' in Alignment.
397                 //
398                 for (BitsOfAlignment = 0; Alignment != 0; BitsOfAlignment++) {
399                   Alignment = RShiftU64 (Alignment, 1);
400                 }
401 
402                 AddrLen   = RootBridgeInstance->ResAllocNode[Index].Length;
403                 Alignment = RootBridgeInstance->ResAllocNode[Index].Alignment;
404 
405                 DEBUG ((EFI_D_INFO, "\n\nResource Type to assign :   %x\n", Index));
406                 DEBUG ((EFI_D_INFO, "  Length to allocate:       %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
407                 DEBUG ((EFI_D_INFO, "  Aligment:                 %x\n", Alignment));
408 
409                 switch (Index) {
410                   case TypeIo:
411                       if (RootBridgeInstance->Aperture.IoBase < RootBridgeInstance->Aperture.IoLimit) {
412                         //
413                         // It is impossible for 0xFFFF Alignment for IO16
414                         //
415                         if (BitsOfAlignment >= 16)
416                           Alignment = 0;
417 
418                         BaseAddress = RootBridgeInstance->Aperture.IoBase;
419 
420                         //
421                         // Have to make sure Aligment is handled seeing we are doing direct address allocation
422                         //
423                         if ((BaseAddress & ~(Alignment)) != BaseAddress)
424                           BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
425 
426                         while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.IoLimit + 1) {
427 
428                           Status = gDS->AllocateIoSpace ( EfiGcdAllocateAddress, EfiGcdIoTypeIo, BitsOfAlignment,
429                                                           AddrLen, &BaseAddress, mDriverImageHandle, NULL );
430 
431                           if (!EFI_ERROR (Status)) {
432                             RootBridgeInstance->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
433                             RootBridgeInstance->ResAllocNode[Index].Status  = ResAllocated;
434                             goto TypeIoFound;
435                           }
436 
437                           BaseAddress += (Alignment + 1);
438                         } // while
439 
440                       } // if
441 
442                       TypeIoFound:
443                       if (RootBridgeInstance->ResAllocNode[Index].Status  != ResAllocated) {
444                         //
445                         // No Room at the Inn for this resources request
446                         //
447                         ReturnStatus = EFI_OUT_OF_RESOURCES;
448                       } // if
449 
450                       break;
451 
452                   case TypeMem32:
453                       if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
454 
455                         BaseAddress = RootBridgeInstance->Aperture.Mem32Base;
456                         //
457                         // Have to make sure Aligment is handled seeing we are doing direct address allocation
458                         //
459                         if ((BaseAddress & ~(Alignment)) != BaseAddress)
460                           BaseAddress = ((BaseAddress + Alignment) & ~(Alignment));
461 
462                         while((BaseAddress + AddrLen) <= RootBridgeInstance->Aperture.Mem32Limit + 1) {
463 
464                           Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
465                                                             BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
466 
467                           if (!EFI_ERROR (Status)) {
468                             RootBridgeInstance->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
469                             RootBridgeInstance->ResAllocNode[Index].Status  = ResAllocated;
470                             goto TypeMem32Found;
471                           } // if
472 
473                           BaseAddress += (Alignment + 1);
474                         } // while
475                       } // if
476 
477                       TypeMem32Found:
478                       if (RootBridgeInstance->ResAllocNode[Index].Status  != ResAllocated) {
479                         //
480                         // No Room at the Inn for this resources request
481                         //
482                         ReturnStatus = EFI_OUT_OF_RESOURCES;
483                       }
484 
485                       break;
486 
487                   case TypePMem32:
488                       StartTypePMem32:
489                       if (RootBridgeInstance->Aperture.Mem32Base < RootBridgeInstance->Aperture.Mem32Limit) {
490 
491                         BaseAddress = RootBridgeInstance->Aperture.Mem32Limit + 1;
492                         BaseAddress -= AddrLen;
493 
494                         //
495                         // Have to make sure Aligment is handled seeing we are doing direct address allocation
496                         //
497                         if ((BaseAddress & ~(Alignment)) != BaseAddress)
498                           BaseAddress = ((BaseAddress) & ~(Alignment));
499 
500                         while(RootBridgeInstance->Aperture.Mem32Base <= BaseAddress) {
501 
502                           DEBUG ((EFI_D_INFO, "      Attempting %x allocation at 0x%lx .....", Index, BaseAddress));
503                           Status = gDS->AllocateMemorySpace ( EfiGcdAllocateAddress, EfiGcdMemoryTypeMemoryMappedIo,
504                                                   BitsOfAlignment, AddrLen, &BaseAddress, mDriverImageHandle, NULL);
505 
506                           if (!EFI_ERROR (Status)) {
507                             RootBridgeInstance->ResAllocNode[Index].Base    = (UINT64) BaseAddress;
508                             RootBridgeInstance->ResAllocNode[Index].Status  = ResAllocated;
509                             DEBUG ((EFI_D_INFO, "... Passed!!\n"));
510                             goto TypePMem32Found;
511                           }
512                           DEBUG ((EFI_D_INFO, "... Failed!!\n"));
513                           BaseAddress -= (Alignment + 1);
514                         } // while
515                       } // if
516 
517                       TypePMem32Found:
518                       if (RootBridgeInstance->ResAllocNode[Index].Status  != ResAllocated) {
519                         //
520                         // No Room at the Inn for this resources request
521                         //
522                         ReturnStatus = EFI_OUT_OF_RESOURCES;
523                       }
524 
525                       break;
526 
527                   case TypeMem64:
528                   case TypePMem64:
529                       if (RootBridgeInstance->ResAllocNode[Index].Status  != ResAllocated) {
530                         //
531                         // If 64-bit resourcing is not available, then try as PMem32
532                         //
533                         goto StartTypePMem32;
534                       }
535 
536                       break;
537 
538                   default:
539                       break;
540                 } // End switch (Index)
541 
542                 DEBUG ((EFI_D_INFO, "Resource Type Assigned:   %x\n", Index));
543                 if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
544                   DEBUG ((EFI_D_INFO, "  Base Address Assigned: %x\n", RootBridgeInstance->ResAllocNode[Index].Base));
545                   DEBUG ((EFI_D_INFO, "  Length Assigned:       %x\n", RootBridgeInstance->ResAllocNode[Index].Length));
546                 } else {
547                   DEBUG ((DEBUG_ERROR, "  Resource Allocation failed!  There was no room at the inn\n"));
548                 }
549 
550               }
551             }
552 
553             List = List->ForwardLink;
554           }
555 
556           if (ReturnStatus == EFI_OUT_OF_RESOURCES) {
557             DEBUG ((DEBUG_ERROR, "Resource allocation Failed. Continue booting the system.\n"));
558           }
559 
560           //
561           // Set resource to zero for nodes where allocation fails
562           //
563           List = HostBridgeInstance->Head.ForwardLink;
564           while (List != &HostBridgeInstance->Head) {
565             RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
566             for (Index = TypeIo; Index < TypeBus; Index++) {
567               if (RootBridgeInstance->ResAllocNode[Index].Status != ResAllocated) {
568                 RootBridgeInstance->ResAllocNode[Index].Length = 0;
569               }
570             }
571             List = List->ForwardLink;
572           }
573           return ReturnStatus;
574         } else {
575           return EFI_NOT_READY;
576         }
577         //
578         // HostBridgeInstance->CanRestarted = FALSE;
579         //
580         break;
581 
582     case EfiPciHostBridgeSetResources:
583         //
584         // HostBridgeInstance->CanRestarted = FALSE;
585         //
586         break;
587 
588     case EfiPciHostBridgeFreeResources:
589         //
590         // HostBridgeInstance->CanRestarted = FALSE;
591         //
592         ReturnStatus  = EFI_SUCCESS;
593         List          = HostBridgeInstance->Head.ForwardLink;
594         while (List != &HostBridgeInstance->Head) {
595           RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
596           for (Index = TypeIo; Index < TypeBus; Index++) {
597             if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
598               AddrLen     = RootBridgeInstance->ResAllocNode[Index].Length;
599               BaseAddress = (EFI_PHYSICAL_ADDRESS) RootBridgeInstance->ResAllocNode[Index].Base;
600               switch (Index) {
601                 case TypeIo:
602                     Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
603                     if (EFI_ERROR (Status)) {
604                       ReturnStatus = Status;
605                     }
606                     break;
607 
608                 case TypeMem32:
609                     Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
610                     if (EFI_ERROR (Status)) {
611                       ReturnStatus = Status;
612                     }
613                     break;
614 
615                 case TypePMem32:
616                     break;
617 
618                 case TypeMem64:
619                     break;
620 
621                 case TypePMem64:
622                     Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
623                     if (EFI_ERROR (Status)) {
624                       ReturnStatus = Status;
625                     }
626                     break;
627 
628                 default:
629                     break;
630               } // end switch (Index)
631 
632               RootBridgeInstance->ResAllocNode[Index].Type    = Index;
633               RootBridgeInstance->ResAllocNode[Index].Base    = 0;
634               RootBridgeInstance->ResAllocNode[Index].Length  = 0;
635               RootBridgeInstance->ResAllocNode[Index].Status  = ResNone;
636             }
637           }
638 
639           List = List->ForwardLink;
640         }
641 
642         HostBridgeInstance->ResourceSubmited  = FALSE;
643         HostBridgeInstance->CanRestarted      = TRUE;
644         return ReturnStatus;
645         break;
646 
647     case EfiPciHostBridgeEndResourceAllocation:
648         //
649         // Resource enumeration is done. Perform any activities that
650         // must wait until that time.
651         //
652         break;
653 
654     default:
655         return EFI_INVALID_PARAMETER;
656   } // End switch (Phase)
657 
658   return EFI_SUCCESS;
659 }
660 
661 EFI_STATUS
662 EFIAPI
GetNextRootBridge(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN OUT EFI_HANDLE * RootBridgeHandle)663 GetNextRootBridge (
664   IN     EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
665   IN OUT EFI_HANDLE                                       *RootBridgeHandle
666   )
667 /*++
668 
669 Routine Description:
670   Return the device handle of the next PCI root bridge that is associated with
671   this Host Bridge.
672 
673 Arguments:
674 
675   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
676   RootBridgeHandle  -  Returns the device handle of the next PCI Root Bridge.
677                        On input, it holds the RootBridgeHandle returned by the most
678                        recent call to GetNextRootBridge().The handle for the first
679                        PCI Root Bridge is returned if RootBridgeHandle is NULL on input.
680 
681 Returns:
682 
683   EFI_SUCCESS            -  Succeed.
684   EFI_NOT_FOUND          -  Next PCI root bridge not found.
685   EFI_INVALID_PARAMETER  -  Wrong parameter passed in.
686 
687 --*/
688 {
689   BOOLEAN                   NoRootBridge;
690   EFI_LIST_ENTRY            *List;
691   PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
692   PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
693 
694   NoRootBridge        = TRUE;
695   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
696   List                = HostBridgeInstance->Head.ForwardLink;
697 
698   while (List != &HostBridgeInstance->Head) {
699     NoRootBridge        = FALSE;
700     RootBridgeInstance  = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
701     if (*RootBridgeHandle == NULL) {
702       //
703       // Return the first Root Bridge Handle of the Host Bridge
704       //
705       *RootBridgeHandle = RootBridgeInstance->Handle;
706       return EFI_SUCCESS;
707     } else {
708       if (*RootBridgeHandle == RootBridgeInstance->Handle) {
709         //
710         // Get next if have
711         //
712         List = List->ForwardLink;
713         if (List != &HostBridgeInstance->Head) {
714           RootBridgeInstance  = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
715           *RootBridgeHandle   = RootBridgeInstance->Handle;
716           return EFI_SUCCESS;
717         } else {
718           return EFI_NOT_FOUND;
719         }
720       }
721     }
722 
723     List = List->ForwardLink;
724     //
725     // end while
726     //
727   }
728 
729   if (NoRootBridge) {
730     return EFI_NOT_FOUND;
731   } else {
732     return EFI_INVALID_PARAMETER;
733   }
734 }
735 
736 EFI_STATUS
737 EFIAPI
GetAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT UINT64 * Attributes)738 GetAttributes (
739   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
740   IN  EFI_HANDLE                                       RootBridgeHandle,
741   OUT UINT64                                           *Attributes
742   )
743 /*++
744 
745 Routine Description:
746   Returns the attributes of a PCI Root Bridge.
747 
748 Arguments:
749 
750   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
751   RootBridgeHandle  -  The device handle of the PCI Root Bridge
752                        that the caller is interested in.
753   Attributes        -  The pointer to attributes of the PCI Root Bridge.
754 
755 Returns:
756 
757   EFI_SUCCESS            -  Succeed.
758   EFI_INVALID_PARAMETER  -  Attributes parameter passed in is NULL or
759                             RootBridgeHandle is not an EFI_HANDLE
760                             that was returned on a previous call to
761                             GetNextRootBridge().
762 
763 --*/
764 {
765   EFI_LIST_ENTRY            *List;
766   PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
767   PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
768 
769   if (Attributes == NULL) {
770     return EFI_INVALID_PARAMETER;
771   }
772 
773   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
774   List                = HostBridgeInstance->Head.ForwardLink;
775 
776   while (List != &HostBridgeInstance->Head) {
777     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
778     if (RootBridgeHandle == RootBridgeInstance->Handle) {
779       *Attributes = RootBridgeInstance->RootBridgeAllocAttrib;
780       return EFI_SUCCESS;
781     }
782 
783     List = List->ForwardLink;
784   }
785   //
786   // RootBridgeHandle is not an EFI_HANDLE
787   // that was returned on a previous call to GetNextRootBridge()
788   //
789   return EFI_INVALID_PARAMETER;
790 }
791 
792 EFI_STATUS
793 EFIAPI
StartBusEnumeration(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)794 StartBusEnumeration (
795   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
796   IN  EFI_HANDLE                                       RootBridgeHandle,
797   OUT VOID                                             **Configuration
798   )
799 /*++
800 
801 Routine Description:
802   This is the request from the PCI enumerator to set up
803   the specified PCI Root Bridge for bus enumeration process.
804 
805 Arguments:
806 
807   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
808   RootBridgeHandle  -  The PCI Root Bridge to be set up.
809   Configuration     -  Pointer to the pointer to the PCI bus resource descriptor.
810 
811 Returns:
812 
813   EFI_SUCCESS            -  Succeed.
814   EFI_OUT_OF_RESOURCES   -  Not enough pool to be allocated.
815   EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
816 
817 --*/
818 {
819   EFI_LIST_ENTRY            *List;
820   PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
821   PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
822   VOID                      *Buffer;
823   UINT8                     *Temp;
824   EFI_STATUS                Status;
825   UINTN                     BusStart;
826   UINTN                     BusEnd;
827   UINT64                    BusReserve;
828 
829   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
830   List                = HostBridgeInstance->Head.ForwardLink;
831 
832   while (List != &HostBridgeInstance->Head) {
833     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
834     if (RootBridgeHandle == RootBridgeInstance->Handle) {
835       //
836       // Set up the Root Bridge for Bus Enumeration
837       //
838       BusStart  = RootBridgeInstance->Aperture.BusBase;
839       BusEnd    = RootBridgeInstance->Aperture.BusLimit;
840       BusReserve = RootBridgeInstance->Aperture.BusReserve;
841       //
842       // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
843       //
844       Status = gBS->AllocatePool (
845                       EfiBootServicesData,
846                       sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
847                       &Buffer
848                       );
849       if (EFI_ERROR (Status)) {
850         return EFI_OUT_OF_RESOURCES;
851       }
852 
853       Temp  = (UINT8 *) Buffer;
854 
855       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Desc                  = ACPI_ADDRESS_SPACE_DESCRIPTOR;
856       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->Len                   = 0x2B;
857       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->ResType               = ACPI_ADDRESS_SPACE_TYPE_BUS;
858       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->GenFlag               = 0;
859       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->SpecificFlag          = 0;
860       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrSpaceGranularity  = 0;
861       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMin          = BusStart;
862       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrRangeMax          = BusReserve;
863       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrTranslationOffset = 0;
864       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp)->AddrLen               = BusEnd - BusStart + 1;
865 
866       Temp = Temp + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
867       ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc = ACPI_END_TAG_DESCRIPTOR;
868       ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum = 0x0;
869 
870       *Configuration = Buffer;
871       return EFI_SUCCESS;
872     }
873 
874     List = List->ForwardLink;
875   }
876 
877   return EFI_INVALID_PARAMETER;
878 }
879 
880 EFI_STATUS
881 EFIAPI
SetBusNumbers(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)882 SetBusNumbers (
883   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
884   IN EFI_HANDLE                                       RootBridgeHandle,
885   IN VOID                                             *Configuration
886   )
887 /*++
888 
889 Routine Description:
890   This function programs the PCI Root Bridge hardware so that
891   it decodes the specified PCI bus range.
892 
893 Arguments:
894 
895   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
896   RootBridgeHandle  -  The PCI Root Bridge whose bus range is to be programmed.
897   Configuration     -  The pointer to the PCI bus resource descriptor.
898 
899 Returns:
900 
901   EFI_SUCCESS            -  Succeed.
902   EFI_INVALID_PARAMETER  -  Wrong parameters passed in.
903 
904 --*/
905 {
906   EFI_LIST_ENTRY            *List;
907   PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
908   PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
909   UINT8                     *Ptr;
910   UINTN                     BusStart;
911   UINTN                     BusEnd;
912   UINTN                     BusLen;
913 
914   if (Configuration == NULL) {
915     return EFI_INVALID_PARAMETER;
916   }
917 
918   Ptr = Configuration;
919 
920   //
921   // Check the Configuration is valid
922   //
923   if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
924     return EFI_INVALID_PARAMETER;
925   }
926 
927   if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
928     return EFI_INVALID_PARAMETER;
929   }
930 
931   Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
932   if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
933     return EFI_INVALID_PARAMETER;
934   }
935 
936   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
937   List                = HostBridgeInstance->Head.ForwardLink;
938 
939   Ptr                 = Configuration;
940 
941   while (List != &HostBridgeInstance->Head) {
942     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
943     if (RootBridgeHandle == RootBridgeInstance->Handle) {
944       BusStart  = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrRangeMin;
945       BusLen    = (UINTN) ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Ptr)->AddrLen;
946       BusEnd    = BusStart + BusLen - 1;
947 
948       if (BusStart > BusEnd) {
949         return EFI_INVALID_PARAMETER;
950       }
951 
952       if ((BusStart < RootBridgeInstance->Aperture.BusBase) || (BusEnd > RootBridgeInstance->Aperture.BusLimit)) {
953         return EFI_INVALID_PARAMETER;
954       }
955       //
956       // Update the Bus Range
957       //
958       RootBridgeInstance->ResAllocNode[TypeBus].Base    = BusStart;
959       RootBridgeInstance->ResAllocNode[TypeBus].Length  = BusLen;
960       RootBridgeInstance->ResAllocNode[TypeBus].Status  = ResAllocated;
961       RootBridgeInstance->BusScanCount++;
962       if (RootBridgeInstance->BusScanCount > 0) {
963         //
964         // Only care about the 2nd PCI bus scanning
965         //
966         RootBridgeInstance->BusNumberAssigned = TRUE;
967       }
968 
969       return EFI_SUCCESS;
970     }
971 
972     List = List->ForwardLink;
973   }
974 
975   return EFI_INVALID_PARAMETER;
976 }
977 
978 EFI_STATUS
979 EFIAPI
SubmitResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)980 SubmitResources (
981   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
982   IN EFI_HANDLE                                       RootBridgeHandle,
983   IN VOID                                             *Configuration
984   )
985 /*++
986 
987 Routine Description:
988 
989   Submits the I/O and memory resource requirements for the specified PCI Root Bridge.
990 
991 Arguments:
992   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
993   RootBridgeHandle  -  The PCI Root Bridge whose I/O and memory resource requirements.
994                        are being submitted.
995   Configuration     -  The pointer to the PCI I/O and PCI memory resource descriptor.
996 
997 Returns:
998 
999   EFI_SUCCESS            -  Succeed.
1000   EFI_INVALID_PARAMETER  -  Wrong parameters passed in.
1001 
1002 --*/
1003 {
1004   EFI_LIST_ENTRY                    *List;
1005   PCI_HOST_BRIDGE_INSTANCE          *HostBridgeInstance;
1006   PCI_ROOT_BRIDGE_INSTANCE          *RootBridgeInstance;
1007   UINT8                             *Temp;
1008   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
1009   UINT64                            AddrLen;
1010   UINT64                            Alignment;
1011   UINT64                            Value;
1012 
1013   //
1014   // Check the input parameter: Configuration
1015   //
1016   if (Configuration == NULL) {
1017     return EFI_INVALID_PARAMETER;
1018   }
1019 
1020   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1021   List                = HostBridgeInstance->Head.ForwardLink;
1022 
1023   Temp = (UINT8 *) Configuration;
1024   while (List != &HostBridgeInstance->Head) {
1025     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1026     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1027       //
1028       // Check the resource descriptors.
1029       // If the Configuration includes one or more invalid resource descriptors, all the resource
1030       // descriptors are ignored and the function returns EFI_INVALID_PARAMETER.
1031       //
1032       while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1033         ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1034         DEBUG ((EFI_D_INFO, " ptr->ResType:%x \n",ptr->ResType));
1035         DEBUG ((EFI_D_INFO, "  ptr->AddrLen:0x%lx AddrRangeMin:0x%lx AddrRangeMax:0x%lx\n\n",ptr->AddrLen,ptr->AddrRangeMin,ptr->AddrRangeMax));
1036 
1037         switch (ptr->ResType) {
1038           case ACPI_ADDRESS_SPACE_TYPE_MEM:
1039             if (ptr->AddrSpaceGranularity != 32 && ptr->AddrSpaceGranularity != 64) {
1040               return EFI_INVALID_PARAMETER;
1041             }
1042             if (ptr->AddrSpaceGranularity == 32 && ptr->AddrLen > 0xffffffff) {
1043               return EFI_INVALID_PARAMETER;
1044             }
1045             //
1046             // If the PCI root bridge does not support separate windows for nonprefetchable and
1047             // prefetchable memory, then the PCI bus driver needs to include requests for
1048             // prefetchable memory in the nonprefetchable memory pool.
1049             //
1050             if ((RootBridgeInstance->RootBridgeAllocAttrib & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) != 0 &&
1051                 ((ptr->SpecificFlag & (BIT2 | BIT1)) != 0)) {
1052               return EFI_INVALID_PARAMETER;
1053             }
1054           case ACPI_ADDRESS_SPACE_TYPE_IO:
1055             //
1056             // Check aligment, it should be of the form 2^n-1
1057             //
1058             Value = Power2MaxMemory (ptr->AddrRangeMax + 1);
1059             if (Value != (ptr->AddrRangeMax + 1)) {
1060               CpuDeadLoop();
1061               return EFI_INVALID_PARAMETER;
1062             }
1063             break;
1064           case ACPI_ADDRESS_SPACE_TYPE_BUS:
1065           default:
1066             return EFI_INVALID_PARAMETER;
1067         }
1068         Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1069       }
1070       if (*Temp != ACPI_END_TAG_DESCRIPTOR) {
1071         return EFI_INVALID_PARAMETER;
1072       }
1073 
1074       Temp = (UINT8 *) Configuration;
1075       while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1076         ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1077 
1078         switch (ptr->ResType) {
1079         case ACPI_ADDRESS_SPACE_TYPE_MEM:
1080           AddrLen   = (UINT64) ptr->AddrLen;
1081           Alignment = (UINT64) ptr->AddrRangeMax;
1082           if (ptr->AddrSpaceGranularity == 32) {
1083             if (ptr->SpecificFlag == 0x06) {
1084               //
1085               // Apply from GCD
1086               //
1087               RootBridgeInstance->ResAllocNode[TypePMem32].Status = ResSubmitted;
1088             } else {
1089               RootBridgeInstance->ResAllocNode[TypeMem32].Length    = AddrLen;
1090               RootBridgeInstance->ResAllocNode[TypeMem32].Alignment = Alignment;
1091               RootBridgeInstance->ResAllocNode[TypeMem32].Status    = ResRequested;
1092               HostBridgeInstance->ResourceSubmited                  = TRUE;
1093             }
1094           }
1095 
1096           if (ptr->AddrSpaceGranularity == 64) {
1097             if (ptr->SpecificFlag == 0x06) {
1098               RootBridgeInstance->ResAllocNode[TypePMem64].Status = ResSubmitted;
1099             } else {
1100               RootBridgeInstance->ResAllocNode[TypeMem64].Length    = AddrLen;
1101               RootBridgeInstance->ResAllocNode[TypeMem64].Alignment = Alignment;
1102               RootBridgeInstance->ResAllocNode[TypeMem64].Status    = ResSubmitted;
1103               HostBridgeInstance->ResourceSubmited                  = TRUE;
1104             }
1105           }
1106           break;
1107 
1108         case ACPI_ADDRESS_SPACE_TYPE_IO:
1109           AddrLen   = (UINT64) ptr->AddrLen;
1110           Alignment = (UINT64) ptr->AddrRangeMax;
1111           RootBridgeInstance->ResAllocNode[TypeIo].Length     = AddrLen;
1112           RootBridgeInstance->ResAllocNode[TypeIo].Alignment  = Alignment;
1113           RootBridgeInstance->ResAllocNode[TypeIo].Status     = ResRequested;
1114           HostBridgeInstance->ResourceSubmited                = TRUE;
1115           break;
1116 
1117         default:
1118           break;
1119         }
1120 
1121         Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1122       }
1123 
1124       return EFI_SUCCESS;
1125     }
1126 
1127     List = List->ForwardLink;
1128   }
1129 
1130   return EFI_INVALID_PARAMETER;
1131 }
1132 
1133 EFI_STATUS
1134 EFIAPI
GetProposedResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)1135 GetProposedResources (
1136   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1137   IN  EFI_HANDLE                                       RootBridgeHandle,
1138   OUT VOID                                             **Configuration
1139   )
1140 /*++
1141 
1142 Routine Description:
1143   This function returns the proposed resource settings for the specified
1144   PCI Root Bridge.
1145 
1146 Arguments:
1147 
1148   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1149   RootBridgeHandle  -  The PCI Root Bridge handle.
1150   Configuration     -  The pointer to the pointer to the PCI I/O
1151                        and memory resource descriptor.
1152 
1153 Returns:
1154 
1155   EFI_SUCCESS            -  Succeed.
1156   EFI_OUT_OF_RESOURCES   -  Not enough pool to be allocated.
1157   EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
1158 
1159 --*/
1160 {
1161   EFI_LIST_ENTRY                    *List;
1162   PCI_HOST_BRIDGE_INSTANCE          *HostBridgeInstance;
1163   PCI_ROOT_BRIDGE_INSTANCE          *RootBridgeInstance;
1164   UINTN                             Index;
1165   UINTN                             Number;
1166   VOID                              *Buffer;
1167   UINT8                             *Temp;
1168   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr;
1169   EFI_STATUS                        Status;
1170   UINT64                            ResStatus;
1171 
1172   Buffer  = NULL;
1173   Number  = 0;
1174   //
1175   // Get the Host Bridge Instance from the resource allocation protocol
1176   //
1177   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1178   List                = HostBridgeInstance->Head.ForwardLink;
1179 
1180   //
1181   // Enumerate the root bridges in this host bridge
1182   //
1183   while (List != &HostBridgeInstance->Head) {
1184     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1185     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1186       for (Index = 0; Index < TypeBus; Index++) {
1187         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1188           Number++;
1189         }
1190       }
1191 
1192       if (Number > 0) {
1193         Status = gBS->AllocatePool (
1194                         EfiBootServicesData,
1195                         Number * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR),
1196                         &Buffer
1197                         );
1198 
1199         if (EFI_ERROR (Status)) {
1200           return EFI_OUT_OF_RESOURCES;
1201         }
1202 
1203         ZeroMem (Buffer, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * Number + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
1204       }
1205 
1206       ASSERT (Buffer != NULL);
1207       Temp = Buffer;
1208       for (Index = 0; Index < TypeBus; Index++) {
1209         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1210           ptr       = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp;
1211           ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
1212 
1213           switch (Index) {
1214 
1215           case TypeIo:
1216             //
1217             // Io
1218             //
1219             ptr->Desc                   = 0x8A;
1220             ptr->Len                    = 0x2B;
1221             ptr->ResType                = 1;
1222             ptr->GenFlag                = 0;
1223             ptr->SpecificFlag           = 0;
1224             ptr->AddrRangeMin           = RootBridgeInstance->ResAllocNode[Index].Base;
1225             ptr->AddrRangeMax           = 0;
1226             ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1227             ptr->AddrLen                = RootBridgeInstance->ResAllocNode[Index].Length;
1228             break;
1229 
1230           case TypeMem32:
1231             //
1232             // Memory 32
1233             //
1234             ptr->Desc                   = 0x8A;
1235             ptr->Len                    = 0x2B;
1236             ptr->ResType                = 0;
1237             ptr->GenFlag                = 0;
1238             ptr->SpecificFlag           = 0;
1239             ptr->AddrSpaceGranularity   = 32;
1240             ptr->AddrRangeMin           = RootBridgeInstance->ResAllocNode[Index].Base;
1241             ptr->AddrRangeMax           = 0;
1242             ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1243             ptr->AddrLen                = RootBridgeInstance->ResAllocNode[Index].Length;
1244             break;
1245 
1246           case TypePMem32:
1247             //
1248             // Prefetch memory 32
1249             //
1250             ptr->Desc                   = 0x8A;
1251             ptr->Len                    = 0x2B;
1252             ptr->ResType                = 0;
1253             ptr->GenFlag                = 0;
1254             ptr->SpecificFlag           = 6;
1255             ptr->AddrSpaceGranularity   = 32;
1256             ptr->AddrRangeMin           = 0;
1257             ptr->AddrRangeMax           = 0;
1258             ptr->AddrTranslationOffset  = EFI_RESOURCE_NONEXISTENT;
1259             ptr->AddrLen                = 0;
1260             break;
1261 
1262           case TypeMem64:
1263             //
1264             // Memory 64
1265             //
1266             ptr->Desc                   = 0x8A;
1267             ptr->Len                    = 0x2B;
1268             ptr->ResType                = 0;
1269             ptr->GenFlag                = 0;
1270             ptr->SpecificFlag           = 0;
1271             ptr->AddrSpaceGranularity   = 64;
1272             ptr->AddrRangeMin           = RootBridgeInstance->ResAllocNode[Index].Base;
1273             ptr->AddrRangeMax           = 0;
1274             ptr->AddrTranslationOffset  = (ResStatus == ResAllocated) ? EFI_RESOURCE_SATISFIED : EFI_RESOURCE_LESS;
1275             ptr->AddrLen                = RootBridgeInstance->ResAllocNode[Index].Length;
1276             break;
1277 
1278           case TypePMem64:
1279             //
1280             // Prefetch memory 64
1281             //
1282             ptr->Desc                   = 0x8A;
1283             ptr->Len                    = 0x2B;
1284             ptr->ResType                = 0;
1285             ptr->GenFlag                = 0;
1286             ptr->SpecificFlag           = 6;
1287             ptr->AddrSpaceGranularity   = 64;
1288             ptr->AddrRangeMin           = 0;
1289             ptr->AddrRangeMax           = 0;
1290             ptr->AddrTranslationOffset  = EFI_RESOURCE_NONEXISTENT;
1291             ptr->AddrLen                = 0;
1292             break;
1293           }
1294 
1295           Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1296         }
1297       }
1298 
1299       ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Desc      = 0x79;
1300       ((EFI_ACPI_END_TAG_DESCRIPTOR *) Temp)->Checksum  = 0x0;
1301 
1302       *Configuration = Buffer;
1303 
1304       return EFI_SUCCESS;
1305     }
1306 
1307     List = List->ForwardLink;
1308   }
1309 
1310   return EFI_INVALID_PARAMETER;
1311 }
1312 
1313 EFI_STATUS
1314 EFIAPI
PreprocessController(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase)1315 PreprocessController (
1316   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL          *This,
1317   IN  EFI_HANDLE                                                RootBridgeHandle,
1318   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS               PciAddress,
1319   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE              Phase
1320   )
1321 /*++
1322 
1323 Routine Description:
1324   This function is called for all the PCI controllers that the PCI
1325   bus driver finds. Can be used to Preprogram the controller.
1326 
1327 Arguments:
1328 
1329   This              -  The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
1330   RootBridgeHandle  -  The PCI Root Bridge handle.
1331   PciAddress        -  Address of the controller on the PCI bus.
1332   Phase             -  The Phase during resource allocation.
1333 
1334 Returns:
1335 
1336   EFI_SUCCESS            -  Succeed.
1337   EFI_INVALID_PARAMETER  -  RootBridgeHandle is not a valid handle.
1338 
1339 --*/
1340 {
1341   BOOLEAN                   RootBridgeFound;
1342   EFI_LIST_ENTRY            *List;
1343   PCI_HOST_BRIDGE_INSTANCE  *HostBridgeInstance;
1344   PCI_ROOT_BRIDGE_INSTANCE  *RootBridgeInstance;
1345 
1346   if (RootBridgeHandle == NULL) {
1347     return EFI_INVALID_PARAMETER;
1348   }
1349 
1350   RootBridgeFound     = FALSE;
1351   HostBridgeInstance  = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1352   List                = HostBridgeInstance->Head.ForwardLink;
1353 
1354   while (List != &HostBridgeInstance->Head) {
1355     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1356 
1357     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1358       RootBridgeFound = TRUE;
1359       break;
1360     }
1361     //
1362     // Get next if have
1363     //
1364     List = List->ForwardLink;
1365   }
1366 
1367   if (RootBridgeFound == FALSE) {
1368     return EFI_INVALID_PARAMETER;
1369   }
1370 
1371   return EFI_SUCCESS;
1372 }
1373 
1374 UINT64
Power2MaxMemory(IN UINT64 MemoryLength)1375 Power2MaxMemory (
1376   IN UINT64                     MemoryLength
1377   )
1378 /*++
1379 
1380 Routine Description:
1381 
1382   Calculate maximum memory length that can be fit to a mtrr.
1383 
1384 Arguments:
1385 
1386   MemoryLength  -  Input memory length.
1387 
1388 Returns:
1389 
1390   Returned Maximum length.
1391 
1392 --*/
1393 {
1394   UINT64  Result;
1395 
1396   if (RShiftU64 (MemoryLength, 32)) {
1397     Result = LShiftU64 ((UINT64) GetPowerOfTwo64 ((UINT32) RShiftU64 (MemoryLength, 32)), 32);
1398   } else {
1399     Result = (UINT64) GetPowerOfTwo64 ((UINT32) MemoryLength);
1400   }
1401 
1402   return Result;
1403 }
1404