diff options
author | Tom Rini <trini@konsulko.com> | 2022-12-19 17:29:55 +0300 |
---|---|---|
committer | Tom Rini <trini@konsulko.com> | 2022-12-21 21:09:01 +0300 |
commit | 14f43797d0a696248c09d298e2f2809dded345ba (patch) | |
tree | 23fc5bc462689f07f389cc0b8e7f7bedd35253ff /lib | |
parent | 9c955393f7a27ded250fef7688e0065b44a3343f (diff) | |
parent | 2243922edca9f56a9d5519b9d6e36f5d7a18434d (diff) | |
download | u-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/Kconfig | 47 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/efi_loader/Kconfig | 6 | ||||
-rw-r--r-- | lib/efi_loader/efi_conformance.c | 8 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_ecpt.c | 6 | ||||
-rw-r--r-- | lib/semihosting.c | 186 |
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); +} |