Blob Blame History Raw
From c2226b3d1a4d9fc1daeb8dc6b9034d1fb46c1308 Mon Sep 17 00:00:00 2001
From: Michael Brown <mcb30@ipxe.org>
Date: Sun, 14 Jul 2019 15:27:01 +0100
Subject: [PATCH] [arm] Provide dummy implementations for {in,out}[s]{b,w,l}

It is currently not possible to build the all-drivers iPXE binaries
for ARM, since there is no implementation for inb(), outb(), etc.

There is no common standard for accessing I/O space on ARM platforms,
and there are almost no ARM-compatible peripherals that actually
require I/O space accesses.

Provide dummy implementations that behave as though no device is
present (i.e. ignore writes, return all bits high for reads).  This is
sufficient to allow the all-drivers binaries to link, and should cause
drivers to behave as though no I/O space peripherals are present in
the system.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
---
 src/arch/arm/include/ipxe/arm_io.h | 77 +++++++++++++++++++++++-------
 1 file changed, 59 insertions(+), 18 deletions(-)

diff --git a/src/arch/arm/include/ipxe/arm_io.h b/src/arch/arm/include/ipxe/arm_io.h
index f8765af752..105f22bfbf 100644
--- a/src/arch/arm/include/ipxe/arm_io.h
+++ b/src/arch/arm/include/ipxe/arm_io.h
@@ -43,42 +43,83 @@ IOAPI_INLINE ( arm, bus_to_phys ) ( unsigned long bus_addr ) {
  *
  */
 
-#define ARM_READX( _api_func, _type, _insn_suffix, _reg_prefix )	      \
+#define ARM_READX( _suffix, _type, _insn_suffix, _reg_prefix )		      \
 static inline __always_inline _type					      \
-IOAPI_INLINE ( arm, _api_func ) ( volatile _type *io_addr ) {		      \
+IOAPI_INLINE ( arm, read ## _suffix ) ( volatile _type *io_addr ) {	      \
 	_type data;							      \
 	__asm__ __volatile__ ( "ldr" _insn_suffix " %" _reg_prefix "0, %1"    \
 			       : "=r" ( data ) : "Qo" ( *io_addr ) );	      \
 	return data;							      \
 }
 #ifdef __aarch64__
-ARM_READX ( readb, uint8_t, "b", "w" );
-ARM_READX ( readw, uint16_t, "h", "w" );
-ARM_READX ( readl, uint32_t, "", "w" );
-ARM_READX ( readq, uint64_t, "", "" );
+ARM_READX ( b, uint8_t, "b", "w" );
+ARM_READX ( w, uint16_t, "h", "w" );
+ARM_READX ( l, uint32_t, "", "w" );
+ARM_READX ( q, uint64_t, "", "" );
 #else
-ARM_READX ( readb, uint8_t, "b", "" );
-ARM_READX ( readw, uint16_t, "h", "" );
-ARM_READX ( readl, uint32_t, "", "" );
+ARM_READX ( b, uint8_t, "b", "" );
+ARM_READX ( w, uint16_t, "h", "" );
+ARM_READX ( l, uint32_t, "", "" );
 #endif
 
-#define ARM_WRITEX( _api_func, _type, _insn_suffix, _reg_prefix )			\
+#define ARM_WRITEX( _suffix, _type, _insn_suffix, _reg_prefix )		      \
 static inline __always_inline void					      \
-IOAPI_INLINE ( arm, _api_func ) ( _type data, volatile _type *io_addr ) {     \
+IOAPI_INLINE ( arm, write ## _suffix ) ( _type data,			      \
+					 volatile _type *io_addr ) {	      \
 	__asm__ __volatile__ ( "str" _insn_suffix " %" _reg_prefix "0, %1"    \
 			       : : "r" ( data ), "Qo" ( *io_addr ) );	      \
 }
 #ifdef __aarch64__
-ARM_WRITEX ( writeb, uint8_t, "b", "w" );
-ARM_WRITEX ( writew, uint16_t, "h", "w" );
-ARM_WRITEX ( writel, uint32_t, "", "w" );
-ARM_WRITEX ( writeq, uint64_t, "", "" );
+ARM_WRITEX ( b, uint8_t, "b", "w" );
+ARM_WRITEX ( w, uint16_t, "h", "w" );
+ARM_WRITEX ( l, uint32_t, "", "w" );
+ARM_WRITEX ( q, uint64_t, "", "" );
 #else
-ARM_WRITEX ( writeb, uint8_t, "b", "" );
-ARM_WRITEX ( writew, uint16_t, "h", "" );
-ARM_WRITEX ( writel, uint32_t, "", "" );
+ARM_WRITEX ( b, uint8_t, "b", "" );
+ARM_WRITEX ( w, uint16_t, "h", "" );
+ARM_WRITEX ( l, uint32_t, "", "" );
 #endif
 
+/*
+ * Dummy PIO reads and writes up to 32 bits
+ *
+ * There is no common standard for I/O-space access for ARM, and
+ * non-MMIO peripherals are vanishingly rare.  Provide dummy
+ * implementations that will allow code to link and should cause
+ * drivers to simply fail to detect hardware at runtime.
+ *
+ */
+
+#define ARM_INX( _suffix, _type )					      \
+static inline __always_inline _type					      \
+IOAPI_INLINE ( arm, in ## _suffix ) ( volatile _type *io_addr __unused) {     \
+	return ~( (_type) 0 );						      \
+}									      \
+static inline __always_inline void					      \
+IOAPI_INLINE ( arm, ins ## _suffix ) ( volatile _type *io_addr __unused,      \
+				       _type *data, unsigned int count ) {    \
+	memset ( data, 0xff, count * sizeof ( *data ) );		      \
+}
+ARM_INX ( b, uint8_t );
+ARM_INX ( w, uint16_t );
+ARM_INX ( l, uint32_t );
+
+#define ARM_OUTX( _suffix, _type )					      \
+static inline __always_inline void					      \
+IOAPI_INLINE ( arm, out ## _suffix ) ( _type data __unused,		      \
+				       volatile _type *io_addr __unused ) {   \
+	/* Do nothing */						      \
+}									      \
+static inline __always_inline void					      \
+IOAPI_INLINE ( arm, outs ## _suffix ) ( volatile _type *io_addr __unused,     \
+					const _type *data __unused,	      \
+					unsigned int count __unused ) {	      \
+	/* Do nothing */						      \
+}
+ARM_OUTX ( b, uint8_t );
+ARM_OUTX ( w, uint16_t );
+ARM_OUTX ( l, uint32_t );
+
 /*
  * Slow down I/O
  *