Home | History | Annotate | Download | only in CpuRuntimeDxe
      1 /**@file
      2 
      3 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 Module Name:
     13 
     14   CpuIo.c
     15 
     16 Abstract:
     17 
     18   This is the code that publishes the CPU I/O Protocol.
     19   The intent herein is to have a single I/O service that can load
     20   as early as possible, extend into runtime, and be layered upon by
     21   the implementations of architectural protocols and the PCI Root
     22   Bridge I/O Protocol.
     23 
     24 **/
     25 
     26 #include <CpuDriver.h>
     27 
     28 #define IA32_MAX_IO_ADDRESS   0xFFFF
     29 #define IA32_MAX_MEM_ADDRESS  0xFFFFFFFF
     30 
     31 EFI_STATUS
     32 CpuIoCheckAddressRange (
     33   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
     34   IN  UINT64                            Address,
     35   IN  UINTN                             Count,
     36   IN  VOID                              *Buffer,
     37   IN  UINT64                            Limit
     38   );
     39 
     40 EFI_STATUS
     41 EFIAPI
     42 CpuMemoryServiceRead (
     43   IN  EFI_CPU_IO2_PROTOCOL              *This,
     44   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
     45   IN  UINT64                            Address,
     46   IN  UINTN                             Count,
     47   IN  OUT VOID                          *Buffer
     48   )
     49 /*++
     50 
     51 Routine Description:
     52 
     53   Perform the Memory Access Read service for the CPU I/O Protocol
     54 
     55 Arguments:
     56 
     57   Pointer to an instance of the CPU I/O Protocol
     58   Width of the Memory Access
     59   Address of the Memory access
     60   Count of the number of accesses to perform
     61   Pointer to the buffer to read or write from memory
     62 
     63 Returns:
     64 
     65   Status
     66 
     67   EFI_SUCCESS             - The data was read from or written to the EFI
     68                             System.
     69   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
     70   EFI_INVALID_PARAMETER   - Buffer is NULL.
     71   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
     72   EFI_UNSUPPORTED         - The address range specified by Address, Width,
     73                             and Count is not valid for this EFI System.
     74 
     75 --*/
     76 // TODO:    This - add argument and description to function comment
     77 {
     78   EFI_STATUS  Status;
     79 
     80   if (!Buffer) {
     81     return EFI_INVALID_PARAMETER;
     82   }
     83 
     84   if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
     85     return EFI_INVALID_PARAMETER;
     86   }
     87 
     88   Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
     89   if (EFI_ERROR (Status)) {
     90     return Status;
     91   }
     92 
     93   //
     94   // Do nothing for Nt32 version
     95   //
     96   return EFI_UNSUPPORTED;
     97 }
     98 
     99 EFI_STATUS
    100 EFIAPI
    101 CpuMemoryServiceWrite (
    102   IN EFI_CPU_IO2_PROTOCOL               *This,
    103   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
    104   IN  UINT64                            Address,
    105   IN  UINTN                             Count,
    106   IN  OUT VOID                          *Buffer
    107   )
    108 /*++
    109 
    110 Routine Description:
    111 
    112   Perform the Memory Access Read service for the CPU I/O Protocol
    113 
    114 Arguments:
    115 
    116   Pointer to an instance of the CPU I/O Protocol
    117   Width of the Memory Access
    118   Address of the Memory access
    119   Count of the number of accesses to perform
    120   Pointer to the buffer to read or write from memory
    121 
    122 Returns:
    123 
    124   Status
    125 
    126   EFI_SUCCESS             - The data was read from or written to the EFI System.
    127   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
    128   EFI_INVALID_PARAMETER   - Buffer is NULL.
    129   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
    130   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
    131                             Count is not valid for this EFI System.
    132 
    133 --*/
    134 // TODO:    This - add argument and description to function comment
    135 {
    136   EFI_STATUS  Status;
    137 
    138   if (!Buffer) {
    139     return EFI_INVALID_PARAMETER;
    140   }
    141 
    142   if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
    143     return EFI_INVALID_PARAMETER;
    144   }
    145 
    146   Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS);
    147   if (EFI_ERROR (Status)) {
    148     return Status;
    149   }
    150 
    151   //
    152   // Do nothing for Nt32 version
    153   //
    154   return EFI_UNSUPPORTED;
    155 }
    156 
    157 EFI_STATUS
    158 EFIAPI
    159 CpuIoServiceRead (
    160   IN EFI_CPU_IO2_PROTOCOL               *This,
    161   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
    162   IN  UINT64                            UserAddress,
    163   IN  UINTN                             Count,
    164   IN  OUT VOID                          *UserBuffer
    165   )
    166 /*++
    167 
    168 Routine Description:
    169 
    170   This is the service that implements the I/O read
    171 
    172 Arguments:
    173 
    174   Pointer to an instance of the CPU I/O Protocol
    175   Width of the Memory Access
    176   Address of the I/O access
    177   Count of the number of accesses to perform
    178   Pointer to the buffer to read or write from I/O space
    179 
    180 Returns:
    181 
    182   Status
    183   EFI_SUCCESS             - The data was read from or written to the EFI System.
    184   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
    185   EFI_INVALID_PARAMETER   - Buffer is NULL.
    186   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
    187   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
    188                             Count is not valid for this EFI System.
    189 --*/
    190 // TODO:    This - add argument and description to function comment
    191 // TODO:    UserAddress - add argument and description to function comment
    192 // TODO:    UserBuffer - add argument and description to function comment
    193 {
    194   UINTN       Address;
    195   EFI_STATUS  Status;
    196 
    197   if (!UserBuffer) {
    198     return EFI_INVALID_PARAMETER;
    199   }
    200 
    201   Address = (UINTN) UserAddress;
    202 
    203   if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
    204     return EFI_INVALID_PARAMETER;
    205   }
    206 
    207   Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
    208   if (EFI_ERROR (Status)) {
    209     return Status;
    210   }
    211 
    212   //
    213   // Do nothing for Nt32 version
    214   //
    215   return EFI_UNSUPPORTED;
    216 }
    217 
    218 EFI_STATUS
    219 EFIAPI
    220 CpuIoServiceWrite (
    221   IN EFI_CPU_IO2_PROTOCOL               *This,
    222   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
    223   IN  UINT64                            UserAddress,
    224   IN  UINTN                             Count,
    225   IN  OUT VOID                          *UserBuffer
    226   )
    227 /*++
    228 
    229 Routine Description:
    230 
    231 
    232   This is the service that implements the I/O Write
    233 
    234 Arguments:
    235 
    236   Pointer to an instance of the CPU I/O Protocol
    237   Width of the Memory Access
    238   Address of the I/O access
    239   Count of the number of accesses to perform
    240   Pointer to the buffer to read or write from I/O space
    241 
    242 Returns:
    243 
    244   Status
    245 
    246   Status
    247   EFI_SUCCESS             - The data was read from or written to the EFI System.
    248   EFI_INVALID_PARAMETER   - Width is invalid for this EFI System.
    249   EFI_INVALID_PARAMETER   - Buffer is NULL.
    250   EFI_UNSUPPORTED         - The Buffer is not aligned for the given Width.
    251   EFI_UNSUPPORTED         - The address range specified by Address, Width, and
    252                             Count is not valid for this EFI System.
    253 
    254 --*/
    255 // TODO:    This - add argument and description to function comment
    256 // TODO:    UserAddress - add argument and description to function comment
    257 // TODO:    UserBuffer - add argument and description to function comment
    258 {
    259   UINTN       Address;
    260   EFI_STATUS  Status;
    261 
    262   if (!UserBuffer) {
    263     return EFI_INVALID_PARAMETER;
    264   }
    265 
    266   Address = (UINTN) UserAddress;
    267 
    268   if ((Width < 0) || (Width >= EfiCpuIoWidthMaximum)) {
    269     return EFI_INVALID_PARAMETER;
    270   }
    271 
    272   Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS);
    273   if (EFI_ERROR (Status)) {
    274     return Status;
    275   }
    276 
    277   //
    278   // Do nothing for Nt32 version
    279   //
    280   return EFI_UNSUPPORTED;
    281 }
    282 
    283 
    284 EFI_STATUS
    285 CpuIoCheckAddressRange (
    286   IN  EFI_CPU_IO_PROTOCOL_WIDTH         Width,
    287   IN  UINT64                            Address,
    288   IN  UINTN                             Count,
    289   IN  VOID                              *Buffer,
    290   IN  UINT64                            Limit
    291   )
    292 /*++
    293 
    294 Routine Description:
    295 
    296   TODO: Add function description
    297 
    298 Arguments:
    299 
    300   Width   - TODO: add argument description
    301   Address - TODO: add argument description
    302   Count   - TODO: add argument description
    303   Buffer  - TODO: add argument description
    304   Limit   - TODO: add argument description
    305 
    306 Returns:
    307 
    308   EFI_UNSUPPORTED - TODO: Add description for return value
    309   EFI_UNSUPPORTED - TODO: Add description for return value
    310   EFI_UNSUPPORTED - TODO: Add description for return value
    311   EFI_SUCCESS - TODO: Add description for return value
    312 
    313 --*/
    314 {
    315   UINTN AlignMask;
    316 
    317   if (Address > Limit) {
    318     return EFI_UNSUPPORTED;
    319   }
    320 
    321   //
    322   // For FiFo type, the target address won't increase during the access, so treat count as 1
    323   //
    324   if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) {
    325     Count = 1;
    326   }
    327 
    328   Width = (EFI_CPU_IO_PROTOCOL_WIDTH)(Width & 0x03);
    329   if (Address - 1 + ((UINTN)1 << Width) * Count > Limit) {
    330     return EFI_UNSUPPORTED;
    331   }
    332 
    333   AlignMask = ((UINTN)1 << Width) - 1;
    334   if ((UINTN) Buffer & AlignMask) {
    335     return EFI_UNSUPPORTED;
    336   }
    337 
    338   return EFI_SUCCESS;
    339 }
    340 
    341 
    342