• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Provides the basic interfaces to abstract a PCI Host Bridge Resource
3   Allocation
4 
5   Copyright (C) 2015, Red Hat, Inc.
6   Copyright (c) 2008 - 2013, Intel Corporation. All rights reserved.<BR>
7 
8   This program and the accompanying materials are licensed and made available
9   under the terms and conditions of the BSD License which accompanies this
10   distribution.  The full text of the license may be found at
11   http://opensource.org/licenses/bsd-license.php
12 
13   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 
16 **/
17 
18 #include <Library/QemuFwCfgLib.h>
19 
20 #include "PciHostBridge.h"
21 
22 STATIC
23 CONST
24 EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mRootBridgeDevicePathTemplate = {
25   {
26     {
27       ACPI_DEVICE_PATH,
28       ACPI_DP,
29       {
30         (UINT8) (sizeof(ACPI_HID_DEVICE_PATH)),
31         (UINT8) ((sizeof(ACPI_HID_DEVICE_PATH)) >> 8)
32       }
33     },
34     EISA_PNP_ID(0x0A03), // HID
35     0                    // UID
36   },
37 
38   {
39     END_DEVICE_PATH_TYPE,
40     END_ENTIRE_DEVICE_PATH_SUBTYPE,
41     {
42       END_DEVICE_PATH_LENGTH,
43       0
44     }
45   }
46 };
47 
48 EFI_HANDLE mDriverImageHandle;
49 
50 PCI_HOST_BRIDGE_INSTANCE mPciHostBridgeInstanceTemplate = {
51   PCI_HOST_BRIDGE_SIGNATURE,  // Signature
52   NULL,                       // HostBridgeHandle
53   {NULL, NULL},               // Head
54   FALSE,                      // ResourceSubiteed
55   TRUE,                       // CanRestarted
56   {
57     NotifyPhase,
58     GetNextRootBridge,
59     GetAttributes,
60     StartBusEnumeration,
61     SetBusNumbers,
62     SubmitResources,
63     GetProposedResources,
64     PreprocessController
65   }
66 };
67 
68 //
69 // Implementation
70 //
71 
72 /**
73   Allocate and initialize a root bridge.
74 
75   param[in]  RootBusNumber     The bus number of the root bus (root bridge) to
76                                create.
77 
78   param[in]  MaxSubBusNumber   The inclusive maximum bus number that can be
79                                assigned to any subordinate bus found behind any
80                                PCI bridge hanging off this root bus.
81 
82                                The caller is repsonsible for ensuring that
83                                RootBusNumber <= MaxSubBusNumber. If
84                                RootBusNumber equals MaxSubBusNumber, then the
85                                root bus has no room for subordinate buses.
86 
87   param[in]  HostBridgeHandle  The EFI_HANDLE corresponding to the host bridge
88                                that is the parent of the root bridge to create.
89                                HostBridgeHandle is expected to have
90                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
91                                installed on it.
92 
93   param[out] RootBus           The private PCI_ROOT_BRIDGE_INSTANCE that has
94                                been created as the result of the function call.
95 
96   @retval EFI_SUCCESS           Initialization successful. A new
97                                 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL has been
98                                 created as the child of HostBridgeHandle. A
99                                 device path consisting of an ACPI device path
100                                 node, with UID = RootBusNumber, has been
101                                 installed on the same new handle.
102 
103   @retval EFI_OUT_OF_RESOURCES  Memory allocation failed.
104 
105   @return                       Error codes from
106                                 gBS->InstallMultipleProtocolInterfaces().
107 **/
108 STATIC
109 EFI_STATUS
InitRootBridge(IN UINT8 RootBusNumber,IN UINT8 MaxSubBusNumber,IN EFI_HANDLE HostBridgeHandle,OUT PCI_ROOT_BRIDGE_INSTANCE ** RootBus)110 InitRootBridge (
111   IN  UINT8                    RootBusNumber,
112   IN  UINT8                    MaxSubBusNumber,
113   IN  EFI_HANDLE               HostBridgeHandle,
114   OUT PCI_ROOT_BRIDGE_INSTANCE **RootBus
115   )
116 {
117   PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
118   PCI_ROOT_BRIDGE_RESOURCE_APERTURE ResAperture;
119   EFI_STATUS                        Status;
120 
121   ASSERT (RootBusNumber <= MaxSubBusNumber);
122 
123   PrivateData = AllocateZeroPool (sizeof *PrivateData);
124   if (PrivateData == NULL) {
125     return EFI_OUT_OF_RESOURCES;
126   }
127 
128   PrivateData->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
129 
130   CopyMem (&PrivateData->DevicePath, &mRootBridgeDevicePathTemplate,
131     sizeof mRootBridgeDevicePathTemplate);
132   PrivateData->DevicePath.AcpiDevicePath.UID = RootBusNumber;
133 
134   ResAperture.BusBase  = RootBusNumber;
135   ResAperture.BusLimit = MaxSubBusNumber;
136   ResAperture.MemBase  = BASE_2GB;
137   ResAperture.MemLimit = BASE_4GB - 1;
138   ResAperture.IoBase   = 0;
139   ResAperture.IoLimit  = MAX_UINT16;
140   //
141   // The function call below allocates no resources and performs no actions
142   // that have to be rolled back on later failure. It always succeeds.
143   //
144   Status = RootBridgeConstructor (&PrivateData->Io, HostBridgeHandle,
145              EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM, &ResAperture);
146   ASSERT_EFI_ERROR (Status);
147 
148   Status = gBS->InstallMultipleProtocolInterfaces (&PrivateData->Handle,
149                   &gEfiDevicePathProtocolGuid,      &PrivateData->DevicePath,
150                   &gEfiPciRootBridgeIoProtocolGuid, &PrivateData->Io,
151                   NULL);
152   if (EFI_ERROR (Status)) {
153     goto FreePrivateData;
154   }
155 
156   DEBUG ((EFI_D_INFO,
157     "%a: installed root bus %d, with room for %d subordinate bus(es)\n",
158     __FUNCTION__, RootBusNumber, MaxSubBusNumber - RootBusNumber));
159   *RootBus = PrivateData;
160   return EFI_SUCCESS;
161 
162 FreePrivateData:
163   FreePool (PrivateData);
164   return Status;
165 }
166 
167 
168 /**
169   Uninitialize and free a root bridge set up with InitRootBridge().
170 
171   On return, the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance and the device path
172   will have been released, freeing RootBus->Handle as well.
173 
174   param[in] RootBus  The private PCI_ROOT_BRIDGE_INSTANCE that has been created
175                      with InitRootBridge(), and should be released.
176 **/
177 STATIC
178 VOID
UninitRootBridge(IN PCI_ROOT_BRIDGE_INSTANCE * RootBus)179 UninitRootBridge (
180   IN PCI_ROOT_BRIDGE_INSTANCE *RootBus
181   )
182 {
183   EFI_STATUS Status;
184 
185   Status = gBS->UninstallMultipleProtocolInterfaces (RootBus->Handle,
186                   &gEfiDevicePathProtocolGuid,      &RootBus->DevicePath,
187                   &gEfiPciRootBridgeIoProtocolGuid, &RootBus->Io,
188                   NULL);
189   ASSERT_EFI_ERROR (Status);
190   FreePool (RootBus);
191 }
192 
193 
194 /**
195   Entry point of this driver
196 
197   @param ImageHandle     Handle of driver image
198   @param SystemTable     Point to EFI_SYSTEM_TABLE
199 
200   @retval EFI_OUT_OF_RESOURCES  Can not allocate memory resource
201   @retval EFI_DEVICE_ERROR      Can not install the protocol instance
202   @retval EFI_SUCCESS           Success to initialize the Pci host bridge.
203 **/
204 EFI_STATUS
205 EFIAPI
InitializePciHostBridge(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)206 InitializePciHostBridge (
207   IN EFI_HANDLE        ImageHandle,
208   IN EFI_SYSTEM_TABLE  *SystemTable
209   )
210 {
211   EFI_STATUS                  Status;
212   FIRMWARE_CONFIG_ITEM        FwCfgItem;
213   UINTN                       FwCfgSize;
214   UINT64                      ExtraRootBridgesLeft;
215   UINTN                       LastRootBridgeNumber;
216   UINTN                       RootBridgeNumber;
217   PCI_HOST_BRIDGE_INSTANCE    *HostBridge;
218   PCI_ROOT_BRIDGE_INSTANCE    *RootBus;
219   EFI_STATUS                  UninstallStatus;
220 
221   mDriverImageHandle = ImageHandle;
222 
223   //
224   // Create Host Bridge Device Handle
225   //
226   HostBridge = AllocateCopyPool (sizeof(PCI_HOST_BRIDGE_INSTANCE),
227                  &mPciHostBridgeInstanceTemplate);
228   if (HostBridge == NULL) {
229     return EFI_OUT_OF_RESOURCES;
230   }
231 
232   InitializeListHead (&HostBridge->Head);
233 
234   Status = gBS->InstallMultipleProtocolInterfaces (
235                   &HostBridge->HostBridgeHandle,
236                   &gEfiPciHostBridgeResourceAllocationProtocolGuid,
237                   &HostBridge->ResAlloc,
238                   NULL
239                   );
240   if (EFI_ERROR (Status)) {
241     goto FreeHostBridge;
242   }
243 
244   //
245   // QEMU provides the number of extra root buses, shortening the exhaustive
246   // search below. If there is no hint, the feature is missing.
247   //
248   Status = QemuFwCfgFindFile ("etc/extra-pci-roots", &FwCfgItem, &FwCfgSize);
249   if (EFI_ERROR (Status) || FwCfgSize != sizeof ExtraRootBridgesLeft) {
250     ExtraRootBridgesLeft = 0;
251   } else {
252     QemuFwCfgSelectItem (FwCfgItem);
253     QemuFwCfgReadBytes (FwCfgSize, &ExtraRootBridgesLeft);
254     DEBUG ((EFI_D_INFO, "%a: %Lu extra root buses reported by QEMU\n",
255       __FUNCTION__, ExtraRootBridgesLeft));
256   }
257 
258   //
259   // The "main" root bus is always there.
260   //
261   LastRootBridgeNumber = 0;
262 
263   //
264   // Scan all other root buses. If function 0 of any device on a bus returns a
265   // VendorId register value different from all-bits-one, then that bus is
266   // alive.
267   //
268   for (RootBridgeNumber = 1;
269        RootBridgeNumber < 256 && ExtraRootBridgesLeft > 0;
270        ++RootBridgeNumber) {
271     UINTN Device;
272 
273     for (Device = 0; Device <= MAX_PCI_DEVICE_NUMBER; ++Device) {
274       if (PciRead16 (PCI_LIB_ADDRESS (RootBridgeNumber, Device, 0,
275                        PCI_VENDOR_ID_OFFSET)) != MAX_UINT16) {
276         break;
277       }
278     }
279     if (Device <= MAX_PCI_DEVICE_NUMBER) {
280       //
281       // Found the next root bus. We can now install the *previous* one,
282       // because now we know how big a bus number range *that* one has, for any
283       // subordinate buses that might exist behind PCI bridges hanging off it.
284       //
285       Status = InitRootBridge ((UINT8)LastRootBridgeNumber,
286                  (UINT8)(RootBridgeNumber - 1), HostBridge->HostBridgeHandle,
287                  &RootBus);
288       if (EFI_ERROR (Status)) {
289         goto RollbackProtocols;
290       }
291       InsertTailList (&HostBridge->Head, &RootBus->Link);
292       LastRootBridgeNumber = RootBridgeNumber;
293       --ExtraRootBridgesLeft;
294     }
295   }
296 
297   //
298   // Install the last root bus (which might be the only, ie. main, root bus, if
299   // we've found no extra root buses).
300   //
301   Status = InitRootBridge ((UINT8)LastRootBridgeNumber, 255,
302              HostBridge->HostBridgeHandle, &RootBus);
303   if (EFI_ERROR (Status)) {
304     goto RollbackProtocols;
305   }
306   InsertTailList (&HostBridge->Head, &RootBus->Link);
307 
308   return EFI_SUCCESS;
309 
310 RollbackProtocols:
311   while (!IsListEmpty (&HostBridge->Head)) {
312     LIST_ENTRY *Entry;
313 
314     Entry = GetFirstNode (&HostBridge->Head);
315     RemoveEntryList (Entry);
316     RootBus = DRIVER_INSTANCE_FROM_LIST_ENTRY (Entry);
317     UninitRootBridge (RootBus);
318   }
319   UninstallStatus = gBS->UninstallMultipleProtocolInterfaces (
320                            HostBridge->HostBridgeHandle,
321                            &gEfiPciHostBridgeResourceAllocationProtocolGuid,
322                            &HostBridge->ResAlloc,
323                            NULL
324                            );
325   ASSERT_EFI_ERROR (UninstallStatus);
326 
327 FreeHostBridge:
328   FreePool (HostBridge);
329 
330   return Status;
331 }
332 
333 
334 /**
335   These are the notifications from the PCI bus driver that it is about to enter
336   a certain phase of the PCI enumeration process.
337 
338   This member function can be used to notify the host bridge driver to perform
339   specific actions, including any chipset-specific initialization, so that the
340   chipset is ready to enter the next phase. Eight notification points are
341   defined at this time. See belows:
342 
343   EfiPciHostBridgeBeginEnumeration       Resets the host bridge PCI apertures
344                                          and internal data structures. The PCI
345                                          enumerator should issue this
346                                          notification before starting a fresh
347                                          enumeration process. Enumeration
348                                          cannot be restarted after sending any
349                                          other notification such as
350                                          EfiPciHostBridgeBeginBusAllocation.
351 
352   EfiPciHostBridgeBeginBusAllocation     The bus allocation phase is about to
353                                          begin. No specific action is required
354                                          here. This notification can be used to
355                                          perform any chipset-specific
356                                          programming.
357 
358   EfiPciHostBridgeEndBusAllocation       The bus allocation and bus programming
359                                          phase is complete. No specific action
360                                          is required here. This notification
361                                          can be used to perform any
362                                          chipset-specific programming.
363 
364   EfiPciHostBridgeBeginResourceAllocation
365                                          The resource allocation phase is about
366                                          to begin. No specific action is
367                                          required here. This notification can
368                                          be used to perform any
369                                          chipset-specific programming.
370 
371   EfiPciHostBridgeAllocateResources      Allocates resources per previously
372                                          submitted requests for all the PCI
373                                          root bridges. These resource settings
374                                          are returned on the next call to
375                                          GetProposedResources(). Before calling
376                                          NotifyPhase() with a Phase of
377                                          EfiPciHostBridgeAllocateResource, the
378                                          PCI bus enumerator is responsible for
379                                          gathering I/O and memory requests for
380                                          all the PCI root bridges and
381                                          submitting these requests using
382                                          SubmitResources(). This function pads
383                                          the resource amount to suit the root
384                                          bridge hardware, takes care of
385                                          dependencies between the PCI root
386                                          bridges, and calls the Global
387                                          Coherency Domain (GCD) with the
388                                          allocation request. In the case of
389                                          padding, the allocated range could be
390                                          bigger than what was requested.
391 
392   EfiPciHostBridgeSetResources           Programs the host bridge hardware to
393                                          decode previously allocated resources
394                                          (proposed resources) for all the PCI
395                                          root bridges. After the hardware is
396                                          programmed, reassigning resources will
397                                          not be supported. The bus settings are
398                                          not affected.
399 
400   EfiPciHostBridgeFreeResources          Deallocates resources that were
401                                          previously allocated for all the PCI
402                                          root bridges and resets the I/O and
403                                          memory apertures to their initial
404                                          state. The bus settings are not
405                                          affected. If the request to allocate
406                                          resources fails, the PCI enumerator
407                                          can use this notification to
408                                          deallocate previous resources, adjust
409                                          the requests, and retry allocation.
410 
411   EfiPciHostBridgeEndResourceAllocation  The resource allocation phase is
412                                          completed. No specific action is
413                                          required here. This notification can
414                                          be used to perform any chipsetspecific
415                                          programming.
416 
417   @param[in] This                The instance pointer of
418                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
419 
420   @param[in] Phase               The phase during enumeration
421 
422   @retval EFI_NOT_READY          This phase cannot be entered at this time. For
423                                  example, this error is valid for a Phase of
424                                  EfiPciHostBridgeAllocateResources if
425                                  SubmitResources() has not been called for one
426                                  or more PCI root bridges before this call
427 
428   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
429                                  This error is valid for a Phase of
430                                  EfiPciHostBridgeSetResources.
431 
432   @retval EFI_INVALID_PARAMETER  Invalid phase parameter
433 
434   @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
435                                  lack of resources. This error is valid for a
436                                  Phase of EfiPciHostBridgeAllocateResources if
437                                  the previously submitted resource requests
438                                  cannot be fulfilled or were only partially
439                                  fulfilled.
440 
441   @retval EFI_SUCCESS            The notification was accepted without any
442                                  errors.
443 **/
444 EFI_STATUS
445 EFIAPI
NotifyPhase(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase)446 NotifyPhase(
447   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
448   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE    Phase
449   )
450 {
451   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
452   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
453   PCI_RESOURCE_TYPE                     Index;
454   LIST_ENTRY                            *List;
455   EFI_PHYSICAL_ADDRESS                  BaseAddress;
456   UINT64                                AddrLen;
457   UINTN                                 BitsOfAlignment;
458   EFI_STATUS                            Status;
459   EFI_STATUS                            ReturnStatus;
460 
461   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
462 
463   switch (Phase) {
464 
465   case EfiPciHostBridgeBeginEnumeration:
466     if (HostBridgeInstance->CanRestarted) {
467       //
468       // Reset the Each Root Bridge
469       //
470       List = HostBridgeInstance->Head.ForwardLink;
471 
472       while (List != &HostBridgeInstance->Head) {
473         RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
474         for (Index = TypeIo; Index < TypeMax; Index++) {
475           RootBridgeInstance->ResAllocNode[Index].Type      = Index;
476           RootBridgeInstance->ResAllocNode[Index].Base      = 0;
477           RootBridgeInstance->ResAllocNode[Index].Length    = 0;
478           RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
479         }
480 
481         List = List->ForwardLink;
482       }
483 
484       HostBridgeInstance->ResourceSubmited = FALSE;
485       HostBridgeInstance->CanRestarted     = TRUE;
486     } else {
487       //
488       // Can not restart
489       //
490       return EFI_NOT_READY;
491     }
492     break;
493 
494   case EfiPciHostBridgeEndEnumeration:
495     break;
496 
497   case EfiPciHostBridgeBeginBusAllocation:
498     //
499     // No specific action is required here, can perform any chipset specific
500     // programing
501     //
502     HostBridgeInstance->CanRestarted = FALSE;
503     break;
504 
505   case EfiPciHostBridgeEndBusAllocation:
506     //
507     // No specific action is required here, can perform any chipset specific
508     // programing
509     //
510     //HostBridgeInstance->CanRestarted = FALSE;
511     break;
512 
513   case EfiPciHostBridgeBeginResourceAllocation:
514     //
515     // No specific action is required here, can perform any chipset specific
516     // programing
517     //
518     //HostBridgeInstance->CanRestarted = FALSE;
519     break;
520 
521   case EfiPciHostBridgeAllocateResources:
522     ReturnStatus = EFI_SUCCESS;
523     if (HostBridgeInstance->ResourceSubmited) {
524       //
525       // Take care of the resource dependencies between the root bridges
526       //
527       List = HostBridgeInstance->Head.ForwardLink;
528 
529       while (List != &HostBridgeInstance->Head) {
530         RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
531         for (Index = TypeIo; Index < TypeBus; Index++) {
532           if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
533 
534             AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
535 
536             //
537             // Get the number of '1' in Alignment.
538             //
539             BitsOfAlignment =
540               (UINTN)(HighBitSet64 (
541                         RootBridgeInstance->ResAllocNode[Index].Alignment
542                         ) + 1);
543 
544             switch (Index) {
545 
546               case TypeIo:
547                 //
548                 // It is impossible for this chipset to align 0xFFFF for IO16
549                 // So clear it
550                 //
551                 if (BitsOfAlignment >= 16) {
552                   BitsOfAlignment = 0;
553                 }
554 
555                 Status = gDS->AllocateIoSpace (
556                                 EfiGcdAllocateAnySearchBottomUp,
557                                 EfiGcdIoTypeIo,
558                                 BitsOfAlignment,
559                                 AddrLen,
560                                 &BaseAddress,
561                                 mDriverImageHandle,
562                                 NULL
563                                 );
564 
565                 if (!EFI_ERROR (Status)) {
566                   RootBridgeInstance->ResAllocNode[Index].Base   =
567                     (UINTN)BaseAddress;
568                   RootBridgeInstance->ResAllocNode[Index].Status =
569                     ResAllocated;
570                 } else {
571                   ReturnStatus = Status;
572                   if (Status != EFI_OUT_OF_RESOURCES) {
573                     RootBridgeInstance->ResAllocNode[Index].Length = 0;
574                   }
575                 }
576 
577                 break;
578 
579 
580               case TypeMem32:
581                 //
582                 // It is impossible for this chipset to align 0xFFFFFFFF for
583                 // Mem32
584                 // So clear it
585                 //
586 
587                 if (BitsOfAlignment >= 32) {
588                   BitsOfAlignment = 0;
589                 }
590 
591                 Status = gDS->AllocateMemorySpace (
592                                 EfiGcdAllocateAnySearchBottomUp,
593                                 EfiGcdMemoryTypeMemoryMappedIo,
594                                 BitsOfAlignment,
595                                 AddrLen,
596                                 &BaseAddress,
597                                 mDriverImageHandle,
598                                 NULL
599                                 );
600 
601                 if (!EFI_ERROR (Status)) {
602                   // We were able to allocate the PCI memory
603                   RootBridgeInstance->ResAllocNode[Index].Base   =
604                     (UINTN)BaseAddress;
605                   RootBridgeInstance->ResAllocNode[Index].Status =
606                     ResAllocated;
607 
608                 } else {
609                   // Not able to allocate enough PCI memory
610                   ReturnStatus = Status;
611 
612                   if (Status != EFI_OUT_OF_RESOURCES) {
613                     RootBridgeInstance->ResAllocNode[Index].Length = 0;
614                   }
615                   ASSERT (FALSE);
616                 }
617                 break;
618 
619               case TypePMem32:
620               case TypeMem64:
621               case TypePMem64:
622                   ReturnStatus = EFI_ABORTED;
623                   break;
624               default:
625                 ASSERT (FALSE);
626                 break;
627               }; //end switch
628           }
629         }
630 
631         List = List->ForwardLink;
632       }
633 
634       return ReturnStatus;
635 
636     } else {
637       return EFI_NOT_READY;
638     }
639     break;
640 
641   case EfiPciHostBridgeSetResources:
642     break;
643 
644   case EfiPciHostBridgeFreeResources:
645     ReturnStatus = EFI_SUCCESS;
646     List = HostBridgeInstance->Head.ForwardLink;
647     while (List != &HostBridgeInstance->Head) {
648       RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
649       for (Index = TypeIo; Index < TypeBus; Index++) {
650         if (RootBridgeInstance->ResAllocNode[Index].Status == ResAllocated) {
651           AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
652           BaseAddress = RootBridgeInstance->ResAllocNode[Index].Base;
653           switch (Index) {
654 
655           case TypeIo:
656             Status = gDS->FreeIoSpace (BaseAddress, AddrLen);
657             if (EFI_ERROR (Status)) {
658               ReturnStatus = Status;
659             }
660             break;
661 
662           case TypeMem32:
663             Status = gDS->FreeMemorySpace (BaseAddress, AddrLen);
664             if (EFI_ERROR (Status)) {
665               ReturnStatus = Status;
666             }
667             break;
668 
669           case TypePMem32:
670             break;
671 
672           case TypeMem64:
673             break;
674 
675           case TypePMem64:
676             break;
677 
678           default:
679             ASSERT (FALSE);
680             break;
681 
682           }; //end switch
683           RootBridgeInstance->ResAllocNode[Index].Type      = Index;
684           RootBridgeInstance->ResAllocNode[Index].Base      = 0;
685           RootBridgeInstance->ResAllocNode[Index].Length    = 0;
686           RootBridgeInstance->ResAllocNode[Index].Status    = ResNone;
687         }
688       }
689 
690       List = List->ForwardLink;
691     }
692 
693     HostBridgeInstance->ResourceSubmited = FALSE;
694     HostBridgeInstance->CanRestarted     = TRUE;
695     return ReturnStatus;
696 
697   case EfiPciHostBridgeEndResourceAllocation:
698     HostBridgeInstance->CanRestarted = FALSE;
699     break;
700 
701   default:
702     return EFI_INVALID_PARAMETER;
703   }
704 
705   return EFI_SUCCESS;
706 }
707 
708 /**
709   Return the device handle of the next PCI root bridge that is associated with
710   this Host Bridge.
711 
712   This function is called multiple times to retrieve the device handles of all
713   the PCI root bridges that are associated with this PCI host bridge. Each PCI
714   host bridge is associated with one or more PCI root bridges. On each call,
715   the handle that was returned by the previous call is passed into the
716   interface, and on output the interface returns the device handle of the next
717   PCI root bridge. The caller can use the handle to obtain the instance of the
718   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL for that root bridge. When there are no more
719   PCI root bridges to report, the interface returns EFI_NOT_FOUND. A PCI
720   enumerator must enumerate the PCI root bridges in the order that they are
721   returned by this function.
722 
723   For D945 implementation, there is only one root bridge in PCI host bridge.
724 
725   @param[in]       This              The instance pointer of
726                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
727 
728   @param[in, out]  RootBridgeHandle  Returns the device handle of the next PCI
729                                      root bridge.
730 
731   @retval EFI_SUCCESS            If parameter RootBridgeHandle = NULL, then
732                                  return the first Rootbridge handle of the
733                                  specific Host bridge and return EFI_SUCCESS.
734 
735   @retval EFI_NOT_FOUND          Can not find the any more root bridge in
736                                  specific host bridge.
737 
738   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not an EFI_HANDLE that was
739                                  returned on a previous call to
740                                  GetNextRootBridge().
741 **/
742 EFI_STATUS
743 EFIAPI
GetNextRootBridge(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN OUT EFI_HANDLE * RootBridgeHandle)744 GetNextRootBridge(
745   IN       EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
746   IN OUT   EFI_HANDLE                                       *RootBridgeHandle
747   )
748 {
749   BOOLEAN                               NoRootBridge;
750   LIST_ENTRY                            *List;
751   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
752   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
753 
754   NoRootBridge = TRUE;
755   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
756   List = HostBridgeInstance->Head.ForwardLink;
757 
758 
759   while (List != &HostBridgeInstance->Head) {
760     NoRootBridge = FALSE;
761     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
762     if (*RootBridgeHandle == NULL) {
763       //
764       // Return the first Root Bridge Handle of the Host Bridge
765       //
766       *RootBridgeHandle = RootBridgeInstance->Handle;
767       return EFI_SUCCESS;
768     } else {
769       if (*RootBridgeHandle == RootBridgeInstance->Handle) {
770         //
771         // Get next if have
772         //
773         List = List->ForwardLink;
774         if (List!=&HostBridgeInstance->Head) {
775           RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
776           *RootBridgeHandle = RootBridgeInstance->Handle;
777           return EFI_SUCCESS;
778         } else {
779           return EFI_NOT_FOUND;
780         }
781       }
782     }
783 
784     List = List->ForwardLink;
785   } //end while
786 
787   if (NoRootBridge) {
788     return EFI_NOT_FOUND;
789   } else {
790     return EFI_INVALID_PARAMETER;
791   }
792 }
793 
794 /**
795   Returns the allocation attributes of a PCI root bridge.
796 
797   The function returns the allocation attributes of a specific PCI root bridge.
798   The attributes can vary from one PCI root bridge to another. These attributes
799   are different from the decode-related attributes that are returned by the
800   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
801   RootBridgeHandle parameter is used to specify the instance of the PCI root
802   bridge. The device handles of all the root bridges that are associated with
803   this host bridge must be obtained by calling GetNextRootBridge(). The
804   attributes are static in the sense that they do not change during or after
805   the enumeration process. The hardware may provide mechanisms to change the
806   attributes on the fly, but such changes must be completed before
807   EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is installed. The permitted
808   values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
809   "Related Definitions" below. The caller uses these attributes to combine
810   multiple resource requests.
811 
812   For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI
813   bus enumerator needs to include requests for the prefetchable memory in the
814   nonprefetchable memory pool and not request any prefetchable memory.
815 
816   Attribute                             Description
817   ------------------------------------  ---------------------------------------
818   EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM  If this bit is set, then the PCI root
819                                         bridge does not support separate
820                                         windows for nonprefetchable and
821                                         prefetchable memory. A PCI bus driver
822                                         needs to include requests for
823                                         prefetchable memory in the
824                                         nonprefetchable memory pool.
825 
826   EFI_PCI_HOST_BRIDGE_MEM64_DECODE      If this bit is set, then the PCI root
827                                         bridge supports 64-bit memory windows.
828                                         If this bit is not set, the PCI bus
829                                         driver needs to include requests for a
830                                         64-bit memory address in the
831                                         corresponding 32-bit memory pool.
832 
833   @param[in]   This               The instance pointer of
834                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
835 
836   @param[in]   RootBridgeHandle   The device handle of the PCI root bridge in
837                                   which the caller is interested. Type
838                                   EFI_HANDLE is defined in
839                                   InstallProtocolInterface() in the UEFI 2.0
840                                   Specification.
841 
842   @param[out]  Attributes         The pointer to attribte of root bridge, it is
843                                   output parameter
844 
845   @retval EFI_INVALID_PARAMETER   Attribute pointer is NULL
846 
847   @retval EFI_INVALID_PARAMETER   RootBridgehandle is invalid.
848 
849   @retval EFI_SUCCESS             Success to get attribute of interested root
850                                   bridge.
851 **/
852 EFI_STATUS
853 EFIAPI
GetAttributes(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT UINT64 * Attributes)854 GetAttributes(
855   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
856   IN  EFI_HANDLE                                       RootBridgeHandle,
857   OUT UINT64                                           *Attributes
858   )
859 {
860   LIST_ENTRY                            *List;
861   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
862   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
863 
864   if (Attributes == NULL) {
865     return EFI_INVALID_PARAMETER;
866   }
867 
868   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
869   List = HostBridgeInstance->Head.ForwardLink;
870 
871   while (List != &HostBridgeInstance->Head) {
872     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
873     if (RootBridgeHandle == RootBridgeInstance->Handle) {
874       *Attributes = RootBridgeInstance->RootBridgeAttrib;
875       return EFI_SUCCESS;
876     }
877     List = List->ForwardLink;
878   }
879 
880   //
881   // RootBridgeHandle is not an EFI_HANDLE
882   // that was returned on a previous call to GetNextRootBridge()
883   //
884   return EFI_INVALID_PARAMETER;
885 }
886 
887 /**
888   Sets up the specified PCI root bridge for the bus enumeration process.
889 
890   This member function sets up the root bridge for bus enumeration and returns
891   the PCI bus range over which the search should be performed in ACPI 2.0
892   resource descriptor format.
893 
894   @param[in]   This              The
895                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
896                                  instance.
897 
898   @param[in]   RootBridgeHandle  The PCI Root Bridge to be set up.
899 
900   @param[out]  Configuration     Pointer to the pointer to the PCI bus resource
901                                  descriptor.
902 
903   @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
904 
905   @retval EFI_OUT_OF_RESOURCES  Fail to allocate ACPI resource descriptor tag.
906 
907   @retval EFI_SUCCESS           Sucess to allocate ACPI resource descriptor.
908 **/
909 EFI_STATUS
910 EFIAPI
StartBusEnumeration(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)911 StartBusEnumeration(
912   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
913   IN  EFI_HANDLE                                       RootBridgeHandle,
914   OUT VOID                                             **Configuration
915   )
916 {
917   LIST_ENTRY                            *List;
918   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
919   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
920   VOID                                  *Buffer;
921   UINT8                                 *Temp;
922   UINT64                                BusStart;
923   UINT64                                BusEnd;
924 
925   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
926   List = HostBridgeInstance->Head.ForwardLink;
927 
928   while (List != &HostBridgeInstance->Head) {
929     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
930     if (RootBridgeHandle == RootBridgeInstance->Handle) {
931       //
932       // Set up the Root Bridge for Bus Enumeration
933       //
934       BusStart = RootBridgeInstance->BusBase;
935       BusEnd   = RootBridgeInstance->BusLimit;
936       //
937       // Program the Hardware(if needed) if error return EFI_DEVICE_ERROR
938       //
939 
940       Buffer = AllocatePool (
941                  sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
942                  sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
943                  );
944       if (Buffer == NULL) {
945         return EFI_OUT_OF_RESOURCES;
946       }
947 
948       Temp = (UINT8 *)Buffer;
949 
950       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Desc = 0x8A;
951       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->Len  = 0x2B;
952       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->ResType = 2;
953       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->GenFlag = 0;
954       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->SpecificFlag = 0;
955       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrSpaceGranularity = 0;
956       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMin = BusStart;
957       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrRangeMax = 0;
958       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrTranslationOffset = 0;
959       ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Temp)->AddrLen =
960         BusEnd - BusStart + 1;
961 
962       Temp = Temp + sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
963       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
964       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
965 
966       *Configuration = Buffer;
967       return EFI_SUCCESS;
968     }
969     List = List->ForwardLink;
970   }
971 
972   return EFI_INVALID_PARAMETER;
973 }
974 
975 /**
976   Programs the PCI root bridge hardware so that it decodes the specified PCI
977   bus range.
978 
979   This member function programs the specified PCI root bridge to decode the bus
980   range that is specified by the input parameter Configuration.
981   The bus range information is specified in terms of the ACPI 2.0 resource
982   descriptor format.
983 
984   @param[in] This              The
985                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
986                                instance
987 
988   @param[in] RootBridgeHandle  The PCI Root Bridge whose bus range is to be
989                                programmed
990 
991   @param[in] Configuration     The pointer to the PCI bus resource descriptor
992 
993   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
994                                  handle.
995 
996   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
997 
998   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
999                                  2.0 resource descriptor.
1000 
1001   @retval EFI_INVALID_PARAMETER  Configuration does not include a valid ACPI
1002                                  2.0 bus resource descriptor.
1003 
1004   @retval EFI_INVALID_PARAMETER  Configuration includes valid ACPI 2.0 resource
1005                                  descriptors other than bus descriptors.
1006 
1007   @retval EFI_INVALID_PARAMETER  Configuration contains one or more invalid
1008                                  ACPI resource descriptors.
1009 
1010   @retval EFI_INVALID_PARAMETER  "Address Range Minimum" is invalid for this
1011                                  root bridge.
1012 
1013   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this
1014                                  root bridge.
1015 
1016   @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
1017 
1018   @retval EFI_SUCCESS            The bus range for the PCI root bridge was
1019                                  programmed.
1020 **/
1021 EFI_STATUS
1022 EFIAPI
SetBusNumbers(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)1023 SetBusNumbers(
1024   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1025   IN EFI_HANDLE                                       RootBridgeHandle,
1026   IN VOID                                             *Configuration
1027   )
1028 {
1029   LIST_ENTRY                            *List;
1030   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
1031   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
1032   UINT8                                 *Ptr;
1033   UINTN                                 BusStart;
1034   UINTN                                 BusEnd;
1035   UINTN                                 BusLen;
1036 
1037   if (Configuration == NULL) {
1038     return EFI_INVALID_PARAMETER;
1039   }
1040 
1041   Ptr = Configuration;
1042 
1043   //
1044   // Check the Configuration is valid
1045   //
1046   if(*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
1047     return EFI_INVALID_PARAMETER;
1048   }
1049 
1050   if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != 2) {
1051     return EFI_INVALID_PARAMETER;
1052   }
1053 
1054   Ptr += sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1055   if (*Ptr != ACPI_END_TAG_DESCRIPTOR) {
1056     return EFI_INVALID_PARAMETER;
1057   }
1058 
1059   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1060   List = HostBridgeInstance->Head.ForwardLink;
1061 
1062   Ptr = Configuration;
1063 
1064   while (List != &HostBridgeInstance->Head) {
1065     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1066     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1067       EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
1068 
1069       Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
1070       BusStart = (UINTN)Desc->AddrRangeMin;
1071       BusLen = (UINTN)Desc->AddrLen;
1072       BusEnd = BusStart + BusLen - 1;
1073 
1074       if (BusStart > BusEnd) {
1075         return EFI_INVALID_PARAMETER;
1076       }
1077 
1078       if ((BusStart < RootBridgeInstance->BusBase) ||
1079           (BusEnd > RootBridgeInstance->BusLimit)) {
1080         return EFI_INVALID_PARAMETER;
1081       }
1082 
1083       //
1084       // Update the Bus Range
1085       //
1086       RootBridgeInstance->ResAllocNode[TypeBus].Base   = BusStart;
1087       RootBridgeInstance->ResAllocNode[TypeBus].Length = BusLen;
1088       RootBridgeInstance->ResAllocNode[TypeBus].Status = ResAllocated;
1089 
1090       //
1091       // Program the Root Bridge Hardware
1092       //
1093 
1094       return EFI_SUCCESS;
1095     }
1096 
1097     List = List->ForwardLink;
1098   }
1099 
1100   return EFI_INVALID_PARAMETER;
1101 }
1102 
1103 
1104 /**
1105   Submits the I/O and memory resource requirements for the specified PCI root
1106   bridge.
1107 
1108   This function is used to submit all the I/O and memory resources that are
1109   required by the specified PCI root bridge. The input parameter Configuration
1110   is used to specify the following:
1111   - The various types of resources that are required
1112   - The associated lengths in terms of ACPI 2.0 resource descriptor format
1113 
1114   @param[in] This              Pointer to the
1115                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1116                                instance.
1117 
1118   @param[in] RootBridgeHandle  The PCI root bridge whose I/O and memory
1119                                resource requirements are being submitted.
1120 
1121   @param[in] Configuration     The pointer to the PCI I/O and PCI memory
1122                                resource descriptor.
1123 
1124   @retval EFI_SUCCESS            The I/O and memory resource requests for a PCI
1125                                  root bridge were accepted.
1126 
1127   @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
1128                                  handle.
1129 
1130   @retval EFI_INVALID_PARAMETER  Configuration is NULL.
1131 
1132   @retval EFI_INVALID_PARAMETER  Configuration does not point to a valid ACPI
1133                                  2.0 resource descriptor.
1134 
1135   @retval EFI_INVALID_PARAMETER  Configuration includes requests for one or
1136                                  more resource types that are not supported by
1137                                  this PCI root bridge. This error will happen
1138                                  if the caller did not combine resources
1139                                  according to Attributes that were returned by
1140                                  GetAllocAttributes().
1141 
1142   @retval EFI_INVALID_PARAMETER  Address Range Maximum" is invalid.
1143 
1144   @retval EFI_INVALID_PARAMETER  "Address Range Length" is invalid for this PCI
1145                                  root bridge.
1146 
1147   @retval EFI_INVALID_PARAMETER  "Address Space Granularity" is invalid for
1148                                  this PCI root bridge.
1149 **/
1150 EFI_STATUS
1151 EFIAPI
SubmitResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,IN VOID * Configuration)1152 SubmitResources(
1153   IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1154   IN EFI_HANDLE                                       RootBridgeHandle,
1155   IN VOID                                             *Configuration
1156   )
1157 {
1158   LIST_ENTRY                            *List;
1159   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
1160   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
1161   UINT8                                 *Temp;
1162   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
1163   UINT64                                AddrLen;
1164   UINT64                                Alignment;
1165 
1166   //
1167   // Check the input parameter: Configuration
1168   //
1169   if (Configuration == NULL) {
1170     return EFI_INVALID_PARAMETER;
1171   }
1172 
1173   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1174   List = HostBridgeInstance->Head.ForwardLink;
1175 
1176   Temp = (UINT8 *)Configuration;
1177   while ( *Temp == 0x8A) {
1178     Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1179   }
1180   if (*Temp != 0x79) {
1181     return EFI_INVALID_PARAMETER;
1182   }
1183 
1184   Temp = (UINT8 *)Configuration;
1185   while (List != &HostBridgeInstance->Head) {
1186     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1187     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1188       while ( *Temp == 0x8A) {
1189         Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1190 
1191         //
1192         // Check Address Length
1193         //
1194         if (Ptr->AddrLen > 0xffffffff) {
1195           return EFI_INVALID_PARAMETER;
1196         }
1197 
1198         //
1199         // Check address range alignment
1200         //
1201         if (Ptr->AddrRangeMax >= 0xffffffff ||
1202             Ptr->AddrRangeMax != (GetPowerOfTwo64 (
1203                                     Ptr->AddrRangeMax + 1) - 1)) {
1204           return EFI_INVALID_PARAMETER;
1205         }
1206 
1207         switch (Ptr->ResType) {
1208 
1209         case 0:
1210 
1211           //
1212           // Check invalid Address Sapce Granularity
1213           //
1214           if (Ptr->AddrSpaceGranularity != 32) {
1215             return EFI_INVALID_PARAMETER;
1216           }
1217 
1218           //
1219           // check the memory resource request is supported by PCI root bridge
1220           //
1221           if (RootBridgeInstance->RootBridgeAttrib ==
1222                 EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM &&
1223               Ptr->SpecificFlag == 0x06) {
1224             return EFI_INVALID_PARAMETER;
1225           }
1226 
1227           AddrLen = Ptr->AddrLen;
1228           Alignment = Ptr->AddrRangeMax;
1229           if (Ptr->AddrSpaceGranularity == 32) {
1230             if (Ptr->SpecificFlag == 0x06) {
1231               //
1232               // Apply from GCD
1233               //
1234               RootBridgeInstance->ResAllocNode[TypePMem32].Status =
1235                 ResSubmitted;
1236             } else {
1237               RootBridgeInstance->ResAllocNode[TypeMem32].Length = AddrLen;
1238               RootBridgeInstance->ResAllocNode[TypeMem32].Alignment =
1239                 Alignment;
1240               RootBridgeInstance->ResAllocNode[TypeMem32].Status =
1241                 ResRequested;
1242               HostBridgeInstance->ResourceSubmited = TRUE;
1243             }
1244           }
1245 
1246           if (Ptr->AddrSpaceGranularity == 64) {
1247             if (Ptr->SpecificFlag == 0x06) {
1248               RootBridgeInstance->ResAllocNode[TypePMem64].Status =
1249                 ResSubmitted;
1250             } else {
1251               RootBridgeInstance->ResAllocNode[TypeMem64].Status =
1252                 ResSubmitted;
1253             }
1254           }
1255           break;
1256 
1257         case 1:
1258           AddrLen = (UINTN) Ptr->AddrLen;
1259           Alignment = (UINTN) Ptr->AddrRangeMax;
1260           RootBridgeInstance->ResAllocNode[TypeIo].Length  = AddrLen;
1261           RootBridgeInstance->ResAllocNode[TypeIo].Alignment = Alignment;
1262           RootBridgeInstance->ResAllocNode[TypeIo].Status  = ResRequested;
1263           HostBridgeInstance->ResourceSubmited = TRUE;
1264           break;
1265 
1266         default:
1267             break;
1268         };
1269 
1270         Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
1271       }
1272 
1273       return EFI_SUCCESS;
1274     }
1275 
1276     List = List->ForwardLink;
1277   }
1278 
1279   return EFI_INVALID_PARAMETER;
1280 }
1281 
1282 /**
1283    Returns the proposed resource settings for the specified PCI root bridge.
1284 
1285    This member function returns the proposed resource settings for the
1286    specified PCI root bridge. The proposed resource settings are prepared when
1287    NotifyPhase() is called with a Phase of EfiPciHostBridgeAllocateResources.
1288    The output parameter Configuration specifies the following:
1289    - The various types of resources, excluding bus resources, that are
1290      allocated
1291    - The associated lengths in terms of ACPI 2.0 resource descriptor format
1292 
1293    @param[in]  This              Pointer to the
1294                                EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1295                                  instance.
1296 
1297    @param[in]  RootBridgeHandle  The PCI root bridge handle. Type EFI_HANDLE is
1298                                  defined in InstallProtocolInterface() in the
1299                                  UEFI 2.0 Specification.
1300 
1301    @param[out] Configuration     The pointer to the pointer to the PCI I/O and
1302                                  memory resource descriptor.
1303 
1304    @retval EFI_SUCCESS            The requested parameters were returned.
1305 
1306    @retval EFI_INVALID_PARAMETER  RootBridgeHandle is not a valid root bridge
1307                                   handle.
1308 
1309    @retval EFI_DEVICE_ERROR       Programming failed due to a hardware error.
1310 
1311    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a
1312                                   lack of resources.
1313 **/
1314 EFI_STATUS
1315 EFIAPI
GetProposedResources(IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL * This,IN EFI_HANDLE RootBridgeHandle,OUT VOID ** Configuration)1316 GetProposedResources(
1317   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
1318   IN  EFI_HANDLE                                       RootBridgeHandle,
1319   OUT VOID                                             **Configuration
1320   )
1321 {
1322   LIST_ENTRY                            *List;
1323   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
1324   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
1325   UINTN                                 Index;
1326   UINTN                                 Number;
1327   VOID                                  *Buffer;
1328   UINT8                                 *Temp;
1329   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     *Ptr;
1330   UINT64                                ResStatus;
1331 
1332   Buffer = NULL;
1333   Number = 0;
1334   //
1335   // Get the Host Bridge Instance from the resource allocation protocol
1336   //
1337   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1338   List = HostBridgeInstance->Head.ForwardLink;
1339 
1340   //
1341   // Enumerate the root bridges in this host bridge
1342   //
1343   while (List != &HostBridgeInstance->Head) {
1344     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1345     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1346       for (Index = 0; Index < TypeBus; Index ++) {
1347         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1348           Number ++;
1349         }
1350       }
1351 
1352       if (Number ==  0) {
1353         return EFI_INVALID_PARAMETER;
1354       }
1355 
1356       Buffer = AllocateZeroPool (
1357                  Number * sizeof(EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) +
1358                  sizeof(EFI_ACPI_END_TAG_DESCRIPTOR)
1359                  );
1360       if (Buffer == NULL) {
1361         return EFI_OUT_OF_RESOURCES;
1362       }
1363 
1364       Temp = Buffer;
1365       for (Index = 0; Index < TypeBus; Index ++) {
1366         if (RootBridgeInstance->ResAllocNode[Index].Status != ResNone) {
1367           Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp ;
1368           ResStatus = RootBridgeInstance->ResAllocNode[Index].Status;
1369 
1370           switch (Index) {
1371 
1372           case TypeIo:
1373             //
1374             // Io
1375             //
1376             Ptr->Desc = 0x8A;
1377             Ptr->Len  = 0x2B;
1378             Ptr->ResType = 1;
1379             Ptr->GenFlag = 0;
1380             Ptr->SpecificFlag = 0;
1381             Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1382             Ptr->AddrRangeMax = 0;
1383             Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1384                                            EFI_RESOURCE_SATISFIED :
1385                                            EFI_RESOURCE_LESS;
1386             Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1387             break;
1388 
1389           case TypeMem32:
1390             //
1391             // Memory 32
1392             //
1393             Ptr->Desc = 0x8A;
1394             Ptr->Len  = 0x2B;
1395             Ptr->ResType = 0;
1396             Ptr->GenFlag = 0;
1397             Ptr->SpecificFlag = 0;
1398             Ptr->AddrSpaceGranularity = 32;
1399             Ptr->AddrRangeMin = RootBridgeInstance->ResAllocNode[Index].Base;
1400             Ptr->AddrRangeMax = 0;
1401             Ptr->AddrTranslationOffset = (ResStatus == ResAllocated) ?
1402                                            EFI_RESOURCE_SATISFIED :
1403                                            EFI_RESOURCE_LESS;
1404             Ptr->AddrLen = RootBridgeInstance->ResAllocNode[Index].Length;
1405             break;
1406 
1407           case TypePMem32:
1408             //
1409             // Prefetch memory 32
1410             //
1411             Ptr->Desc = 0x8A;
1412             Ptr->Len  = 0x2B;
1413             Ptr->ResType = 0;
1414             Ptr->GenFlag = 0;
1415             Ptr->SpecificFlag = 6;
1416             Ptr->AddrSpaceGranularity = 32;
1417             Ptr->AddrRangeMin = 0;
1418             Ptr->AddrRangeMax = 0;
1419             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1420             Ptr->AddrLen = 0;
1421             break;
1422 
1423           case TypeMem64:
1424             //
1425             // Memory 64
1426             //
1427             Ptr->Desc = 0x8A;
1428             Ptr->Len  = 0x2B;
1429             Ptr->ResType = 0;
1430             Ptr->GenFlag = 0;
1431             Ptr->SpecificFlag = 0;
1432             Ptr->AddrSpaceGranularity = 64;
1433             Ptr->AddrRangeMin = 0;
1434             Ptr->AddrRangeMax = 0;
1435             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1436             Ptr->AddrLen = 0;
1437             break;
1438 
1439           case TypePMem64:
1440             //
1441             // Prefetch memory 64
1442             //
1443             Ptr->Desc = 0x8A;
1444             Ptr->Len  = 0x2B;
1445             Ptr->ResType = 0;
1446             Ptr->GenFlag = 0;
1447             Ptr->SpecificFlag = 6;
1448             Ptr->AddrSpaceGranularity = 64;
1449             Ptr->AddrRangeMin = 0;
1450             Ptr->AddrRangeMax = 0;
1451             Ptr->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
1452             Ptr->AddrLen = 0;
1453             break;
1454           };
1455 
1456           Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
1457         }
1458       }
1459 
1460       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Desc = 0x79;
1461       ((EFI_ACPI_END_TAG_DESCRIPTOR *)Temp)->Checksum = 0x0;
1462 
1463       *Configuration = Buffer;
1464 
1465       return EFI_SUCCESS;
1466     }
1467 
1468     List = List->ForwardLink;
1469   }
1470 
1471   return EFI_INVALID_PARAMETER;
1472 }
1473 
1474 /**
1475   Provides the hooks from the PCI bus driver to every PCI controller
1476   (device/function) at various stages of the PCI enumeration process that allow
1477   the host bridge driver to preinitialize individual PCI controllers before
1478   enumeration.
1479 
1480   This function is called during the PCI enumeration process. No specific
1481   action is expected from this member function. It allows the host bridge
1482   driver to preinitialize individual PCI controllers before enumeration.
1483 
1484   @param This              Pointer to the
1485                            EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
1486                            instance.
1487 
1488   @param RootBridgeHandle  The associated PCI root bridge handle. Type
1489                            EFI_HANDLE is defined in InstallProtocolInterface()
1490                            in the UEFI 2.0 Specification.
1491 
1492   @param PciAddress        The address of the PCI device on the PCI bus. This
1493                            address can be passed to the
1494                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to
1495                            access the PCI configuration space of the device.
1496                            See Table 12-1 in the UEFI 2.0 Specification for the
1497                            definition of
1498                            EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
1499 
1500   @param Phase             The phase of the PCI device enumeration.
1501 
1502   @retval EFI_SUCCESS              The requested parameters were returned.
1503 
1504   @retval EFI_INVALID_PARAMETER    RootBridgeHandle is not a valid root bridge
1505                                    handle.
1506 
1507   @retval EFI_INVALID_PARAMETER    Phase is not a valid phase that is defined
1508                                    in
1509                                   EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
1510 
1511   @retval EFI_DEVICE_ERROR         Programming failed due to a hardware error.
1512                                    The PCI enumerator should not enumerate this
1513                                    device, including its child devices if it is
1514                                    a PCI-to-PCI bridge.
1515 **/
1516 EFI_STATUS
1517 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)1518 PreprocessController (
1519   IN  EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL        *This,
1520   IN  EFI_HANDLE                                              RootBridgeHandle,
1521   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS             PciAddress,
1522   IN  EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE            Phase
1523   )
1524 {
1525   PCI_HOST_BRIDGE_INSTANCE              *HostBridgeInstance;
1526   PCI_ROOT_BRIDGE_INSTANCE              *RootBridgeInstance;
1527   LIST_ENTRY                            *List;
1528 
1529   HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
1530   List = HostBridgeInstance->Head.ForwardLink;
1531 
1532   //
1533   // Enumerate the root bridges in this host bridge
1534   //
1535   while (List != &HostBridgeInstance->Head) {
1536     RootBridgeInstance = DRIVER_INSTANCE_FROM_LIST_ENTRY (List);
1537     if (RootBridgeHandle == RootBridgeInstance->Handle) {
1538       break;
1539     }
1540     List = List->ForwardLink;
1541   }
1542   if (List == &HostBridgeInstance->Head) {
1543     return EFI_INVALID_PARAMETER;
1544   }
1545 
1546   if ((UINT32)Phase > EfiPciBeforeResourceCollection) {
1547     return EFI_INVALID_PARAMETER;
1548   }
1549 
1550   return EFI_SUCCESS;
1551 }
1552