Home | History | Annotate | Download | only in PciHostBridge
      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
     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
    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
    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
    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
    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
    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
    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
   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
   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
   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