X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=OvmfPkg%2FLibrary%2FQemuFwCfgLib%2FQemuFwCfgLib.c;h=a228c029dfb909edadb3247017264c182ea6f0e7;hb=2b631390f9f5f6971c3c8a7f0f47160b80cf072b;hp=985b383c26b80249a9542f821c89fabafc9db53b;hpb=0dc231c9bd1a5aecfbcd373a50dc348a5dfbd38a;p=mirror_edk2.git diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c index 985b383c26..a228c029df 100644 --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c @@ -2,6 +2,7 @@ Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.
Copyright (C) 2013, Red Hat, Inc. + Copyright (c) 2017, AMD Incorporated. All rights reserved.
This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -22,99 +23,90 @@ #include #include -STATIC BOOLEAN mQemuFwCfgSupported = FALSE; +#include "QemuFwCfgLibInternal.h" /** - Reads an 8-bit I/O port fifo into a block of memory. - - Reads the 8-bit I/O fifo port specified by Port. - - The port is read Count times, and the read data is - stored in the provided Buffer. - - This function must guarantee that all I/O read and write operations are - serialized. - - If 8-bit I/O port operations are not supported, then ASSERT(). + 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 Port The I/O port to read. - @param Count The number of times to read I/O port. - @param Buffer The buffer to store the read data into. + @param[in] QemuFwCfgItem - Firmware Configuration item to read **/ VOID EFIAPI -IoReadFifo8 ( - IN UINTN Port, - IN UINTN Count, - OUT VOID *Buffer - ); - -/** - Writes an 8-bit I/O port fifo from a block of memory. - - Writes the 8-bit I/O fifo port specified by Port. - - The port is written Count times, and the data are obtained - from the provided Buffer. - - This function must guarantee that all I/O read and write operations are - serialized. +QemuFwCfgSelectItem ( + IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem + ) +{ + DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem)); + IoWrite16 (0x510, (UINT16)(UINTN) QemuFwCfgItem); +} - If 8-bit I/O port operations are not supported, then ASSERT(). - @param Port The I/O port to read. - @param Count The number of times to read I/O port. - @param Buffer The buffer to store the read data into. +/** + Transfer an array of bytes using the DMA interface. + @param[in] Size Size in bytes to transfer. + @param[in,out] Buffer Buffer to read data into or write data from. May be + NULL if Size is zero. + @param[in] Write TRUE if writing to fw_cfg from Buffer, FALSE if + reading from fw_cfg into Buffer. **/ VOID -EFIAPI -IoWriteFifo8 ( - IN UINTN Port, - IN UINTN Count, - OUT VOID *Buffer - ); - - -/** - Returns a boolean indicating if the firmware configuration interface - is available or not. +InternalQemuFwCfgDmaBytes ( + IN UINT32 Size, + IN OUT VOID *Buffer OPTIONAL, + IN BOOLEAN Write + ) +{ + volatile FW_CFG_DMA_ACCESS Access; + UINT32 AccessHigh, AccessLow; + UINT32 Status; - This function may change fw_cfg state. + if (Size == 0) { + return; + } - @retval TRUE The interface is available - @retval FALSE The interface is not available + Access.Control = SwapBytes32 ( + Write ? FW_CFG_DMA_CTL_WRITE : FW_CFG_DMA_CTL_READ + ); + Access.Length = SwapBytes32 (Size); + Access.Address = SwapBytes64 ((UINTN)Buffer); -**/ -BOOLEAN -EFIAPI -QemuFwCfgIsAvailable ( - VOID - ) -{ - return InternalQemuFwCfgIsAvailable (); -} + // + // Delimit the transfer from (a) modifications to Access, (b) in case of a + // write, from writes to Buffer by the caller. + // + MemoryFence (); + // + // Start the transfer. + // + AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32); + AccessLow = (UINT32)(UINTN)&Access; + IoWrite32 (0x514, SwapBytes32 (AccessHigh)); + IoWrite32 (0x518, SwapBytes32 (AccessLow)); -/** - 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. + // + // Don't look at Access.Control before starting the transfer. + // + MemoryFence (); - @param[in] QemuFwCfgItem - Firmware Configuration item to read + // + // Wait for the transfer to complete. + // + do { + Status = SwapBytes32 (Access.Control); + ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0); + } while (Status != 0); -**/ -VOID -EFIAPI -QemuFwCfgSelectItem ( - IN FIRMWARE_CONFIG_ITEM QemuFwCfgItem - ) -{ - DEBUG ((EFI_D_INFO, "Select Item: 0x%x\n", (UINT16)(UINTN) QemuFwCfgItem)); - IoWrite16 (0x510, (UINT16)(UINTN) QemuFwCfgItem); + // + // After a read, the caller will want to use Buffer. + // + MemoryFence (); } @@ -132,6 +124,10 @@ InternalQemuFwCfgReadBytes ( IN VOID *Buffer OPTIONAL ) { + if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) { + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, FALSE); + return; + } IoReadFifo8 (0x511, Size, Buffer); } @@ -180,6 +176,10 @@ QemuFwCfgWriteBytes ( ) { if (InternalQemuFwCfgIsAvailable ()) { + if (InternalQemuFwCfgDmaIsAvailable () && Size <= MAX_UINT32) { + InternalQemuFwCfgDmaBytes ((UINT32)Size, Buffer, TRUE); + return; + } IoWriteFifo8 (0x511, Size, Buffer); } } @@ -265,39 +265,6 @@ QemuFwCfgRead64 ( } -RETURN_STATUS -EFIAPI -QemuFwCfgInitialize ( - VOID - ) -{ - UINT32 Signature; - UINT32 Revision; - - // - // Enable the access routines while probing to see if it is supported. - // - mQemuFwCfgSupported = TRUE; - - QemuFwCfgSelectItem (QemuFwCfgItemSignature); - Signature = QemuFwCfgRead32 (); - DEBUG ((EFI_D_INFO, "FW CFG Signature: 0x%x\n", Signature)); - QemuFwCfgSelectItem (QemuFwCfgItemInterfaceVersion); - Revision = QemuFwCfgRead32 (); - DEBUG ((EFI_D_INFO, "FW CFG Revision: 0x%x\n", Revision)); - if ((Signature != SIGNATURE_32 ('Q', 'E', 'M', 'U')) || - (Revision < 1) - ) { - DEBUG ((EFI_D_INFO, "QemuFwCfg interface not supported.\n")); - mQemuFwCfgSupported = FALSE; - return RETURN_SUCCESS; - } - - DEBUG ((EFI_D_INFO, "QemuFwCfg interface is supported.\n")); - return RETURN_SUCCESS; -} - - /** Find the configuration item corresponding to the firmware configuration file. @@ -333,11 +300,12 @@ QemuFwCfgFindFile ( UINT32 FileSize; UINT16 FileSelect; UINT16 FileReserved; - CHAR8 FName[56]; + CHAR8 FName[QEMU_FW_CFG_FNAME_SIZE]; FileSize = QemuFwCfgRead32 (); FileSelect = QemuFwCfgRead16 (); FileReserved = QemuFwCfgRead16 (); + (VOID) FileReserved; /* Force a do-nothing reference. */ InternalQemuFwCfgReadBytes (sizeof (FName), FName); if (AsciiStrCmp (Name, FName) == 0) { @@ -352,19 +320,28 @@ QemuFwCfgFindFile ( /** - Returns a boolean indicating if the firmware configuration interface is - available for library-internal purposes. + Determine if S3 support is explicitly enabled. - This function never changes fw_cfg state. - - @retval TRUE The interface is available internally. - @retval FALSE The interface is not available internally. + @retval TRUE if S3 support is explicitly enabled. + FALSE otherwise. This includes unavailability of the firmware + configuration interface. **/ BOOLEAN EFIAPI -InternalQemuFwCfgIsAvailable ( +QemuFwCfgS3Enabled ( VOID ) { - return mQemuFwCfgSupported; + RETURN_STATUS Status; + FIRMWARE_CONFIG_ITEM FwCfgItem; + UINTN FwCfgSize; + UINT8 SystemStates[6]; + + Status = QemuFwCfgFindFile ("etc/system-states", &FwCfgItem, &FwCfgSize); + if (Status != RETURN_SUCCESS || FwCfgSize != sizeof SystemStates) { + return FALSE; + } + QemuFwCfgSelectItem (FwCfgItem); + QemuFwCfgReadBytes (sizeof SystemStates, SystemStates); + return (BOOLEAN) (SystemStates[3] & BIT7); }