public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap
@ 2018-02-21 15:25 Leif Lindholm
  2018-02-21 15:56 ` Laszlo Ersek
  2018-02-21 18:09 ` Ard Biesheuvel
  0 siblings, 2 replies; 4+ messages in thread
From: Leif Lindholm @ 2018-02-21 15:25 UTC (permalink / raw)
  To: edk2-devel
  Cc: Michael D Kinney, Liming Gao, Meenakshi Aggarwal, udit.kumar,
	v.sethi, ard.biesheuvel

When performing MMIO to a destination of the opposite endianness to the
executing processor, this library provides automatic byte order reversal
on inputs and outputs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
---

As promised in the dark and distant past:
https://www.mail-archive.com/edk2-devel@lists.01.org/msg33447.html

This starts out as a clone of MdePkg/Include/Library/IoLib.h,
implementing simple wrappers that depend on an IoLib instance to perform
any actual accesses.

Comments are mostly nonsense, since they've not been changed from their
originals in IoLib.h. If people feel this library is a sensible approach,
I'll fix that up before I send a v1.

I have explicitly excluded:
- non-MMIO accesses (could you really end up with mixed endianness in
  such a system?)
- bitfields (would either require duplicating code or merging this all
  into the BaseIoLibIntrinsic module, which is already a bit on the
  bloated side)
