[edk2] [PATCH 07/12] OvmfPkg/QemuFwCfgS3Lib: add boot script opcode generation APIs to libclass

Laszlo Ersek posted 12 patches 7 years, 8 months ago
There is a newer version of this series
[edk2] [PATCH 07/12] OvmfPkg/QemuFwCfgS3Lib: add boot script opcode generation APIs to libclass
Posted by Laszlo Ersek 7 years, 8 months ago
Introduce the following APIs:

- QemuFwCfgS3TransferOwnership(): central function that registers a
  callback function, with a context parameter, for when ACPI S3 Boot
  Script opcodes can be produced. This function also allocates reserved
  memory for the opcodes to operate upon.

  The client module is supposed to produce the boot script fragment in the
  callback function.

- QemuFwCfgS3WriteBytes(), QemuFwCfgS3ReadBytes(), QemuFwCfgS3SkipBytes(),
  QemuFwCfgS3CheckValue(): helper functions, available only to the above
  callback function, for composing the boot script fragment.
  QemuFwCfgS3SkipBytes() can double as a plain "select" whenever
  necessary.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=394
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/Include/Library/QemuFwCfgS3Lib.h | 318 ++++++++++++++++++++
 1 file changed, 318 insertions(+)

diff --git a/OvmfPkg/Include/Library/QemuFwCfgS3Lib.h b/OvmfPkg/Include/Library/QemuFwCfgS3Lib.h
index 1c473610d11c..3499de3c74cc 100644
--- a/OvmfPkg/Include/Library/QemuFwCfgS3Lib.h
+++ b/OvmfPkg/Include/Library/QemuFwCfgS3Lib.h
@@ -19,6 +19,8 @@
 #ifndef __FW_CFG_S3_LIB__
 #define __FW_CFG_S3_LIB__
 
