]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/QemuVideoDxe: Helper functions for unaligned port I/O.
authorPhil Dennis-Jordan <phil@philjordan.eu>
Fri, 7 Apr 2017 06:25:57 +0000 (18:25 +1200)
committerLaszlo Ersek <lersek@redhat.com>
Fri, 7 Apr 2017 10:22:30 +0000 (12:22 +0200)
The VMWare SVGA display device implemented by Qemu (-vga vmware) uses
an I/O-type BAR which is laid out such that some register offsets are
not aligned to the read/write width with which they are expected to be
accessed. (The register value port has an offset of 1 and requires
32 bit wide read/write access.)

The EFI_PCI_IO_PROTOCOL's Io.Read/Io.Write functions do not support
such unaligned I/O.

Before a driver for this device can be added to QemuVideoDxe, helper
functions for unaligned I/O are therefore required. This adds the
functions UnalignedIoWrite32 and UnalignedIoRead32, based on IoLib's
IoWrite32 and IoRead32, for the Ia32 and X64 architectures. Port I/O
requires inline assembly, so implementations are provided for the GCC,
ICC, and Microsoft compiler families. Such I/O is not possible on other
architectures, a dummy (ASSERT()ing) implementation is therefore
provided to satisfy the linker.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Phil Dennis-Jordan <phil@philjordan.eu>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>
OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c [new file with mode: 0644]
OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c [new file with mode: 0644]
OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h [new file with mode: 0644]
OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c [new file with mode: 0644]
OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c [new file with mode: 0644]

index affb6ffd88e0781d99bfd951ca356b7ff8e774f6..346a5aed94faae3e935a5be411159b27a99ce7c3 100644 (file)
 \r
 [Sources.Ia32, Sources.X64]\r
   VbeShim.c\r