- buffers operations (let's avoid those until we find we need them)

MdePkg/Include/Library/IoLibSwap.h             | 395 ++++++++++++++++++++
 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf |  44 +++
 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni |  23 ++
 MdePkg/Library/BaseIoLibSwap/IoLibSwap.c       | 491 +++++++++++++++++++++++++
 MdePkg/MdePkg.dec                              |   3 +
 MdePkg/MdePkg.dsc                              |   1 +
 6 files changed, 957 insertions(+)
 create mode 100644 MdePkg/Include/Library/IoLibSwap.h
 create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
 create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
 create mode 100644 MdePkg/Library/BaseIoLibSwap/IoLibSwap.c

diff --git a/MdePkg/Include/Library/IoLibSwap.h b/MdePkg/Include/Library/IoLibSwap.h
new file mode 100644
index 0000000000..f13c8d86e7
--- /dev/null
+++ b/MdePkg/Include/Library/IoLibSwap.h
@@ -0,0 +1,395 @@
+/** @file
+  Provide byte-swapping services to access MMIO registers.
+
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
+
+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 __IO_LIB_SWAP_H__
+#define __IO_LIB_SWAP_H__
+
+/**
+  Reads a 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT16
+EFIAPI
+SwapMmioRead16 (
+  IN      UINTN                     Address
+  );
+
+/**
+  Writes a 16-bit MMIO register.
+
+  Writes the 16-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+  @return Value.
+
+**/
+UINT16
+EFIAPI
+SwapMmioWrite16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    Value
+  );
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 16-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    OrData
+  );
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 16-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioAnd16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData
+  );
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 16-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  );
+
+/**
+  Reads a 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT32
+EFIAPI
+SwapMmioRead32 (
+  IN      UINTN                     Address
+  );
+
+/**
+  Writes a 32-bit MMIO register.
+
+  Writes the 32-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+  @return Value.
+
+**/
+UINT32
+EFIAPI
+SwapMmioWrite32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    Value
+  );
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 32-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    OrData
+  );
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 32-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioAnd32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData
+  );
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 32-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  );
+
+/**
+  Reads a 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT64
+EFIAPI
+SwapMmioRead64 (
+  IN      UINTN                     Address
+  );
+
+/**
+  Writes a 64-bit MMIO register.
+
+  Writes the 64-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioWrite64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    Value
+  );
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 64-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioOr64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    OrData
+  );
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 64-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioAnd64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    AndData
+  );
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 64-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioAndThenOr64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    AndData,
+  IN      UINT64                    OrData
+  );
+
+#endif
+
diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
new file mode 100644
index 0000000000..59d774dc97
--- /dev/null
+++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
@@ -0,0 +1,44 @@
+## @file
+#  Byte swapping I/O Library.
+#
+#  Byte swapping I/O Library for all architectures. Only MMIO supported. I/O
+#  accesses take place through the normal IoLib, but values read and written
+#  are byte-reversed to interact with peripherals of non-native endianness.
+#
+#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
+#  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
+#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+#
+#  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                    = 0x0001001a
+  BASE_NAME                      = BaseIoLibSwap
+  MODULE_UNI_FILE                = BaseIoLibSwap.uni
+  FILE_GUID                      = 073c3fbd-ff0d-41b6-a209-1e42fd2a3bab
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = IoLibSwap
+
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 EBC IPF ARM AARCH64
+#
+
+[Sources]
+  IoLibSwap.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+
+[LibraryClasses]
+  BaseLib
+#  DebugLib
+  IoLib
diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
new file mode 100644
index 0000000000..e35b4abef7
--- /dev/null
+++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
@@ -0,0 +1,23 @@
+// /** @file
+// Byte swapping I/O Library.
+//
+// Byte swapping I/O Library for all architectures. Only MMIO supported. I/O
+// accesses take place through the normal IoLib, but values read and written
+// are byte-reversed to interact with peripherals of non-native endianness.
+//
+// Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Byte swapping I/O Library"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Byte swapping I/O Library for all architectures. Only MMIO supported. I/O accesses take place through the normal IoLib, but values read and written are byte-reversed to interact with peripherals of non-native endianness."
+
diff --git a/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
new file mode 100644
index 0000000000..6eb675de20
--- /dev/null
+++ b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
@@ -0,0 +1,491 @@
+/** @file
+  Provide byte-swapping services to access MMIO registers.
+
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
+Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
+
+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/BaseLib.h>
+#include <Library/IoLib.h>
+
+/**
+  Reads a 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT16
+EFIAPI
+SwapMmioRead16 (
+  IN      UINTN                     Address
+  )
+{
+  return SwapBytes16 (MmioRead16 (Address));
+}
+
+/**
+  Writes a 16-bit MMIO register.
+
+  Writes the 16-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+  @return Value.
+
+**/
+UINT16
+EFIAPI
+SwapMmioWrite16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    Value
+  )
+{
+  (VOID) MmioWrite16 (Address, SwapBytes16 (Value));
+
+  return Value;
+}
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 16-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    OrData
+  )
+{
+  UINT16 Value;
+
+  Value = SwapMmioRead16 (Address);
+  Value |= OrData;
+
+  return SwapMmioWrite16 (Address, Value);
+}
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 16-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioAnd16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData
+  )
+{
+  UINT16 Value;
+
+  Value = SwapMmioRead16 (Address);
+  Value &= AndData;
+
+  return SwapMmioWrite16 (Address, Value);
+}
+
+/**
+  Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 16-bit MMIO register.
+
+  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 16-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 16-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 16-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT16
+EFIAPI
+SwapMmioAndThenOr16 (
+  IN      UINTN                     Address,
+  IN      UINT16                    AndData,
+  IN      UINT16                    OrData
+  )
+{
+  UINT16 Value;
+
+  Value = SwapMmioRead16 (Address);
+  Value &= AndData;
+  Value |= OrData;
+
+  return SwapMmioWrite16 (Address, Value);
+}
+
+/**
+  Reads a 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT32
+EFIAPI
+SwapMmioRead32 (
+  IN      UINTN                     Address
+  )
+{
+  return SwapBytes32 (MmioRead32 (Address));
+}
+
+/**
+  Writes a 32-bit MMIO register.
+
+  Writes the 32-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+  @return Value.
+
+**/
+UINT32
+EFIAPI
+SwapMmioWrite32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    Value
+  )
+{
+  (VOID) MmioWrite32 (Address, SwapBytes32 (Value));
+
+  return Value;
+}
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 32-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    OrData
+  )
+{
+  UINT32 Value;
+
+  Value = SwapMmioRead32 (Address);
+  Value |= OrData;
+
+  return SwapMmioWrite32 (Address, Value);
+}
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 32-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioAnd32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData
+  )
+{
+  UINT32 Value;
+
+  Value = SwapMmioRead32 (Address);
+  Value &= AndData;
+
+  return SwapMmioWrite32 (Address, Value);
+}
+
+/**
+  Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 32-bit MMIO register.
+
+  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 32-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 32-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 32-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT32
+EFIAPI
+SwapMmioAndThenOr32 (
+  IN      UINTN                     Address,
+  IN      UINT32                    AndData,
+  IN      UINT32                    OrData
+  )
+{
+  UINT32 Value;
+
+  Value = SwapMmioRead32 (Address);
+  Value &= AndData;
+  Value |= OrData;
+
+  return SwapMmioWrite32 (Address, Value);
+}
+
+/**
+  Reads a 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
+  returned. This function must guarantee that all MMIO read and write
+  operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to read.
+
+  @return The value read.
+
+**/
+UINT64
+EFIAPI
+SwapMmioRead64 (
+  IN      UINTN                     Address
+  )
+{
+  return SwapBytes64 (MmioRead64 (Address));
+}
+
+/**
+  Writes a 64-bit MMIO register.
+
+  Writes the 64-bit MMIO register specified by Address with the value specified
+  by Value and returns Value. This function must guarantee that all MMIO read
+  and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  Value   The value to write to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioWrite64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    Value
+  )
+{
+  (VOID) MmioWrite64 (Address, SwapBytes64 (Value));
+
+  return Value;
+}
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
+  result back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise
+  OR between the read result and the value specified by OrData, and
+  writes the result to the 64-bit MMIO register specified by Address. The value
+  written to the MMIO register is returned. This function must guarantee that
+  all MMIO read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  OrData  The value to OR with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioOr64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    OrData
+  )
+{
+  UINT64 Value;
+
+  Value = SwapMmioRead64 (Address);
+  Value |= OrData;
+
+  return SwapMmioWrite64 (Address, Value);
+}
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result
+  back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, and writes the
+  result to the 64-bit MMIO register specified by Address. The value written to
+  the MMIO register is returned. This function must guarantee that all MMIO
+  read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioAnd64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    AndData
+  )
+{
+  UINT64 Value;
+
+  Value = SwapMmioRead64 (Address);
+  Value &= AndData;
+
+  return SwapMmioWrite64 (Address, Value);
+}
+
+/**
+  Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise
+  OR, and writes the result back to the 64-bit MMIO register.
+
+  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
+  between the read result and the value specified by AndData, performs a
+  bitwise OR between the result of the AND operation and the value specified by
+  OrData, and writes the result to the 64-bit MMIO register specified by
+  Address. The value written to the MMIO register is returned. This function
+  must guarantee that all MMIO read and write operations are serialized.
+
+  If 64-bit MMIO register operations are not supported, then ASSERT().
+  If Address is not aligned on a 64-bit boundary, then ASSERT().
+
+  @param  Address The MMIO register to write.
+  @param  AndData The value to AND with the read value from the MMIO register.
+  @param  OrData  The value to OR with the result of the AND operation.
+
+  @return The value written back to the MMIO register.
+
+**/
+UINT64
+EFIAPI
+SwapMmioAndThenOr64 (
+  IN      UINTN                     Address,
+  IN      UINT64                    AndData,
+  IN      UINT64                    OrData
+  )
+{
+  UINT64 Value;
+
+  Value = SwapMmioRead64 (Address);
+  Value &= AndData;
+  Value |= OrData;
+
+  return SwapMmioWrite64 (Address, Value);
+}
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 0e64f22f4a..98016f47e9 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -160,6 +160,9 @@ [LibraryClasses]
   ##  @libraryclass  Provide services to access I/O Ports and MMIO registers.
   IoLib|Include/Library/IoLib.h
 
+  ##  @libraryclass  Provide byte-swapping services to access MMIO registers.
+  IoLibSwap|Include/Library/IoLibSwap.h
+
   ##  @libraryclass  Provide services to create, get and update HSTI table in AIP protocol.
   HstiLib|Include/Library/HstiLib.h
 
diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
index 60efd722e9..a2f2696394 100644
--- a/MdePkg/MdePkg.dsc
+++ b/MdePkg/MdePkg.dsc
@@ -60,6 +60,7 @@ [Components]
   MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
   MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
   MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
   MdePkg/Library/BaseLib/BaseLib.inf
   MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
   MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
-- 
2.11.0



^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap
  2018-02-21 15:25 [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap Leif Lindholm
@ 2018-02-21 15:56 ` Laszlo Ersek
  2018-02-21 18:09 ` Ard Biesheuvel
  1 sibling, 0 replies; 4+ messages in thread
From: Laszlo Ersek @ 2018-02-21 15:56 UTC (permalink / raw)
  To: Leif Lindholm; +Cc: edk2-devel, ard.biesheuvel, Liming Gao, Michael D Kinney

On 02/21/18 16:25, Leif Lindholm wrote:
> When performing MMIO to a destination of the opposite endianness to the
> executing processor, this library provides automatic byte order reversal
> on inputs and outputs.
> 
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> ---
> 
> As promised in the dark and distant past:
> https://www.mail-archive.com/edk2-devel@lists.01.org/msg33447.html
> 
> This starts out as a clone of MdePkg/Include/Library/IoLib.h,
> implementing simple wrappers that depend on an IoLib instance to perform
> any actual accesses.
> 
> Comments are mostly nonsense, since they've not been changed from their
> originals in IoLib.h. If people feel this library is a sensible approach,
> I'll fix that up before I send a v1.
> 
> I have explicitly excluded:
> - non-MMIO accesses (could you really end up with mixed endianness in
>   such a system?)
> - bitfields (would either require duplicating code or merging this all
>   into the BaseIoLibIntrinsic module, which is already a bit on the
>   bloated side)
> - buffers operations (let's avoid those until we find we need them)
> 
> MdePkg/Include/Library/IoLibSwap.h             | 395 ++++++++++++++++++++
>  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf |  44 +++
>  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni |  23 ++
>  MdePkg/Library/BaseIoLibSwap/IoLibSwap.c       | 491 +++++++++++++++++++++++++
>  MdePkg/MdePkg.dec                              |   3 +
>  MdePkg/MdePkg.dsc                              |   1 +
>  6 files changed, 957 insertions(+)
>  create mode 100644 MdePkg/Include/Library/IoLibSwap.h
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/IoLibSwap.c

UEFI drivers are supposed to go through PciIo instances in order to
access config space and MMIO registers of PCI devices (and I assume most
devices are PCI), and the related PciIo member functions are LE-only.
Thus, in such device drivers (for the exceptional(?) PCI device that has
custom BE registers), the byte swapping will have to occur at the call
sites (or at least higher-level wrapper functions).

Which makes me think that this library is primarily for BE platform
devices that are exposed via DXE drivers or (maybe) PEIMs. Is that
corect? If so, can you please state it in the commit message?

Also I would suggest calling the new functions "BE" or "BigEndian" or
something similar -- once we turn this into a lib class, byte swapping
becomes an implementation detail. The API should reflect the goal, which
is "talking to BE platform devices".

The @file comments should be updated similarly, IMO; "non-native
endianness" should simply be "big endian", and the swapping language
should be dropped -- for PI/UEFI, only LE is native (it is hard-coded by
the spec(s), IIRC).

... Another superficial comment: in the INF file, there's a commented
out DebugLib entry under [LibraryClasses]; I guess that's unintended.

To clarify, I'm neutral on this library, I'd just like its documentation
to be clear on when someone should consider using it.

Thanks!
Laszlo


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap
  2018-02-21 15:25 [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap Leif Lindholm
  2018-02-21 15:56 ` Laszlo Ersek
@ 2018-02-21 18:09 ` Ard Biesheuvel
  2018-02-22  4:51   ` Udit Kumar
  1 sibling, 1 reply; 4+ messages in thread
From: Ard Biesheuvel @ 2018-02-21 18:09 UTC (permalink / raw)
  To: Leif Lindholm
  Cc: edk2-devel@lists.01.org, Michael D Kinney, Liming Gao,
	Meenakshi Aggarwal, Udit Kumar, Varun Sethi

On 21 February 2018 at 15:25, Leif Lindholm <leif.lindholm@linaro.org> wrote:
> When performing MMIO to a destination of the opposite endianness to the
> executing processor, this library provides automatic byte order reversal
> on inputs and outputs.
>

As pointed out by Laszlo, 'opposite' is ill defined, as it is not a
property of the device nor is it a property of the CPU/platform (even
though UEFI is likely to remain little endian for the foreseeable
future)

So BigEndianIoLib seems more appropriate as a library class, and it
does need to be a separate class so that a single driver can perform
both LE and BE MMIO (which, as was pointed out, is the case for any
driver that drives a BE MMIO peripheral but uses LE MMIO for serial
port DEBUG output)



> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> ---
>
> As promised in the dark and distant past:
> https://www.mail-archive.com/edk2-devel@lists.01.org/msg33447.html
>
> This starts out as a clone of MdePkg/Include/Library/IoLib.h,
> implementing simple wrappers that depend on an IoLib instance to perform
> any actual accesses.
>
> Comments are mostly nonsense, since they've not been changed from their
> originals in IoLib.h. If people feel this library is a sensible approach,
> I'll fix that up before I send a v1.
>
> I have explicitly excluded:
> - non-MMIO accesses (could you really end up with mixed endianness in
>   such a system?)
> - bitfields (would either require duplicating code or merging this all
>   into the BaseIoLibIntrinsic module, which is already a bit on the
>   bloated side)
> - buffers operations (let's avoid those until we find we need them)
>
> MdePkg/Include/Library/IoLibSwap.h             | 395 ++++++++++++++++++++

If you create a library class, please declare it in the .dec file

>  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf |  44 +++
>  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni |  23 ++
>  MdePkg/Library/BaseIoLibSwap/IoLibSwap.c       | 491 +++++++++++++++++++++++++
>  MdePkg/MdePkg.dec                              |   3 +
>  MdePkg/MdePkg.dsc                              |   1 +
>  6 files changed, 957 insertions(+)
>  create mode 100644 MdePkg/Include/Library/IoLibSwap.h
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
>  create mode 100644 MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
>
> diff --git a/MdePkg/Include/Library/IoLibSwap.h b/MdePkg/Include/Library/IoLibSwap.h
> new file mode 100644
> index 0000000000..f13c8d86e7
> --- /dev/null
> +++ b/MdePkg/Include/Library/IoLibSwap.h
> @@ -0,0 +1,395 @@
> +/** @file
> +  Provide byte-swapping services to access MMIO registers.
> +
> +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
> +
> +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 __IO_LIB_SWAP_H__
> +#define __IO_LIB_SWAP_H__
> +
> +/**
> +  Reads a 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioRead16 (
> +  IN      UINTN                     Address
> +  );
> +
> +/**
> +  Writes a 16-bit MMIO register.
> +
> +  Writes the 16-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +  @return Value.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    Value
> +  );
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 16-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    OrData
> +  );
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 16-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData
> +  );
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 16-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  );
> +
> +/**
> +  Reads a 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioRead32 (
> +  IN      UINTN                     Address
> +  );
> +
> +/**
> +  Writes a 32-bit MMIO register.
> +
> +  Writes the 32-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +  @return Value.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    Value
> +  );
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 32-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    OrData
> +  );
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 32-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData
> +  );
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 32-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  );
> +
> +/**
> +  Reads a 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioRead64 (
> +  IN      UINTN                     Address
> +  );
> +
> +/**
> +  Writes a 64-bit MMIO register.
> +
> +  Writes the 64-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioWrite64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    Value
> +  );
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 64-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioOr64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    OrData
> +  );
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 64-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioAnd64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    AndData
> +  );
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 64-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioAndThenOr64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    AndData,
> +  IN      UINT64                    OrData
> +  );
> +
> +#endif
> +
> diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> new file mode 100644
> index 0000000000..59d774dc97
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> @@ -0,0 +1,44 @@
> +## @file
> +#  Byte swapping I/O Library.
> +#
> +#  Byte swapping I/O Library for all architectures. Only MMIO supported. I/O
> +#  accesses take place through the normal IoLib, but values read and written
> +#  are byte-reversed to interact with peripherals of non-native endianness.
> +#
> +#  Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
> +#  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
> +#  Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +#
> +#  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                    = 0x0001001a
> +  BASE_NAME                      = BaseIoLibSwap
> +  MODULE_UNI_FILE                = BaseIoLibSwap.uni
> +  FILE_GUID                      = 073c3fbd-ff0d-41b6-a209-1e42fd2a3bab
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = IoLibSwap
> +
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 EBC IPF ARM AARCH64
> +#
> +
> +[Sources]
> +  IoLibSwap.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +#  DebugLib
> +  IoLib
> diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> new file mode 100644
> index 0000000000..e35b4abef7
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> @@ -0,0 +1,23 @@
> +// /** @file
> +// Byte swapping I/O Library.
> +//
> +// Byte swapping I/O Library for all architectures. Only MMIO supported. I/O
> +// accesses take place through the normal IoLib, but values read and written
> +// are byte-reversed to interact with peripherals of non-native endianness.
> +//
> +// Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
> +//
> +// 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.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Byte swapping I/O Library"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "Byte swapping I/O Library for all architectures. Only MMIO supported. I/O accesses take place through the normal IoLib, but values read and written are byte-reversed to interact with peripherals of non-native endianness."
> +
> diff --git a/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> new file mode 100644
> index 0000000000..6eb675de20
> --- /dev/null
> +++ b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> @@ -0,0 +1,491 @@
> +/** @file
> +  Provide byte-swapping services to access MMIO registers.
> +
> +Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
> +Copyright (c) 2018, Linaro ltd. All rights reserved.<BR>
> +
> +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/BaseLib.h>
> +#include <Library/IoLib.h>
> +
> +/**
> +  Reads a 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address. The 16-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioRead16 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return SwapBytes16 (MmioRead16 (Address));
> +}
> +
> +/**
> +  Writes a 16-bit MMIO register.
> +
> +  Writes the 16-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +  @return Value.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioWrite16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    Value
> +  )
> +{
> +  (VOID) MmioWrite16 (Address, SwapBytes16 (Value));
> +
> +  return Value;
> +}
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 16-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  UINT16 Value;
> +
> +  Value = SwapMmioRead16 (Address);
> +  Value |= OrData;
> +
> +  return SwapMmioWrite16 (Address, Value);
> +}
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 16-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioAnd16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData
> +  )
> +{
> +  UINT16 Value;
> +
> +  Value = SwapMmioRead16 (Address);
> +  Value &= AndData;
> +
> +  return SwapMmioWrite16 (Address, Value);
> +}
> +
> +/**
> +  Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 16-bit MMIO register.
> +
> +  Reads the 16-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 16-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 16-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT16
> +EFIAPI
> +SwapMmioAndThenOr16 (
> +  IN      UINTN                     Address,
> +  IN      UINT16                    AndData,
> +  IN      UINT16                    OrData
> +  )
> +{
> +  UINT16 Value;
> +
> +  Value = SwapMmioRead16 (Address);
> +  Value &= AndData;
> +  Value |= OrData;
> +
> +  return SwapMmioWrite16 (Address, Value);
> +}
> +
> +/**
> +  Reads a 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address. The 32-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioRead32 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return SwapBytes32 (MmioRead32 (Address));
> +}
> +
> +/**
> +  Writes a 32-bit MMIO register.
> +
> +  Writes the 32-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +  @return Value.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioWrite32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    Value
> +  )
> +{
> +  (VOID) MmioWrite32 (Address, SwapBytes32 (Value));
> +
> +  return Value;
> +}
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 32-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  UINT32 Value;
> +
> +  Value = SwapMmioRead32 (Address);
> +  Value |= OrData;
> +
> +  return SwapMmioWrite32 (Address, Value);
> +}
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 32-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioAnd32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData
> +  )
> +{
> +  UINT32 Value;
> +
> +  Value = SwapMmioRead32 (Address);
> +  Value &= AndData;
> +
> +  return SwapMmioWrite32 (Address, Value);
> +}
> +
> +/**
> +  Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 32-bit MMIO register.
> +
> +  Reads the 32-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 32-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 32-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT32
> +EFIAPI
> +SwapMmioAndThenOr32 (
> +  IN      UINTN                     Address,
> +  IN      UINT32                    AndData,
> +  IN      UINT32                    OrData
> +  )
> +{
> +  UINT32 Value;
> +
> +  Value = SwapMmioRead32 (Address);
> +  Value &= AndData;
> +  Value |= OrData;
> +
> +  return SwapMmioWrite32 (Address, Value);
> +}
> +
> +/**
> +  Reads a 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address. The 64-bit read value is
> +  returned. This function must guarantee that all MMIO read and write
> +  operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to read.
> +
> +  @return The value read.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioRead64 (
> +  IN      UINTN                     Address
> +  )
> +{
> +  return SwapBytes64 (MmioRead64 (Address));
> +}
> +
> +/**
> +  Writes a 64-bit MMIO register.
> +
> +  Writes the 64-bit MMIO register specified by Address with the value specified
> +  by Value and returns Value. This function must guarantee that all MMIO read
> +  and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  Value   The value to write to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioWrite64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    Value
> +  )
> +{
> +  (VOID) MmioWrite64 (Address, SwapBytes64 (Value));
> +
> +  return Value;
> +}
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
> +  result back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise
> +  OR between the read result and the value specified by OrData, and
> +  writes the result to the 64-bit MMIO register specified by Address. The value
> +  written to the MMIO register is returned. This function must guarantee that
> +  all MMIO read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  OrData  The value to OR with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioOr64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    OrData
> +  )
> +{
> +  UINT64 Value;
> +
> +  Value = SwapMmioRead64 (Address);
> +  Value |= OrData;
> +
> +  return SwapMmioWrite64 (Address, Value);
> +}
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result
> +  back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, and writes the
> +  result to the 64-bit MMIO register specified by Address. The value written to
> +  the MMIO register is returned. This function must guarantee that all MMIO
> +  read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioAnd64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    AndData
> +  )
> +{
> +  UINT64 Value;
> +
> +  Value = SwapMmioRead64 (Address);
> +  Value &= AndData;
> +
> +  return SwapMmioWrite64 (Address, Value);
> +}
> +
> +/**
> +  Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise
> +  OR, and writes the result back to the 64-bit MMIO register.
> +
> +  Reads the 64-bit MMIO register specified by Address, performs a bitwise AND
> +  between the read result and the value specified by AndData, performs a
> +  bitwise OR between the result of the AND operation and the value specified by
> +  OrData, and writes the result to the 64-bit MMIO register specified by
> +  Address. The value written to the MMIO register is returned. This function
> +  must guarantee that all MMIO read and write operations are serialized.
> +
> +  If 64-bit MMIO register operations are not supported, then ASSERT().
> +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> +
> +  @param  Address The MMIO register to write.
> +  @param  AndData The value to AND with the read value from the MMIO register.
> +  @param  OrData  The value to OR with the result of the AND operation.
> +
> +  @return The value written back to the MMIO register.
> +
> +**/
> +UINT64
> +EFIAPI
> +SwapMmioAndThenOr64 (
> +  IN      UINTN                     Address,
> +  IN      UINT64                    AndData,
> +  IN      UINT64                    OrData
> +  )
> +{
> +  UINT64 Value;
> +
> +  Value = SwapMmioRead64 (Address);
> +  Value &= AndData;
> +  Value |= OrData;
> +
> +  return SwapMmioWrite64 (Address, Value);
> +}
> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
> index 0e64f22f4a..98016f47e9 100644
> --- a/MdePkg/MdePkg.dec
> +++ b/MdePkg/MdePkg.dec
> @@ -160,6 +160,9 @@ [LibraryClasses]
>    ##  @libraryclass  Provide services to access I/O Ports and MMIO registers.
>    IoLib|Include/Library/IoLib.h
>
> +  ##  @libraryclass  Provide byte-swapping services to access MMIO registers.
> +  IoLibSwap|Include/Library/IoLibSwap.h
> +
>    ##  @libraryclass  Provide services to create, get and update HSTI table in AIP protocol.
>    HstiLib|Include/Library/HstiLib.h
>
> diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc
> index 60efd722e9..a2f2696394 100644
> --- a/MdePkg/MdePkg.dsc
> +++ b/MdePkg/MdePkg.dsc
> @@ -60,6 +60,7 @@ [Components]
>    MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
>    MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
>    MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
> +  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
>    MdePkg/Library/BaseLib/BaseLib.inf
>    MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
>    MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollectionRedBlackTreeLib.inf
> --
> 2.11.0
>


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap
  2018-02-21 18:09 ` Ard Biesheuvel
@ 2018-02-22  4:51   ` Udit Kumar
  0 siblings, 0 replies; 4+ messages in thread
From: Udit Kumar @ 2018-02-22  4:51 UTC (permalink / raw)
  To: Ard Biesheuvel, Leif Lindholm
  Cc: edk2-devel@lists.01.org, Michael D Kinney, Liming Gao,
	Meenakshi Aggarwal, Varun Sethi

Hi Ard. 

> -----Original Message-----
> From: Ard Biesheuvel [mailto:ard.biesheuvel@linaro.org]
> Sent: Wednesday, February 21, 2018 11:39 PM
> To: Leif Lindholm <leif.lindholm@linaro.org>
> Cc: edk2-devel@lists.01.org; Michael D Kinney
> <michael.d.kinney@intel.com>; Liming Gao <liming.gao@intel.com>;
> Meenakshi Aggarwal <meenakshi.aggarwal@nxp.com>; Udit Kumar
> <udit.kumar@nxp.com>; Varun Sethi <V.Sethi@nxp.com>
> Subject: Re: [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap
> 
> On 21 February 2018 at 15:25, Leif Lindholm <leif.lindholm@linaro.org>
> wrote:
> > When performing MMIO to a destination of the opposite endianness to
> > the executing processor, this library provides automatic byte order
> > reversal on inputs and outputs.
> >
> 
> As pointed out by Laszlo, 'opposite' is ill defined, as it is not a property of
> the device nor is it a property of the CPU/platform (even though UEFI is
> likely to remain little endian for the foreseeable
> future)

Is this assumption, of part of UEFI specs ?
 
> So BigEndianIoLib seems more appropriate as a library class, and it does
> need to be a separate class so that a single driver can perform both LE and
> BE MMIO (which, as was pointed out, is the case for any driver that drives a
> BE MMIO peripheral but uses LE MMIO for serial port DEBUG output)

Yes, We need two lib here, we can discuss on name.

Thanks 
Udit 

> 
> 
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > Signed-off-by: Leif Lindholm <leif.lindholm@linaro.org>
> > ---
> >
> > As promised in the dark and distant past:
> >
> https://emea01.safelinks.protection.outlook.com/?url=https%3A%2F%2Fww
> w
> > .mail-archive.com%2Fedk2-
> devel%40lists.01.org%2Fmsg33447.html&data=02%
> >
> 7C01%7Cudit.kumar%40nxp.com%7C503430fe81e544d1df8b08d57956346f%7
> C686ea
> >
> 1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C636548333521065509&sdata=
> AR1g64t
> > C4ag8V18MYGN5bimkXe7FQj%2BEYbzONr%2BLFXM%3D&reserved=0
> >
> > This starts out as a clone of MdePkg/Include/Library/IoLib.h,
> > implementing simple wrappers that depend on an IoLib instance to
> > perform any actual accesses.
> >
> > Comments are mostly nonsense, since they've not been changed from
> > their originals in IoLib.h. If people feel this library is a sensible
> > approach, I'll fix that up before I send a v1.
> >
> > I have explicitly excluded:
> > - non-MMIO accesses (could you really end up with mixed endianness in
> >   such a system?)
> > - bitfields (would either require duplicating code or merging this all
> >   into the BaseIoLibIntrinsic module, which is already a bit on the
> >   bloated side)
> > - buffers operations (let's avoid those until we find we need them)
> >
> > MdePkg/Include/Library/IoLibSwap.h             | 395 ++++++++++++++++++++
> 
> If you create a library class, please declare it in the .dec file
> 
> >  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf |  44 +++
> > MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni |  23 ++
> >  MdePkg/Library/BaseIoLibSwap/IoLibSwap.c       | 491
> +++++++++++++++++++++++++
> >  MdePkg/MdePkg.dec                              |   3 +
> >  MdePkg/MdePkg.dsc                              |   1 +
> >  6 files changed, 957 insertions(+)
> >  create mode 100644 MdePkg/Include/Library/IoLibSwap.h
> >  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> >  create mode 100644 MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> >  create mode 100644 MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> >
> > diff --git a/MdePkg/Include/Library/IoLibSwap.h
> > b/MdePkg/Include/Library/IoLibSwap.h
> > new file mode 100644
> > index 0000000000..f13c8d86e7
> > --- /dev/null
> > +++ b/MdePkg/Include/Library/IoLibSwap.h
> > @@ -0,0 +1,395 @@
> > +/** @file
> > +  Provide byte-swapping services to access MMIO registers.
> > +
> > +Copyright (c) 2006 - 2012, Intel Corporation. All rights
> > +reserved.<BR> Copyright (c) 2017, AMD Incorporated. All rights
> > +reserved.<BR> Copyright (c) 2018, Linaro ltd. All rights
> > +reserved.<BR>
> > +
> > +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
> >
> +https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> > +nsource.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40
> >
> +nxp.com%7C503430fe81e544d1df8b08d57956346f%7C686ea1d3bc2b4c6fa9
> 2cd99c
> >
> +5c301635%7C0%7C0%7C636548333521065509&sdata=gW0hj%2FR0rTXl%2Bl
> Jr6mAiu
> > +aGSy7ZHoxOiy35WIRO26JE%3D&reserved=0
> > +
> > +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 __IO_LIB_SWAP_H__
> > +#define __IO_LIB_SWAP_H__
> > +
> > +/**
> > +  Reads a 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address. The 16-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioRead16 (
> > +  IN      UINTN                     Address
> > +  );
> > +
> > +/**
> > +  Writes a 16-bit MMIO register.
> > +
> > +  Writes the 16-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +  @return Value.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    Value
> > +  );
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 16-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    OrData
> > +  );
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 16-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData
> > +  );
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 16-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  );
> > +
> > +/**
> > +  Reads a 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address. The 32-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioRead32 (
> > +  IN      UINTN                     Address
> > +  );
> > +
> > +/**
> > +  Writes a 32-bit MMIO register.
> > +
> > +  Writes the 32-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +  @return Value.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    Value
> > +  );
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 32-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    OrData
> > +  );
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 32-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData
> > +  );
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 32-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  );
> > +
> > +/**
> > +  Reads a 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address. The 64-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioRead64 (
> > +  IN      UINTN                     Address
> > +  );
> > +
> > +/**
> > +  Writes a 64-bit MMIO register.
> > +
> > +  Writes the 64-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioWrite64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    Value
> > +  );
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 64-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioOr64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    OrData
> > +  );
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 64-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioAnd64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    AndData
> > +  );
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 64-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioAndThenOr64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    AndData,
> > +  IN      UINT64                    OrData
> > +  );
> > +
> > +#endif
> > +
> > diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> > b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> > new file mode 100644
> > index 0000000000..59d774dc97
> > --- /dev/null
> > +++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> > @@ -0,0 +1,44 @@
> > +## @file
> > +#  Byte swapping I/O Library.
> > +#
> > +#  Byte swapping I/O Library for all architectures. Only MMIO
> > +supported. I/O #  accesses take place through the normal IoLib, but
> > +values read and written #  are byte-reversed to interact with peripherals
> of non-native endianness.
> > +#
> > +#  Copyright (c) 2007 - 2015, Intel Corporation. All rights
> > +reserved.<BR> #  Portions copyright (c) 2008 - 2009, Apple Inc. All
> > +rights reserved.<BR> #  Copyright (c) 2017, AMD Incorporated. All
> > +rights reserved.<BR> # #  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 #
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopen
> source.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C503430fe81e544d
> 1df8b08d57956346f%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6
> 36548333521065509&sdata=gW0hj%2FR0rTXl%2BlJr6mAiuaGSy7ZHoxOiy35W
> IRO26JE%3D&reserved=0.
> > +#  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                    = 0x0001001a
> > +  BASE_NAME                      = BaseIoLibSwap
> > +  MODULE_UNI_FILE                = BaseIoLibSwap.uni
> > +  FILE_GUID                      = 073c3fbd-ff0d-41b6-a209-1e42fd2a3bab
> > +  MODULE_TYPE                    = BASE
> > +  VERSION_STRING                 = 1.0
> > +  LIBRARY_CLASS                  = IoLibSwap
> > +
> > +
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64 EBC IPF ARM AARCH64
> > +#
> > +
> > +[Sources]
> > +  IoLibSwap.c
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +
> > +[LibraryClasses]
> > +  BaseLib
> > +#  DebugLib
> > +  IoLib
> > diff --git a/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> > b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> > new file mode 100644
> > index 0000000000..e35b4abef7
> > --- /dev/null
> > +++ b/MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.uni
> > @@ -0,0 +1,23 @@
> > +// /** @file
> > +// Byte swapping I/O Library.
> > +//
> > +// Byte swapping I/O Library for all architectures. Only MMIO
> > +supported. I/O // accesses take place through the normal IoLib, but
> > +values read and written // are byte-reversed to interact with peripherals
> of non-native endianness.
> > +//
> > +// Copyright (c) 2018, Linaro ltd. All rights reserved.<BR> // //
> > +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 //
> https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fopen
> source.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40nxp.com%7C503430fe81e544d
> 1df8b08d57956346f%7C686ea1d3bc2b4c6fa92cd99c5c301635%7C0%7C0%7C6
> 36548333521065509&sdata=gW0hj%2FR0rTXl%2BlJr6mAiuaGSy7ZHoxOiy35W
> IRO26JE%3D&reserved=0.
> > +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> > +BASIS, // WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND,
> EITHER EXPRESS OR IMPLIED.
> > +//
> > +// **/
> > +
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US "Byte swapping
> I/O Library"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "Byte swapping
> I/O Library for all architectures. Only MMIO supported. I/O accesses take
> place through the normal IoLib, but values read and written are byte-
> reversed to interact with peripherals of non-native endianness."
> > +
> > diff --git a/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> > b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> > new file mode 100644
> > index 0000000000..6eb675de20
> > --- /dev/null
> > +++ b/MdePkg/Library/BaseIoLibSwap/IoLibSwap.c
> > @@ -0,0 +1,491 @@
> > +/** @file
> > +  Provide byte-swapping services to access MMIO registers.
> > +
> > +Copyright (c) 2006 - 2012, Intel Corporation. All rights
> > +reserved.<BR> Copyright (c) 2017, AMD Incorporated. All rights
> > +reserved.<BR> Copyright (c) 2018, Linaro ltd. All rights
> > +reserved.<BR>
> > +
> > +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
> >
> +https://emea01.safelinks.protection.outlook.com/?url=http%3A%2F%2Fope
> > +nsource.org%2Flicenses%2Fbsd-
> license.php&data=02%7C01%7Cudit.kumar%40
> >
> +nxp.com%7C503430fe81e544d1df8b08d57956346f%7C686ea1d3bc2b4c6fa9
> 2cd99c
> >
> +5c301635%7C0%7C0%7C636548333521065509&sdata=gW0hj%2FR0rTXl%2Bl
> Jr6mAiu
> > +aGSy7ZHoxOiy35WIRO26JE%3D&reserved=0
> > +
> > +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/BaseLib.h>
> > +#include <Library/IoLib.h>
> > +
> > +/**
> > +  Reads a 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address. The 16-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioRead16 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  return SwapBytes16 (MmioRead16 (Address)); }
> > +
> > +/**
> > +  Writes a 16-bit MMIO register.
> > +
> > +  Writes the 16-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +  @return Value.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioWrite16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    Value
> > +  )
> > +{
> > +  (VOID) MmioWrite16 (Address, SwapBytes16 (Value));
> > +
> > +  return Value;
> > +}
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 16-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  UINT16 Value;
> > +
> > +  Value = SwapMmioRead16 (Address);
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite16 (Address, Value); }
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 16-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioAnd16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData
> > +  )
> > +{
> > +  UINT16 Value;
> > +
> > +  Value = SwapMmioRead16 (Address);
> > +  Value &= AndData;
> > +
> > +  return SwapMmioWrite16 (Address, Value); }
> > +
> > +/**
> > +  Reads a 16-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 16-bit MMIO register.
> > +
> > +  Reads the 16-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 16-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 16-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 16-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT16
> > +EFIAPI
> > +SwapMmioAndThenOr16 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT16                    AndData,
> > +  IN      UINT16                    OrData
> > +  )
> > +{
> > +  UINT16 Value;
> > +
> > +  Value = SwapMmioRead16 (Address);
> > +  Value &= AndData;
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite16 (Address, Value); }
> > +
> > +/**
> > +  Reads a 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address. The 32-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioRead32 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  return SwapBytes32 (MmioRead32 (Address)); }
> > +
> > +/**
> > +  Writes a 32-bit MMIO register.
> > +
> > +  Writes the 32-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +  @return Value.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioWrite32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    Value
> > +  )
> > +{
> > +  (VOID) MmioWrite32 (Address, SwapBytes32 (Value));
> > +
> > +  return Value;
> > +}
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 32-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  UINT32 Value;
> > +
> > +  Value = SwapMmioRead32 (Address);
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite32 (Address, Value); }
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 32-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioAnd32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData
> > +  )
> > +{
> > +  UINT32 Value;
> > +
> > +  Value = SwapMmioRead32 (Address);
> > +  Value &= AndData;
> > +
> > +  return SwapMmioWrite32 (Address, Value); }
> > +
> > +/**
> > +  Reads a 32-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 32-bit MMIO register.
> > +
> > +  Reads the 32-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 32-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 32-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 32-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT32
> > +EFIAPI
> > +SwapMmioAndThenOr32 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT32                    AndData,
> > +  IN      UINT32                    OrData
> > +  )
> > +{
> > +  UINT32 Value;
> > +
> > +  Value = SwapMmioRead32 (Address);
> > +  Value &= AndData;
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite32 (Address, Value); }
> > +
> > +/**
> > +  Reads a 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address. The 64-bit
> > + read value is  returned. This function must guarantee that all MMIO
> > + read and write  operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to read.
> > +
> > +  @return The value read.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioRead64 (
> > +  IN      UINTN                     Address
> > +  )
> > +{
> > +  return SwapBytes64 (MmioRead64 (Address)); }
> > +
> > +/**
> > +  Writes a 64-bit MMIO register.
> > +
> > +  Writes the 64-bit MMIO register specified by Address with the value
> > + specified  by Value and returns Value. This function must guarantee
> > + that all MMIO read  and write operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  Value   The value to write to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioWrite64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    Value
> > +  )
> > +{
> > +  (VOID) MmioWrite64 (Address, SwapBytes64 (Value));
> > +
> > +  return Value;
> > +}
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise OR, and writes the
> > +  result back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise  OR between the read result and the value specified by
> > + OrData, and  writes the result to the 64-bit MMIO register specified
> > + by Address. The value  written to the MMIO register is returned.
> > + This function must guarantee that  all MMIO read and write operations
> are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  OrData  The value to OR with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioOr64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    OrData
> > +  )
> > +{
> > +  UINT64 Value;
> > +
> > +  Value = SwapMmioRead64 (Address);
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite64 (Address, Value); }
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise AND, and writes
> > +the result
> > +  back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, and writes the  result to the 64-bit MMIO register
> > + specified by Address. The value written to  the MMIO register is
> > + returned. This function must guarantee that all MMIO  read and write
> operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioAnd64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    AndData
> > +  )
> > +{
> > +  UINT64 Value;
> > +
> > +  Value = SwapMmioRead64 (Address);
> > +  Value &= AndData;
> > +
> > +  return SwapMmioWrite64 (Address, Value); }
> > +
> > +/**
> > +  Reads a 64-bit MMIO register, performs a bitwise AND followed by a
> > +bitwise
> > +  OR, and writes the result back to the 64-bit MMIO register.
> > +
> > +  Reads the 64-bit MMIO register specified by Address, performs a
> > + bitwise AND  between the read result and the value specified by
> > + AndData, performs a  bitwise OR between the result of the AND
> > + operation and the value specified by  OrData, and writes the result
> > + to the 64-bit MMIO register specified by  Address. The value written
> > + to the MMIO register is returned. This function  must guarantee that all
> MMIO read and write operations are serialized.
> > +
> > +  If 64-bit MMIO register operations are not supported, then ASSERT().
> > +  If Address is not aligned on a 64-bit boundary, then ASSERT().
> > +
> > +  @param  Address The MMIO register to write.
> > +  @param  AndData The value to AND with the read value from the MMIO
> register.
> > +  @param  OrData  The value to OR with the result of the AND operation.
> > +
> > +  @return The value written back to the MMIO register.
> > +
> > +**/
> > +UINT64
> > +EFIAPI
> > +SwapMmioAndThenOr64 (
> > +  IN      UINTN                     Address,
> > +  IN      UINT64                    AndData,
> > +  IN      UINT64                    OrData
> > +  )
> > +{
> > +  UINT64 Value;
> > +
> > +  Value = SwapMmioRead64 (Address);
> > +  Value &= AndData;
> > +  Value |= OrData;
> > +
> > +  return SwapMmioWrite64 (Address, Value); }
> > diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index
> > 0e64f22f4a..98016f47e9 100644
> > --- a/MdePkg/MdePkg.dec
> > +++ b/MdePkg/MdePkg.dec
> > @@ -160,6 +160,9 @@ [LibraryClasses]
> >    ##  @libraryclass  Provide services to access I/O Ports and MMIO
> registers.
> >    IoLib|Include/Library/IoLib.h
> >
> > +  ##  @libraryclass  Provide byte-swapping services to access MMIO
> registers.
> > +  IoLibSwap|Include/Library/IoLibSwap.h
> > +
> >    ##  @libraryclass  Provide services to create, get and update HSTI table in
> AIP protocol.
> >    HstiLib|Include/Library/HstiLib.h
> >
> > diff --git a/MdePkg/MdePkg.dsc b/MdePkg/MdePkg.dsc index
> > 60efd722e9..a2f2696394 100644
> > --- a/MdePkg/MdePkg.dsc
> > +++ b/MdePkg/MdePkg.dsc
> > @@ -60,6 +60,7 @@ [Components]
> >    MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
> >    MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf
> >
> > MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib
> > .inf
> > +  MdePkg/Library/BaseIoLibSwap/BaseIoLibSwap.inf
> >    MdePkg/Library/BaseLib/BaseLib.inf
> >    MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
> >
> >
> MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrderedCollect
> > ionRedBlackTreeLib.inf
> > --
> > 2.11.0
> >

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-02-22  4:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-02-21 15:25 [RFC PATCH] MdePkg: add byte-swapping MMIO BaseIoLibSwap Leif Lindholm
2018-02-21 15:56 ` Laszlo Ersek
2018-02-21 18:09 ` Ard Biesheuvel
2018-02-22  4:51   ` Udit Kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox