diff --git a/MAINTAINERS b/MAINTAINERS index 33fd4652a4..c41bc89fe9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -476,6 +476,7 @@ F: doc/README.uefi F: doc/README.iscsi F: Documentation/efi.rst F: include/capitalization.h +F: include/charset.h F: include/cp1250.h F: include/cp437.h F: include/efi* diff --git a/cmd/Kconfig b/cmd/Kconfig index fd1beb0684..0d36da2a5c 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1436,6 +1436,7 @@ config CMD_DISPLAY config CMD_EFIDEBUG bool "efidebug - display/configure UEFI environment" depends on EFI_LOADER + select EFI_DEVICE_PATH_TO_TEXT default n help Enable the 'efidebug' command which provides a subset of UEFI diff --git a/cmd/bootefi.c b/cmd/bootefi.c index 52116b308c..c19256e00d 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -196,11 +196,16 @@ static void *get_config_table(const efi_guid_t *guid) /** * efi_install_fdt() - install fdt passed by a command argument + * + * If fdt_opt is available, the device tree located at that memory address will + * will be installed as configuration table, otherwise the device tree located + * at the address indicated by environment variable fdtcontroladdr will be used. + * + * On architectures (x86) using ACPI tables device trees shall not be installed + * as configuration table. + * * @fdt_opt: pointer to argument * Return: status code - * - * If specified, fdt will be installed as configuration table, - * otherwise no fdt will be passed. */ static efi_status_t efi_install_fdt(const char *fdt_opt) { @@ -314,32 +319,15 @@ static efi_status_t do_bootefi_exec(efi_handle_t handle) } /** - * do_efibootmgr() - execute EFI Boot Manager + * do_efibootmgr() - execute EFI boot manager * - * @fdt_opt: string of fdt start address * Return: status code - * - * Execute EFI Boot Manager */ -static int do_efibootmgr(const char *fdt_opt) +static int do_efibootmgr(void) { efi_handle_t handle; efi_status_t ret; - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - printf("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } - - ret = efi_install_fdt(fdt_opt); - if (ret == EFI_INVALID_PARAMETER) - return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - ret = efi_bootmgr_load(&handle); if (ret != EFI_SUCCESS) { printf("EFI boot manager: Cannot load any image\n"); @@ -355,16 +343,15 @@ static int do_efibootmgr(const char *fdt_opt) } /* - * do_bootefi_image() - execute EFI binary from command line + * do_bootefi_image() - execute EFI binary + * + * Set up memory image for the binary to be loaded, prepare device path, and + * then call do_bootefi_exec() to execute it. * * @image_opt: string of image start address - * @fdt_opt: string of fdt start address * Return: status code - * - * Set up memory image for the binary to be loaded, prepare - * device path and then call do_bootefi_exec() to execute it. */ -static int do_bootefi_image(const char *image_opt, const char *fdt_opt) +static int do_bootefi_image(const char *image_opt) { void *image_buf; struct efi_device_path *device_path, *image_path; @@ -374,20 +361,6 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt) efi_handle_t mem_handle = NULL, handle; efi_status_t ret; - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - printf("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } - - ret = efi_install_fdt(fdt_opt); - if (ret == EFI_INVALID_PARAMETER) - return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - #ifdef CONFIG_CMD_BOOTEFI_HELLO if (!strcmp(image_opt, "hello")) { char *saddr; @@ -547,33 +520,16 @@ static void bootefi_run_finish(struct efi_loaded_image_obj *image_obj, } /** - * do_efi_selftest() - execute EFI Selftest + * do_efi_selftest() - execute EFI selftest * - * @fdt_opt: string of fdt start address * Return: status code - * - * Execute EFI Selftest */ -static int do_efi_selftest(const char *fdt_opt) +static int do_efi_selftest(void) { struct efi_loaded_image_obj *image_obj; struct efi_loaded_image *loaded_image_info; efi_status_t ret; - /* Initialize EFI drivers */ - ret = efi_init_obj_list(); - if (ret != EFI_SUCCESS) { - printf("Error: Cannot initialize UEFI sub-system, r = %lu\n", - ret & ~EFI_ERROR_MASK); - return CMD_RET_FAILURE; - } - - ret = efi_install_fdt(fdt_opt); - if (ret == EFI_INVALID_PARAMETER) - return CMD_RET_USAGE; - else if (ret != EFI_SUCCESS) - return CMD_RET_FAILURE; - ret = bootefi_test_prepare(&image_obj, &loaded_image_info, "\\selftest", "efi_selftest"); if (ret != EFI_SUCCESS) @@ -587,20 +543,44 @@ static int do_efi_selftest(const char *fdt_opt) } #endif /* CONFIG_CMD_BOOTEFI_SELFTEST */ -/* Interpreter command to boot an arbitrary EFI image from memory */ +/** + * do_bootefi() - execute `bootefi` command + * + * @cmdtp: table entry describing command + * @flag: bitmap indicating how the command was invoked + * @argc: number of arguments + * @argv: command line arguments + * Return: status code + */ static int do_bootefi(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { + efi_status_t ret; + if (argc < 2) return CMD_RET_USAGE; + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + printf("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + return CMD_RET_FAILURE; + } + + ret = efi_install_fdt(argc > 2 ? argv[2] : NULL); + if (ret == EFI_INVALID_PARAMETER) + return CMD_RET_USAGE; + else if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + if (!strcmp(argv[1], "bootmgr")) - return do_efibootmgr(argc > 2 ? argv[2] : NULL); + return do_efibootmgr(); #ifdef CONFIG_CMD_BOOTEFI_SELFTEST else if (!strcmp(argv[1], "selftest")) - return do_efi_selftest(argc > 2 ? argv[2] : NULL); + return do_efi_selftest(); #endif - return do_bootefi_image(argv[1], argc > 2 ? argv[2] : NULL); + return do_bootefi_image(argv[1]); } #ifdef CONFIG_SYS_LONGHELP diff --git a/include/charset.h b/include/charset.h index 65087f76d1..4f7ae8fafd 100644 --- a/include/charset.h +++ b/include/charset.h @@ -46,9 +46,9 @@ int utf8_put(s32 code, char **dst); * * @src: utf-8 string * @count: maximum number of code points to convert - * Return: length in bytes after conversion to utf-16 without the + * Return: length in u16 after conversion to utf-16 without the * trailing \0. If an invalid UTF-8 sequence is hit one - * word will be reserved for a replacement character. + * u16 will be reserved for a replacement character. */ size_t utf8_utf16_strnlen(const char *src, size_t count); @@ -56,8 +56,9 @@ size_t utf8_utf16_strnlen(const char *src, size_t count); * utf8_utf16_strlen() - length of a utf-8 string after conversion to utf-16 * * @src: utf-8 string - * Return: length in bytes after conversion to utf-16 without the - * trailing \0. -1 if the utf-8 string is not valid. + * Return: length in u16 after conversion to utf-16 without the + * trailing \0. If an invalid UTF-8 sequence is hit one + * u16 will be reserved for a replacement character. */ #define utf8_utf16_strlen(a) utf8_utf16_strnlen((a), SIZE_MAX) @@ -127,7 +128,8 @@ size_t utf16_utf8_strnlen(const u16 *src, size_t count); * * @src: utf-16 string * Return: length in bytes after conversion to utf-8 without the - * trailing \0. -1 if the utf-16 string is not valid. + * trailing \0. If an invalid UTF-16 sequence is hit one + * byte will be reserved for a replacement character. */ #define utf16_utf8_strlen(a) utf16_utf8_strnlen((a), SIZE_MAX) diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 50b050159c..6501ee56aa 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,5 +1,5 @@ config EFI_LOADER - bool "Support running EFI Applications in U-Boot" + bool "Support running UEFI applications" depends on (ARM || X86 || RISCV || SANDBOX) && OF_LIBFDT # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT @@ -11,43 +11,22 @@ config EFI_LOADER select REGEX imply CFB_CONSOLE_ANSI help - Select this option if you want to run EFI applications (like grub2) - on top of U-Boot. If this option is enabled, U-Boot will expose EFI - interfaces to a loaded EFI application, enabling it to reuse U-Boot's - device drivers. + Select this option if you want to run UEFI applications (like GNU + GRUB or iPXE) on top of U-Boot. If this option is enabled, U-Boot + will expose the UEFI API to a loaded application, enabling it to + reuse U-Boot's device drivers. -config EFI_UNICODE_CAPITALIZATION - bool "Support Unicode capitalization" - depends on EFI_LOADER +if EFI_LOADER + +config EFI_DEVICE_PATH_TO_TEXT + bool "Device path to text protocol" default y help - Select this option to enable correct handling of the capitalization of - Unicode codepoints in the range 0x0000-0xffff. If this option is not - set, only the the correct handling of the letters of the codepage - used by the FAT file system is ensured. - -config EFI_PLATFORM_LANG_CODES - string "Language codes supported by firmware" - depends on EFI_LOADER - default "en-US" - help - This value is used to initialize the PlatformLangCodes variable. Its - value is a semicolon (;) separated list of language codes in native - RFC 4646 format, e.g. "en-US;de-DE". The first language code is used - to initialize the PlatformLang variable. - -config EFI_LOADER_BOUNCE_BUFFER - bool "EFI Applications use bounce buffers for DMA operations" - depends on EFI_LOADER && ARM64 - default n - help - Some hardware does not support DMA to full 64bit addresses. For this - hardware we can create a bounce buffer so that payloads don't have to - worry about platform details. + The device path to text protocol converts device nodes and paths to + human readable strings. config EFI_LOADER_HII - bool "Expose HII protocols to EFI applications" - depends on EFI_LOADER + bool "HII protocols" default y help The Human Interface Infrastructure is a complicated framework that @@ -56,3 +35,43 @@ config EFI_LOADER_HII U-Boot implements enough of its features to be able to run the UEFI Shell, but not more than that. + +config EFI_UNICODE_COLLATION_PROTOCOL + bool "Unicode collation protocol" + default y + help + The Unicode collation protocol is used for lexical comparisons. It is + required to run the UEFI shell. + +if EFI_UNICODE_COLLATION_PROTOCOL + +config EFI_UNICODE_CAPITALIZATION + bool "Support Unicode capitalization" + default y + help + Select this option to enable correct handling of the capitalization of + Unicode codepoints in the range 0x0000-0xffff. If this option is not + set, only the the correct handling of the letters of the codepage + used by the FAT file system is ensured. + +endif + +config EFI_LOADER_BOUNCE_BUFFER + bool "EFI Applications use bounce buffers for DMA operations" + depends on ARM64 + default n + help + Some hardware does not support DMA to full 64bit addresses. For this + hardware we can create a bounce buffer so that payloads don't have to + worry about platform details. + +config EFI_PLATFORM_LANG_CODES + string "Language codes supported by firmware" + default "en-US" + help + This value is used to initialize the PlatformLangCodes variable. Its + value is a semicolon (;) separated list of language codes in native + RFC 4646 format, e.g. "en-US;de-DE". The first language code is used + to initialize the PlatformLang variable. + +endif diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 4e90a35896..f3d6773bf6 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -21,16 +21,16 @@ obj-y += efi_bootmgr.o obj-y += efi_boottime.o obj-y += efi_console.o obj-y += efi_device_path.o -obj-y += efi_device_path_to_text.o +obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_device_path_to_text.o obj-y += efi_device_path_utilities.o obj-y += efi_file.o -obj-y += efi_hii.o efi_hii_config.o +obj-$(CONFIG_EFI_LOADER_HII) += efi_hii.o efi_hii_config.o obj-y += efi_image_loader.o obj-y += efi_memory.o obj-y += efi_root_node.o obj-y += efi_runtime.o obj-y += efi_setup.o -obj-y += efi_unicode_collation.o +obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL) += efi_unicode_collation.o obj-y += efi_variable.o obj-y += efi_watchdog.o obj-$(CONFIG_LCD) += efi_gop.o diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index b97d55cb45..ec6f5758de 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -181,10 +181,12 @@ static void efi_queue_event(struct efi_event *event, bool check_tpl) /* Check TPL */ if (check_tpl && efi_tpl >= event->notify_tpl) return; + event->is_queued = false; EFI_CALL_VOID(event->notify_function(event, event->notify_context)); + } else { + event->is_queued = false; } - event->is_queued = false; } /** @@ -513,10 +515,8 @@ efi_status_t efi_remove_protocol(const efi_handle_t handle, ret = efi_search_protocol(handle, protocol, &handler); if (ret != EFI_SUCCESS) return ret; - if (guidcmp(handler->guid, protocol)) - return EFI_INVALID_PARAMETER; if (handler->protocol_interface != protocol_interface) - return EFI_INVALID_PARAMETER; + return EFI_NOT_FOUND; list_del(&handler->link); free(handler); return EFI_SUCCESS; @@ -1439,7 +1439,7 @@ static efi_status_t efi_locate_handle( *buffer_size = size; - /* The buffer size is sufficient but there is not buffer */ + /* The buffer size is sufficient but there is no buffer */ if (!buffer) return EFI_INVALID_PARAMETER; @@ -2261,7 +2261,7 @@ static efi_status_t EFIAPI efi_locate_device_path( EFI_ENTRY("%pUl, %p, %p", protocol, device_path, device); - if (!protocol || !device_path || !*device_path || !device) { + if (!protocol || !device_path || !*device_path) { ret = EFI_INVALID_PARAMETER; goto out; } @@ -2294,6 +2294,10 @@ static efi_status_t EFIAPI efi_locate_device_path( /* Check if dp is a subpath of device_path */ if (memcmp(*device_path, dp, len_dp)) continue; + if (!device) { + ret = EFI_INVALID_PARAMETER; + goto out; + } *device = handles[i]; len_best = len_dp; } diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index e219f84b28..f3a9579076 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -78,9 +78,9 @@ static char *dp_acpi(char *s, struct efi_device_path *dp) case DEVICE_PATH_SUB_TYPE_ACPI_DEVICE: { struct efi_device_path_acpi_path *adp = (struct efi_device_path_acpi_path *)dp; - s += sprintf(s, "Acpi(PNP%04x", EISA_PNP_NUM(adp->hid)); - if (adp->uid) - s += sprintf(s, ",%d", adp->uid); + + s += sprintf(s, "Acpi(PNP%04X", EISA_PNP_NUM(adp->hid)); + s += sprintf(s, ",%d", adp->uid); s += sprintf(s, ")"); break; } diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c index 776077cc35..76dcaa48f4 100644 --- a/lib/efi_loader/efi_memory.c +++ b/lib/efi_loader/efi_memory.c @@ -318,6 +318,44 @@ uint64_t efi_add_memory_map(uint64_t start, uint64_t pages, int memory_type, return start; } +/** + * efi_check_allocated() - validate address to be freed + * + * Check that the address is within allocated memory: + * + * * The address cannot be NULL. + * * The address must be in a range of the memory map. + * * The address may not point to EFI_CONVENTIONAL_MEMORY. + * + * Page alignment is not checked as this is not a requirement of + * efi_free_pool(). + * + * @addr: address of page to be freed + * @must_be_allocated: return success if the page is allocated + * Return: status code + */ +static efi_status_t efi_check_allocated(u64 addr, bool must_be_allocated) +{ + struct efi_mem_list *item; + + if (!addr) + return EFI_INVALID_PARAMETER; + list_for_each_entry(item, &efi_mem, link) { + u64 start = item->desc.physical_start; + u64 end = start + (item->desc.num_pages << EFI_PAGE_SHIFT); + + if (addr >= start && addr < end) { + if (must_be_allocated ^ + (item->desc.type == EFI_CONVENTIONAL_MEMORY)) + return EFI_SUCCESS; + else + return EFI_NOT_FOUND; + } + } + + return EFI_NOT_FOUND; +} + static uint64_t efi_find_free_memory(uint64_t len, uint64_t max_addr) { struct list_head *lhandle; @@ -373,7 +411,7 @@ efi_status_t efi_allocate_pages(int type, int memory_type, efi_uintn_t pages, uint64_t *memory) { u64 len = pages << EFI_PAGE_SHIFT; - efi_status_t r = EFI_SUCCESS; + efi_status_t ret; uint64_t addr; /* Check import parameters */ @@ -387,43 +425,35 @@ efi_status_t efi_allocate_pages(int type, int memory_type, case EFI_ALLOCATE_ANY_PAGES: /* Any page */ addr = efi_find_free_memory(len, -1ULL); - if (!addr) { - r = EFI_NOT_FOUND; - break; - } + if (!addr) + return EFI_OUT_OF_RESOURCES; break; case EFI_ALLOCATE_MAX_ADDRESS: /* Max address */ addr = efi_find_free_memory(len, *memory); - if (!addr) { - r = EFI_NOT_FOUND; - break; - } + if (!addr) + return EFI_OUT_OF_RESOURCES; break; case EFI_ALLOCATE_ADDRESS: /* Exact address, reserve it. The addr is already in *memory. */ + ret = efi_check_allocated(*memory, false); + if (ret != EFI_SUCCESS) + return EFI_NOT_FOUND; addr = *memory; break; default: /* UEFI doesn't specify other allocation types */ - r = EFI_INVALID_PARAMETER; - break; + return EFI_INVALID_PARAMETER; } - if (r == EFI_SUCCESS) { - uint64_t ret; + /* Reserve that map in our memory maps */ + if (efi_add_memory_map(addr, pages, memory_type, true) != addr) + /* Map would overlap, bail out */ + return EFI_OUT_OF_RESOURCES; - /* Reserve that map in our memory maps */ - ret = efi_add_memory_map(addr, pages, memory_type, true); - if (ret == addr) { - *memory = addr; - } else { - /* Map would overlap, bail out */ - r = EFI_OUT_OF_RESOURCES; - } - } + *memory = addr; - return r; + return EFI_SUCCESS; } void *efi_alloc(uint64_t len, int memory_type) @@ -450,6 +480,11 @@ void *efi_alloc(uint64_t len, int memory_type) efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages) { uint64_t r = 0; + efi_status_t ret; + + ret = efi_check_allocated(memory, true); + if (ret != EFI_SUCCESS) + return ret; /* Sanity check */ if (!memory || (memory & EFI_PAGE_MASK) || !pages) { @@ -511,11 +546,12 @@ efi_status_t efi_allocate_pool(int pool_type, efi_uintn_t size, void **buffer) */ efi_status_t efi_free_pool(void *buffer) { - efi_status_t r; + efi_status_t ret; struct efi_pool_allocation *alloc; - if (buffer == NULL) - return EFI_INVALID_PARAMETER; + ret = efi_check_allocated((uintptr_t)buffer, true); + if (ret != EFI_SUCCESS) + return ret; alloc = container_of(buffer, struct efi_pool_allocation, data); @@ -528,9 +564,9 @@ efi_status_t efi_free_pool(void *buffer) /* Avoid double free */ alloc->checksum = 0; - r = efi_free_pages((uintptr_t)alloc, alloc->num_pages); + ret = efi_free_pages((uintptr_t)alloc, alloc->num_pages); - return r; + return ret; } /* diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index 38514e0820..d8496cc3c2 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -52,15 +52,19 @@ efi_status_t efi_root_node_register(void) (&efi_root, /* Device path protocol */ &efi_guid_device_path, dp, +#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) /* Device path to text protocol */ &efi_guid_device_path_to_text_protocol, (void *)&efi_device_path_to_text, +#endif /* Device path utilities protocol */ &efi_guid_device_path_utilities_protocol, (void *)&efi_device_path_utilities, +#if CONFIG_IS_ENABLED(EFI_UNICODE_COLLATION_PROTOCOL) /* Unicode collation protocol */ &efi_guid_unicode_collation_protocol, (void *)&efi_unicode_collation_protocol, +#endif #if CONFIG_IS_ENABLED(EFI_LOADER_HII) /* HII string protocol */ &efi_guid_hii_string_protocol, diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index c69ad7a9c0..d0bebc7d0c 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -17,7 +17,6 @@ efi_selftest_config_table.o \ efi_selftest_controllers.o \ efi_selftest_console.o \ efi_selftest_crc32.o \ -efi_selftest_devicepath.o \ efi_selftest_devicepath_util.o \ efi_selftest_events.o \ efi_selftest_event_groups.o \ @@ -34,11 +33,13 @@ efi_selftest_textinput.o \ efi_selftest_textinputex.o \ efi_selftest_textoutput.o \ efi_selftest_tpl.o \ -efi_selftest_unicode_collation.o \ efi_selftest_util.o \ efi_selftest_variables.o \ efi_selftest_watchdog.o +obj-$(CONFIG_EFI_DEVICE_PATH_TO_TEXT) += efi_selftest_devicepath.o +obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL) += efi_selftest_unicode_collation.o + obj-$(CONFIG_CPU_V7) += efi_selftest_unaligned.o obj-$(CONFIG_EFI_LOADER_HII) += efi_selftest_hii.o diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 3502b8088f..8bbbd48c54 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -296,6 +296,7 @@ static char *string16(char *buf, char *end, u16 *s, int field_width, return buf; } +#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) static char *device_path_string(char *buf, char *end, void *dp, int field_width, int precision, int flags) { @@ -314,6 +315,7 @@ static char *device_path_string(char *buf, char *end, void *dp, int field_width, return buf; } #endif +#endif #ifdef CONFIG_CMD_NET static char *mac_address_string(char *buf, char *end, u8 *addr, int field_width, @@ -451,7 +453,7 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, switch (*fmt) { /* Device paths only exist in the EFI context. */ -#if CONFIG_IS_ENABLED(EFI_LOADER) && !defined(API_BUILD) +#if CONFIG_IS_ENABLED(EFI_DEVICE_PATH_TO_TEXT) && !defined(API_BUILD) case 'D': return device_path_string(buf, end, ptr, field_width, precision, flags);