Home | History | Annotate | Download | only in CpuIoPei
      1 /** @file
      2   Produces the CPU I/O PPI.
      3 
      4 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are 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 "CpuIoPei.h"
     16 
     17 //
     18 // Instance of CPU I/O PPI
     19 //
     20 EFI_PEI_CPU_IO_PPI  gCpuIoPpi = {
     21   {
     22     CpuMemoryServiceRead,
     23     CpuMemoryServiceWrite
     24   },
     25   {
     26     CpuIoServiceRead,
     27     CpuIoServiceWrite
     28   },
     29   CpuIoRead8,
     30   CpuIoRead16,
     31   CpuIoRead32,
     32   CpuIoRead64,
     33   CpuIoWrite8,
     34   CpuIoWrite16,
     35   CpuIoWrite32,
     36   CpuIoWrite64,
     37   CpuMemRead8,
     38   CpuMemRead16,
     39   CpuMemRead32,
     40   CpuMemRead64,
     41   CpuMemWrite8,
     42   CpuMemWrite16,
     43   CpuMemWrite32,
     44   CpuMemWrite64
     45 };
     46 
     47 //
     48 // PPI Descriptor used to install the CPU I/O PPI
     49 //
     50 EFI_PEI_PPI_DESCRIPTOR gPpiList = {
     51   (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
     52   &gEfiPeiCpuIoPpiInstalledGuid,
     53   NULL
     54 };
     55 
     56 //
     57 // Lookup table for increment values based on transfer widths
     58 //
     59 UINT8 mInStride[] = {
     60   1, // EfiPeiCpuIoWidthUint8
     61   2, // EfiPeiCpuIoWidthUint16
     62   4, // EfiPeiCpuIoWidthUint32
     63   8, // EfiPeiCpuIoWidthUint64
     64   0, // EfiPeiCpuIoWidthFifoUint8
     65   0, // EfiPeiCpuIoWidthFifoUint16
     66   0, // EfiPeiCpuIoWidthFifoUint32
     67   0, // EfiPeiCpuIoWidthFifoUint64
     68   1, // EfiPeiCpuIoWidthFillUint8
     69   2, // EfiPeiCpuIoWidthFillUint16
     70   4, // EfiPeiCpuIoWidthFillUint32
     71   8  // EfiPeiCpuIoWidthFillUint64
     72 };
     73 
     74 //
     75 // Lookup table for increment values based on transfer widths
     76 //
     77 UINT8 mOutStride[] = {
     78   1, // EfiPeiCpuIoWidthUint8
     79   2, // EfiPeiCpuIoWidthUint16
     80   4, // EfiPeiCpuIoWidthUint32
     81   8, // EfiPeiCpuIoWidthUint64
     82   1, // EfiPeiCpuIoWidthFifoUint8
     83   2, // EfiPeiCpuIoWidthFifoUint16
     84   4, // EfiPeiCpuIoWidthFifoUint32
     85   8, // EfiPeiCpuIoWidthFifoUint64
     86   0, // EfiPeiCpuIoWidthFillUint8
     87   0, // EfiPeiCpuIoWidthFillUint16
     88   0, // EfiPeiCpuIoWidthFillUint32
     89   0  // EfiPeiCpuIoWidthFillUint64
     90 };
     91 
     92 /**
     93   Check parameters to a CPU I/O PPI service request.
     94 
     95   @param[in]  MmioOperation  TRUE for an MMIO operation, FALSE for I/O Port operation.
     96   @param[in]  Width          The width of the access. Enumerated in bytes.
     97   @param[in]  Address        The physical address of the access.
     98   @param[in]  Count          The number of accesses to perform.
     99   @param[in]  Buffer         A pointer to the buffer of data.
    100 
    101   @retval EFI_SUCCESS            The parameters for this request pass the checks.
    102   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
    103   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
    104   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
    105                                  and Count is not valid for this EFI system.
    106 
    107 **/
    108 EFI_STATUS
    109 CpuIoCheckParameter (
    110   IN BOOLEAN                   MmioOperation,
    111   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
    112   IN UINT64                    Address,
    113   IN UINTN                     Count,
    114   IN VOID                      *Buffer
    115   )
    116 {
    117   UINT64  MaxCount;
    118   UINT64  Limit;
    119 
    120   //
    121   // Check to see if Buffer is NULL
    122   //
    123   if (Buffer == NULL) {
    124     return EFI_INVALID_PARAMETER;
    125   }
    126 
    127   //
    128   // Check to see if Width is in the valid range
    129   //
    130   if ((UINT32)Width >= EfiPeiCpuIoWidthMaximum) {
    131     return EFI_INVALID_PARAMETER;
    132   }
    133 
    134   //
    135   // For FIFO type, the target address won't increase during the access,
    136   // so treat Count as 1
    137   //
    138   if (Width >= EfiPeiCpuIoWidthFifoUint8 && Width <= EfiPeiCpuIoWidthFifoUint64) {
    139     Count = 1;
    140   }
    141 
    142   //
    143   // Check to see if Width is in the valid range for I/O Port operations
    144   //
    145   Width = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
    146   if (!MmioOperation && (Width == EfiPeiCpuIoWidthUint64)) {
    147     return EFI_INVALID_PARAMETER;
    148   }
    149 
    150   //
    151   // Check to see if any address associated with this transfer exceeds the maximum
    152   // allowed address.  The maximum address implied by the parameters passed in is
    153   // Address + Size * Count.  If the following condition is met, then the transfer
    154   // is not supported.
    155   //
    156   //    Address + Size * Count > (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS) + 1
    157   //
    158   // Since MAX_ADDRESS can be the maximum integer value supported by the CPU and Count
    159   // can also be the maximum integer value supported by the CPU, this range
    160   // check must be adjusted to avoid all overflow conditions.
    161   //
    162   // The following form of the range check is equivalent but assumes that
    163   // MAX_ADDRESS and MAX_IO_PORT_ADDRESS are of the form (2^n - 1).
    164   //
    165   Limit = (MmioOperation ? MAX_ADDRESS : MAX_IO_PORT_ADDRESS);
    166   if (Count == 0) {
    167     if (Address > Limit) {
    168       return EFI_UNSUPPORTED;
    169     }
    170   } else {
    171     MaxCount = RShiftU64 (Limit, Width);
    172     if (MaxCount < (Count - 1)) {
    173       return EFI_UNSUPPORTED;
    174     }
    175     if (Address > LShiftU64 (MaxCount - Count + 1, Width)) {
    176       return EFI_UNSUPPORTED;
    177     }
    178   }
    179 
    180   return EFI_SUCCESS;
    181 }
    182 
    183 /**
    184   Reads memory-mapped registers.
    185 
    186   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
    187                            published by the PEI Foundation.
    188   @param[in]  This         Pointer to local data for the interface.
    189   @param[in]  Width        The width of the access. Enumerated in bytes.
    190   @param[in]  Address      The physical address of the access.
    191   @param[in]  Count        The number of accesses to perform.
    192   @param[out] Buffer       A pointer to the buffer of data.
    193 
    194   @retval EFI_SUCCESS            The function completed successfully.
    195   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
    196   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
    197   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
    198                                  and Count is not valid for this EFI system.
    199 
    200 **/
    201 EFI_STATUS
    202 EFIAPI
    203 CpuMemoryServiceRead (
    204   IN  CONST EFI_PEI_SERVICES    **PeiServices,
    205   IN  CONST EFI_PEI_CPU_IO_PPI  *This,
    206   IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
    207   IN  UINT64                    Address,
    208   IN  UINTN                     Count,
    209   OUT VOID                      *Buffer
    210   )
    211 {
    212   EFI_STATUS                Status;
    213   UINT8                     InStride;
    214   UINT8                     OutStride;
    215   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
    216   BOOLEAN                   Aligned;
    217   UINT8                     *Uint8Buffer;
    218 
    219   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
    220   if (EFI_ERROR (Status)) {
    221     return Status;
    222   }
    223 
    224   //
    225   // Select loop based on the width of the transfer
    226   //
    227   InStride = mInStride[Width];
    228   OutStride = mOutStride[Width];
    229   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
    230   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
    231   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    232     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
    233       *Uint8Buffer = MmioRead8 ((UINTN)Address);
    234     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
    235       if (Aligned) {
    236         *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
    237       } else {
    238         WriteUnaligned16 ((UINT16 *)Uint8Buffer, MmioRead16 ((UINTN)Address));
    239       }
    240     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
    241       if (Aligned) {
    242         *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
    243       } else {
    244         WriteUnaligned32 ((UINT32 *)Uint8Buffer, MmioRead32 ((UINTN)Address));
    245       }
    246     } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
    247       if (Aligned) {
    248         *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
    249       } else {
    250         WriteUnaligned64 ((UINT64 *)Uint8Buffer, MmioRead64 ((UINTN)Address));
    251       }
    252     }
    253   }
    254   return EFI_SUCCESS;
    255 }
    256 
    257 /**
    258   Writes memory-mapped registers.
    259 
    260   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
    261                            published by the PEI Foundation.
    262   @param[in]  This         Pointer to local data for the interface.
    263   @param[in]  Width        The width of the access. Enumerated in bytes.
    264   @param[in]  Address      The physical address of the access.
    265   @param[in]  Count        The number of accesses to perform.
    266   @param[in]  Buffer       A pointer to the buffer of data.
    267 
    268   @retval EFI_SUCCESS            The function completed successfully.
    269   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
    270   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
    271   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
    272                                  and Count is not valid for this EFI system.
    273 
    274 **/
    275 EFI_STATUS
    276 EFIAPI
    277 CpuMemoryServiceWrite (
    278   IN CONST EFI_PEI_SERVICES    **PeiServices,
    279   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    280   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
    281   IN UINT64                    Address,
    282   IN UINTN                     Count,
    283   IN VOID                      *Buffer
    284   )
    285 {
    286   EFI_STATUS                Status;
    287   UINT8                     InStride;
    288   UINT8                     OutStride;
    289   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
    290   BOOLEAN                   Aligned;
    291   UINT8                     *Uint8Buffer;
    292 
    293   Status = CpuIoCheckParameter (TRUE, Width, Address, Count, Buffer);
    294   if (EFI_ERROR (Status)) {
    295     return Status;
    296   }
    297 
    298   //
    299   // Select loop based on the width of the transfer
    300   //
    301   InStride = mInStride[Width];
    302   OutStride = mOutStride[Width];
    303   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
    304   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
    305   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    306     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
    307       MmioWrite8 ((UINTN)Address, *Uint8Buffer);
    308     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
    309       if (Aligned) {
    310         MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
    311       } else {
    312         MmioWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
    313       }
    314     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
    315       if (Aligned) {
    316         MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
    317       } else {
    318         MmioWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
    319       }
    320     } else if (OperationWidth == EfiPeiCpuIoWidthUint64) {
    321       if (Aligned) {
    322         MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
    323       } else {
    324         MmioWrite64 ((UINTN)Address, ReadUnaligned64 ((UINT64 *)Uint8Buffer));
    325       }
    326     }
    327   }
    328   return EFI_SUCCESS;
    329 }
    330 
    331 /**
    332   Reads I/O registers.
    333 
    334   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
    335                            published by the PEI Foundation.
    336   @param[in]  This         Pointer to local data for the interface.
    337   @param[in]  Width        The width of the access. Enumerated in bytes.
    338   @param[in]  Address      The physical address of the access.
    339   @param[in]  Count        The number of accesses to perform.
    340   @param[out] Buffer       A pointer to the buffer of data.
    341 
    342   @retval EFI_SUCCESS            The function completed successfully.
    343   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
    344   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
    345   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
    346                                  and Count is not valid for this EFI system.
    347 
    348 **/
    349 EFI_STATUS
    350 EFIAPI
    351 CpuIoServiceRead (
    352   IN  CONST EFI_PEI_SERVICES    **PeiServices,
    353   IN  CONST EFI_PEI_CPU_IO_PPI  *This,
    354   IN  EFI_PEI_CPU_IO_PPI_WIDTH  Width,
    355   IN  UINT64                    Address,
    356   IN  UINTN                     Count,
    357   OUT VOID                      *Buffer
    358   )
    359 {
    360   EFI_STATUS                Status;
    361   UINT8                     InStride;
    362   UINT8                     OutStride;
    363   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
    364   BOOLEAN                   Aligned;
    365   UINT8                     *Uint8Buffer;
    366 
    367   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
    368   if (EFI_ERROR (Status)) {
    369     return Status;
    370   }
    371 
    372   //
    373   // Select loop based on the width of the transfer
    374   //
    375   InStride = mInStride[Width];
    376   OutStride = mOutStride[Width];
    377   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
    378   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
    379   for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    380     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
    381       *Uint8Buffer = IoRead8 ((UINTN)Address);
    382     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
    383       if (Aligned) {
    384         *((UINT16 *)Uint8Buffer) = IoRead16 ((UINTN)Address);
    385       } else {
    386         WriteUnaligned16 ((UINT16 *)Uint8Buffer, IoRead16 ((UINTN)Address));
    387       }
    388     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
    389       if (Aligned) {
    390         *((UINT32 *)Uint8Buffer) = IoRead32 ((UINTN)Address);
    391       } else {
    392         WriteUnaligned32 ((UINT32 *)Uint8Buffer, IoRead32 ((UINTN)Address));
    393       }
    394     }
    395   }
    396 
    397   return EFI_SUCCESS;
    398 }
    399 
    400 /**
    401   Write I/O registers.
    402 
    403   @param[in]  PeiServices  An indirect pointer to the PEI Services Table
    404                            published by the PEI Foundation.
    405   @param[in]  This         Pointer to local data for the interface.
    406   @param[in]  Width        The width of the access. Enumerated in bytes.
    407   @param[in]  Address      The physical address of the access.
    408   @param[in]  Count        The number of accesses to perform.
    409   @param[in]  Buffer       A pointer to the buffer of data.
    410 
    411   @retval EFI_SUCCESS            The function completed successfully.
    412   @retval EFI_INVALID_PARAMETER  Width is invalid for this EFI system.
    413   @retval EFI_INVALID_PARAMETER  Buffer is NULL.
    414   @retval EFI_UNSUPPORTED        The address range specified by Address, Width,
    415                                  and Count is not valid for this EFI system.
    416 
    417 **/
    418 EFI_STATUS
    419 EFIAPI
    420 CpuIoServiceWrite (
    421   IN CONST EFI_PEI_SERVICES    **PeiServices,
    422   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    423   IN EFI_PEI_CPU_IO_PPI_WIDTH  Width,
    424   IN UINT64                    Address,
    425   IN UINTN                     Count,
    426   IN VOID                      *Buffer
    427   )
    428 {
    429   EFI_STATUS                Status;
    430   UINT8                     InStride;
    431   UINT8                     OutStride;
    432   EFI_PEI_CPU_IO_PPI_WIDTH  OperationWidth;
    433   BOOLEAN                   Aligned;
    434   UINT8                     *Uint8Buffer;
    435 
    436   //
    437   // Make sure the parameters are valid
    438   //
    439   Status = CpuIoCheckParameter (FALSE, Width, Address, Count, Buffer);
    440   if (EFI_ERROR (Status)) {
    441     return Status;
    442   }
    443 
    444   //
    445   // Select loop based on the width of the transfer
    446   //
    447   InStride = mInStride[Width];
    448   OutStride = mOutStride[Width];
    449   OperationWidth = (EFI_PEI_CPU_IO_PPI_WIDTH) (Width & 0x03);
    450   Aligned = (BOOLEAN)(((UINTN)Buffer & (mInStride[OperationWidth] - 1)) == 0x00);
    451   for (Uint8Buffer = (UINT8 *)Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
    452     if (OperationWidth == EfiPeiCpuIoWidthUint8) {
    453       IoWrite8 ((UINTN)Address, *Uint8Buffer);
    454     } else if (OperationWidth == EfiPeiCpuIoWidthUint16) {
    455       if (Aligned) {
    456         IoWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
    457       } else {
    458         IoWrite16 ((UINTN)Address, ReadUnaligned16 ((UINT16 *)Uint8Buffer));
    459       }
    460     } else if (OperationWidth == EfiPeiCpuIoWidthUint32) {
    461       if (Aligned) {
    462         IoWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
    463       } else {
    464         IoWrite32 ((UINTN)Address, ReadUnaligned32 ((UINT32 *)Uint8Buffer));
    465       }
    466     }
    467   }
    468 
    469   return EFI_SUCCESS;
    470 }
    471 
    472 /**
    473   8-bit I/O read operations.
    474 
    475   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    476                           by the PEI Foundation.
    477   @param[in] This         Pointer to local data for the interface.
    478   @param[in] Address      The physical address of the access.
    479 
    480   @return  An 8-bit value returned from the I/O space.
    481 **/
    482 UINT8
    483 EFIAPI
    484 CpuIoRead8 (
    485   IN CONST EFI_PEI_SERVICES    **PeiServices,
    486   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    487   IN UINT64                    Address
    488   )
    489 {
    490   return IoRead8 ((UINTN)Address);
    491 }
    492 
    493 /**
    494   16-bit I/O read operations.
    495 
    496   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    497                           by the PEI Foundation.
    498   @param[in] This         Pointer to local data for the interface.
    499   @param[in] Address      The physical address of the access.
    500 
    501   @return  A 16-bit value returned from the I/O space.
    502 
    503 **/
    504 UINT16
    505 EFIAPI
    506 CpuIoRead16 (
    507   IN CONST EFI_PEI_SERVICES    **PeiServices,
    508   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    509   IN UINT64                    Address
    510   )
    511 {
    512   return IoRead16 ((UINTN)Address);
    513 }
    514 
    515 /**
    516   32-bit I/O read operations.
    517 
    518   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    519                           by the PEI Foundation.
    520   @param[in] This         Pointer to local data for the interface.
    521   @param[in] Address      The physical address of the access.
    522 
    523   @return  A 32-bit value returned from the I/O space.
    524 
    525 **/
    526 UINT32
    527 EFIAPI
    528 CpuIoRead32 (
    529   IN CONST EFI_PEI_SERVICES     **PeiServices,
    530   IN CONST EFI_PEI_CPU_IO_PPI   *This,
    531   IN UINT64                     Address
    532   )
    533 {
    534   return IoRead32 ((UINTN)Address);
    535 }
    536 
    537 /**
    538   64-bit I/O read operations.
    539 
    540   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    541                           by the PEI Foundation.
    542   @param[in] This         Pointer to local data for the interface.
    543   @param[in] Address      The physical address of the access.
    544 
    545   @return  A 64-bit value returned from the I/O space.
    546 
    547 **/
    548 UINT64
    549 EFIAPI
    550 CpuIoRead64 (
    551   IN CONST EFI_PEI_SERVICES    **PeiServices,
    552   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    553   IN UINT64                    Address
    554   )
    555 {
    556   return IoRead64 ((UINTN)Address);
    557 }
    558 
    559 /**
    560   8-bit I/O write operations.
    561 
    562   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    563                           by the PEI Foundation.
    564   @param[in] This         Pointer to local data for the interface.
    565   @param[in] Address      The physical address of the access.
    566   @param[in] Data         The data to write.
    567 
    568 **/
    569 VOID
    570 EFIAPI
    571 CpuIoWrite8 (
    572   IN CONST EFI_PEI_SERVICES    **PeiServices,
    573   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    574   IN UINT64                    Address,
    575   IN UINT8                     Data
    576   )
    577 {
    578   IoWrite8 ((UINTN)Address, Data);
    579 }
    580 
    581 /**
    582   16-bit I/O write operations.
    583 
    584   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    585                           by the PEI Foundation.
    586   @param[in] This         Pointer to local data for the interface.
    587   @param[in] Address      The physical address of the access.
    588   @param[in] Data         The data to write.
    589 
    590 **/
    591 VOID
    592 EFIAPI
    593 CpuIoWrite16 (
    594   IN CONST EFI_PEI_SERVICES    **PeiServices,
    595   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    596   IN UINT64                    Address,
    597   IN UINT16                    Data
    598   )
    599 {
    600   IoWrite16 ((UINTN)Address, Data);
    601 }
    602 
    603 /**
    604   32-bit I/O write operations.
    605 
    606   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    607                           by the PEI Foundation.
    608   @param[in] This         Pointer to local data for the interface.
    609   @param[in] Address      The physical address of the access.
    610   @param[in] Data         The data to write.
    611 
    612 **/
    613 VOID
    614 EFIAPI
    615 CpuIoWrite32 (
    616   IN CONST EFI_PEI_SERVICES    **PeiServices,
    617   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    618   IN UINT64                    Address,
    619   IN UINT32                    Data
    620   )
    621 {
    622   IoWrite32 ((UINTN)Address, Data);
    623 }
    624 
    625 /**
    626   64-bit I/O write operations.
    627 
    628   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    629                           by the PEI Foundation.
    630   @param[in] This         Pointer to local data for the interface.
    631   @param[in] Address      The physical address of the access.
    632   @param[in] Data         The data to write.
    633 
    634 **/
    635 VOID
    636 EFIAPI
    637 CpuIoWrite64 (
    638   IN CONST EFI_PEI_SERVICES    **PeiServices,
    639   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    640   IN UINT64                    Address,
    641   IN UINT64                    Data
    642   )
    643 {
    644   IoWrite64 ((UINTN)Address, Data);
    645 }
    646 
    647 /**
    648   8-bit memory read operations.
    649 
    650   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    651                           by the PEI Foundation.
    652   @param[in] This         Pointer to local data for the interface.
    653   @param[in] Address      The physical address of the access.
    654 
    655   @return  An 8-bit value returned from the memory space.
    656 
    657 **/
    658 UINT8
    659 EFIAPI
    660 CpuMemRead8 (
    661   IN CONST EFI_PEI_SERVICES    **PeiServices,
    662   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    663   IN UINT64                    Address
    664   )
    665 {
    666   return MmioRead8 ((UINTN)Address);
    667 }
    668 
    669 /**
    670   16-bit memory read operations.
    671 
    672   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    673                           by the PEI Foundation.
    674   @param[in] This         Pointer to local data for the interface.
    675   @param[in] Address      The physical address of the access.
    676 
    677   @return  A 16-bit value returned from the memory space.
    678 
    679 **/
    680 UINT16
    681 EFIAPI
    682 CpuMemRead16 (
    683   IN CONST EFI_PEI_SERVICES    **PeiServices,
    684   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    685   IN UINT64                    Address
    686   )
    687 {
    688   return MmioRead16 ((UINTN)Address);
    689 }
    690 
    691 /**
    692   32-bit memory read operations.
    693 
    694   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    695                           by the PEI Foundation.
    696   @param[in] This         Pointer to local data for the interface.
    697   @param[in] Address      The physical address of the access.
    698 
    699   @return  A 32-bit value returned from the memory space.
    700 
    701 **/
    702 UINT32
    703 EFIAPI
    704 CpuMemRead32 (
    705   IN CONST EFI_PEI_SERVICES    **PeiServices,
    706   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    707   IN UINT64                    Address
    708   )
    709 {
    710   return MmioRead32 ((UINTN)Address);
    711 }
    712 
    713 /**
    714   64-bit memory read operations.
    715 
    716   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    717                           by the PEI Foundation.
    718   @param[in] This         Pointer to local data for the interface.
    719   @param[in] Address      The physical address of the access.
    720 
    721   @return  A 64-bit value returned from the memory space.
    722 
    723 **/
    724 UINT64
    725 EFIAPI
    726 CpuMemRead64 (
    727   IN CONST EFI_PEI_SERVICES    **PeiServices,
    728   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    729   IN UINT64                    Address
    730   )
    731 {
    732   return MmioRead64 ((UINTN)Address);
    733 }
    734 
    735 /**
    736   8-bit memory write operations.
    737 
    738   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    739                           by the PEI Foundation.
    740   @param[in] This         Pointer to local data for the interface.
    741   @param[in] Address      The physical address of the access.
    742   @param[in] Data         The data to write.
    743 
    744 **/
    745 VOID
    746 EFIAPI
    747 CpuMemWrite8 (
    748   IN CONST EFI_PEI_SERVICES    **PeiServices,
    749   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    750   IN UINT64                    Address,
    751   IN  UINT8                    Data
    752   )
    753 {
    754   MmioWrite8 ((UINTN)Address, Data);
    755 }
    756 
    757 /**
    758   16-bit memory write operations.
    759 
    760   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    761                           by the PEI Foundation.
    762   @param[in] This         Pointer to local data for the interface.
    763   @param[in] Address      The physical address of the access.
    764   @param[in] Data         The data to write.
    765 
    766 **/
    767 VOID
    768 EFIAPI
    769 CpuMemWrite16 (
    770   IN CONST EFI_PEI_SERVICES    **PeiServices,
    771   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    772   IN UINT64                    Address,
    773   IN UINT16                    Data
    774   )
    775 {
    776   MmioWrite16 ((UINTN)Address, Data);
    777 }
    778 
    779 /**
    780   32-bit memory write operations.
    781 
    782   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    783                           by the PEI Foundation.
    784   @param[in] This         Pointer to local data for the interface.
    785   @param[in] Address      The physical address of the access.
    786   @param[in] Data         The data to write.
    787 
    788 **/
    789 VOID
    790 EFIAPI
    791 CpuMemWrite32 (
    792   IN CONST EFI_PEI_SERVICES    **PeiServices,
    793   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    794   IN UINT64                    Address,
    795   IN UINT32                    Data
    796   )
    797 {
    798   MmioWrite32 ((UINTN)Address, Data);
    799 }
    800 
    801 /**
    802   64-bit memory write operations.
    803 
    804   @param[in] PeiServices  An indirect pointer to the PEI Services Table published
    805                           by the PEI Foundation.
    806   @param[in] This         Pointer to local data for the interface.
    807   @param[in] Address      The physical address of the access.
    808   @param[in] Data         The data to write.
    809 
    810 **/
    811 VOID
    812 EFIAPI
    813 CpuMemWrite64 (
    814   IN CONST EFI_PEI_SERVICES    **PeiServices,
    815   IN CONST EFI_PEI_CPU_IO_PPI  *This,
    816   IN UINT64                    Address,
    817   IN UINT64                    Data
    818   )
    819 {
    820   MmioWrite64 ((UINTN)Address, Data);
    821 }
    822 
    823 /**
    824   The Entry point of the CPU I/O PEIM
    825 
    826   This function is the Entry point of the CPU I/O PEIM which installs CpuIoPpi.
    827 
    828   @param[in]  FileHandle   Pointer to image file handle.
    829   @param[in]  PeiServices  Pointer to PEI Services Table
    830 
    831   @retval EFI_SUCCESS  CPU I/O PPI successfully installed
    832 
    833 **/
    834 EFI_STATUS
    835 EFIAPI
    836 CpuIoInitialize (
    837   IN EFI_PEI_FILE_HANDLE     FileHandle,
    838   IN CONST EFI_PEI_SERVICES  **PeiServices
    839   )
    840 {
    841   EFI_STATUS  Status;
    842 
    843   //
    844   // Register so it will be automatically shadowed to memory
    845   //
    846   Status = PeiServicesRegisterForShadow (FileHandle);
    847 
    848   //
    849   // Make CpuIo pointer in PeiService table point to gCpuIoPpi
    850   //
    851   (*((EFI_PEI_SERVICES **)PeiServices))->CpuIo = &gCpuIoPpi;
    852 
    853   if (Status == EFI_ALREADY_STARTED) {
    854     //
    855     // Shadow completed and running from memory
    856     //
    857     DEBUG ((EFI_D_INFO, "CpuIO PPI has been loaded into memory.  Reinstalled PPI=0x%x\n", &gCpuIoPpi));
    858   } else {
    859     Status = PeiServicesInstallPpi (&gPpiList);
    860     ASSERT_EFI_ERROR (Status);
    861   }
    862 
    863   return EFI_SUCCESS;
    864 }
    865