Introduce the new public API QemuFwCfgSkipBytes(), for advancing over bytes in the selected firmware configuration item without transferring data between the item and the caller. When the DMA interface is available (the common case), the operation is instantaneous. As a fallback, provide a loop of chunked reads into a small stack-allocated scratch buffer. This patch enables OvmfPkg/QemuFwCfgLib to overwrite part of a writeable fw_cfg file, which will be particularly useful for the upcoming QEMU_LOADER_WRITE_POINTER command in OvmfPkg/AcpiPlatformDxe. Cc: Jordan Justen <jordan.l.justen@intel.com> Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=359 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
266 lines
6.5 KiB
C
266 lines
6.5 KiB
C
/** @file
|
|
QEMU/KVM Firmware Configuration access
|
|
|
|
Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
|
|
Copyright (C) 2013, Red Hat, Inc.
|
|
|
|
This program and the accompanying materials
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
**/
|
|
|
|
#ifndef __FW_CFG_LIB__
|
|
#define __FW_CFG_LIB__
|
|
|
|
//
|
|
// The size, in bytes, of names of firmware configuration files, including at
|
|
// least one terminating NUL byte.
|
|
//
|
|
#define QEMU_FW_CFG_FNAME_SIZE 56
|
|
|
|
//
|
|
// If the following bit is set in the UINT32 fw_cfg revision / feature bitmap
|
|
// -- read from key 0x0001 with the basic IO Port or MMIO method --, then the
|
|
// DMA interface is available.
|
|
//
|
|
#define FW_CFG_F_DMA BIT1
|
|
|
|
//
|
|
// Macros for the FW_CFG_DMA_ACCESS.Control bitmap (in native encoding).
|
|
//
|
|
#define FW_CFG_DMA_CTL_ERROR BIT0
|
|
#define FW_CFG_DMA_CTL_READ BIT1
|
|
#define FW_CFG_DMA_CTL_SKIP BIT2
|
|
#define FW_CFG_DMA_CTL_SELECT BIT3
|
|
#define FW_CFG_DMA_CTL_WRITE BIT4
|
|
|
|
typedef enum {
|
|
QemuFwCfgItemSignature = 0x0000,
|
|
QemuFwCfgItemInterfaceVersion = 0x0001,
|
|
QemuFwCfgItemSystemUuid = 0x0002,
|
|
QemuFwCfgItemRamSize = 0x0003,
|
|
QemuFwCfgItemGraphicsEnabled = 0x0004,
|
|
QemuFwCfgItemSmpCpuCount = 0x0005,
|
|
QemuFwCfgItemMachineId = 0x0006,
|
|
QemuFwCfgItemKernelAddress = 0x0007,
|
|
QemuFwCfgItemKernelSize = 0x0008,
|
|
QemuFwCfgItemKernelCommandLine = 0x0009,
|
|
QemuFwCfgItemInitrdAddress = 0x000a,
|
|
QemuFwCfgItemInitrdSize = 0x000b,
|
|
QemuFwCfgItemBootDevice = 0x000c,
|
|
QemuFwCfgItemNumaData = 0x000d,
|
|
QemuFwCfgItemBootMenu = 0x000e,
|
|
QemuFwCfgItemMaximumCpuCount = 0x000f,
|
|
QemuFwCfgItemKernelEntry = 0x0010,
|
|
QemuFwCfgItemKernelData = 0x0011,
|
|
QemuFwCfgItemInitrdData = 0x0012,
|
|
QemuFwCfgItemCommandLineAddress = 0x0013,
|
|
QemuFwCfgItemCommandLineSize = 0x0014,
|
|
QemuFwCfgItemCommandLineData = 0x0015,
|
|
QemuFwCfgItemKernelSetupAddress = 0x0016,
|
|
QemuFwCfgItemKernelSetupSize = 0x0017,
|
|
QemuFwCfgItemKernelSetupData = 0x0018,
|
|
QemuFwCfgItemFileDir = 0x0019,
|
|
|
|
QemuFwCfgItemX86AcpiTables = 0x8000,
|
|
QemuFwCfgItemX86SmbiosTables = 0x8001,
|
|
QemuFwCfgItemX86Irq0Override = 0x8002,
|
|
QemuFwCfgItemX86E820Table = 0x8003,
|
|
QemuFwCfgItemX86HpetData = 0x8004,
|
|
|
|
} FIRMWARE_CONFIG_ITEM;
|
|
|
|
//
|
|
// Communication structure for the DMA access method. All fields are encoded in
|
|
// big endian.
|
|
//
|
|
#pragma pack (1)
|
|
typedef struct {
|
|
UINT32 Control;
|
|
UINT32 Length;
|
|
UINT64 Address;
|
|
} FW_CFG_DMA_ACCESS;
|
|
#pragma pack ()
|
|
|
|
/**
|
|
Returns a boolean indicating if the firmware configuration interface
|
|
is available or not.
|
|
|
|
This function may change fw_cfg state.
|
|
|
|
@retval TRUE The interface is available
|
|
@retval FALSE The interface is not available
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
QemuFwCfgIsAvailable (
|
|
VOID
|
|
);
|
|
|
|
|
|
/**
|
|
Selects a firmware configuration item for reading.
|
|
|
|
Following this call, any data read from this item will start from
|
|
the beginning of the configuration item's data.
|
|
|
|
@param[in] QemuFwCfgItem - Firmware Configuration item to read
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
QemuFwCfgSelectItem (
|
|
IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem
|
|
);
|
|
|
|
|
|
/**
|
|
Reads firmware configuration bytes into a buffer
|
|
|
|
If called multiple times, then the data read will
|
|
continue at the offset of the firmware configuration
|
|
item where the previous read ended.
|
|
|
|
@param[in] Size - Size in bytes to read
|
|
@param[in] Buffer - Buffer to store data into
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
QemuFwCfgReadBytes (
|
|
IN UINTN Size,
|
|
IN VOID *Buffer OPTIONAL
|
|
);
|
|
|
|
|
|
/**
|
|
Writes firmware configuration bytes from a buffer
|
|
|
|
If called multiple times, then the data written will
|
|
continue at the offset of the firmware configuration
|
|
item where the previous write ended.
|
|
|
|
@param[in] Size - Size in bytes to write
|
|
@param[in] Buffer - Buffer to read data from
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
QemuFwCfgWriteBytes (
|
|
IN UINTN Size,
|
|
IN VOID *Buffer
|
|
);
|
|
|
|
|
|
/**
|
|
Skip bytes in the firmware configuration item.
|
|
|
|
Increase the offset of the firmware configuration item without transferring
|
|
bytes between the item and a caller-provided buffer. Subsequent read, write
|
|
or skip operations will commence at the increased offset.
|
|
|
|
@param[in] Size Number of bytes to skip.
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
QemuFwCfgSkipBytes (
|
|
IN UINTN Size
|
|
);
|
|
|
|
|
|
/**
|
|
Reads a UINT8 firmware configuration value
|
|
|
|
@return Value of Firmware Configuration item read
|
|
|
|
**/
|
|
UINT8
|
|
EFIAPI
|
|
QemuFwCfgRead8 (
|
|
VOID
|
|
);
|
|
|
|
|
|
/**
|
|
Reads a UINT16 firmware configuration value
|
|
|
|
@return Value of Firmware Configuration item read
|
|
|
|
**/
|
|
UINT16
|
|
EFIAPI
|
|
QemuFwCfgRead16 (
|
|
VOID
|
|
);
|
|
|
|
|
|
/**
|
|
Reads a UINT32 firmware configuration value
|
|
|
|
@return Value of Firmware Configuration item read
|
|
|
|
**/
|
|
UINT32
|
|
EFIAPI
|
|
QemuFwCfgRead32 (
|
|
VOID
|
|
);
|
|
|
|
|
|
/**
|
|
Reads a UINT64 firmware configuration value
|
|
|
|
@return Value of Firmware Configuration item read
|
|
|
|
**/
|
|
UINT64
|
|
EFIAPI
|
|
QemuFwCfgRead64 (
|
|
VOID
|
|
);
|
|
|
|
|
|
/**
|
|
Find the configuration item corresponding to the firmware configuration file.
|
|
|
|
@param[in] Name - Name of file to look up.
|
|
@param[out] Item - Configuration item corresponding to the file, to be passed
|
|
to QemuFwCfgSelectItem ().
|
|
@param[out] Size - Number of bytes in the file.
|
|
|
|
@return RETURN_SUCCESS If file is found.
|
|
RETURN_NOT_FOUND If file is not found.
|
|
RETURN_UNSUPPORTED If firmware configuration is unavailable.
|
|
|
|
**/
|
|
RETURN_STATUS
|
|
EFIAPI
|
|
QemuFwCfgFindFile (
|
|
IN CONST CHAR8 *Name,
|
|
OUT FIRMWARE_CONFIG_ITEM *Item,
|
|
OUT UINTN *Size
|
|
);
|
|
|
|
|
|
/**
|
|
Determine if S3 support is explicitly enabled.
|
|
|
|
@retval TRUE if S3 support is explicitly enabled.
|
|
FALSE otherwise. This includes unavailability of the firmware
|
|
configuration interface.
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
QemuFwCfgS3Enabled (
|
|
VOID
|
|
);
|
|
|
|
#endif
|
|
|