+#include <Base.h>
+
 /**
   Determine if S3 support is explicitly enabled.
 
@@ -36,4 +38,320 @@ QemuFwCfgS3Enabled (
   VOID
   );
 
+
+/**
+  Prototype for the callback function that the client module provides.
+
+  In the callback function, the client module calls the
+  QemuFwCfgS3WriteBytes(), QemuFwCfgS3ReadBytes(), QemuFwCfgS3SkipBytes(), and
+  QemuFwCfgS3CheckValue() 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
+  QemuFwCfgS3TransferOwnership() (see below), or after
+  QemuFwCfgS3TransferOwnership() 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
+                                QemuFwCfgS3TransferOwnership()) 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
+                                QemuFwCfgS3TransferOwnership() internally.
+
+                                ScratchBuffer is typed and sized by the client
+                                module when it calls
+                                QemuFwCfgS3TransferOwnership(). 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
+                                QemuFwCfgS3ReadBytes() and
+                                QemuFwCfgS3WriteBytes(). It passes field
+                                addresses and sizes in structures in the union
+                                as ScratchData and ValueSize to
+                                QemuFwCfgS3CheckValue().
+
+                                ScratchBuffer is aligned at 8 bytes.
+**/
+typedef
+VOID (EFIAPI FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION) (
+  IN OUT VOID *Context,      OPTIONAL
+  IN OUT VOID *ScratchBuffer
+  );
+
+
+/**
+  Install the client module's FW_CFG_BOOT_SCRIPT_APPEND_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] Append             FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION to invoke
+                                when the production of ACPI S3 Boot Script
+                                opcodes becomes possible. Append() may be
+                                called immediately from
+                                QemuFwCfgS3TransferOwnership().
+
+  @param[in,out] Context        Client-provided data structure for the Append()
+                                callback function to consume.
+
+                                If Context points to dynamically allocated
+                                memory, then Append() must release it.
+
+                                If Context points to dynamically allocated
+                                memory, and QemuFwCfgS3TransferOwnership()
+                                returns successfully, then the caller of
+                                QemuFwCfgS3TransferOwnership() must neither
+                                dereference nor even evaluate Context any
+                                longer, as ownership of the referenced area has
+                                been transferred to Append().
+
+  @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 Append().
+
+  @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           Append() has been installed, and the
+                                   ownership of Context has been transferred.
+                                   Reserved memory has been allocated for the
+                                   scratch buffer.
+
+                                   A successful invocation of
+                                   QemuFwCfgS3TransferOwnership() cannot be
+                                   rolled back.
+
+  @return                          Error codes from underlying functions.
+**/
+EFIAPI
+RETURN_STATUS
+QemuFwCfgS3TransferOwnership (
+  IN     FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION *Append,
+  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 QemuFwCfgS3WriteBytes() 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_APPEND_FUNCTION, which was passed to
+  QemuFwCfgS3TransferOwnership() as Append.
+
+  @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
+                                 QemuFwCfgS3TransferOwnership().
+
+  @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.
+**/
+EFIAPI
+RETURN_STATUS
+QemuFwCfgS3WriteBytes (
+  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 QemuFwCfgS3ReadBytes() 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_APPEND_FUNCTION, which was passed to
+  QemuFwCfgS3TransferOwnership() as Append.
+
+  @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
+                                 QemuFwCfgS3TransferOwnership().
+
+  @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.
+**/
+EFIAPI
+RETURN_STATUS
+QemuFwCfgS3ReadBytes (
+  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_APPEND_FUNCTION, which was passed to
+  QemuFwCfgS3TransferOwnership() as Append.
+
+  @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.
+**/
+EFIAPI
+RETURN_STATUS
+QemuFwCfgS3SkipBytes (
+  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_APPEND_FUNCTION, which was passed to
+  QemuFwCfgS3TransferOwnership() as Append.
+
+  @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 QemuFwCfgS3ReadBytes() ahead of
+                          QemuFwCfgS3CheckValue().
+
+                          ScratchData must point into ScratchBuffer, which was
+                          allocated, and passed to Append(), by
+                          QemuFwCfgS3TransferOwnership().
+
+                          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.
+**/
+EFIAPI
+RETURN_STATUS
+QemuFwCfgS3CheckValue (
+  IN VOID   *ScratchData,
+  IN UINT8  ValueSize,
+  IN UINT64 ValueMask,
+  IN UINT64 Value
+  );
+
 #endif
-- 
2.9.3


_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 07/12] OvmfPkg/QemuFwCfgS3Lib: add boot script opcode generation APIs to libclass
Posted by Jordan Justen 7 years, 7 months ago
On 2017-02-22 17:48:09, Laszlo Ersek wrote:
> +EFIAPI
> +RETURN_STATUS
> +QemuFwCfgS3TransferOwnership (
> +  IN     FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION *Append,
> +  IN OUT VOID                               *Context,          OPTIONAL
> +  IN     UINTN                              ScratchBufferSize
> +  );

I think this might be better named something like
QemuFwCfgS3CallWhenBootScriptReady. (Wow, that is verbose. Maybe you
have a better idea.)

-Jordan
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Re: [edk2] [PATCH 07/12] OvmfPkg/QemuFwCfgS3Lib: add boot script opcode generation APIs to libclass
Posted by Laszlo Ersek 7 years, 7 months ago
On 03/10/17 10:58, Jordan Justen wrote:
> On 2017-02-22 17:48:09, Laszlo Ersek wrote:
>> +EFIAPI
>> +RETURN_STATUS
>> +QemuFwCfgS3TransferOwnership (
>> +  IN     FW_CFG_BOOT_SCRIPT_APPEND_FUNCTION *Append,
>> +  IN OUT VOID                               *Context,          OPTIONAL
>> +  IN     UINTN                              ScratchBufferSize
>> +  );
> 
> I think this might be better named something like
> QemuFwCfgS3CallWhenBootScriptReady. (Wow, that is verbose. Maybe you
> have a better idea.)

No, I like your suggestion.

Thanks
Laszlo

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel