text: /** @file
    S3 support for QEMU fw_cfg
  
    This library class enables driver modules (a) to query whether S3 support was
    enabled on the QEMU command line, (b) to produce fw_cfg DMA operations that
    are to be replayed at S3 resume time.
  
    Copyright (C) 2017, Red Hat, Inc.
  
    SPDX-License-Identifier: BSD-2-Clause-Patent
  **/
  
  #ifndef __FW_CFG_S3_LIB__
  #define __FW_CFG_S3_LIB__
  
  #include <Base.h>
  
  /**
    Determine if S3 support is explicitly enabled.
  
    @retval  TRUE   If S3 support is explicitly enabled. Other functions in this
                    library may be called (subject to their individual
                    restrictions).
  
             FALSE  Otherwise. This includes unavailability of the firmware
                    configuration interface. No other function in this library
                    must be called.
  **/
  BOOLEAN
  EFIAPI
  QemuFwCfgS3Enabled (
    VOID
    );
  
  
  /**
    Prototype for the callback function that the client module provides.
  
    In the callback function, the client module calls the
    QemuFwCfgS3ScriptWriteBytes(), QemuFwCfgS3ScriptReadBytes(),
    QemuFwCfgS3ScriptSkipBytes(), and QemuFwCfgS3ScriptCheckValue() functions.
    Those functions produce ACPI S3 Boot Script opcodes that will perform fw_cfg
    DMA operations, and will check any desired values that were read, during S3
    resume.
  
    The callback function is invoked when the production of ACPI S3 Boot Script
    opcodes becomes possible. This may occur directly on the call stack of
    QemuFwCfgS3CallWhenBootScriptReady() (see below), or after
    QemuFwCfgS3CallWhenBootScriptReady() has successfully returned.
  
    The callback function must not return if it fails -- in the general case,
    there is noone to propagate any errors to. Therefore, on error, an error
    message should be logged, and CpuDeadLoop() must be called.
  
    @param[in,out] Context        Carries information from the client module
                                  itself (i.e., from the invocation of
                                  QemuFwCfgS3CallWhenBootScriptReady()) to the
                                  callback function.
  
                                  If Context points to dynamically allocated
                                  storage, then the callback function must
                                  release it.
  
    @param[in,out] ScratchBuffer  Points to reserved memory, allocated by
                                  QemuFwCfgS3CallWhenBootScriptReady()
                                  internally.
  
                                  ScratchBuffer is typed and sized by the client
                                  module when it calls
                                  QemuFwCfgS3CallWhenBootScriptReady(). The
                                  client module defines a union type of
                                  structures for ScratchBuffer such that the
                                  union can hold client data for any desired
                                  fw_cfg DMA read and write operations, and value
                                  checking.
  
                                  The callback function casts ScratchBuffer to
                                  the union type described above. It passes union
                                  member sizes as NumberOfBytes to
                                  QemuFwCfgS3ScriptReadBytes() and
                                  QemuFwCfgS3ScriptWriteBytes(). It passes field
                                  addresses and sizes in structures in the union
                                  as ScratchData and ValueSize to
                                  QemuFwCfgS3ScriptCheckValue().
  
                                  ScratchBuffer is aligned at 8 bytes.
  **/
  typedef
  VOID (EFIAPI FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION) (
    IN OUT VOID *Context,      OPTIONAL
    IN OUT VOID *ScratchBuffer
    );
  
  
  /**
    Install the client module's FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION callback for
    when the production of ACPI S3 Boot Script opcodes becomes possible.
  
    Take ownership of the client-provided Context, and pass it to the callback
    function, when the latter is invoked.
  
    Allocate scratch space for those ACPI S3 Boot Script opcodes to work upon
    that the client will produce in the callback function.
  
    @param[in] Callback           FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION to invoke
                                  when the production of ACPI S3 Boot Script
                                  opcodes becomes possible. Callback() may be
                                  called immediately from
                                  QemuFwCfgS3CallWhenBootScriptReady().
  
    @param[in,out] Context        Client-provided data structure for the
                                  Callback() callback function to consume.
  
                                  If Context points to dynamically allocated
                                  memory, then Callback() must release it.
  
                                  If Context points to dynamically allocated
                                  memory, and
                                  QemuFwCfgS3CallWhenBootScriptReady() returns
                                  successfully, then the caller of
                                  QemuFwCfgS3CallWhenBootScriptReady() must
                                  neither dereference nor even evaluate Context
                                  any longer, as ownership of the referenced area
                                  has been transferred to Callback().
  
    @param[in] ScratchBufferSize  The size of the scratch buffer that will hold,
                                  in reserved memory, all client data read,
                                  written, and checked by the ACPI S3 Boot Script
                                  opcodes produced by Callback().
  
    @retval RETURN_UNSUPPORTED       The library instance does not support this
                                     function.
  
    @retval RETURN_NOT_FOUND         The fw_cfg DMA interface to QEMU is
                                     unavailable.
  
    @retval RETURN_BAD_BUFFER_SIZE   ScratchBufferSize is too large.
  
    @retval RETURN_OUT_OF_RESOURCES  Memory allocation failed.
  
    @retval RETURN_SUCCESS           Callback() has been installed, and the
                                     ownership of Context has been transferred.
                                     Reserved memory has been allocated for the
                                     scratch buffer.
  
                                     A successful invocation of
                                     QemuFwCfgS3CallWhenBootScriptReady() cannot
                                     be rolled back.
  
    @return                          Error codes from underlying functions.
  **/
  RETURN_STATUS
  EFIAPI
  QemuFwCfgS3CallWhenBootScriptReady (
    IN     FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION *Callback,
    IN OUT VOID                                 *Context,          OPTIONAL
    IN     UINTN                                ScratchBufferSize
    );
  
  
  /**
    Produce ACPI S3 Boot Script opcodes that (optionally) select an fw_cfg item,
    and transfer data to it.
  
    The opcodes produced by QemuFwCfgS3ScriptWriteBytes() will first restore
    NumberOfBytes bytes in ScratchBuffer in-place, in reserved memory, then write
    them to fw_cfg using DMA.
  
    If the operation fails during S3 resume, the boot script will hang.
  
    This function may only be called from the client module's
    FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION, which was passed to
    QemuFwCfgS3CallWhenBootScriptReady() as Callback.
  
    @param[in] FirmwareConfigItem  The UINT16 selector key of the firmware config
                                   item to write, expressed as INT32. If
                                   FirmwareConfigItem is -1, no selection is
                                   made, the write will occur to the currently
                                   selected item, at its currently selected
                                   offset. Otherwise, the specified item will be
                                   selected, and the write will occur at offset
                                   0.
  
    @param[in] NumberOfBytes       Size of the data to restore in ScratchBuffer,
                                   and to write from ScratchBuffer, during S3
                                   resume. NumberOfBytes must not exceed
                                   ScratchBufferSize, which was passed to
                                   QemuFwCfgS3CallWhenBootScriptReady().
  
    @retval RETURN_SUCCESS            The opcodes were appended to the ACPI S3
                                      Boot Script successfully. There is no way
                                      to undo this action.
  
    @retval RETURN_INVALID_PARAMETER  FirmwareConfigItem is invalid.
  
    @retval RETURN_BAD_BUFFER_SIZE    NumberOfBytes is larger than
                                      ScratchBufferSize.
  
    @return                           Error codes from underlying functions.
  **/
  RETURN_STATUS
  EFIAPI
  QemuFwCfgS3ScriptWriteBytes (
    IN INT32 FirmwareConfigItem,
    IN UINTN NumberOfBytes
    );
  
  
  /**
    Produce ACPI S3 Boot Script opcodes that (optionally) select an fw_cfg item,
    and transfer data from it.
  
    The opcodes produced by QemuFwCfgS3ScriptReadBytes() will read NumberOfBytes
    bytes from fw_cfg using DMA, storing the result in ScratchBuffer, in reserved
    memory.
  
    If the operation fails during S3 resume, the boot script will hang.
  
    This function may only be called from the client module's
    FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION, which was passed to
    QemuFwCfgS3CallWhenBootScriptReady() as Callback.
  
    @param[in] FirmwareConfigItem  The UINT16 selector key of the firmware config
                                   item to read, expressed as INT32. If
                                   FirmwareConfigItem is -1, no selection is
                                   made, the read will occur from the currently
                                   selected item, from its currently selected
                                   offset. Otherwise, the specified item will be
                                   selected, and the read will occur from offset
                                   0.
  
    @param[in] NumberOfBytes       Size of the data to read during S3 resume.
                                   NumberOfBytes must not exceed
                                   ScratchBufferSize, which was passed to
                                   QemuFwCfgS3CallWhenBootScriptReady().
  
    @retval RETURN_SUCCESS            The opcodes were appended to the ACPI S3
                                      Boot Script successfully. There is no way
                                      to undo this action.
  
    @retval RETURN_INVALID_PARAMETER  FirmwareConfigItem is invalid.
  
    @retval RETURN_BAD_BUFFER_SIZE    NumberOfBytes is larger than
                                      ScratchBufferSize.
  
    @return                           Error codes from underlying functions.
  **/
  RETURN_STATUS
  EFIAPI
  QemuFwCfgS3ScriptReadBytes (
    IN INT32 FirmwareConfigItem,
    IN UINTN NumberOfBytes
    );
  
  
  /**
    Produce ACPI S3 Boot Script opcodes that (optionally) select an fw_cfg item,
    and increase its offset.
  
    If the operation fails during S3 resume, the boot script will hang.
  
    This function may only be called from the client module's
    FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION, which was passed to
    QemuFwCfgS3CallWhenBootScriptReady() as Callback.
  
    @param[in] FirmwareConfigItem  The UINT16 selector key of the firmware config
                                   item to advance the offset of, expressed as
                                   INT32. If FirmwareConfigItem is -1, no
                                   selection is made, and the offset for the
                                   currently selected item is increased.
                                   Otherwise, the specified item will be
                                   selected, and the offset increment will occur
                                   from offset 0.
  
    @param[in] NumberOfBytes       The number of bytes to skip in the subject
                                   fw_cfg item.
  
    @retval RETURN_SUCCESS            The opcodes were appended to the ACPI S3
                                      Boot Script successfully. There is no way
                                      to undo this action.
  
    @retval RETURN_INVALID_PARAMETER  FirmwareConfigItem is invalid.
  
    @retval RETURN_BAD_BUFFER_SIZE    NumberOfBytes is too large.
  
    @return                           Error codes from underlying functions.
  **/
  RETURN_STATUS
  EFIAPI
  QemuFwCfgS3ScriptSkipBytes (
    IN INT32 FirmwareConfigItem,
    IN UINTN NumberOfBytes
    );
  
  
  /**
    Produce ACPI S3 Boot Script opcodes that check a value in ScratchBuffer.
  
    If the check fails during S3 resume, the boot script will hang.
  
    This function may only be called from the client module's
    FW_CFG_BOOT_SCRIPT_CALLBACK_FUNCTION, which was passed to
    QemuFwCfgS3CallWhenBootScriptReady() as Callback.
  
    @param[in] ScratchData  Pointer to the UINT8, UINT16, UINT32 or UINT64 field
                            in ScratchBuffer that should be checked. The caller
                            is responsible for populating the field during S3
                            resume, by calling QemuFwCfgS3ScriptReadBytes() ahead
                            of QemuFwCfgS3ScriptCheckValue().
  
                            ScratchData must point into ScratchBuffer, which was
                            allocated, and passed to Callback(), by
                            QemuFwCfgS3CallWhenBootScriptReady().
  
                            ScratchData must be aligned at ValueSize bytes.
  
    @param[in] ValueSize    One of 1, 2, 4 or 8, specifying the size of the field
                            to check.
  
    @param[in] ValueMask    The value read from ScratchData is binarily AND-ed
                            with ValueMask, and the result is compared against
                            Value. If the masked data equals Value, the check
                            passes, and the boot script can proceed. Otherwise,
                            the check fails, and the boot script hangs.
  
    @param[in] Value        Refer to ValueMask.
  
    @retval RETURN_SUCCESS            The opcodes were appended to the ACPI S3
                                      Boot Script successfully. There is no way
                                      to undo this action.
  
    @retval RETURN_INVALID_PARAMETER  ValueSize is invalid.
  
    @retval RETURN_INVALID_PARAMETER  ValueMask or Value cannot be represented in
                                      ValueSize bytes.
  
    @retval RETURN_INVALID_PARAMETER  ScratchData is not aligned at ValueSize
                                      bytes.
  
    @retval RETURN_BAD_BUFFER_SIZE    The ValueSize bytes at ScratchData aren't
                                      wholly contained in the ScratchBufferSize
                                      bytes at ScratchBuffer.
  
    @return                           Error codes from underlying functions.
  **/
  RETURN_STATUS
  EFIAPI
  QemuFwCfgS3ScriptCheckValue (
    IN VOID   *ScratchData,
    IN UINT8  ValueSize,
    IN UINT64 ValueMask,
    IN UINT64 Value
    );
  
  #endif
  