summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
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/rsa/rsa-verify.c20
-rw-r--r--lib/semihosting.c186
7 files changed, 252 insertions, 23 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index c39fc523214..def36f275ce 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 f2cfd1e4289..d77b33e7f48 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 e2b643871bf..b498c72206f 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 a49aae92497..3036d46349a 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 e8cc13545db..09c5e96c5e1 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/rsa/rsa-verify.c b/lib/rsa/rsa-verify.c
index 9605c376390..2f3b3440391 100644
--- a/lib/rsa/rsa-verify.c
+++ b/lib/rsa/rsa-verify.c
@@ -23,18 +23,6 @@
#include <u-boot/rsa-mod-exp.h>
#include <u-boot/rsa.h>
-#ifndef __UBOOT__
-/*
- * NOTE:
- * Since host tools, like mkimage, make use of openssl library for
- * RSA encryption, rsa_verify_with_pkey()/rsa_gen_key_prop() are
- * of no use and should not be compiled in.
- * So just turn off CONFIG_RSA_VERIFY_WITH_PKEY.
- */
-
-#undef CONFIG_RSA_VERIFY_WITH_PKEY
-#endif
-
/* Default public exponent for backward compatibility */
#define RSA_DEFAULT_PUBEXP 65537
@@ -506,7 +494,13 @@ int rsa_verify_hash(struct image_sign_info *info,
{
int ret = -EACCES;
- if (CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY) && !info->fdt_blob) {
+ /*
+ * Since host tools, like mkimage, make use of openssl library for
+ * RSA encryption, rsa_verify_with_pkey()/rsa_gen_key_prop() are
+ * of no use and should not be compiled in.
+ */
+ if (!tools_build() && CONFIG_IS_ENABLED(RSA_VERIFY_WITH_PKEY) &&
+ !info->fdt_blob) {
/* don't rely on fdt properties */
ret = rsa_verify_with_pkey(info, hash, sig, sig_len);
if (ret)
diff --git a/lib/semihosting.c b/lib/semihosting.c
new file mode 100644
index 00000000000..831774e3566
--- /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);
+}