aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/Kconfig21
-rw-r--r--arch/arm/lib/semihosting.c21
-rw-r--r--include/semihosting.h30
3 files changed, 72 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index b2e2873448f..f277929c991 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -414,6 +414,16 @@ config SEMIHOSTING
on the host system. If you don't have a debugger attached then trying
to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+config SEMIHOSTING_FALLBACK
+ bool "Recover gracefully when semihosting fails"
+ depends on SEMIHOSTING && ARM64
+ default y
+ help
+ Normally, if U-Boot makes a semihosting call and no debugger is
+ attached, then it will panic due to a synchronous abort
+ exception. This config adds an exception handler which will allow
+ U-Boot to recover. Say 'y' if unsure.
+
config SPL_SEMIHOSTING
bool "Support ARM semihosting in SPL"
depends on SPL
@@ -427,6 +437,17 @@ config SPL_SEMIHOSTING
on the host system. If you don't have a debugger attached then trying
to do this will likely cause U-Boot to hang. Say 'n' if you are unsure.
+config SPL_SEMIHOSTING_FALLBACK
+ bool "Recover gracefully when semihosting fails in SPL"
+ depends on SPL_SEMIHOSTING && ARM64
+ select ARMV8_SPL_EXCEPTION_VECTORS
+ default y
+ help
+ Normally, if U-Boot makes a semihosting call and no debugger is
+ attached, then it will panic due to a synchronous abort
+ exception. This config adds an exception handler which will allow
+ U-Boot to recover. Say 'y' if unsure.
+
config SYS_THUMB_BUILD
bool "Build U-Boot using the Thumb instruction set"
depends on !ARM64
diff --git a/arch/arm/lib/semihosting.c b/arch/arm/lib/semihosting.c
index 7595dbc4a93..dbea2b06fb2 100644
--- a/arch/arm/lib/semihosting.c
+++ b/arch/arm/lib/semihosting.c
@@ -20,6 +20,7 @@
#define SYSWRITE 0x05
#define SYSREAD 0x06
#define SYSREADC 0x07
+#define SYSISERROR 0x08
#define SYSSEEK 0x0A
#define SYSFLEN 0x0C
#define SYSERRNO 0x13
@@ -41,6 +42,26 @@ static noinline long smh_trap(unsigned int sysnum, void *addr)
return result;
}
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+static bool _semihosting_enabled = true;
+static bool try_semihosting = true;
+
+bool semihosting_enabled(void)
+{
+ if (try_semihosting) {
+ smh_trap(SYSERRNO, NULL);
+ try_semihosting = false;
+ }
+
+ return _semihosting_enabled;
+}
+
+void disable_semihosting(void)
+{
+ _semihosting_enabled = false;
+}
+#endif
+
/**
* smh_errno() - Read the host's errno
*
diff --git a/include/semihosting.h b/include/semihosting.h
index 6f3c29786ce..9816233c508 100644
--- a/include/semihosting.h
+++ b/include/semihosting.h
@@ -6,6 +6,36 @@
#ifndef _SEMIHOSTING_H
#define _SEMIHOSTING_H
+#if CONFIG_IS_ENABLED(SEMIHOSTING_FALLBACK)
+/**
+ * semihosting_enabled() - Determine whether semihosting is supported
+ *
+ * Semihosting-based drivers should call this function before making other
+ * semihosting calls.
+ *
+ * Return: %true if a debugger is attached which supports semihosting, %false
+ * otherwise
+ */
+bool semihosting_enabled(void);
+
+/**
+ * disable_semihosting() - Cause semihosting_enabled() to return false
+ *
+ * If U-Boot ever receives an unhandled exception caused by a semihosting trap,
+ * the trap handler should call this function.
+ */
+void disable_semihosting(void);
+#else
+static inline bool semihosting_enabled(void)
+{
+ return CONFIG_IS_ENABLED(SEMIHOSTING);
+}
+
+static inline void disable_semihosting(void)
+{
+}
+#endif
+
/**
* enum smh_open_mode - Numeric file modes for use with smh_open()
* MODE_READ: 'r'