From f2bcdcd5540522a47aa23186f824d07a3bed9884 Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Thu, 2 Jun 2016 10:17:58 +0800 Subject: BraswellPlatformPkg: Add SmmIoLib Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Guo Mang --- BraswellPlatformPkg/Library/SmmIo/SmmIo.c | 355 +++++++++++++++++++++++++ BraswellPlatformPkg/Library/SmmIo/SmmIoLib.inf | 35 +++ BraswellPlatformPkg/Library/SmmIo/SmmPciIo.c | 162 +++++++++++ 3 files changed, 552 insertions(+) create mode 100644 BraswellPlatformPkg/Library/SmmIo/SmmIo.c create mode 100644 BraswellPlatformPkg/Library/SmmIo/SmmIoLib.inf create mode 100644 BraswellPlatformPkg/Library/SmmIo/SmmPciIo.c (limited to 'BraswellPlatformPkg') diff --git a/BraswellPlatformPkg/Library/SmmIo/SmmIo.c b/BraswellPlatformPkg/Library/SmmIo/SmmIo.c new file mode 100644 index 0000000000..3b0d4fc45d --- /dev/null +++ b/BraswellPlatformPkg/Library/SmmIo/SmmIo.c @@ -0,0 +1,355 @@ +/** @file + SMM I/O access utility implementation file, for Ia32 + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +// +// Include files +// +#include "Library/SmmIoLib.h" + +/** + Do a one byte IO read + + @param[in] Address IO address to read + + @return Data read + +**/ +UINT8 +SmmIoRead8 ( + IN UINT16 Address + ) +{ + UINT8 Buffer; + + ASSERT (mSmst); + + mSmst->SmmIo.Io.Read ( + &mSmst->SmmIo, + SMM_IO_UINT8, + Address, + 1, + &Buffer + ); + + return Buffer; +} + +/** + Do a one byte IO write + + @param[in] Address IO address to write + @param[in] Data Data to write + +**/ +VOID +SmmIoWrite8 ( + IN UINT16 Address, + IN UINT8 Data + ) +{ + ASSERT (mSmst); + + mSmst->SmmIo.Io.Write ( + &mSmst->SmmIo, + SMM_IO_UINT8, + Address, + 1, + &Data + ); +} + +/** + Do a two byte IO read + + @param[in] Address IO address to read + + @return Data read + +**/ +UINT16 +SmmIoRead16 ( + IN UINT16 Address + ) +{ + UINT16 Buffer; + + ASSERT (mSmst); + + mSmst->SmmIo.Io.Read ( + &mSmst->SmmIo, + SMM_IO_UINT16, + Address, + 1, + &Buffer + ); + + return Buffer; +} + +/** + Do a two byte IO write + + @param[in] Address IO address to write + @param[in] Data Data to write + +**/ +VOID +SmmIoWrite16 ( + IN UINT16 Address, + IN UINT16 Data + ) +{ + ASSERT (mSmst); + + mSmst->SmmIo.Io.Write ( + &mSmst->SmmIo, + SMM_IO_UINT16, + Address, + 1, + &Data + ); +} + +/** + Do a four byte IO read + + @param[in] Address IO address to read + + @retval Data read + +**/ +UINT32 +SmmIoRead32 ( + IN UINT16 Address + ) +{ + UINT32 Buffer; + + ASSERT (mSmst); + + mSmst->SmmIo.Io.Read ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Address, + 1, + &Buffer + ); + + return Buffer; +} + +/** + Do a four byte IO write + + @param[in] Address IO address to write + @param[in] Data Data to write + +**/ +VOID +SmmIoWrite32 ( + IN UINT16 Address, + IN UINT32 Data + ) +{ + ASSERT (mSmst); + + mSmst->SmmIo.Io.Write ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Address, + 1, + &Data + ); +} + +/** + Do a one byte Memory write + + @param[in] Dest Memory address to write + @param[in] Data Data to write + +**/ +VOID +SmmMemWrite8 ( + IN UINT64 Dest, + IN UINT8 Data + ) +{ + mSmst->SmmIo.Mem.Write ( + &mSmst->SmmIo, + SMM_IO_UINT8, + Dest, + 1, + &Data + ); + + return ; +} + +/** + Do a one byte Memory read + + @param[in] Dest Memory address to read + + @Return Data read + +**/ +UINT8 +SmmMemRead8 ( + IN UINT64 Dest + ) +{ + UINT8 Data; + mSmst->SmmIo.Mem.Read ( + &mSmst->SmmIo, + SMM_IO_UINT8, + Dest, + 1, + &Data + ); + + return Data; +} + +/** + Do a two bytes Memory write + + @param[in] Dest Memory address to write + @param[in] Data Data to write + +**/ +VOID +SmmMemWrite16 ( + IN UINT64 Dest, + IN UINT16 Data + ) +{ + mSmst->SmmIo.Mem.Write ( + &mSmst->SmmIo, + SMM_IO_UINT16, + Dest, + 1, + &Data + ); + + return ; +} + +/** + Do a two bytes Memory read + + @param[in] Dest Memory address to read + + @return Data read + +**/ +UINT16 +SmmMemRead16 ( + IN UINT64 Dest + ) +{ + UINT16 Data; + mSmst->SmmIo.Mem.Read ( + &mSmst->SmmIo, + SMM_IO_UINT16, + Dest, + 1, + &Data + ); + + return Data; +} + +/** + Do a four bytes Memory write + + @param[in] Dest Memory address to write + @param[in] Data Data to write + +**/ +VOID +SmmMemWrite32 ( + IN UINT64 Dest, + IN UINT32 Data + ) +{ + mSmst->SmmIo.Mem.Write ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Dest, + 1, + &Data + ); + + return ; +} + +/** + Do a four bytes Memory read + + @param[in] Dest Memory address to read + + @return Data read + +**/ +UINT32 +SmmMemRead32 ( + IN UINT64 Dest + ) +{ + UINT32 Data; + mSmst->SmmIo.Mem.Read ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Dest, + 1, + &Data + ); + + return Data; +} + +/** + Do a four bytes Memory read, then AND with Data, then write back to the same address + + @param[in] Dest Memory address to write + @param[in] Data Data to do AND + +**/ +VOID +SmmMemAnd32 ( + IN UINT64 Dest, + IN UINT32 Data + ) +{ + UINT32 Data_And; + mSmst->SmmIo.Mem.Read ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Dest, + 1, + &Data_And + ); + Data_And&=Data; + mSmst->SmmIo.Mem.Write ( + &mSmst->SmmIo, + SMM_IO_UINT32, + Dest, + 1, + &Data_And + ); + + return ; +} diff --git a/BraswellPlatformPkg/Library/SmmIo/SmmIoLib.inf b/BraswellPlatformPkg/Library/SmmIo/SmmIoLib.inf new file mode 100644 index 0000000000..17b5aa5d49 --- /dev/null +++ b/BraswellPlatformPkg/Library/SmmIo/SmmIoLib.inf @@ -0,0 +1,35 @@ +## @file +# Component description file for SMM IO Library. +# +# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.
+# +# 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. +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SmmIoLib + FILE_GUID = A6A16CCB-91B0-42f4-B4F3-D16D7A8662E6 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = SmmIoLib + +[Sources] + SmmIo.c + SmmPciIo.c + +[Packages] + MdePkg/MdePkg.dec + BraswellPlatformPkg/BraswellPlatformPkg.dec + +[LibraryClasses] + PciLib + IoLib + BaseLib diff --git a/BraswellPlatformPkg/Library/SmmIo/SmmPciIo.c b/BraswellPlatformPkg/Library/SmmIo/SmmPciIo.c new file mode 100644 index 0000000000..5af687e3b1 --- /dev/null +++ b/BraswellPlatformPkg/Library/SmmIo/SmmPciIo.c @@ -0,0 +1,162 @@ +/** @file + SMM PCI config space I/O access utility implementation file, for Ia32 + + Copyright (c) 1999 - 2015, Intel Corporation. All rights reserved.
+ + 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. + +**/ + +#include "Library/SmmIoLib.h" + +STATIC +EFI_STATUS +SmmSingleSegmentPciAccess ( + IN EFI_SMM_CPU_IO2_PROTOCOL *CpuIo, + IN BOOLEAN IsWrite, + IN SMM_PCI_IO_WIDTH Width, + IN SMM_PCI_IO_ADDRESS *Address, + IN OUT VOID *Buffer + ); + +/** + Read value from the specified PCI config space register + + @param[in] Width The width (8, 16 or 32 bits) of accessed pci config space register + @param[in] Address The address of the accessed pci register (bus, dev, func, offset) + @param[in, out] Buffer The returned value + + @retval EFI_SUCCESS All operations successfully + @retval EFI_INVALID_PARAMETER Width is not valid or dosn't match register address + @retval Other error code If any error occured when calling libiary functions + +**/ +EFI_STATUS +SmmPciCfgRead ( + IN SMM_PCI_IO_WIDTH Width, + IN SMM_PCI_IO_ADDRESS *Address, + IN OUT VOID *Buffer + ) +{ + EFI_SMM_CPU_IO2_PROTOCOL *SmmCpuIo; + + ASSERT (mSmst); + + SmmCpuIo = &(mSmst->SmmIo); + + return SmmSingleSegmentPciAccess (SmmCpuIo, FALSE, Width, Address, Buffer); +} + +/** + Write value into the specified PCI config space register + + @param[in] Width The width (8, 16 or 32 bits) of accessed pci config space register + @param[in] Address The address of the accessed pci register (bus, dev, func, offset) + @param[in, out] Buffer The returned value + + @retval EFI_SUCCESS All operations successfully + @retval EFI_INVALID_PARAMETER Width is not valid or dosn't match register address + @retval Other error code If any error occured when calling libiary functions + +**/ +EFI_STATUS +SmmPciCfgWrite ( + IN SMM_PCI_IO_WIDTH Width, + IN SMM_PCI_IO_ADDRESS *Address, + IN OUT VOID *Buffer + ) +{ + EFI_SMM_CPU_IO2_PROTOCOL *SmmCpuIo; + + ASSERT (mSmst); + + SmmCpuIo = &(mSmst->SmmIo); + + return SmmSingleSegmentPciAccess (SmmCpuIo, TRUE, Width, Address, Buffer); +} + +/** + Access a PCI config space address, including read and write + + @param[in] CpuIo The cpu I/O accessing interface provided by EFI runtime sys table + @param[in] IsWrite Indicates whether this operation is a write access or read + @param[in] Width The width (8, 16 or 32 bits) of accessed pci config space register + @param[in] Address The address of the accessed pci register (bus, dev, func, offset) + @param[in, out] Buffer The returned value when this is a reading operation or the data + to be written when this is a writing one + + @retval EFI_SUCCESS All operations successfully + @retval EFI_INVALID_PARAMETER Width is not valid or dosn't match register address + @retval Other error code If any error occured when calling libiary functions + +**/ +STATIC +EFI_STATUS +SmmSingleSegmentPciAccess ( + IN EFI_SMM_CPU_IO2_PROTOCOL *CpuIo, + IN BOOLEAN IsWrite, + IN SMM_PCI_IO_WIDTH Width, + IN SMM_PCI_IO_ADDRESS *Address, + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + PCI_CONFIG_ACCESS_CF8 PciCf8Data; + UINT64 PciDataReg; + + // + // PCI Config access are all 32-bit alligned, but by accessing the + // CONFIG_DATA_REGISTER (0xcfc) with different widths more cycle types + // are possible on PCI. + // + // To read a byte of PCI config space you load 0xcf8 and + // read 0xcfc, 0xcfd, 0xcfe, 0xcff + // + // The validation of passed in arguments "Address" will be checked in the + // CPU IO functions, so we don't check them here + // + + if (Width >= SmmPciWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + PciCf8Data.Bits.Reg = Address->Register & 0xfc; + PciCf8Data.Bits.Func = Address->Function; + PciCf8Data.Bits.Dev = Address->Device; + PciCf8Data.Bits.Bus = Address->Bus; + PciCf8Data.Bits.Reserved = 0; + PciCf8Data.Bits.Enable = 1; + + Status = CpuIo->Io.Write (CpuIo, SmmPciWidthUint32, 0xcf8, 1, &PciCf8Data); + if (EFI_ERROR (Status)) { + return Status; + } + + PciDataReg = 0xcfc + (Address->Register & 0x03); + + if (IsWrite) { + // + // This is a Pci write operation, write data into (0xcfc + offset) + // + Status = CpuIo->Io.Write (CpuIo, Width, PciDataReg, 1, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + // + // This is a Pci Read operation, read returned data from (0xcfc + offset) + // + Status = CpuIo->Io.Read (CpuIo, Width, PciDataReg, 1, Buffer); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; +} -- cgit v1.2.3