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