+  UnalignedIoGcc.c    | GCC\r
+  UnalignedIoMsc.c    | MSFT\r
+  UnalignedIoIcc.c    | INTEL\r
+\r
+[Sources.IPF, Sources.EBC, Sources.ARM, Sources.AARCH64]\r
+  UnalignedIoUnsupported.c\r
 \r
 [Packages]\r
   MdePkg/MdePkg.dec\r
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoGcc.c
new file mode 100644 (file)
index 0000000..105d55d
--- /dev/null
@@ -0,0 +1,70 @@
+/** @file\r
+  Unaligned Port I/O. This file has compiler specifics for GCC as there is no\r
+  ANSI C standard for doing IO.\r
+\r
+  Based on IoLibGcc.c.\r
+\r
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "UnalignedIoInternal.h"\r
+\r
+/**\r
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type\r
+  address.\r
+\r
+  Writes the 32-bit I/O port specified by Port with the value specified by\r
+  Value and returns Value. This function must guarantee that all I/O read and\r
+  write operations are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port   I/O port address\r
+  @param[in]  Value  32-bit word to write\r
+\r
+  @return The value written to the I/O port.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoWrite32 (\r
+  IN      UINTN                     Port,\r
+  IN      UINT32                    Value\r
+  )\r
+{\r
+  __asm__ __volatile__ ( "outl %0, %1" : : "a" (Value), "d" ((UINT16)Port) );\r
+  return Value;\r
+}\r
+\r
+/**\r
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.\r
+\r
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is\r
+  returned. This function must guarantee that all I/O read and write operations\r
+  are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port  The I/O port to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoRead32 (\r
+  IN      UINTN                     Port\r
+  )\r
+{\r
+  UINT32 Data;\r
+  __asm__ __volatile__ ( "inl %1, %0" : "=a" (Data) : "d" ((UINT16)Port) );\r
+  return Data;\r
+}\r
+\r
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoIcc.c
new file mode 100644 (file)
index 0000000..79f3e44
--- /dev/null
@@ -0,0 +1,80 @@
+/** @file\r
+  Unaligned port I/O. This file has compiler specifics for ICC as there\r
+  is no ANSI C standard for doing IO.\r
+\r
+  Based on IoLibIcc.c.\r
+\r
+  Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "UnalignedIoInternal.h"\r
+\r
+/**\r
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type\r
+  address.\r
+\r
+  Writes the 32-bit I/O port specified by Port with the value specified by\r
+  Value and returns Value. This function must guarantee that all I/O read and\r
+  write operations are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port   I/O port address\r
+  @param[in]  Value  32-bit word to write\r
+\r
+  @return The value written to the I/O port.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoWrite32 (\r
+  IN      UINTN                     Port,\r
+  IN      UINT32                    Value\r
+  )\r
+{\r
+  __asm {\r
+    mov eax, dword ptr [Value]\r
+    mov dx, word ptr [Port]\r
+    out dx, eax\r
+  }\r
+\r
+  return Value;\r
+}\r
+\r
+/**\r
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.\r
+\r
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is\r
+  returned. This function must guarantee that all I/O read and write operations\r
+  are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port  The I/O port to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoRead32 (\r
+  IN      UINTN                     Port\r
+  )\r
+{\r
+  UINT32 Data;\r
+\r
+  __asm {\r
+    mov dx, word ptr [Port]\r
+    in  eax, dx\r
+    mov dword ptr [Data], eax\r
+  }\r
+\r
+  return Data;\r
+}\r
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h b/OvmfPkg/QemuVideoDxe/UnalignedIoInternal.h
new file mode 100644 (file)
index 0000000..234de6c
--- /dev/null
@@ -0,0 +1,59 @@
+/** @file\r
+  Unaligned port I/O, with implementations for various x86 compilers and a\r
+  dummy for platforms which do not support unaligned port I/O.\r
+\r
+  Copyright (c) 2017, Phil Dennis-Jordan.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _UNALIGNED_IO_INTERNAL_H_\r
+#define _UNALIGNED_IO_INTERNAL_H_\r
+\r
+/**\r
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type address.\r
+\r
+  Writes the 32-bit I/O port specified by Port with the value specified by Value\r
+  and returns Value. This function must guarantee that all I/O read and write\r
+  operations are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port   I/O port address\r
+  @param[in]  Value  32-bit word to write\r
+\r
+  @return The value written to the I/O port.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoWrite32 (\r
+  IN      UINTN                     Port,\r
+  IN      UINT32                    Value\r
+  );\r
+\r
+/**\r
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.\r
+\r
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is\r
+  returned. This function must guarantee that all I/O read and write operations\r
+  are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port  The I/O port to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoRead32 (\r
+  IN      UINTN                     Port\r
+  );\r
+\r
+#endif\r
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c b/OvmfPkg/QemuVideoDxe/UnalignedIoMsc.c
new file mode 100644 (file)
index 0000000..a466bae
--- /dev/null
@@ -0,0 +1,78 @@
+/** @file\r
+  Unaligned port I/O. This file has compiler specifics for Microsoft C as there\r
+  is no ANSI C standard for doing IO.\r
+\r
+  Based on IoLibMsc.c\r
+\r
+  Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include "UnalignedIoInternal.h"\r
+\r
+unsigned long  _inpd (unsigned short port);\r
+unsigned long  _outpd (unsigned short port, unsigned long dataword );\r
+void          _ReadWriteBarrier (void);\r
+\r
+/**\r
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type\r
+  address.\r
+\r
+  Writes the 32-bit I/O port specified by Port with the value specified by\r
+  Value and returns Value. This function must guarantee that all I/O read and\r
+  write operations are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port   I/O port address\r
+  @param[in]  Value  32-bit word to write\r
+\r
+  @return The value written to the I/O port.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoWrite32 (\r
+  IN      UINTN                     Port,\r
+  IN      UINT32                    Value\r
+  )\r
+{\r
+  _ReadWriteBarrier ();\r
+  _outpd ((UINT16)Port, Value);\r
+  _ReadWriteBarrier ();\r
+  return Value;\r
+}\r
+\r
+/**\r
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.\r
+\r
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is\r
+  returned. This function must guarantee that all I/O read and write operations\r
+  are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port  The I/O port to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoRead32 (\r
+  IN      UINTN                     Port\r
+  )\r
+{\r
+  UINT32                            Value;\r
+\r
+  _ReadWriteBarrier ();\r
+  Value = _inpd ((UINT16)Port);\r
+  _ReadWriteBarrier ();\r
+  return Value;\r
+}\r
diff --git a/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c b/OvmfPkg/QemuVideoDxe/UnalignedIoUnsupported.c
new file mode 100644 (file)
index 0000000..57560ab
--- /dev/null
@@ -0,0 +1,66 @@
+/** @file\r
+  Unaligned port I/O dummy implementation for platforms which do not support it.\r
+\r
+  Copyright (c) 2017, Phil Dennis-Jordan.<BR>\r
+  This program and the accompanying materials are licensed and made available\r
+  under the terms and conditions of the BSD License which accompanies this\r
+  distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+\r
+#include <Library/DebugLib.h>\r
+#include "UnalignedIoInternal.h"\r
+\r
+/**\r
+  Performs a 32-bit write to the specified, possibly unaligned I/O-type\r
+  address.\r
+\r
+  Writes the 32-bit I/O port specified by Port with the value specified by\r
+  Value and returns Value. This function must guarantee that all I/O read and\r
+  write operations are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port   I/O port address\r
+  @param[in]  Value  32-bit word to write\r
+\r
+  @return The value written to the I/O port.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoWrite32 (\r
+  IN      UINTN                     Port,\r
+  IN      UINT32                    Value\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return Value;\r
+}\r
+\r
+/**\r
+  Reads a 32-bit word from the specified, possibly unaligned I/O-type address.\r
+\r
+  Reads the 32-bit I/O port specified by Port. The 32-bit read value is\r
+  returned. This function must guarantee that all I/O read and write operations\r
+  are serialized.\r
+\r
+  If 32-bit unaligned I/O port operations are not supported, then ASSERT().\r
+\r
+  @param[in]  Port  The I/O port to read.\r
+\r
+  @return The value read.\r
+\r
+**/\r
+UINT32\r
+UnalignedIoRead32 (\r
+  IN      UINTN                     Port\r
+  )\r
+{\r
+  ASSERT (FALSE);\r
+  return 0;\r
+}\r