355 lines
15 KiB
C
355 lines
15 KiB
C
/** @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
|