1 /** @file
2   PCI Root Bridge Io Protocol implementation
3 
4 Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are
6 licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution.  The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9 
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "PciHostBridge.h"
16 
17 typedef struct {
18   EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR     SpaceDesp[TypeMax];
19   EFI_ACPI_END_TAG_DESCRIPTOR           EndDesp;
20 } RESOURCE_CONFIGURATION;
21 
22 RESOURCE_CONFIGURATION Configuration = {
23   {{0x8A, 0x2B, 1, 0, 0, 0, 0, 0, 0, 0},
24   {0x8A, 0x2B, 0, 0, 0, 32, 0, 0, 0, 0},
25   {0x8A, 0x2B, 0, 0, 6, 32, 0, 0, 0, 0},
26   {0x8A, 0x2B, 0, 0, 0, 64, 0, 0, 0, 0},
27   {0x8A, 0x2B, 0, 0, 6, 64, 0, 0, 0, 0},
28   {0x8A, 0x2B, 2, 0, 0, 0, 0, 0, 0, 0}},
29   {0x79, 0}
30 };
31 
32 //
33 // Protocol Member Function Prototypes
34 //
35 
36 /**
37    Polls an address in memory mapped I/O space until an exit condition is met, or
38    a timeout occurs.
39 
40    This function provides a standard way to poll a PCI memory location. A PCI memory read
41    operation is performed at the PCI memory address specified by Address for the width specified
42    by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
43    read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
44    Mask) is equal to Value.
45 
46    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
47    @param[in]   Width     Signifies the width of the memory operations.
48    @param[in]   Address   The base address of the memory operations. The caller is
49                           responsible for aligning Address if required.
50    @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
51                           are ignored. The bits in the bytes below Width which are zero in
52                           Mask are ignored when polling the memory address.
53    @param[in]   Value     The comparison value used for the polling exit criteria.
54    @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
55                           be of poorer granularity.
56    @param[out]  Result    Pointer to the last value read from the memory location.
57 
58    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
59    @retval EFI_INVALID_PARAMETER  Width is invalid.
60    @retval EFI_INVALID_PARAMETER  Result is NULL.
61    @retval EFI_TIMEOUT            Delay expired before a match occurred.
62    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
63 
64 **/
65 EFI_STATUS
66 EFIAPI
67 RootBridgeIoPollMem (
68   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
69   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
70   IN  UINT64                                 Address,
71   IN  UINT64                                 Mask,
72   IN  UINT64                                 Value,
73   IN  UINT64                                 Delay,
74   OUT UINT64                                 *Result
75   );
76 
77 /**
78    Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
79    satisfied or after a defined duration.
80 
81    This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
82    performed at the PCI I/O address specified by Address for the width specified by Width.
83    The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
84    repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
85    to Value.
86 
87    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
88    @param[in] Width     Signifies the width of the I/O operations.
89    @param[in] Address   The base address of the I/O operations. The caller is responsible
90                         for aligning Address if required.
91    @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
92                         are ignored. The bits in the bytes below Width which are zero in
93                         Mask are ignored when polling the I/O address.
94    @param[in] Value     The comparison value used for the polling exit criteria.
95    @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
96                         be of poorer granularity.
97    @param[out] Result   Pointer to the last value read from the memory location.
98 
99    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
100    @retval EFI_INVALID_PARAMETER  Width is invalid.
101    @retval EFI_INVALID_PARAMETER  Result is NULL.
102    @retval EFI_TIMEOUT            Delay expired before a match occurred.
103    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
104 
105 **/
106 EFI_STATUS
107 EFIAPI
108 RootBridgeIoPollIo (
109   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
110   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
111   IN  UINT64                                 Address,
112   IN  UINT64                                 Mask,
113   IN  UINT64                                 Value,
114   IN  UINT64                                 Delay,
115   OUT UINT64                                 *Result
116   );
117 
118 /**
119    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
120 
121    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
122    registers in the PCI root bridge memory space.
123    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
124    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
125 
126    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
127    @param[in]   Width     Signifies the width of the memory operation.
128    @param[in]   Address   The base address of the memory operation. The caller is
129                           responsible for aligning the Address if required.
130    @param[in]   Count     The number of memory operations to perform. Bytes moved is
131                           Width size * Count, starting at Address.
132    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
133                           write operations, the source buffer to write data from.
134 
135    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
136    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
137    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
138    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
139 
140 **/
141 EFI_STATUS
142 EFIAPI
143 RootBridgeIoMemRead (
144   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
145   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
146   IN     UINT64                                 Address,
147   IN     UINTN                                  Count,
148   OUT    VOID                                   *Buffer
149   );
150 
151 /**
152    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
153 
154    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
155    registers in the PCI root bridge memory space.
156    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
157    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
158 
159    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
160    @param[in]   Width     Signifies the width of the memory operation.
161    @param[in]   Address   The base address of the memory operation. The caller is
162                           responsible for aligning the Address if required.
163    @param[in]   Count     The number of memory operations to perform. Bytes moved is
164                           Width size * Count, starting at Address.
165    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
166                           write operations, the source buffer to write data from.
167 
168    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
169    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
170    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
171    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
172 **/
173 EFI_STATUS
174 EFIAPI
175 RootBridgeIoMemWrite (
176   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
177   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
178   IN     UINT64                                 Address,
179   IN     UINTN                                  Count,
180   IN     VOID                                   *Buffer
181   );
182 
183 /**
184    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
185 
186    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
187    @param[in]   Width       Signifies the width of the memory operations.
188    @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
189                             aligning the Address if required.
190    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
191                             size * Count, starting at Address.
192    @param[out]  UserBuffer  For read operations, the destination buffer to store the results. For
193                             write operations, the source buffer to write data from.
194 
195    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
196    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
197    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
198    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
199 
200 **/
201 EFI_STATUS
202 EFIAPI
203 RootBridgeIoIoRead (
204   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
205   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
206   IN     UINT64                                 UserAddress,
207   IN     UINTN                                  Count,
208   OUT    VOID                                   *UserBuffer
209   );
210 
211 /**
212    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
213 
214    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
215    @param[in]   Width       Signifies the width of the memory operations.
216    @param[in]   UserAddress The base address of the I/O operation. The caller is responsible for
217                             aligning the Address if required.
218    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
219                             size * Count, starting at Address.
220    @param[in]   UserBuffer  For read operations, the destination buffer to store the results. For
221                             write operations, the source buffer to write data from.
222 
223    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
224    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
225    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
226    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
227 
228 **/
229 EFI_STATUS
230 EFIAPI
231 RootBridgeIoIoWrite (
232   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
233   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
234   IN     UINT64                                 UserAddress,
235   IN     UINTN                                  Count,
236   IN     VOID                                   *UserBuffer
237   );
238 
239 /**
240    Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
241    root bridge memory space.
242 
243    The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
244    space to another region of PCI root bridge memory space. This is especially useful for video scroll
245    operation on a memory mapped video buffer.
246    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
247    any alignment and memory width restrictions that a PCI root bridge on a platform might require.
248 
249    @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
250    @param[in] Width       Signifies the width of the memory operations.
251    @param[in] DestAddress The destination address of the memory operation. The caller is
252                           responsible for aligning the DestAddress if required.
253    @param[in] SrcAddress  The source address of the memory operation. The caller is
254                           responsible for aligning the SrcAddress if required.
255    @param[in] Count       The number of memory operations to perform. Bytes moved is
256                           Width size * Count, starting at DestAddress and SrcAddress.
257 
258    @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
259    @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
260    @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
261 
262 **/
263 EFI_STATUS
264 EFIAPI
265 RootBridgeIoCopyMem (
266   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
267   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
268   IN     UINT64                                 DestAddress,
269   IN     UINT64                                 SrcAddress,
270   IN     UINTN                                  Count
271   );
272 
273 /**
274    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
275 
276    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
277    registers for a PCI controller.
278    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
279    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
280    require.
281 
282    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
283    @param[in]   Width     Signifies the width of the memory operations.
284    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
285    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
286                           moved is Width size * Count, starting at Address.
287    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
288                           write operations, the source buffer to write data from.
289 
290    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
291    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
292    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
293    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
294 
295 **/
296 EFI_STATUS
297 EFIAPI
298 RootBridgeIoPciRead (
299   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
300   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
301   IN     UINT64                                 Address,
302   IN     UINTN                                  Count,
303   OUT    VOID                                   *Buffer
304   );
305 
306 /**
307    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
308 
309    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
310    registers for a PCI controller.
311    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
312    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
313    require.
314 
315    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
316    @param[in]   Width     Signifies the width of the memory operations.
317    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
318    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
319                           moved is Width size * Count, starting at Address.
320    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
321                           write operations, the source buffer to write data from.
322 
323    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
324    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
325    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
326    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
327 
328 **/
329 EFI_STATUS
330 EFIAPI
331 RootBridgeIoPciWrite (
332   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
333   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
334   IN     UINT64                                 Address,
335   IN     UINTN                                  Count,
336   IN     VOID                                   *Buffer
337   );
338 
339 /**
340    Provides the PCI controller-specific addresses required to access system memory from a
341    DMA bus master.
342 
343    The Map() function provides the PCI controller specific addresses needed to access system
344    memory. This function is used to map system memory for PCI bus master DMA accesses.
345 
346    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
347    @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
348    @param[in]       HostAddress     The system memory address to map to the PCI controller.
349    @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
350    @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
351                                     to access the system memory's HostAddress.
352    @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
353 
354    @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
355    @retval EFI_INVALID_PARAMETER  Operation is invalid.
356    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
357    @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
358    @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
359    @retval EFI_INVALID_PARAMETER  Mapping is NULL.
360    @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
361    @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
362    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
363 
364 **/
365 EFI_STATUS
366 EFIAPI
367 RootBridgeIoMap (
368   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
369   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
370   IN     VOID                                       *HostAddress,
371   IN OUT UINTN                                      *NumberOfBytes,
372   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
373   OUT    VOID                                       **Mapping
374   );
375 
376 /**
377    Completes the Map() operation and releases any corresponding resources.
378 
379    The Unmap() function completes the Map() operation and releases any corresponding resources.
380    If the operation was an EfiPciOperationBusMasterWrite or
381    EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
382    Any resources used for the mapping are freed.
383 
384    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
385    @param[in] Mapping   The mapping value returned from Map().
386 
387    @retval EFI_SUCCESS            The range was unmapped.
388    @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
389    @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
390 
391 **/
392 EFI_STATUS
393 EFIAPI
394 RootBridgeIoUnmap (
395   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
396   IN  VOID                             *Mapping
397   );
398 
399 /**
400    Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
401    EfiPciOperationBusMasterCommonBuffer64 mapping.
402 
403    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
404    @param Type        This parameter is not used and must be ignored.
405    @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
406    @param Pages       The number of pages to allocate.
407    @param HostAddress A pointer to store the base system memory address of the allocated range.
408    @param Attributes  The requested bit mask of attributes for the allocated range. Only
409                       the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
410                       and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
411 
412    @retval EFI_SUCCESS            The requested memory pages were allocated.
413    @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
414    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
415    @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
416                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
417    @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
418 
419 **/
420 EFI_STATUS
421 EFIAPI
422 RootBridgeIoAllocateBuffer (
423   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
424   IN  EFI_ALLOCATE_TYPE                Type,
425   IN  EFI_MEMORY_TYPE                  MemoryType,
426   IN  UINTN                            Pages,
427   OUT VOID                             **HostAddress,
428   IN  UINT64                           Attributes
429   );
430 
431 /**
432    Frees memory that was allocated with AllocateBuffer().
433 
434    The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
435 
436    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
437    @param Pages       The number of pages to free.
438    @param HostAddress The base system memory address of the allocated range.
439 
440    @retval EFI_SUCCESS            The requested memory pages were freed.
441    @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
442                                   was not allocated with AllocateBuffer().
443 
444 **/
445 EFI_STATUS
446 EFIAPI
447 RootBridgeIoFreeBuffer (
448   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
449   IN  UINTN                            Pages,
450   OUT VOID                             *HostAddress
451   );
452 
453 /**
454    Flushes all PCI posted write transactions from a PCI host bridge to system memory.
455 
456    The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
457    memory. Posted write transactions are generated by PCI bus masters when they perform write
458    transactions to target addresses in system memory.
459    This function does not flush posted write transactions from any PCI bridges. A PCI controller
460    specific action must be taken to guarantee that the posted write transactions have been flushed from
461    the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
462    a PCI read transaction from the PCI controller prior to calling Flush().
463 
464    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
465 
466    @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
467                               bridge to system memory.
468    @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
469                               host bridge due to a hardware error.
470 
471 **/
472 EFI_STATUS
473 EFIAPI
474 RootBridgeIoFlush (
475   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This
476   );
477 
478 /**
479    Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
480    attributes that a PCI root bridge is currently using.
481 
482    The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
483    and the mask of attributes that the PCI root bridge is currently using.
484 
485    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
486    @param Supported   A pointer to the mask of attributes that this PCI root bridge
487                       supports setting with SetAttributes().
488    @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
489                       currently using.
490 
491    @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
492                                   bridge supports is returned in Supports. If Attributes is
493                                   not NULL, then the attributes that the PCI root bridge is currently
494                                   using is returned in Attributes.
495    @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
496 
497 **/
498 EFI_STATUS
499 EFIAPI
500 RootBridgeIoGetAttributes (
501   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
502   OUT UINT64                           *Supported,
503   OUT UINT64                           *Attributes
504   );
505 
506 /**
507    Sets attributes for a resource range on a PCI root bridge.
508 
509    The SetAttributes() function sets the attributes specified in Attributes for the PCI root
510    bridge on the resource range specified by ResourceBase and ResourceLength. Since the
511    granularity of setting these attributes may vary from resource type to resource type, and from
512    platform to platform, the actual resource range and the one passed in by the caller may differ. As a
513    result, this function may set the attributes specified by Attributes on a larger resource range
514    than the caller requested. The actual range is returned in ResourceBase and
515    ResourceLength. The caller is responsible for verifying that the actual range for which the
516    attributes were set is acceptable.
517 
518    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
519    @param[in]       Attributes      The mask of attributes to set. If the attribute bit
520                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
521                                     MEMORY_DISABLE is set, then the resource range is specified by
522                                     ResourceBase and ResourceLength. If
523                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
524                                     MEMORY_DISABLE are not set, then ResourceBase and
525                                     ResourceLength are ignored, and may be NULL.
526    @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
527                                     by the attributes specified by Attributes.
528    @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
529                                     attributes specified by Attributes.
530 
531    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
532    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
533    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
534 
535 **/
536 EFI_STATUS
537 EFIAPI
538 RootBridgeIoSetAttributes (
539   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
540   IN     UINT64                           Attributes,
541   IN OUT UINT64                           *ResourceBase,
542   IN OUT UINT64                           *ResourceLength
543   );
544 
545 /**
546    Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
547    resource descriptors.
548 
549    There are only two resource descriptor types from the ACPI Specification that may be used to
550    describe the current resources allocated to a PCI root bridge. These are the QWORD Address
551    Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
552    QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
553    or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
554    Address Space Descriptors followed by an End Tag.
555 
556    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
557    @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
558                             current configuration of this PCI root bridge. The storage for the
559                             ACPI 2.0 resource descriptors is allocated by this function. The
560                             caller must treat the return buffer as read-only data, and the buffer
561                             must not be freed by the caller.
562 
563    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
564    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
565    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
566 
567 **/
568 EFI_STATUS
569 EFIAPI
570 RootBridgeIoConfiguration (
571   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
572   OUT    VOID                             **Resources
573   );
574 
575 //
576 // Memory Controller Pci Root Bridge Io Module Variables
577 //
578 EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
579 
580 //
581 // Lookup table for increment values based on transfer widths
582 //
583 UINT8 mInStride[] = {
584   1, // EfiPciWidthUint8
585   2, // EfiPciWidthUint16
586   4, // EfiPciWidthUint32
587   8, // EfiPciWidthUint64
588   0, // EfiPciWidthFifoUint8
589   0, // EfiPciWidthFifoUint16
590   0, // EfiPciWidthFifoUint32
591   0, // EfiPciWidthFifoUint64
592   1, // EfiPciWidthFillUint8
593   2, // EfiPciWidthFillUint16
594   4, // EfiPciWidthFillUint32
595   8  // EfiPciWidthFillUint64
596 };
597 
598 //
599 // Lookup table for increment values based on transfer widths
600 //
601 UINT8 mOutStride[] = {
602   1, // EfiPciWidthUint8
603   2, // EfiPciWidthUint16
604   4, // EfiPciWidthUint32
605   8, // EfiPciWidthUint64
606   1, // EfiPciWidthFifoUint8
607   2, // EfiPciWidthFifoUint16
608   4, // EfiPciWidthFifoUint32
609   8, // EfiPciWidthFifoUint64
610   0, // EfiPciWidthFillUint8
611   0, // EfiPciWidthFillUint16
612   0, // EfiPciWidthFillUint32
613   0  // EfiPciWidthFillUint64
614 };
615 
616 /**
617 
618   Construct the Pci Root Bridge Io protocol
619 
620   @param Protocol         Point to protocol instance
621   @param HostBridgeHandle Handle of host bridge
622   @param Attri            Attribute of host bridge
623   @param ResAperture      ResourceAperture for host bridge
624 
625   @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
626 
627 **/
628 EFI_STATUS
RootBridgeConstructor(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * Protocol,IN EFI_HANDLE HostBridgeHandle,IN UINT64 Attri,IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE * ResAperture)629 RootBridgeConstructor (
630   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL    *Protocol,
631   IN EFI_HANDLE                         HostBridgeHandle,
632   IN UINT64                             Attri,
633   IN PCI_ROOT_BRIDGE_RESOURCE_APERTURE  *ResAperture
634   )
635 {
636   EFI_STATUS                        Status;
637   PCI_ROOT_BRIDGE_INSTANCE          *PrivateData;
638   PCI_RESOURCE_TYPE                 Index;
639 
640   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (Protocol);
641 
642   //
643   // The host to PCI bridge. The host memory addresses are direct mapped to PCI
644   // addresses, so there's no need to translate them. IO addresses need
645   // translation however.
646   //
647   PrivateData->MemBase       = ResAperture->MemBase;
648   PrivateData->IoBase        = ResAperture->IoBase;
649   PrivateData->IoTranslation = ResAperture->IoTranslation;
650 
651   //
652   // The host bridge only supports 32bit addressing for memory
653   // and standard IA32 16bit io
654   //
655   PrivateData->MemLimit = ResAperture->MemLimit;
656   PrivateData->IoLimit  = ResAperture->IoLimit;
657 
658   //
659   // Bus Aperture for this Root Bridge (Possible Range)
660   //
661   PrivateData->BusBase  = ResAperture->BusBase;
662   PrivateData->BusLimit = ResAperture->BusLimit;
663 
664   //
665   // Specific for this chipset
666   //
667   for (Index = TypeIo; Index < TypeMax; Index++) {
668     PrivateData->ResAllocNode[Index].Type      = Index;
669     PrivateData->ResAllocNode[Index].Base      = 0;
670     PrivateData->ResAllocNode[Index].Length    = 0;
671     PrivateData->ResAllocNode[Index].Status    = ResNone;
672   }
673 
674   PrivateData->RootBridgeAttrib = Attri;
675 
676   PrivateData->Supports    = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
677                              EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
678                              EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
679                              EFI_PCI_ATTRIBUTE_VGA_IO_16  | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
680   PrivateData->Attributes  = PrivateData->Supports;
681 
682   Protocol->ParentHandle   = HostBridgeHandle;
683 
684   Protocol->PollMem        = RootBridgeIoPollMem;
685   Protocol->PollIo         = RootBridgeIoPollIo;
686 
687   Protocol->Mem.Read       = RootBridgeIoMemRead;
688   Protocol->Mem.Write      = RootBridgeIoMemWrite;
689 
690   Protocol->Io.Read        = RootBridgeIoIoRead;
691   Protocol->Io.Write       = RootBridgeIoIoWrite;
692 
693   Protocol->CopyMem        = RootBridgeIoCopyMem;
694 
695   Protocol->Pci.Read       = RootBridgeIoPciRead;
696   Protocol->Pci.Write      = RootBridgeIoPciWrite;
697 
698   Protocol->Map            = RootBridgeIoMap;
699   Protocol->Unmap          = RootBridgeIoUnmap;
700 
701   Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
702   Protocol->FreeBuffer     = RootBridgeIoFreeBuffer;
703 
704   Protocol->Flush          = RootBridgeIoFlush;
705 
706   Protocol->GetAttributes  = RootBridgeIoGetAttributes;
707   Protocol->SetAttributes  = RootBridgeIoSetAttributes;
708 
709   Protocol->Configuration  = RootBridgeIoConfiguration;
710 
711   Protocol->SegmentNumber  = 0;
712 
713   Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
714   ASSERT_EFI_ERROR (Status);
715 
716   return EFI_SUCCESS;
717 }
718 
719 /**
720   Check parameters for IO,MMIO,PCI read/write services of PCI Root Bridge IO.
721 
722   The I/O operations are carried out exactly as requested. The caller is responsible
723   for satisfying any alignment and I/O width restrictions that a PI System on a
724   platform might require. For example on some platforms, width requests of
725   EfiCpuIoWidthUint64 do not work. Misaligned buffers, on the other hand, will
726   be handled by the driver.
727 
728   @param[in] This           A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
729   @param[in] OperationType  I/O operation type: IO/MMIO/PCI.
730   @param[in] Width          Signifies the width of the I/O or Memory operation.
731   @param[in] Address        The base address of the I/O operation.
732   @param[in] Count          The number of I/O operations to perform. The number of
733                             bytes moved is Width size * Count, starting at Address.
734   @param[in] Buffer         For read operations, the destination buffer to store the results.
735                             For write operations, the source buffer from which to write data.
736 
737   @retval EFI_SUCCESS            The parameters for this request pass the checks.
738   @retval EFI_INVALID_PARAMETER  Width is invalid for this PI system.
739   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
740   @retval EFI_UNSUPPORTED        The Buffer is not aligned for the given Width.
741   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
742                                  and Count is not valid for this PI system.
743 
744 **/
745 EFI_STATUS
RootBridgeIoCheckParameter(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN OPERATION_TYPE OperationType,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)746 RootBridgeIoCheckParameter (
747   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
748   IN OPERATION_TYPE                         OperationType,
749   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
750   IN UINT64                                 Address,
751   IN UINTN                                  Count,
752   IN VOID                                   *Buffer
753   )
754 {
755   PCI_ROOT_BRIDGE_INSTANCE                     *PrivateData;
756   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
757   UINT32                                       Stride;
758   UINT64                                       Base;
759   UINT64                                       Limit;
760 
761   //
762   // Check to see if Buffer is NULL
763   //
764   if (Buffer == NULL) {
765     return EFI_INVALID_PARAMETER;
766   }
767 
768   //
769   // Check to see if Width is in the valid range
770   //
771   if ((UINT32)Width >= EfiPciWidthMaximum) {
772     return EFI_INVALID_PARAMETER;
773   }
774 
775   //
776   // For FIFO type, the target address won't increase during the access,
777   // so treat Count as 1
778   //
779   if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) {
780     Count = 1;
781   }
782 
783   //
784   // Check to see if Width is in the valid range for I/O Port operations
785   //
786   Width = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
787   if ((OperationType != MemOperation) && (Width == EfiPciWidthUint64)) {
788     ASSERT (FALSE);
789     return EFI_INVALID_PARAMETER;
790   }
791 
792   //
793   // Check to see if Address is aligned
794   //
795   Stride = mInStride[Width];
796   if ((Address & (UINT64)(Stride - 1)) != 0) {
797     return EFI_UNSUPPORTED;
798   }
799 
800   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
801 
802   //
803   // Check to see if any address associated with this transfer exceeds the maximum
804   // allowed address.  The maximum address implied by the parameters passed in is
805   // Address + Size * Count.  If the following condition is met, then the transfer
806   // is not supported.
807   //
808   //    Address + Size * Count > Limit + 1
809   //
810   // Since Limit can be the maximum integer value supported by the CPU and Count
811   // can also be the maximum integer value supported by the CPU, this range
812   // check must be adjusted to avoid all oveflow conditions.
813   //
814   if (OperationType == IoOperation) {
815     Base = PrivateData->IoBase;
816     Limit = PrivateData->IoLimit;
817   } else if (OperationType == MemOperation) {
818     Base = PrivateData->MemBase;
819     Limit = PrivateData->MemLimit;
820   } else {
821     PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
822     if (PciRbAddr->Bus < PrivateData->BusBase || PciRbAddr->Bus > PrivateData->BusLimit) {
823       return EFI_INVALID_PARAMETER;
824     }
825 
826     if (PciRbAddr->Device > MAX_PCI_DEVICE_NUMBER || PciRbAddr->Function > MAX_PCI_FUNCTION_NUMBER) {
827       return EFI_INVALID_PARAMETER;
828     }
829 
830     if (PciRbAddr->ExtendedRegister != 0) {
831       Address = PciRbAddr->ExtendedRegister;
832     } else {
833       Address = PciRbAddr->Register;
834     }
835     Base = 0;
836     Limit = MAX_PCI_REG_ADDRESS;
837   }
838 
839   if (Limit < Address) {
840       return EFI_INVALID_PARAMETER;
841   }
842 
843   if (Address < Base) {
844       return EFI_INVALID_PARAMETER;
845   }
846 
847   //
848   // Base <= Address <= Limit
849   //
850   if (Address == 0 && Limit == MAX_UINT64) {
851     //
852     // 2^64 bytes are valid to transfer. With Stride == 1, that's simply
853     // impossible to reach in Count; with Stride in {2, 4, 8}, we can divide
854     // both 2^64 and Stride with 2.
855     //
856     if (Stride > 1 && Count > DivU64x32 (BIT63, Stride / 2)) {
857       return EFI_UNSUPPORTED;
858     }
859   } else {
860     //
861     // (Limit - Address) does not wrap, and it is smaller than MAX_UINT64.
862     //
863     if (Count > DivU64x32 (Limit - Address + 1, Stride)) {
864       return EFI_UNSUPPORTED;
865     }
866   }
867 
868   return EFI_SUCCESS;
869 }
870 
871 /**
872    Internal help function for read and write memory space.
873 
874    @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
875    @param[in]   Write         Switch value for Read or Write.
876    @param[in]   Width         Signifies the width of the memory operations.
877    @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
878    @param[in]   Count         The number of PCI configuration operations to perform. Bytes
879                               moved is Width size * Count, starting at Address.
880    @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
881                               write operations, the source buffer to write data from.
882 
883    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
884    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
885    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
886    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
887 
888 **/
889 EFI_STATUS
RootBridgeIoMemRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)890 RootBridgeIoMemRW (
891   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
892   IN     BOOLEAN                                Write,
893   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
894   IN     UINT64                                 Address,
895   IN     UINTN                                  Count,
896   IN OUT VOID                                   *Buffer
897   )
898 {
899   EFI_STATUS                             Status;
900   UINT8                                  InStride;
901   UINT8                                  OutStride;
902   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
903   UINT8                                  *Uint8Buffer;
904 
905   Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
906   if (EFI_ERROR (Status)) {
907     return Status;
908   }
909 
910   InStride = mInStride[Width];
911   OutStride = mOutStride[Width];
912   OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
913   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
914     if (Write) {
915       switch (OperationWidth) {
916         case EfiPciWidthUint8:
917           MmioWrite8 ((UINTN)Address, *Uint8Buffer);
918           break;
919         case EfiPciWidthUint16:
920           MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
921           break;
922         case EfiPciWidthUint32:
923           MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
924           break;
925         case EfiPciWidthUint64:
926           MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
927           break;
928         default:
929           //
930           // The RootBridgeIoCheckParameter call above will ensure that this
931           // path is not taken.
932           //
933           ASSERT (FALSE);
934           break;
935       }
936     } else {
937       switch (OperationWidth) {
938         case EfiPciWidthUint8:
939           *Uint8Buffer = MmioRead8 ((UINTN)Address);
940           break;
941         case EfiPciWidthUint16:
942           *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
943           break;
944         case EfiPciWidthUint32:
945           *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
946           break;
947         case EfiPciWidthUint64:
948           *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
949           break;
950         default:
951           //
952           // The RootBridgeIoCheckParameter call above will ensure that this
953           // path is not taken.
954           //
955           ASSERT (FALSE);
956           break;
957       }
958     }
959   }
960   return EFI_SUCCESS;
961 }
962 
963 /**
964    Internal help function for read and write IO space.
965 
966    @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
967    @param[in]   Write         Switch value for Read or Write.
968    @param[in]   Width         Signifies the width of the memory operations.
969    @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
970    @param[in]   Count         The number of PCI configuration operations to perform. Bytes
971                               moved is Width size * Count, starting at Address.
972    @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
973                               write operations, the source buffer to write data from.
974 
975    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
976    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
977    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
978    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
979 
980 **/
981 EFI_STATUS
RootBridgeIoIoRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)982 RootBridgeIoIoRW (
983   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
984   IN     BOOLEAN                                Write,
985   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
986   IN     UINT64                                 Address,
987   IN     UINTN                                  Count,
988   IN OUT VOID                                   *Buffer
989   )
990 {
991   EFI_STATUS                             Status;
992   PCI_ROOT_BRIDGE_INSTANCE               *PrivateData;
993   UINT8                                  InStride;
994   UINT8                                  OutStride;
995   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  OperationWidth;
996   UINT8                                  *Uint8Buffer;
997 
998   Status = RootBridgeIoCheckParameter (This, IoOperation, Width, Address, Count, Buffer);
999   if (EFI_ERROR (Status)) {
1000     return Status;
1001   }
1002 
1003   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
1004   //
1005   // The addition below is performed in UINT64 modular arithmetic, in
1006   // accordance with the definition of PcdPciIoTranslation in
1007   // "ArmPlatformPkg.dec". Meaning, the addition below may in fact *decrease*
1008   // Address, implementing a negative offset translation.
1009   //
1010   Address += PrivateData->IoTranslation;
1011 
1012   InStride = mInStride[Width];
1013   OutStride = mOutStride[Width];
1014   OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
1015 
1016   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
1017     if (Write) {
1018       switch (OperationWidth) {
1019         case EfiPciWidthUint8:
1020           MmioWrite8 ((UINTN)Address, *Uint8Buffer);
1021           break;
1022         case EfiPciWidthUint16:
1023           MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
1024           break;
1025         case EfiPciWidthUint32:
1026           MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
1027           break;
1028         default:
1029           //
1030           // The RootBridgeIoCheckParameter call above will ensure that this
1031           // path is not taken.
1032           //
1033           ASSERT (FALSE);
1034           break;
1035       }
1036     } else {
1037       switch (OperationWidth) {
1038         case EfiPciWidthUint8:
1039           *Uint8Buffer = MmioRead8 ((UINTN)Address);
1040           break;
1041         case EfiPciWidthUint16:
1042           *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
1043           break;
1044         case EfiPciWidthUint32:
1045           *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
1046           break;
1047         default:
1048           //
1049           // The RootBridgeIoCheckParameter call above will ensure that this
1050           // path is not taken.
1051           //
1052           ASSERT (FALSE);
1053           break;
1054       }
1055     }
1056   }
1057   return EFI_SUCCESS;
1058 }
1059 
1060 /**
1061    Internal help function for read and write PCI configuration space.
1062 
1063    @param[in]   This          A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1064    @param[in]   Write         Switch value for Read or Write.
1065    @param[in]   Width         Signifies the width of the memory operations.
1066    @param[in]   UserAddress   The address within the PCI configuration space for the PCI controller.
1067    @param[in]   Count         The number of PCI configuration operations to perform. Bytes
1068                               moved is Width size * Count, starting at Address.
1069    @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
1070                               write operations, the source buffer to write data from.
1071 
1072    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1073    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1074    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1075    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1076 
1077 **/
1078 EFI_STATUS
RootBridgeIoPciRW(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN BOOLEAN Write,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)1079 RootBridgeIoPciRW (
1080   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1081   IN BOOLEAN                                Write,
1082   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1083   IN UINT64                                 Address,
1084   IN UINTN                                  Count,
1085   IN OUT VOID                               *Buffer
1086   )
1087 {
1088   EFI_STATUS                                   Status;
1089   UINT8                                        InStride;
1090   UINT8                                        OutStride;
1091   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        OperationWidth;
1092   UINT8                                        *Uint8Buffer;
1093   EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS  *PciRbAddr;
1094   UINTN                                        PcieRegAddr;
1095 
1096   Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
1097   if (EFI_ERROR (Status)) {
1098     return Status;
1099   }
1100 
1101   PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
1102 
1103   PcieRegAddr = (UINTN) PCI_LIB_ADDRESS (
1104                           PciRbAddr->Bus,
1105                           PciRbAddr->Device,
1106                           PciRbAddr->Function,
1107                           (PciRbAddr->ExtendedRegister != 0) ? \
1108                             PciRbAddr->ExtendedRegister :
1109                             PciRbAddr->Register
1110                           );
1111 
1112   InStride = mInStride[Width];
1113   OutStride = mOutStride[Width];
1114   OperationWidth = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) (Width & 0x03);
1115   for (Uint8Buffer = Buffer; Count > 0; PcieRegAddr += InStride, Uint8Buffer += OutStride, Count--) {
1116     if (Write) {
1117       switch (OperationWidth) {
1118         case EfiPciWidthUint8:
1119           PciWrite8 (PcieRegAddr, *Uint8Buffer);
1120           break;
1121         case EfiPciWidthUint16:
1122           PciWrite16 (PcieRegAddr, *((UINT16 *)Uint8Buffer));
1123           break;
1124         case EfiPciWidthUint32:
1125           PciWrite32 (PcieRegAddr, *((UINT32 *)Uint8Buffer));
1126           break;
1127         default:
1128           //
1129           // The RootBridgeIoCheckParameter call above will ensure that this
1130           // path is not taken.
1131           //
1132           ASSERT (FALSE);
1133           break;
1134       }
1135     } else {
1136       switch (OperationWidth) {
1137         case EfiPciWidthUint8:
1138           *Uint8Buffer = PciRead8 (PcieRegAddr);
1139           break;
1140         case EfiPciWidthUint16:
1141           *((UINT16 *)Uint8Buffer) = PciRead16 (PcieRegAddr);
1142           break;
1143         case EfiPciWidthUint32:
1144           *((UINT32 *)Uint8Buffer) = PciRead32 (PcieRegAddr);
1145           break;
1146         default:
1147           //
1148           // The RootBridgeIoCheckParameter call above will ensure that this
1149           // path is not taken.
1150           //
1151           ASSERT (FALSE);
1152           break;
1153       }
1154     }
1155   }
1156 
1157   return EFI_SUCCESS;
1158 }
1159 
1160 /**
1161    Polls an address in memory mapped I/O space until an exit condition is met, or
1162    a timeout occurs.
1163 
1164    This function provides a standard way to poll a PCI memory location. A PCI memory read
1165    operation is performed at the PCI memory address specified by Address for the width specified
1166    by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
1167    read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
1168    Mask) is equal to Value.
1169 
1170    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1171    @param[in]   Width     Signifies the width of the memory operations.
1172    @param[in]   Address   The base address of the memory operations. The caller is
1173                           responsible for aligning Address if required.
1174    @param[in]   Mask      Mask used for the polling criteria. Bytes above Width in Mask
1175                           are ignored. The bits in the bytes below Width which are zero in
1176                           Mask are ignored when polling the memory address.
1177    @param[in]   Value     The comparison value used for the polling exit criteria.
1178    @param[in]   Delay     The number of 100 ns units to poll. Note that timer available may
1179                           be of poorer granularity.
1180    @param[out]  Result    Pointer to the last value read from the memory location.
1181 
1182    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
1183    @retval EFI_INVALID_PARAMETER  Width is invalid.
1184    @retval EFI_INVALID_PARAMETER  Result is NULL.
1185    @retval EFI_TIMEOUT            Delay expired before a match occurred.
1186    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1187 
1188 **/
1189 EFI_STATUS
1190 EFIAPI
RootBridgeIoPollMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)1191 RootBridgeIoPollMem (
1192   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1193   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1194   IN  UINT64                                 Address,
1195   IN  UINT64                                 Mask,
1196   IN  UINT64                                 Value,
1197   IN  UINT64                                 Delay,
1198   OUT UINT64                                 *Result
1199   )
1200 {
1201   EFI_STATUS  Status;
1202   UINT64      NumberOfTicks;
1203   UINT32      Remainder;
1204 
1205   if (Result == NULL) {
1206     return EFI_INVALID_PARAMETER;
1207   }
1208 
1209   if ((UINT32)Width > EfiPciWidthUint64) {
1210     return EFI_INVALID_PARAMETER;
1211   }
1212 
1213   //
1214   // No matter what, always do a single poll.
1215   //
1216   Status = This->Mem.Read (This, Width, Address, 1, Result);
1217   if (EFI_ERROR (Status)) {
1218     return Status;
1219   }
1220   if ((*Result & Mask) == Value) {
1221     return EFI_SUCCESS;
1222   }
1223 
1224   if (Delay == 0) {
1225     return EFI_SUCCESS;
1226 
1227   } else {
1228 
1229     //
1230     // Determine the proper # of metronome ticks to wait for polling the
1231     // location.  The nuber of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
1232     // The "+1" to account for the possibility of the first tick being short
1233     // because we started in the middle of a tick.
1234     //
1235     // BugBug: overriding mMetronome->TickPeriod with UINT32 until Metronome
1236     // protocol definition is updated.
1237     //
1238     NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
1239     if (Remainder != 0) {
1240       NumberOfTicks += 1;
1241     }
1242     NumberOfTicks += 1;
1243 
1244     while (NumberOfTicks != 0) {
1245 
1246       mMetronome->WaitForTick (mMetronome, 1);
1247 
1248       Status = This->Mem.Read (This, Width, Address, 1, Result);
1249       if (EFI_ERROR (Status)) {
1250         return Status;
1251       }
1252 
1253       if ((*Result & Mask) == Value) {
1254         return EFI_SUCCESS;
1255       }
1256 
1257       NumberOfTicks -= 1;
1258     }
1259   }
1260   return EFI_TIMEOUT;
1261 }
1262 
1263 /**
1264    Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
1265    satisfied or after a defined duration.
1266 
1267    This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
1268    performed at the PCI I/O address specified by Address for the width specified by Width.
1269    The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
1270    repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
1271    to Value.
1272 
1273    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1274    @param[in] Width     Signifies the width of the I/O operations.
1275    @param[in] Address   The base address of the I/O operations. The caller is responsible
1276                         for aligning Address if required.
1277    @param[in] Mask      Mask used for the polling criteria. Bytes above Width in Mask
1278                         are ignored. The bits in the bytes below Width which are zero in
1279                         Mask are ignored when polling the I/O address.
1280    @param[in] Value     The comparison value used for the polling exit criteria.
1281    @param[in] Delay     The number of 100 ns units to poll. Note that timer available may
1282                         be of poorer granularity.
1283    @param[out] Result   Pointer to the last value read from the memory location.
1284 
1285    @retval EFI_SUCCESS            The last data returned from the access matched the poll exit criteria.
1286    @retval EFI_INVALID_PARAMETER  Width is invalid.
1287    @retval EFI_INVALID_PARAMETER  Result is NULL.
1288    @retval EFI_TIMEOUT            Delay expired before a match occurred.
1289    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1290 
1291 **/
1292 EFI_STATUS
1293 EFIAPI
RootBridgeIoPollIo(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINT64 Mask,IN UINT64 Value,IN UINT64 Delay,OUT UINT64 * Result)1294 RootBridgeIoPollIo (
1295   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1296   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1297   IN  UINT64                                 Address,
1298   IN  UINT64                                 Mask,
1299   IN  UINT64                                 Value,
1300   IN  UINT64                                 Delay,
1301   OUT UINT64                                 *Result
1302   )
1303 {
1304   EFI_STATUS  Status;
1305   UINT64      NumberOfTicks;
1306   UINT32      Remainder;
1307 
1308   //
1309   // No matter what, always do a single poll.
1310   //
1311 
1312   if (Result == NULL) {
1313     return EFI_INVALID_PARAMETER;
1314   }
1315 
1316   if ((UINT32)Width > EfiPciWidthUint64) {
1317     return EFI_INVALID_PARAMETER;
1318   }
1319 
1320   Status = This->Io.Read (This, Width, Address, 1, Result);
1321   if (EFI_ERROR (Status)) {
1322     return Status;
1323   }
1324   if ((*Result & Mask) == Value) {
1325     return EFI_SUCCESS;
1326   }
1327 
1328   if (Delay == 0) {
1329     return EFI_SUCCESS;
1330 
1331   } else {
1332 
1333     //
1334     // Determine the proper # of metronome ticks to wait for polling the
1335     // location.  The number of ticks is Roundup (Delay / mMetronome->TickPeriod)+1
1336     // The "+1" to account for the possibility of the first tick being short
1337     // because we started in the middle of a tick.
1338     //
1339     NumberOfTicks = DivU64x32Remainder (Delay, (UINT32)mMetronome->TickPeriod, &Remainder);
1340     if (Remainder != 0) {
1341       NumberOfTicks += 1;
1342     }
1343     NumberOfTicks += 1;
1344 
1345     while (NumberOfTicks != 0) {
1346 
1347       mMetronome->WaitForTick (mMetronome, 1);
1348 
1349       Status = This->Io.Read (This, Width, Address, 1, Result);
1350       if (EFI_ERROR (Status)) {
1351         return Status;
1352       }
1353 
1354       if ((*Result & Mask) == Value) {
1355         return EFI_SUCCESS;
1356       }
1357 
1358       NumberOfTicks -= 1;
1359     }
1360   }
1361   return EFI_TIMEOUT;
1362 }
1363 
1364 /**
1365    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
1366 
1367    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
1368    registers in the PCI root bridge memory space.
1369    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1370    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
1371 
1372    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1373    @param[in]   Width     Signifies the width of the memory operation.
1374    @param[in]   Address   The base address of the memory operation. The caller is
1375                           responsible for aligning the Address if required.
1376    @param[in]   Count     The number of memory operations to perform. Bytes moved is
1377                           Width size * Count, starting at Address.
1378    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
1379                           write operations, the source buffer to write data from.
1380 
1381    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1382    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1383    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1384    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1385 
1386 **/
1387 EFI_STATUS
1388 EFIAPI
RootBridgeIoMemRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)1389 RootBridgeIoMemRead (
1390   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1391   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1392   IN     UINT64                                 Address,
1393   IN     UINTN                                  Count,
1394   OUT    VOID                                   *Buffer
1395   )
1396 {
1397   return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
1398 }
1399 
1400 /**
1401    Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
1402 
1403    The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
1404    registers in the PCI root bridge memory space.
1405    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1406    any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
1407 
1408    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1409    @param[in]   Width     Signifies the width of the memory operation.
1410    @param[in]   Address   The base address of the memory operation. The caller is
1411                           responsible for aligning the Address if required.
1412    @param[in]   Count     The number of memory operations to perform. Bytes moved is
1413                           Width size * Count, starting at Address.
1414    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
1415                           write operations, the source buffer to write data from.
1416 
1417    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1418    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1419    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1420    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1421 **/
1422 EFI_STATUS
1423 EFIAPI
RootBridgeIoMemWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)1424 RootBridgeIoMemWrite (
1425   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1426   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1427   IN     UINT64                                 Address,
1428   IN     UINTN                                  Count,
1429   IN     VOID                                   *Buffer
1430   )
1431 {
1432   return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
1433 }
1434 
1435 /**
1436    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
1437 
1438    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1439    @param[in]   Width       Signifies the width of the memory operations.
1440    @param[in]   Address     The base address of the I/O operation. The caller is responsible for
1441                             aligning the Address if required.
1442    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
1443                             size * Count, starting at Address.
1444    @param[out]  Buffer      For read operations, the destination buffer to store the results. For
1445                             write operations, the source buffer to write data from.
1446 
1447    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
1448    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
1449    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
1450    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1451 
1452 **/
1453 EFI_STATUS
1454 EFIAPI
RootBridgeIoIoRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)1455 RootBridgeIoIoRead (
1456   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1457   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1458   IN     UINT64                                 Address,
1459   IN     UINTN                                  Count,
1460   OUT    VOID                                   *Buffer
1461   )
1462 {
1463   return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
1464 }
1465 
1466 /**
1467    Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
1468 
1469    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1470    @param[in]   Width       Signifies the width of the memory operations.
1471    @param[in]   Address     The base address of the I/O operation. The caller is responsible for
1472                             aligning the Address if required.
1473    @param[in]   Count       The number of I/O operations to perform. Bytes moved is Width
1474                             size * Count, starting at Address.
1475    @param[in]   Buffer       For read operations, the destination buffer to store the results. For
1476                             write operations, the source buffer to write data from.
1477 
1478    @retval EFI_SUCCESS              The data was read from or written to the PCI root bridge.
1479    @retval EFI_INVALID_PARAMETER    Width is invalid for this PCI root bridge.
1480    @retval EFI_INVALID_PARAMETER    Buffer is NULL.
1481    @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
1482 
1483 **/
1484 EFI_STATUS
1485 EFIAPI
RootBridgeIoIoWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)1486 RootBridgeIoIoWrite (
1487   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL         *This,
1488   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH   Width,
1489   IN       UINT64                                  Address,
1490   IN       UINTN                                   Count,
1491   IN       VOID                                    *Buffer
1492   )
1493 {
1494   return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
1495 }
1496 
1497 /**
1498    Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
1499    root bridge memory space.
1500 
1501    The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
1502    space to another region of PCI root bridge memory space. This is especially useful for video scroll
1503    operation on a memory mapped video buffer.
1504    The memory operations are carried out exactly as requested. The caller is responsible for satisfying
1505    any alignment and memory width restrictions that a PCI root bridge on a platform might require.
1506 
1507    @param[in] This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
1508    @param[in] Width       Signifies the width of the memory operations.
1509    @param[in] DestAddress The destination address of the memory operation. The caller is
1510                           responsible for aligning the DestAddress if required.
1511    @param[in] SrcAddress  The source address of the memory operation. The caller is
1512                           responsible for aligning the SrcAddress if required.
1513    @param[in] Count       The number of memory operations to perform. Bytes moved is
1514                           Width size * Count, starting at DestAddress and SrcAddress.
1515 
1516    @retval  EFI_SUCCESS             The data was copied from one memory region to another memory region.
1517    @retval  EFI_INVALID_PARAMETER   Width is invalid for this PCI root bridge.
1518    @retval  EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
1519 
1520 **/
1521 EFI_STATUS
1522 EFIAPI
RootBridgeIoCopyMem(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 DestAddress,IN UINT64 SrcAddress,IN UINTN Count)1523 RootBridgeIoCopyMem (
1524   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL              *This,
1525   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH        Width,
1526   IN UINT64                                       DestAddress,
1527   IN UINT64                                       SrcAddress,
1528   IN UINTN                                        Count
1529   )
1530 {
1531   EFI_STATUS  Status;
1532   BOOLEAN     Direction;
1533   UINTN       Stride;
1534   UINTN       Index;
1535   UINT64      Result;
1536 
1537   if ((UINT32)Width > EfiPciWidthUint64) {
1538     return EFI_INVALID_PARAMETER;
1539   }
1540 
1541   if (DestAddress == SrcAddress) {
1542     return EFI_SUCCESS;
1543   }
1544 
1545   Stride = (UINTN)(1 << Width);
1546 
1547   Direction = TRUE;
1548   if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
1549     Direction   = FALSE;
1550     SrcAddress  = SrcAddress  + (Count-1) * Stride;
1551     DestAddress = DestAddress + (Count-1) * Stride;
1552   }
1553 
1554   for (Index = 0;Index < Count;Index++) {
1555     Status = RootBridgeIoMemRead (
1556                This,
1557                Width,
1558                SrcAddress,
1559                1,
1560                &Result
1561                );
1562     if (EFI_ERROR (Status)) {
1563       return Status;
1564     }
1565     Status = RootBridgeIoMemWrite (
1566                This,
1567                Width,
1568                DestAddress,
1569                1,
1570                &Result
1571                );
1572     if (EFI_ERROR (Status)) {
1573       return Status;
1574     }
1575     if (Direction) {
1576       SrcAddress  += Stride;
1577       DestAddress += Stride;
1578     } else {
1579       SrcAddress  -= Stride;
1580       DestAddress -= Stride;
1581     }
1582   }
1583   return EFI_SUCCESS;
1584 }
1585 
1586 /**
1587    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
1588 
1589    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
1590    registers for a PCI controller.
1591    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
1592    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
1593    require.
1594 
1595    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1596    @param[in]   Width     Signifies the width of the memory operations.
1597    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
1598    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
1599                           moved is Width size * Count, starting at Address.
1600    @param[out]  Buffer    For read operations, the destination buffer to store the results. For
1601                           write operations, the source buffer to write data from.
1602 
1603    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1604    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1605    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1606    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1607 
1608 **/
1609 EFI_STATUS
1610 EFIAPI
RootBridgeIoPciRead(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)1611 RootBridgeIoPciRead (
1612   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1613   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1614   IN       UINT64                                 Address,
1615   IN       UINTN                                  Count,
1616   OUT      VOID                                   *Buffer
1617   )
1618 {
1619   return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
1620 }
1621 
1622 /**
1623    Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
1624 
1625    The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
1626    registers for a PCI controller.
1627    The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
1628    any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
1629    require.
1630 
1631    @param[in]   This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1632    @param[in]   Width     Signifies the width of the memory operations.
1633    @param[in]   Address   The address within the PCI configuration space for the PCI controller.
1634    @param[in]   Count     The number of PCI configuration operations to perform. Bytes
1635                           moved is Width size * Count, starting at Address.
1636    @param[in]   Buffer    For read operations, the destination buffer to store the results. For
1637                           write operations, the source buffer to write data from.
1638 
1639    @retval EFI_SUCCESS            The data was read from or written to the PCI root bridge.
1640    @retval EFI_INVALID_PARAMETER  Width is invalid for this PCI root bridge.
1641    @retval EFI_INVALID_PARAMETER  Buffer is NULL.
1642    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1643 
1644 **/
1645 EFI_STATUS
1646 EFIAPI
RootBridgeIoPciWrite(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)1647 RootBridgeIoPciWrite (
1648   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL        *This,
1649   IN       EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH  Width,
1650   IN       UINT64                                 Address,
1651   IN       UINTN                                  Count,
1652   IN       VOID                                   *Buffer
1653   )
1654 {
1655   return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
1656 }
1657 
1658 /**
1659    Provides the PCI controller-specific addresses required to access system memory from a
1660    DMA bus master.
1661 
1662    The Map() function provides the PCI controller specific addresses needed to access system
1663    memory. This function is used to map system memory for PCI bus master DMA accesses.
1664 
1665    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1666    @param[in]       Operation       Indicates if the bus master is going to read or write to system memory.
1667    @param[in]       HostAddress     The system memory address to map to the PCI controller.
1668    @param[in, out]  NumberOfBytes   On input the number of bytes to map. On output the number of bytes that were mapped.
1669    @param[out]      DeviceAddress   The resulting map address for the bus master PCI controller to use
1670                                     to access the system memory's HostAddress.
1671    @param[out]      Mapping         The value to pass to Unmap() when the bus master DMA operation is complete.
1672 
1673    @retval EFI_SUCCESS            The range was mapped for the returned NumberOfBytes.
1674    @retval EFI_INVALID_PARAMETER  Operation is invalid.
1675    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
1676    @retval EFI_INVALID_PARAMETER  NumberOfBytes is NULL.
1677    @retval EFI_INVALID_PARAMETER  DeviceAddress is NULL.
1678    @retval EFI_INVALID_PARAMETER  Mapping is NULL.
1679    @retval EFI_UNSUPPORTED        The HostAddress cannot be mapped as a common buffer.
1680    @retval EFI_DEVICE_ERROR       The system hardware could not map the requested address.
1681    @retval EFI_OUT_OF_RESOURCES   The request could not be completed due to a lack of resources.
1682 
1683 **/
1684 EFI_STATUS
1685 EFIAPI
RootBridgeIoMap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,IN VOID * HostAddress,IN OUT UINTN * NumberOfBytes,OUT EFI_PHYSICAL_ADDRESS * DeviceAddress,OUT VOID ** Mapping)1686 RootBridgeIoMap (
1687   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL            *This,
1688   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION  Operation,
1689   IN     VOID                                       *HostAddress,
1690   IN OUT UINTN                                      *NumberOfBytes,
1691   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
1692   OUT    VOID                                       **Mapping
1693   )
1694 {
1695   EFI_STATUS            Status;
1696   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1697   MAP_INFO              *MapInfo;
1698 
1699   if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
1700     return EFI_INVALID_PARAMETER;
1701   }
1702 
1703   //
1704   // Initialize the return values to their defaults
1705   //
1706   *Mapping = NULL;
1707 
1708   //
1709   // Make sure that Operation is valid
1710   //
1711   if ((UINT32)Operation >= EfiPciOperationMaximum) {
1712     return EFI_INVALID_PARAMETER;
1713   }
1714 
1715   //
1716   // Most PCAT like chipsets can not handle performing DMA above 4GB.
1717   // If any part of the DMA transfer being mapped is above 4GB, then
1718   // map the DMA transfer to a buffer below 4GB.
1719   //
1720   PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
1721   if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
1722 
1723     //
1724     // Common Buffer operations can not be remapped.  If the common buffer
1725     // if above 4GB, then it is not possible to generate a mapping, so return
1726     // an error.
1727     //
1728     if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
1729       return EFI_UNSUPPORTED;
1730     }
1731 
1732     //
1733     // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
1734     // called later.
1735     //
1736     Status = gBS->AllocatePool (
1737                     EfiBootServicesData,
1738                     sizeof(MAP_INFO),
1739                     (VOID **)&MapInfo
1740                     );
1741     if (EFI_ERROR (Status)) {
1742       *NumberOfBytes = 0;
1743       return Status;
1744     }
1745 
1746     //
1747     // Return a pointer to the MAP_INFO structure in Mapping
1748     //
1749     *Mapping = MapInfo;
1750 
1751     //
1752     // Initialize the MAP_INFO structure
1753     //
1754     MapInfo->Operation         = Operation;
1755     MapInfo->NumberOfBytes     = *NumberOfBytes;
1756     MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES(*NumberOfBytes);
1757     MapInfo->HostAddress       = PhysicalAddress;
1758     MapInfo->MappedHostAddress = 0x00000000ffffffff;
1759 
1760     //
1761     // Allocate a buffer below 4GB to map the transfer to.
1762     //
1763     Status = gBS->AllocatePages (
1764                     AllocateMaxAddress,
1765                     EfiBootServicesData,
1766                     MapInfo->NumberOfPages,
1767                     &MapInfo->MappedHostAddress
1768                     );
1769     if (EFI_ERROR (Status)) {
1770       gBS->FreePool (MapInfo);
1771       *NumberOfBytes = 0;
1772       return Status;
1773     }
1774 
1775     //
1776     // If this is a read operation from the Bus Master's point of view,
1777     // then copy the contents of the real buffer into the mapped buffer
1778     // so the Bus Master can read the contents of the real buffer.
1779     //
1780     if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
1781       CopyMem (
1782         (VOID *)(UINTN)MapInfo->MappedHostAddress,
1783         (VOID *)(UINTN)MapInfo->HostAddress,
1784         MapInfo->NumberOfBytes
1785         );
1786     }
1787 
1788     //
1789     // The DeviceAddress is the address of the maped buffer below 4GB
1790     //
1791     *DeviceAddress = MapInfo->MappedHostAddress;
1792   } else {
1793     //
1794     // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
1795     //
1796     *DeviceAddress = PhysicalAddress;
1797   }
1798 
1799   return EFI_SUCCESS;
1800 }
1801 
1802 /**
1803    Completes the Map() operation and releases any corresponding resources.
1804 
1805    The Unmap() function completes the Map() operation and releases any corresponding resources.
1806    If the operation was an EfiPciOperationBusMasterWrite or
1807    EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
1808    Any resources used for the mapping are freed.
1809 
1810    @param[in] This      A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1811    @param[in] Mapping   The mapping value returned from Map().
1812 
1813    @retval EFI_SUCCESS            The range was unmapped.
1814    @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
1815    @retval EFI_DEVICE_ERROR       The data was not committed to the target system memory.
1816 
1817 **/
1818 EFI_STATUS
1819 EFIAPI
RootBridgeIoUnmap(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN VOID * Mapping)1820 RootBridgeIoUnmap (
1821   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1822   IN VOID                             *Mapping
1823   )
1824 {
1825   MAP_INFO    *MapInfo;
1826 
1827   //
1828   // See if the Map() operation associated with this Unmap() required a mapping buffer.
1829   // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
1830   //
1831   if (Mapping != NULL) {
1832     //
1833     // Get the MAP_INFO structure from Mapping
1834     //
1835     MapInfo = (MAP_INFO *)Mapping;
1836 
1837     //
1838     // If this is a write operation from the Bus Master's point of view,
1839     // then copy the contents of the mapped buffer into the real buffer
1840     // so the processor can read the contents of the real buffer.
1841     //
1842     if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
1843       CopyMem (
1844         (VOID *)(UINTN)MapInfo->HostAddress,
1845         (VOID *)(UINTN)MapInfo->MappedHostAddress,
1846         MapInfo->NumberOfBytes
1847         );
1848     }
1849 
1850     //
1851     // Free the mapped buffer and the MAP_INFO structure.
1852     //
1853     gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
1854     gBS->FreePool (Mapping);
1855   }
1856   return EFI_SUCCESS;
1857 }
1858 
1859 /**
1860    Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
1861    EfiPciOperationBusMasterCommonBuffer64 mapping.
1862 
1863    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1864    @param Type        This parameter is not used and must be ignored.
1865    @param MemoryType  The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
1866    @param Pages       The number of pages to allocate.
1867    @param HostAddress A pointer to store the base system memory address of the allocated range.
1868    @param Attributes  The requested bit mask of attributes for the allocated range. Only
1869                       the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
1870                       and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
1871 
1872    @retval EFI_SUCCESS            The requested memory pages were allocated.
1873    @retval EFI_INVALID_PARAMETER  MemoryType is invalid.
1874    @retval EFI_INVALID_PARAMETER  HostAddress is NULL.
1875    @retval EFI_UNSUPPORTED        Attributes is unsupported. The only legal attribute bits are
1876                                   MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
1877    @retval EFI_OUT_OF_RESOURCES   The memory pages could not be allocated.
1878 
1879 **/
1880 EFI_STATUS
1881 EFIAPI
RootBridgeIoAllocateBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN EFI_ALLOCATE_TYPE Type,IN EFI_MEMORY_TYPE MemoryType,IN UINTN Pages,OUT VOID ** HostAddress,IN UINT64 Attributes)1882 RootBridgeIoAllocateBuffer (
1883   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1884   IN  EFI_ALLOCATE_TYPE                Type,
1885   IN  EFI_MEMORY_TYPE                  MemoryType,
1886   IN  UINTN                            Pages,
1887   OUT VOID                             **HostAddress,
1888   IN  UINT64                           Attributes
1889   )
1890 {
1891   EFI_STATUS            Status;
1892   EFI_PHYSICAL_ADDRESS  PhysicalAddress;
1893 
1894   //
1895   // Validate Attributes
1896   //
1897   if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
1898     return EFI_UNSUPPORTED;
1899   }
1900 
1901   //
1902   // Check for invalid inputs
1903   //
1904   if (HostAddress == NULL) {
1905     return EFI_INVALID_PARAMETER;
1906   }
1907 
1908   //
1909   // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
1910   //
1911   if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
1912     return EFI_INVALID_PARAMETER;
1913   }
1914 
1915   //
1916   // Limit allocations to memory below 4GB
1917   //
1918   PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(0xffffffff);
1919 
1920   Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
1921   if (EFI_ERROR (Status)) {
1922     return Status;
1923   }
1924 
1925   *HostAddress = (VOID *)(UINTN)PhysicalAddress;
1926 
1927   return EFI_SUCCESS;
1928 }
1929 
1930 /**
1931    Frees memory that was allocated with AllocateBuffer().
1932 
1933    The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
1934 
1935    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1936    @param Pages       The number of pages to free.
1937    @param HostAddress The base system memory address of the allocated range.
1938 
1939    @retval EFI_SUCCESS            The requested memory pages were freed.
1940    @retval EFI_INVALID_PARAMETER  The memory range specified by HostAddress and Pages
1941                                   was not allocated with AllocateBuffer().
1942 
1943 **/
1944 EFI_STATUS
1945 EFIAPI
RootBridgeIoFreeBuffer(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINTN Pages,OUT VOID * HostAddress)1946 RootBridgeIoFreeBuffer (
1947   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
1948   IN  UINTN                            Pages,
1949   OUT VOID                             *HostAddress
1950   )
1951 {
1952   return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
1953 }
1954 
1955 /**
1956    Flushes all PCI posted write transactions from a PCI host bridge to system memory.
1957 
1958    The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
1959    memory. Posted write transactions are generated by PCI bus masters when they perform write
1960    transactions to target addresses in system memory.
1961    This function does not flush posted write transactions from any PCI bridges. A PCI controller
1962    specific action must be taken to guarantee that the posted write transactions have been flushed from
1963    the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
1964    a PCI read transaction from the PCI controller prior to calling Flush().
1965 
1966    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1967 
1968    @retval EFI_SUCCESS        The PCI posted write transactions were flushed from the PCI host
1969                               bridge to system memory.
1970    @retval EFI_DEVICE_ERROR   The PCI posted write transactions were not flushed from the PCI
1971                               host bridge due to a hardware error.
1972 
1973 **/
1974 EFI_STATUS
1975 EFIAPI
RootBridgeIoFlush(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This)1976 RootBridgeIoFlush (
1977   IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL           *This
1978   )
1979 {
1980   //
1981   // not supported yet
1982   //
1983   return EFI_SUCCESS;
1984 }
1985 
1986 /**
1987    Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
1988    attributes that a PCI root bridge is currently using.
1989 
1990    The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
1991    and the mask of attributes that the PCI root bridge is currently using.
1992 
1993    @param This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
1994    @param Supported   A pointer to the mask of attributes that this PCI root bridge
1995                       supports setting with SetAttributes().
1996    @param Attributes  A pointer to the mask of attributes that this PCI root bridge is
1997                       currently using.
1998 
1999    @retval  EFI_SUCCESS           If Supports is not NULL, then the attributes that the PCI root
2000                                   bridge supports is returned in Supports. If Attributes is
2001                                   not NULL, then the attributes that the PCI root bridge is currently
2002                                   using is returned in Attributes.
2003    @retval  EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
2004 
2005 **/
2006 EFI_STATUS
2007 EFIAPI
RootBridgeIoGetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT UINT64 * Supported,OUT UINT64 * Attributes)2008 RootBridgeIoGetAttributes (
2009   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2010   OUT UINT64                           *Supported,
2011   OUT UINT64                           *Attributes
2012   )
2013 {
2014   PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
2015 
2016   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
2017 
2018   if (Attributes == NULL && Supported == NULL) {
2019     return EFI_INVALID_PARAMETER;
2020   }
2021 
2022   //
2023   // Set the return value for Supported and Attributes
2024   //
2025   if (Supported != NULL) {
2026     *Supported  = PrivateData->Supports;
2027   }
2028 
2029   if (Attributes != NULL) {
2030     *Attributes = PrivateData->Attributes;
2031   }
2032 
2033   return EFI_SUCCESS;
2034 }
2035 
2036 /**
2037    Sets attributes for a resource range on a PCI root bridge.
2038 
2039    The SetAttributes() function sets the attributes specified in Attributes for the PCI root
2040    bridge on the resource range specified by ResourceBase and ResourceLength. Since the
2041    granularity of setting these attributes may vary from resource type to resource type, and from
2042    platform to platform, the actual resource range and the one passed in by the caller may differ. As a
2043    result, this function may set the attributes specified by Attributes on a larger resource range
2044    than the caller requested. The actual range is returned in ResourceBase and
2045    ResourceLength. The caller is responsible for verifying that the actual range for which the
2046    attributes were set is acceptable.
2047 
2048    @param[in]       This            A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2049    @param[in]       Attributes      The mask of attributes to set. If the attribute bit
2050                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
2051                                     MEMORY_DISABLE is set, then the resource range is specified by
2052                                     ResourceBase and ResourceLength. If
2053                                     MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
2054                                     MEMORY_DISABLE are not set, then ResourceBase and
2055                                     ResourceLength are ignored, and may be NULL.
2056    @param[in, out]  ResourceBase    A pointer to the base address of the resource range to be modified
2057                                     by the attributes specified by Attributes.
2058    @param[in, out]  ResourceLength  A pointer to the length of the resource range to be modified by the
2059                                     attributes specified by Attributes.
2060 
2061    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
2062    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
2063    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
2064 
2065 **/
2066 EFI_STATUS
2067 EFIAPI
RootBridgeIoSetAttributes(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,IN UINT64 Attributes,IN OUT UINT64 * ResourceBase,IN OUT UINT64 * ResourceLength)2068 RootBridgeIoSetAttributes (
2069   IN     EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL  *This,
2070   IN     UINT64                           Attributes,
2071   IN OUT UINT64                           *ResourceBase,
2072   IN OUT UINT64                           *ResourceLength
2073   )
2074 {
2075   PCI_ROOT_BRIDGE_INSTANCE            *PrivateData;
2076 
2077   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
2078 
2079   if (Attributes != 0) {
2080     if ((Attributes & (~(PrivateData->Supports))) != 0) {
2081       return EFI_UNSUPPORTED;
2082     }
2083   }
2084 
2085   //
2086   // This is a generic driver for a PC-AT class system.  It does not have any
2087   // chipset specific knowlegde, so none of the attributes can be set or
2088   // cleared.  Any attempt to set attribute that are already set will succeed,
2089   // and any attempt to set an attribute that is not supported will fail.
2090   //
2091   if (Attributes & (~PrivateData->Attributes)) {
2092     return EFI_UNSUPPORTED;
2093   }
2094 
2095   return EFI_SUCCESS;
2096 }
2097 
2098 /**
2099    Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
2100    resource descriptors.
2101 
2102    There are only two resource descriptor types from the ACPI Specification that may be used to
2103    describe the current resources allocated to a PCI root bridge. These are the QWORD Address
2104    Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
2105    QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
2106    or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
2107    Address Space Descriptors followed by an End Tag.
2108 
2109    @param[in]   This        A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
2110    @param[out]  Resources   A pointer to the ACPI 2.0 resource descriptors that describe the
2111                             current configuration of this PCI root bridge. The storage for the
2112                             ACPI 2.0 resource descriptors is allocated by this function. The
2113                             caller must treat the return buffer as read-only data, and the buffer
2114                             must not be freed by the caller.
2115 
2116    @retval  EFI_SUCCESS     The current configuration of this PCI root bridge was returned in Resources.
2117    @retval  EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
2118    @retval  EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
2119 
2120 **/
2121 EFI_STATUS
2122 EFIAPI
RootBridgeIoConfiguration(IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,OUT VOID ** Resources)2123 RootBridgeIoConfiguration (
2124   IN  EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL     *This,
2125   OUT VOID                                **Resources
2126   )
2127 {
2128   PCI_ROOT_BRIDGE_INSTANCE              *PrivateData;
2129   UINTN                                 Index;
2130 
2131   PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
2132 
2133   for (Index = 0; Index < TypeMax; Index++) {
2134     if (PrivateData->ResAllocNode[Index].Status == ResAllocated) {
2135       Configuration.SpaceDesp[Index].AddrRangeMin = PrivateData->ResAllocNode[Index].Base;
2136       Configuration.SpaceDesp[Index].AddrRangeMax = PrivateData->ResAllocNode[Index].Base + PrivateData->ResAllocNode[Index].Length - 1;
2137       Configuration.SpaceDesp[Index].AddrLen      = PrivateData->ResAllocNode[Index].Length;
2138     }
2139   }
2140 
2141   *Resources = &Configuration;
2142   return EFI_SUCCESS;
2143 }
2144 
2145