This will be very verbose, but when trying to pinpoint what operation is bothering an EFI payload, it's very useful to know every entry and exit into barebox-provided services.
Signed-off-by: Ahmad Fatoum <[email protected]> --- common/Kconfig.debug | 7 +++ efi/loader/Makefile | 1 + efi/loader/trace.c | 44 +++++++++++++++ include/efi/loader/trace.h | 111 +++++++++++++++++++++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 efi/loader/trace.c create mode 100644 include/efi/loader/trace.h diff --git a/common/Kconfig.debug b/common/Kconfig.debug index 2de885ebb3f8..64127143a5d6 100644 --- a/common/Kconfig.debug +++ b/common/Kconfig.debug @@ -77,6 +77,13 @@ config DEBUG_PROBES Most consoles do not implement a remove callback to remain operable until the very end. Consoles using DMA, however, must be removed. +config DEBUG_EFI_LOADER_ENTRY + bool "Debug EFI loader entry/exit" + depends on EFI_LOADER + help + If enabled, this will print whenever an EFI payload/app calls + into barebox or is returned to before ExitBootServices. + config DMA_API_DEBUG bool "Enable debugging of DMA-API usage" depends on HAS_DMA diff --git a/efi/loader/Makefile b/efi/loader/Makefile index 0475cfc7452f..1f07cf6005b9 100644 --- a/efi/loader/Makefile +++ b/efi/loader/Makefile @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0 obj-y += memory.o pool_alloc.o +obj-y += trace.o diff --git a/efi/loader/trace.c b/efi/loader/trace.c new file mode 100644 index 000000000000..9eb22805e12e --- /dev/null +++ b/efi/loader/trace.c @@ -0,0 +1,44 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include <efi/loader/trace.h> +#include <linux/minmax.h> + +/* 1 if inside barebox code, 0 if inside EFI payload code */ +static int nesting_level = 1; + +/** + * indent_string() - returns a string for indenting with two spaces per level + * @level: indent level + * + * A maximum of ten indent levels is supported. Higher indent levels will be + * truncated. + * + * Return: A string for indenting with two spaces per level is + * returned. + */ +static const char *indent_string(int level) +{ + const char *indent = " "; + const int max = strlen(indent); + + if (level < 0) + return "!!EFI_EXIT called without matching EFI_ENTRY!! "; + + level = min(max, level * 2); + return &indent[max - level]; +} + +const char *__efi_nesting(void) +{ + return indent_string(nesting_level); +} + +const char *__efi_nesting_inc(void) +{ + return indent_string(nesting_level++); +} + +const char *__efi_nesting_dec(void) +{ + return indent_string(--nesting_level); +} diff --git a/include/efi/loader/trace.h b/include/efi/loader/trace.h new file mode 100644 index 000000000000..93bba7bb88c7 --- /dev/null +++ b/include/efi/loader/trace.h @@ -0,0 +1,111 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +#ifndef __EFI_LOADER_TRACE_H__ +#define __EFI_LOADER_TRACE_H__ + +#include <efi/error.h> +#include <linux/printk.h> + +#ifndef __EFI_PRINT +#ifdef CONFIG_DEBUG_EFI_LOADER_ENTRY +#define __EFI_PRINT(...) pr_info(__VA_ARGS__) +#define __EFI_WARN(...) pr_warning(__VA_ARGS__) +#else +#define __EFI_PRINT(...) pr_debug(__VA_ARGS__) +#define __EFI_WARN(...) pr_debug(__VA_ARGS__) +#endif +#endif + +const char *__efi_nesting(void); +const char *__efi_nesting_inc(void); +const char *__efi_nesting_dec(void); + +/* + * Enter the barebox world from UEFI: + */ +#ifndef EFI_ENTRY +#define EFI_ENTRY(format, ...) do { \ + __EFI_PRINT("%sEFI: Entry %s(" format ")\n", __efi_nesting_inc(), \ + __func__, ##__VA_ARGS__); \ + } while(0) +#endif + +/* + * Exit the barebox world back to UEFI: + */ +#ifndef EFI_EXIT +#define EFI_EXIT(ret) ({ \ + typeof(ret) _r = ret; \ + __EFI_PRINT("%sEFI: Exit: %s: %s (%u)\n", __efi_nesting_dec(), \ + __func__, efi_strerror((uintptr_t)_r), (u32)((uintptr_t) _r & ~EFI_ERROR_MASK)); \ + _r; \ + }) +#endif + +#ifndef EFI_EXIT2 +#define EFI_EXIT2(ret, val) ({ \ + typeof(ret) _r = ret; \ + __EFI_PRINT("%sEFI: Exit: %s: %s (%u) = 0x%llx\n", __efi_nesting_dec(), \ + __func__, efi_strerror((uintptr_t)_r), (u32)((uintptr_t) _r & ~EFI_ERROR_MASK), \ + (u64)(uintptr_t)(val)); \ + _r; \ + }) +#endif + +/* + * Call non-void UEFI function from barebox and retrieve return value: + */ +#ifndef EFI_CALL +#define EFI_CALL(exp) ({ \ + __EFI_PRINT("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \ + typeof(exp) _r = exp; \ + __EFI_PRINT("%sEFI: %lu returned by %s\n", __efi_nesting_dec(), \ + (unsigned long)((uintptr_t)_r & ~EFI_ERROR_MASK), #exp); \ + _r; \ +}) +#endif + +/** + * define EFI_RETURN() - return from EFI_CALL in efi_start_image() + * + * @ret: status code + */ +#ifndef EFI_RETURN +#define EFI_RETURN(ret) ({ \ + typeof(ret) _r = ret; \ + __EFI_PRINT("%sEFI: %lu returned by started image", __efi_nesting_dec(), \ + (unsigned long)((uintptr_t)_r & ~EFI_ERROR_MASK)); \ +}) +#endif + +/* + * Call void UEFI function from barebox: + */ +#ifndef EFI_CALL_VOID +#define EFI_CALL_VOID(exp) do { \ + __EFI_PRINT("%sEFI: Call: %s\n", __efi_nesting_inc(), #exp); \ + exp; \ + __EFI_PRINT("%sEFI: Return From: %s\n", __efi_nesting_dec(), #exp); \ + } while(0) +#endif + +/* + * Write an indented message with EFI prefix + */ +#ifndef EFI_PRINT +#define EFI_PRINT(format, ...) ({ \ + __EFI_PRINT("%sEFI: " format, __efi_nesting(), \ + ##__VA_ARGS__); \ + }) +#endif + +/* + * Write an indented warning with EFI prefix + */ +#ifndef EFI_WARN +#define EFI_WARN(format, ...) ({ \ + __EFI_WARN("%sEFI: " format, __efi_nesting(), \ + ##__VA_ARGS__); \ + }) +#endif + +#endif -- 2.47.3
