summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2022-12-19 17:29:55 +0300
committerTom Rini <trini@konsulko.com>2022-12-21 21:09:01 +0300
commit14f43797d0a696248c09d298e2f2809dded345ba (patch)
tree23fc5bc462689f07f389cc0b8e7f7bedd35253ff /lib
parent9c955393f7a27ded250fef7688e0065b44a3343f (diff)
parent2243922edca9f56a9d5519b9d6e36f5d7a18434d (diff)
downloadu-boot-14f43797d0a696248c09d298e2f2809dded345ba.tar.xz
Merge tag 'v2023.01-rc4' into next
Prepare v2023.01-rc4 Signed-off-by: Tom Rini <trini@konsulko.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig47
-rw-r--r--lib/Makefile2
-rw-r--r--lib/efi_loader/Kconfig6
-rw-r--r--lib/efi_loader/efi_conformance.c8
-rw-r--r--lib/efi_selftest/efi_selftest_ecpt.c6
-rw-r--r--lib/semihosting.c186
6 files changed, 245 insertions, 10 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index c39fc52321..def36f275c 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -74,6 +74,53 @@ config HAVE_PRIVATE_LIBGCC
config LIB_UUID
bool
+config SEMIHOSTING
+ bool "Support semihosting"
+ depends on ARM || RISCV
+ help
+ Semihosting is a method for a target to communicate with a host
+ debugger. It uses special instructions which the debugger will trap
+ on and interpret. This allows U-Boot to read/write files, print to
+ the console, and execute arbitrary commands on the host system.
+
+ Enabling this option will add support for reading and writing files
+ 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 || RISCV)
+ 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 semihosting in SPL"
+ depends on SPL && (ARM || RISCV)
+ help
+ Semihosting is a method for a target to communicate with a host
+ debugger. It uses special instructions which the debugger will trap
+ on and interpret. This allows U-Boot to read/write files, print to
+ the console, and execute arbitrary commands on the host system.
+
+ Enabling this option will add support for reading and writing files
+ 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 || RISCV)
+ select ARMV8_SPL_EXCEPTION_VECTORS if 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 PRINTF
bool
default y
diff --git a/lib/Makefile b/lib/Makefile
index f2cfd1e428..d77b33e7f4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -146,6 +146,8 @@ obj-y += date.o
obj-y += rtc-lib.o
obj-$(CONFIG_LIB_ELF) += elf.o
+obj-$(CONFIG_$(SPL_TPL_)SEMIHOSTING) += semihosting.o
+
#
# Build a fast OID lookup registry from include/linux/oid_registry.h
#
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index e2b643871b..b498c72206 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -384,8 +384,8 @@ config EFI_ECPT
help
Enabling this option created the ECPT UEFI table.
-config EFI_EBBR_2_0_CONFORMANCE
- bool "Add the EBBRv2.0 conformance entry to the ECPT table"
+config EFI_EBBR_2_1_CONFORMANCE
+ bool "Add the EBBRv2.1 conformance entry to the ECPT table"
depends on EFI_ECPT
depends on EFI_LOADER_HII
depends on EFI_RISCV_BOOT_PROTOCOL || !RISCV
@@ -393,7 +393,7 @@ config EFI_EBBR_2_0_CONFORMANCE
depends on EFI_UNICODE_COLLATION_PROTOCOL2
default y
help
- Enabling this option adds the EBBRv2.0 conformance entry to the ECPT UEFI table.
+ Enabling this option adds the EBBRv2.1 conformance entry to the ECPT UEFI table.
config EFI_RISCV_BOOT_PROTOCOL
bool "RISCV_EFI_BOOT_PROTOCOL support"
diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c
index a49aae9249..3036d46349 100644
--- a/lib/efi_loader/efi_conformance.c
+++ b/lib/efi_loader/efi_conformance.c
@@ -12,8 +12,8 @@
#include <malloc.h>
static const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
-static const efi_guid_t efi_ebbr_2_0_guid =
- EFI_CONFORMANCE_PROFILE_EBBR_2_0_GUID;
+static const efi_guid_t efi_ebbr_2_1_guid =
+ EFI_CONFORMANCE_PROFILE_EBBR_2_1_GUID;
/**
* efi_ecpt_register() - Install the ECPT system table.
@@ -38,9 +38,9 @@ efi_status_t efi_ecpt_register(void)
return ret;
}
- if (CONFIG_IS_ENABLED(EFI_EBBR_2_0_CONFORMANCE))
+ if (CONFIG_IS_ENABLED(EFI_EBBR_2_1_CONFORMANCE))
guidcpy(&ecpt->conformance_profiles[num_entries++],
- &efi_ebbr_2_0_guid);
+ &efi_ebbr_2_1_guid);
ecpt->version = EFI_CONFORMANCE_PROFILES_TABLE_VERSION;
ecpt->number_of_profiles = num_entries;
diff --git a/lib/efi_selftest/efi_selftest_ecpt.c b/lib/efi_selftest/efi_selftest_ecpt.c
index e8cc13545d..09c5e96c5e 100644
--- a/lib/efi_selftest/efi_selftest_ecpt.c
+++ b/lib/efi_selftest/efi_selftest_ecpt.c
@@ -10,7 +10,7 @@
#include <efi_selftest.h>
static const efi_guid_t guid_ecpt = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
-static const efi_guid_t guid_ebbr_2_0 = EFI_CONFORMANCE_PROFILE_EBBR_2_0_GUID;
+static const efi_guid_t guid_ebbr_2_1 = EFI_CONFORMANCE_PROFILE_EBBR_2_1_GUID;
/*
* ecpt_find_guid() - find GUID in EFI Conformance Profile Table
@@ -53,9 +53,9 @@ static int execute(void)
return EFI_ST_FAILURE;
}
- if (CONFIG_IS_ENABLED(EFI_EBBR_2_0_CONFORMANCE)) {
+ if (CONFIG_IS_ENABLED(EFI_EBBR_2_1_CONFORMANCE)) {
++expected_entries;
- if (ecpt_find_guid(ecpt, &guid_ebbr_2_0))
+ if (ecpt_find_guid(ecpt, &guid_ebbr_2_1))
return EFI_ST_FAILURE;
}
diff --git a/lib/semihosting.c b/lib/semihosting.c
new file mode 100644
index 0000000000..831774e356
--- /dev/null
+++ b/lib/semihosting.c
@@ -0,0 +1,186 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2022 Sean Anderson <sean.anderson@seco.com>
+ * Copyright 2014 Broadcom Corporation
+ */
+
+#include <common.h>
+#include <log.h>
+#include <semihosting.h>
+
+#define SYSOPEN 0x01
+#define SYSCLOSE 0x02
+#define SYSWRITEC 0x03
+#define SYSWRITE0 0x04
+#define SYSWRITE 0x05
+#define SYSREAD 0x06
+#define SYSREADC 0x07
+#define SYSISERROR 0x08
+#define SYSSEEK 0x0A
+#define SYSFLEN 0x0C
+#define SYSERRNO 0x13
+
+#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
+ *
+ * This gets the value of the host's errno and negates it. The host's errno may
+ * or may not be set, so only call this function if a previous semihosting call
+ * has failed.
+ *
+ * Return: a negative error value
+ */
+static int smh_errno(void)
+{
+ long ret = smh_trap(SYSERRNO, NULL);
+
+ if (ret > 0 && ret < INT_MAX)
+ return -ret;
+ return -EIO;
+}
+
+long smh_open(const char *fname, enum smh_open_mode mode)
+{
+ long fd;
+ struct smh_open_s {
+ const char *fname;
+ unsigned long mode;
+ size_t len;
+ } open;
+
+ debug("%s: file \'%s\', mode \'%u\'\n", __func__, fname, mode);
+
+ open.fname = fname;
+ open.len = strlen(fname);
+ open.mode = mode;
+
+ /* Open the file on the host */
+ fd = smh_trap(SYSOPEN, &open);
+ if (fd == -1)
+ return smh_errno();
+ return fd;
+}
+
+/**
+ * struct smg_rdwr_s - Arguments for read and write
+ * @fd: A file descriptor returned from smh_open()
+ * @memp: Pointer to a buffer of memory of at least @len bytes
+ * @len: The number of bytes to read or write
+ */
+struct smh_rdwr_s {
+ long fd;
+ void *memp;
+ size_t len;
+};
+
+long smh_read(long fd, void *memp, size_t len)
+{
+ long ret;
+ struct smh_rdwr_s read;
+
+ debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
+
+ read.fd = fd;
+ read.memp = memp;
+ read.len = len;
+
+ ret = smh_trap(SYSREAD, &read);
+ if (ret < 0)
+ return smh_errno();
+ return len - ret;
+}
+
+long smh_write(long fd, const void *memp, size_t len, ulong *written)
+{
+ long ret;
+ struct smh_rdwr_s write;
+
+ debug("%s: fd %ld, memp %p, len %zu\n", __func__, fd, memp, len);
+
+ write.fd = fd;
+ write.memp = (void *)memp;
+ write.len = len;
+
+ ret = smh_trap(SYSWRITE, &write);
+ *written = len - ret;
+ if (ret)
+ return smh_errno();
+ return 0;
+}
+
+long smh_close(long fd)
+{
+ long ret;
+
+ debug("%s: fd %ld\n", __func__, fd);
+
+ ret = smh_trap(SYSCLOSE, &fd);
+ if (ret == -1)
+ return smh_errno();
+ return 0;
+}
+
+long smh_flen(long fd)
+{
+ long ret;
+
+ debug("%s: fd %ld\n", __func__, fd);
+
+ ret = smh_trap(SYSFLEN, &fd);
+ if (ret == -1)
+ return smh_errno();
+ return ret;
+}
+
+long smh_seek(long fd, long pos)
+{
+ long ret;
+ struct smh_seek_s {
+ long fd;
+ long pos;
+ } seek;
+
+ debug("%s: fd %ld pos %ld\n", __func__, fd, pos);
+
+ seek.fd = fd;
+ seek.pos = pos;
+
+ ret = smh_trap(SYSSEEK, &seek);
+ if (ret)
+ return smh_errno();
+ return 0;
+}
+
+int smh_getc(void)
+{
+ return smh_trap(SYSREADC, NULL);
+}
+
+void smh_putc(char ch)
+{
+ smh_trap(SYSWRITEC, &ch);
+}
+
+void smh_puts(const char *s)
+{
+ smh_trap(SYSWRITE0, (char *)s);
+}