Home | History | Annotate | Download | only in QemuFwCfgLib
      1 /** @file
      2 
      3   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
      4   Copyright (C) 2013, Red Hat, Inc.
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "Uefi.h"
     17 #include <Library/BaseLib.h>
     18 #include <Library/BaseMemoryLib.h>
     19 #include <Library/DebugLib.h>
     20 #include <Library/IoLib.h>
     21 #include <Library/QemuFwCfgLib.h>
     22 #include <Library/MemoryAllocationLib.h>
     23 #include <Library/UefiBootServicesTableLib.h>
     24 
     25 #include "QemuFwCfgLibInternal.h"
     26 
     27 
     28 /**
     29   Reads an 8-bit I/O port fifo into a block of memory.
     30 
     31   Reads the 8-bit I/O fifo port specified by Port.
     32 
     33   The port is read Count times, and the read data is
     34   stored in the provided Buffer.
     35 
     36   This function must guarantee that all I/O read and write operations are
     37   serialized.
     38 
     39   If 8-bit I/O port operations are not supported, then ASSERT().
     40 
     41   @param  Port    The I/O port to read.
     42   @param  Count   The number of times to read I/O port.
     43   @param  Buffer  The buffer to store the read data into.
     44 
     45 **/
     46 VOID
     47 EFIAPI
     48 IoReadFifo8 (
     49   IN      UINTN                     Port,
     50   IN      UINTN                     Count,
     51   OUT     VOID                      *Buffer
     52   );
     53 
     54 /**
     55   Writes an 8-bit I/O port fifo from a block of memory.
     56 
     57   Writes the 8-bit I/O fifo port specified by Port.
     58 
     59   The port is written Count times, and the data are obtained
     60   from the provided Buffer.
     61 
     62   This function must guarantee that all I/O read and write operations are
     63   serialized.
     64 
     65   If 8-bit I/O port operations are not supported, then ASSERT().
     66 
     67   @param  Port    The I/O port to read.
     68   @param  Count   The number of times to read I/O port.
     69   @param  Buffer  The buffer to store the read data into.
     70 
     71 **/
     72 VOID
     73 EFIAPI
     74 IoWriteFifo8 (
     75   IN      UINTN                     Port,
     76   IN      UINTN                     Count,
     77   OUT     VOID                      *Buffer
     78   );
     79 
     80 
     81 /**
     82   Selects a firmware configuration item for reading.
     83 
     84   Following this call, any data read from this item will start from
     85   the beginning of the configuration item's data.
     86 
     87   @param[in] QemuFwCfgItem - Firmware Configuration item to read
     88 
     89 **/
     90 VOID
     91 EFIAPI
     92 QemuFwCfgSelectItem (
     93   IN FIRMWARE_CONFIG_ITEM   QemuFwCfgItem
     94   )
     95 {
     96   DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem));
     97   IoWrite16 (0x510, (UINT16)(UINTN) QemuFwCfgItem);
     98 }
     99 
    100 
    101 /**
    102   Transfer an array of bytes using the DMA interface.
    103 
    104   @param[in]     Size    Size in bytes to transfer.
    105   @param[in,out] Buffer  Buffer to read data into or write data from. May be
    106                          NULL if Size is zero.
    107   @param[in]     Write   TRUE if writing to fw_cfg from Buffer, FALSE if
    108                          reading from fw_cfg into Buffer.
    109 **/
    110 VOID
    111 InternalQemuFwCfgDmaBytes (
    112   IN     UINT32   Size,
    113   IN OUT VOID     *Buffer OPTIONAL,
    114   IN     BOOLEAN  Write
    115   )
    116 {
    117   volatile FW_CFG_DMA_ACCESS Access;
    118   UINT32                     AccessHigh, AccessLow;
    119   UINT32                     Status;
    120 
    121   if (Size == 0) {
    122     return;
    123   }
    124 
    125   Access.Control = SwapBytes32 (
    126                     Write ? FW_CFG_DMA_CTL_WRITE : FW_CFG_DMA_CTL_READ
    127                     );
    128   Access.Length  = SwapBytes32 (Size);
    129   Access.Address = SwapBytes64 ((UINTN)Buffer);
    130 
    131   //
    132   // Delimit the transfer from (a) modifications to Access, (b) in case of a
    133   // write, from writes to Buffer by the caller.
    134   //
    135   MemoryFence ();
    136 
    137   //
    138   // Start the transfer.
    139   //
    140   AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);
    141   AccessLow  = (UINT32)(UINTN)&Access;
    142   IoWrite32 (0x514, SwapBytes32 (AccessHigh));
    143   IoWrite32 (0x518, SwapBytes32 (AccessLow));
    144 
    145   //
    146   // Don't look at Access.Control before starting the transfer.
    147   //
    148   MemoryFence ();
    149 
    150   //
    151   // Wait for the transfer to complete.
    152   //
    153   do {
    154     Status = SwapBytes32 (Access.Control);
    155     ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
    156   } while (Status != 0);
    157 
    158   //
    159   // After a read, the caller will want to use Buffer.
    160   //
    161   MemoryFence ();
    162 }
    163 
    164 
    165 /**
    166   Reads firmware configuration bytes into a buffer
    167 
    168   @param[in] Size - Size in bytes to read
    169   @param[in] Buffer - Buffer to store data into  (OPTIONAL if Size is 0)
    170 
    171 **/
    172 VOID
    173 EFIAPI
    174 InternalQemuFwCfgReadBytes (
    175   IN UINTN                  Size,
    176   IN VOID                   *Buffer  OPTIONAL
    177   )
    178 {
    179   if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
    180     InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FALSE);
    181     return;
    182   }
    183   IoReadFifo8 (0x511, Size, Buffer);
    184 }
    185 
    186 
    187 /**
    188   Reads firmware configuration bytes into a buffer
    189 
    190   If called multiple times, then the data read will
    191   continue at the offset of the firmware configuration
    192   item where the previous read ended.
    193 
    194   @param[in] Size - Size in bytes to read
    195   @param[in] Buffer - Buffer to store data into
    196 
    197 **/
    198 VOID
    199 EFIAPI
    200 QemuFwCfgReadBytes (
    201   IN UINTN                  Size,
    202   IN VOID                   *Buffer
    203   )
    204 {
    205   if (InternalQemuFwCfgIsAvailable ()) {
    206     InternalQemuFwCfgReadBytes (Size, Buffer);
    207   } else {
    208     ZeroMem (Buffer, Size);
    209   }
    210 }
    211 
    212 /**
    213   Write firmware configuration bytes from a buffer
    214 
    215   If called multiple times, then the data written will
    216   continue at the offset of the firmware configuration
    217   item where the previous write ended.
    218 
    219   @param[in] Size - Size in bytes to write
    220   @param[in] Buffer - Buffer to read data from
    221 
    222 **/
    223 VOID
    224 EFIAPI
    225 QemuFwCfgWriteBytes (
    226   IN UINTN                  Size,
    227   IN VOID                   *Buffer
    228   )
    229 {
    230   if (InternalQemuFwCfgIsAvailable ()) {
    231     if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) {
    232       InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, TRUE);
    233       return;
    234     }
    235     IoWriteFifo8 (0x511, Size, Buffer);
    236   }
    237 }
    238 
    239 
    240 /**
    241   Reads a UINT8 firmware configuration value
    242 
    243   @return    Value of Firmware Configuration item read
    244 
    245 **/
    246 UINT8
    247 EFIAPI
    248 QemuFwCfgRead8 (
    249   VOID
    250   )
    251 {
    252   UINT8 Result;
    253 
    254   QemuFwCfgReadBytes (sizeof (Result), &Result);
    255 
    256   return Result;
    257 }
    258 
    259 
    260 /**
    261   Reads a UINT16 firmware configuration value
    262 
    263   @return    Value of Firmware Configuration item read
    264 
    265 **/
    266 UINT16
    267 EFIAPI
    268 QemuFwCfgRead16 (
    269   VOID
    270   )
    271 {
    272   UINT16 Result;
    273 
    274   QemuFwCfgReadBytes (sizeof (Result), &Result);
    275 
    276   return Result;
    277 }
    278 
    279 
    280 /**
    281   Reads a UINT32 firmware configuration value
    282 
    283   @return    Value of Firmware Configuration item read
    284 
    285 **/
    286 UINT32
    287 EFIAPI
    288 QemuFwCfgRead32 (
    289   VOID
    290   )
    291 {
    292   UINT32 Result;
    293 
    294   QemuFwCfgReadBytes (sizeof (Result), &Result);
    295 
    296   return Result;
    297 }
    298 
    299 
    300 /**
    301   Reads a UINT64 firmware configuration value
    302 
    303   @return    Value of Firmware Configuration item read
    304 
    305 **/
    306 UINT64
    307 EFIAPI
    308 QemuFwCfgRead64 (
    309   VOID
    310   )
    311 {
    312   UINT64 Result;
    313 
    314   QemuFwCfgReadBytes (sizeof (Result), &Result);
    315 
    316   return Result;
    317 }
    318 
    319 
    320 /**
    321   Find the configuration item corresponding to the firmware configuration file.
    322 
    323   @param[in]  Name - Name of file to look up.
    324   @param[out] Item - Configuration item corresponding to the file, to be passed
    325                      to QemuFwCfgSelectItem ().
    326   @param[out] Size - Number of bytes in the file.
    327 
    328   @return    RETURN_SUCCESS       If file is found.
    329              RETURN_NOT_FOUND     If file is not found.
    330              RETURN_UNSUPPORTED   If firmware configuration is unavailable.
    331 
    332 **/
    333 RETURN_STATUS
    334 EFIAPI
    335 QemuFwCfgFindFile (
    336   IN   CONST CHAR8           *Name,
    337   OUT  FIRMWARE_CONFIG_ITEM  *Item,
    338   OUT  UINTN                 *Size
    339   )
    340 {
    341   UINT32 Count;
    342   UINT32 Idx;
    343 
    344   if (!InternalQemuFwCfgIsAvailable ()) {
    345     return RETURN_UNSUPPORTED;
    346   }
    347 
    348   QemuFwCfgSelectItem (QemuFwCfgItemFileDir);
    349   Count = SwapBytes32 (QemuFwCfgRead32 ());
    350 
    351   for (Idx = 0; Idx < Count; ++Idx) {
    352     UINT32 FileSize;
    353     UINT16 FileSelect;
    354     UINT16 FileReserved;
    355     CHAR8  FName[QEMU_FW_CFG_FNAME_SIZE];
    356 
    357     FileSize     = QemuFwCfgRead32 ();
    358     FileSelect   = QemuFwCfgRead16 ();
    359     FileReserved = QemuFwCfgRead16 ();
    360     (VOID) FileReserved; /* Force a do-nothing reference. */
    361     InternalQemuFwCfgReadBytes (sizeof (FName), FName);
    362 
    363     if (AsciiStrCmp (Name, FName) == 0) {
    364       *Item = SwapBytes16 (FileSelect);
    365       *Size = SwapBytes32 (FileSize);
    366       return RETURN_SUCCESS;
    367     }
    368   }
    369 
    370   return RETURN_NOT_FOUND;
    371 }
    372 
    373 
    374 /**
    375   Determine if S3 support is explicitly enabled.
    376 
    377   @retval  TRUE   if S3 support is explicitly enabled.
    378            FALSE  otherwise. This includes unavailability of the firmware
    379                   configuration interface.
    380 **/
    381 BOOLEAN
    382 EFIAPI
    383 QemuFwCfgS3Enabled (
    384   VOID
    385   )
    386 {
    387   RETURN_STATUS        Status;
    388   FIRMWARE_CONFIG_ITEM FwCfgItem;
    389   UINTN                FwCfgSize;
    390   UINT8                SystemStates[6];
    391 
    392   Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize);
    393   if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) {
    394     return FALSE;
    395   }
    396   QemuFwCfgSelectItem (FwCfgItem);
    397   QemuFwCfgReadBytes (sizeof SystemStates, SystemStates);
    398   return (BOOLEAN) (SystemStates[3] & BIT7);
    399 }
    400