Pull request for UEFI sub-system for efi-2021-01-rc2 (2)

The series contains the following enhancements
 
 * preparatory patches for UEFI capsule updates
 * initialization of the emulated RTC using an environment variable
 
 and a bug fix
 
 * If DisconnectController() is called for a child controller that is the
   only child of the driver, the driver must be disconnected.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl+e1WUACgkQxIHbvCwF
 GsRHhQ//X/hQiow1/3YwskyZkC89QPLE+TDeGcRHdy7W2rjfJlOBJtsI1tzvsTWw
 8etgIuoh1MKebJZZQk/ZxKdWOaN3RWP7wL/9c6PHpkkML+WzyLWShf5UgLMWeo3w
 a7t0LW4kfxbzmhg/f4x0Gi3qUh0SiS6T8Q5X/SlJOX091IvCmCOTkGUT6dBogm78
 WnISQvgP3uApOt2s66hVVtFaH4zbXDYwDnQhhUoonRF1AfuE3jTyr39IoNsCdPOx
 vEbTqNKQQnt4yIIaPJlV+KX//jtCCnyLBPrZA1tI2QPyBjADmNcau2OjlBZyJpr0
 1awgSueXgBtMCAp6bHMl9p3eSKYv2f0BvPGljgKrs9dfIZk+XN0w62VuSYwRi7TU
 ZEppINMisM1hC9+7jKNGn0nE9y3UldBSNThWxk8ykpWL+Btv5KeArHK4+916nadQ
 a7t+6Ow7hiVI1Y/3TWaLvCi7xfqsU87QH6dx0nozgBUotuujIqa5lAeSGR9Rc6N2
 PSblEGf8AA8+oGAdBhNvDncHiRLWkUoBqFsaaAk4EiaHQk60InZ9CpQdeMqHErcx
 uLL9JcOCZeStcWF+vWmyU2L49O88HRHvboM7zA+gqLIUilwgKxmlOocoq+0jtA4l
 Bg72F3cI7+g+aTidskEOGo2v2cj0dh32ub5CqRHLdt3PUzP6qhs=
 =mCEL
 -----END PGP SIGNATURE-----

Merge tag 'efi-2020-01-rc2-2' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi

Pull request for UEFI sub-system for efi-2021-01-rc2 (2)

The series contains the following enhancements

* preparatory patches for UEFI capsule updates
* initialization of the emulated RTC using an environment variable

and a bug fix

* If DisconnectController() is called for a child controller that is the
  only child of the driver, the driver must be disconnected.
This commit is contained in:
Tom Rini 2020-11-01 10:56:37 -05:00
commit 41cab8edbc
20 changed files with 390 additions and 107 deletions

View File

@ -599,9 +599,15 @@ endmenu
menu "Update support"
config UPDATE_COMMON
bool
default n
select DFU_WRITE_ALT
config UPDATE_TFTP
bool "Auto-update using fitImage via TFTP"
depends on FIT
select UPDATE_COMMON
help
This option allows performing update of NOR with data in fitImage
sent via TFTP boot.
@ -616,6 +622,15 @@ config UPDATE_TFTP_MSEC_MAX
default 100
depends on UPDATE_TFTP
config UPDATE_FIT
bool "Firmware update using fitImage"
depends on FIT
depends on DFU
select UPDATE_COMMON
help
This option allows performing update of DFU-capable storage with
data in fitImage.
config ANDROID_AB
bool "Android A/B updates"
default n

View File

@ -53,8 +53,7 @@ obj-$(CONFIG_LCD_ROTATION) += lcd_console_rotation.o
obj-$(CONFIG_LCD_DT_SIMPLEFB) += lcd_simplefb.o
obj-$(CONFIG_LYNXKDI) += lynxkdi.o
obj-$(CONFIG_MENU) += menu.o
obj-$(CONFIG_UPDATE_TFTP) += update.o
obj-$(CONFIG_DFU_TFTP) += update.o
obj-$(CONFIG_UPDATE_COMMON) += update.o
obj-$(CONFIG_USB_KEYBOARD) += usb_kbd.o
obj-$(CONFIG_CMDLINE) += cli_readline.o cli_simple.o

View File

@ -73,6 +73,9 @@
#if defined(CONFIG_GPIO_HOG)
#include <asm/gpio.h>
#endif
#ifdef CONFIG_EFI_SETUP_EARLY
#include <efi_loader.h>
#endif
DECLARE_GLOBAL_DATA_PTR;
@ -888,6 +891,9 @@ static init_fnc_t init_sequence_r[] = {
#endif
#if defined(CONFIG_PRAM)
initr_mem,
#endif
#ifdef CONFIG_EFI_SETUP_EARLY
(init_fnc_t)efi_init_obj_list,
#endif
run_main_loop,
};

View File

@ -29,6 +29,7 @@
#include <errno.h>
#include <mtd/cfi_flash.h>
#ifdef CONFIG_DFU_TFTP
/* env variable holding the location of the update file */
#define UPDATE_FILE_ENV "updatefile"
@ -98,6 +99,7 @@ static int update_load(char *filename, ulong msec_max, int cnt_max, ulong addr)
return rv;
}
#endif /* CONFIG_DFU_TFTP */
#ifdef CONFIG_MTD_NOR_FLASH
static int update_flash_protect(int prot, ulong addr_first, ulong addr_last)
@ -231,6 +233,7 @@ static int update_fit_getparams(const void *fit, int noffset, ulong *addr,
return 0;
}
#ifdef CONFIG_DFU_TFTP
int update_tftp(ulong addr, char *interface, char *devstring)
{
char *filename, *env_addr, *fit_image_name;
@ -324,8 +327,10 @@ got_update_file:
}
} else if (fit_image_check_type(fit, noffset,
IH_TYPE_FIRMWARE)) {
ret = dfu_tftp_write(fit_image_name, update_addr,
update_size, interface, devstring);
ret = dfu_write_by_name(fit_image_name,
(void *)update_addr,
update_size, interface,
devstring);
if (ret)
return ret;
}
@ -335,3 +340,71 @@ next_node:
return ret;
}
#endif /* CONFIG_DFU_UPDATE */
#ifdef CONFIG_UPDATE_FIT
/**
* fit_update - update storage with FIT image
* @fit: Pointer to FIT image
*
* Update firmware on storage using FIT image as input.
* The storage area to be update will be identified by the name
* in FIT and matching it to "dfu_alt_info" variable.
*
* Return: 0 - on success, non-zero - otherwise
*/
int fit_update(const void *fit)
{
char *fit_image_name;
ulong update_addr, update_fladdr, update_size;
int images_noffset, ndepth, noffset;
int ret = 0;
if (!fit)
return -EINVAL;
if (!fit_check_format((void *)fit)) {
printf("Bad FIT format of the update file, aborting auto-update\n");
return -EINVAL;
}
/* process updates */
images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
ndepth = 0;
noffset = fdt_next_node(fit, images_noffset, &ndepth);
while (noffset >= 0 && ndepth > 0) {
if (ndepth != 1)
goto next_node;
fit_image_name = (char *)fit_get_name(fit, noffset, NULL);
printf("Processing update '%s' :", fit_image_name);
if (!fit_image_verify(fit, noffset)) {
printf("Error: invalid update hash, aborting\n");
ret = 1;
goto next_node;
}
printf("\n");
if (update_fit_getparams(fit, noffset, &update_addr,
&update_fladdr, &update_size)) {
printf("Error: can't get update parameters, aborting\n");
ret = 1;
goto next_node;
}
if (fit_image_check_type(fit, noffset, IH_TYPE_FIRMWARE)) {
ret = dfu_write_by_name(fit_image_name,
(void *)update_addr,
update_size, NULL, NULL);
if (ret)
return ret;
}
next_node:
noffset = fdt_next_node(fit, noffset, &ndepth);
}
return ret;
}
#endif /* CONFIG_UPDATE_FIT */

View File

@ -14,9 +14,15 @@ config DFU_OVER_TFTP
depends on NET
if DFU
config DFU_WRITE_ALT
bool
default n
config DFU_TFTP
bool "DFU via TFTP"
select DFU_WRITE_ALT
select DFU_OVER_TFTP
select UPDATE_COMMON
help
This option allows performing update of DFU-managed medium with data
sent via TFTP boot.

View File

@ -9,5 +9,5 @@ obj-$(CONFIG_$(SPL_)DFU_MTD) += dfu_mtd.o
obj-$(CONFIG_$(SPL_)DFU_NAND) += dfu_nand.o
obj-$(CONFIG_$(SPL_)DFU_RAM) += dfu_ram.o
obj-$(CONFIG_$(SPL_)DFU_SF) += dfu_sf.o
obj-$(CONFIG_$(SPL_)DFU_TFTP) += dfu_tftp.o
obj-$(CONFIG_$(SPL_)DFU_WRITE_ALT) += dfu_alt.o
obj-$(CONFIG_$(SPL_)DFU_VIRT) += dfu_virt.o

View File

@ -18,7 +18,7 @@
#include <linux/list.h>
#include <linux/compiler.h>
static LIST_HEAD(dfu_list);
LIST_HEAD(dfu_list);
static int dfu_alt_num;
static int alt_num_cnt;
static struct hash_algo *dfu_hash_algo;

125
drivers/dfu/dfu_alt.c Normal file
View File

@ -0,0 +1,125 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015
* Lukasz Majewski <l.majewski@majess.pl>
*/
#include <common.h>
#include <log.h>
#include <malloc.h>
#include <errno.h>
#include <dfu.h>
/**
* dfu_write_by_name() - write data to DFU medium
* @dfu_entity_name: Name of DFU entity to write
* @addr: Address of data buffer to write
* @len: Number of bytes
* @interface: Destination DFU medium (e.g. "mmc")
* @devstring: Instance number of destination DFU medium (e.g. "1")
*
* This function is storing data received on DFU supported medium which
* is specified by @dfu_entity_name.
*
* Return: 0 - on success, error code - otherwise
*/
int dfu_write_by_name(char *dfu_entity_name, void *addr,
unsigned int len, char *interface, char *devstring)
{
char *s, *sb;
int alt_setting_num, ret;
struct dfu_entity *dfu;
debug("%s: name: %s addr: 0x%p len: %d device: %s:%s\n", __func__,
dfu_entity_name, addr, len, interface, devstring);
ret = dfu_init_env_entities(interface, devstring);
if (ret)
goto done;
/*
* We need to copy name pointed by *dfu_entity_name since this text
* is the integral part of the FDT image.
* Any implicit modification (i.e. done by strsep()) will corrupt
* the FDT image and prevent other images to be stored.
*/
s = strdup(dfu_entity_name);
sb = s;
if (!s) {
ret = -ENOMEM;
goto done;
}
strsep(&s, "@");
debug("%s: image name: %s strlen: %zd\n", __func__, sb, strlen(sb));
alt_setting_num = dfu_get_alt(sb);
free(sb);
if (alt_setting_num < 0) {
pr_err("Alt setting [%d] to write not found!",
alt_setting_num);
ret = -ENODEV;
goto done;
}
dfu = dfu_get_entity(alt_setting_num);
if (!dfu) {
pr_err("DFU entity for alt: %d not found!", alt_setting_num);
ret = -ENODEV;
goto done;
}
ret = dfu_write_from_mem_addr(dfu, (void *)addr, len);
done:
dfu_free_entities();
return ret;
}
/**
* dfu_write_by_alt() - write data to DFU medium
* @dfu_alt_num: DFU alt setting number
* @addr: Address of data buffer to write
* @len: Number of bytes
* @interface: Destination DFU medium (e.g. "mmc")
* @devstring: Instance number of destination DFU medium (e.g. "1")
*
* This function is storing data received on DFU supported medium which
* is specified by @dfu_alt_name.
*
* Return: 0 - on success, error code - otherwise
*/
int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
char *interface, char *devstring)
{
struct dfu_entity *dfu;
int ret;
debug("%s: alt: %d addr: 0x%p len: %d device: %s:%s\n", __func__,
dfu_alt_num, addr, len, interface, devstring);
ret = dfu_init_env_entities(interface, devstring);
if (ret)
goto done;
if (dfu_alt_num < 0) {
pr_err("Invalid alt number: %d", dfu_alt_num);
ret = -ENODEV;
goto done;
}
dfu = dfu_get_entity(dfu_alt_num);
if (!dfu) {
pr_err("DFU entity for alt: %d not found!", dfu_alt_num);
ret = -ENODEV;
goto done;
}
ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
done:
dfu_free_entities();
return ret;
}

View File

@ -1,65 +0,0 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2015
* Lukasz Majewski <l.majewski@majess.pl>
*/
#include <common.h>
#include <log.h>
#include <malloc.h>
#include <errno.h>
#include <dfu.h>
int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
char *interface, char *devstring)
{
char *s, *sb;
int alt_setting_num, ret;
struct dfu_entity *dfu;
debug("%s: name: %s addr: 0x%x len: %d device: %s:%s\n", __func__,
dfu_entity_name, addr, len, interface, devstring);
ret = dfu_init_env_entities(interface, devstring);
if (ret)
goto done;
/*
* We need to copy name pointed by *dfu_entity_name since this text
* is the integral part of the FDT image.
* Any implicit modification (i.e. done by strsep()) will corrupt
* the FDT image and prevent other images to be stored.
*/
s = strdup(dfu_entity_name);
sb = s;
if (!s) {
ret = -ENOMEM;
goto done;
}
strsep(&s, "@");
debug("%s: image name: %s strlen: %zd\n", __func__, sb, strlen(sb));
alt_setting_num = dfu_get_alt(sb);
free(sb);
if (alt_setting_num < 0) {
pr_err("Alt setting [%d] to write not found!",
alt_setting_num);
ret = -ENODEV;
goto done;
}
dfu = dfu_get_entity(alt_setting_num);
if (!dfu) {
pr_err("DFU entity for alt: %d not found!", alt_setting_num);
ret = -ENODEV;
goto done;
}
ret = dfu_write_from_mem_addr(dfu, (void *)(uintptr_t)addr, len);
done:
dfu_free_entities();
return ret;
}

View File

@ -68,11 +68,14 @@ config RTC_EMULATION
depends on DM_RTC
help
On a board without hardware clock this software real time clock can be
used. The build time is used to initialize the RTC. So you will have
to adjust the time either manually using the 'date' command or use
the 'sntp' to update the RTC with the time from a network time server.
See CONFIG_CMD_SNTP and CONFIG_BOOTP_NTPSERVER. The RTC time is
advanced according to CPU ticks.
used. The initial time may be provided via the environment variable
'rtc_emul_epoch' as a decimal string indicating seconds since
1970-01-01. If the environment variable is missing, the build time is
used to initialize the RTC. The time can be adjusted manually via the
'date' command or the 'sntp' command can be used to update the RTC
with the time from a network time server. See CONFIG_CMD_SNTP and
CONFIG_BOOTP_NTPSERVER. The RTC time is advanced according to CPU
ticks.
config RTC_ISL1208
bool "Enable ISL1208 driver"

View File

@ -8,6 +8,7 @@
#include <common.h>
#include <div64.h>
#include <dm.h>
#include <env.h>
#include <generated/timestamp_autogenerated.h>
#include <rtc.h>
@ -30,12 +31,6 @@ static int emul_rtc_get(struct udevice *dev, struct rtc_time *time)
struct emul_rtc *priv = dev_get_priv(dev);
u64 now;
if (!priv->offset_us) {
/* Use the build date as initial time */
priv->offset_us = U_BOOT_EPOCH * 1000000ULL - timer_get_us();
priv->isdst = -1;
}
now = timer_get_us() + priv->offset_us;
do_div(now, 1000000);
rtc_to_tm(now, time);
@ -63,6 +58,26 @@ static int emul_rtc_set(struct udevice *dev, const struct rtc_time *time)
return 0;
}
int emul_rtc_probe(struct udevice *dev)
{
struct emul_rtc *priv = dev_get_priv(dev);
const char *epoch_str;
u64 epoch;
epoch_str = env_get("rtc_emul_epoch");
if (epoch_str) {
epoch = simple_strtoull(epoch_str, NULL, 10);
} else {
/* Use the build date as initial time */
epoch = U_BOOT_EPOCH;
}
priv->offset_us = epoch * 1000000ULL - timer_get_us();
priv->isdst = -1;
return 0;
}
static const struct rtc_ops emul_rtc_ops = {
.get = emul_rtc_get,
.set = emul_rtc_set,
@ -72,6 +87,7 @@ U_BOOT_DRIVER(rtc_emul) = {
.name = "rtc_emul",
.id = UCLASS_RTC,
.ops = &emul_rtc_ops,
.probe = emul_rtc_probe,
.priv_auto_alloc_size = sizeof(struct emul_rtc),
};

View File

@ -219,7 +219,7 @@ size_t u16_strlen(const void *in);
size_t u16_strsize(const void *in);
/**
* u16_strlen - count non-zero words
* u16_strnlen() - count non-zero words
*
* This function matches wscnlen_s() if the -fshort-wchar compiler flag is set.
* In the EFI context we explicitly need a function handling u16 strings.

View File

@ -158,6 +158,9 @@ struct dfu_entity {
unsigned int inited:1;
};
struct list_head;
extern struct list_head dfu_list;
#ifdef CONFIG_SET_DFU_ALT_INFO
/**
* set_dfu_alt_info() - set dfu_alt_info environment variable
@ -493,28 +496,52 @@ static inline int dfu_fill_entity_virt(struct dfu_entity *dfu, char *devstr,
}
#endif
#if CONFIG_IS_ENABLED(DFU_WRITE_ALT)
/**
* dfu_tftp_write() - write TFTP data to DFU medium
* dfu_write_by_name() - write data to DFU medium
* @dfu_entity_name: Name of DFU entity to write
* @addr: Address of data buffer to write
* @len: Number of bytes
* @interface: Destination DFU medium (e.g. "mmc")
* @devstring: Instance number of destination DFU medium (e.g. "1")
*
* This function is storing data received via TFTP on DFU supported medium.
* This function is storing data received on DFU supported medium which
* is specified by @dfu_entity_name.
*
* @dfu_entity_name: name of DFU entity to write
* @addr: address of data buffer to write
* @len: number of bytes
* @interface: destination DFU medium (e.g. "mmc")
* @devstring: instance number of destination DFU medium (e.g. "1")
*
* Return: 0 on success, otherwise error code
* Return: 0 - on success, error code - otherwise
*/
#if CONFIG_IS_ENABLED(DFU_TFTP)
int dfu_tftp_write(char *dfu_entity_name, unsigned int addr, unsigned int len,
char *interface, char *devstring);
int dfu_write_by_name(char *dfu_entity_name, void *addr,
unsigned int len, char *interface, char *devstring);
/**
* dfu_write_by_alt() - write data to DFU medium
* @dfu_alt_num: DFU alt setting number
* @addr: Address of data buffer to write
* @len: Number of bytes
* @interface: Destination DFU medium (e.g. "mmc")
* @devstring: Instance number of destination DFU medium (e.g. "1")
*
* This function is storing data received on DFU supported medium which
* is specified by @dfu_alt_name.
*
* Return: 0 - on success, error code - otherwise
*/
int dfu_write_by_alt(int dfu_alt_num, void *addr, unsigned int len,
char *interface, char *devstring);
#else
static inline int dfu_tftp_write(char *dfu_entity_name, unsigned int addr,
unsigned int len, char *interface,
char *devstring)
static inline int dfu_write_by_name(char *dfu_entity_name, void *addr,
unsigned int len, char *interface,
char *devstring)
{
puts("TFTP write support for DFU not available!\n");
puts("write support for DFU not available!\n");
return -ENOSYS;
}
static inline int dfu_write_by_alt(int dfu_alt_num, void *addr,
unsigned int len, char *interface,
char *devstring)
{
puts("write support for DFU not available!\n");
return -ENOSYS;
}
#endif

View File

@ -804,6 +804,9 @@ bool efi_image_parse(void *efi, size_t len, struct efi_image_regions **regp,
/* runtime implementation of memcpy() */
void efi_memcpy_runtime(void *dest, const void *src, size_t n);
/* commonly used helper function */
u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index);
#else /* CONFIG_IS_ENABLED(EFI_LOADER) */
/* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */

View File

@ -1602,4 +1602,16 @@ struct fit_loadable_tbl {
.handler = _handler, \
}
/**
* fit_update - update storage with FIT image
* @fit: Pointer to FIT image
*
* Update firmware on storage using FIT image as input.
* The storage area to be update will be identified by the name
* in FIT and matching it to "dfu_alt_info" variable.
*
* Return: 0 on success, non-zero otherwise
*/
int fit_update(const void *fit);
#endif /* __IMAGE_H__ */

View File

@ -27,6 +27,10 @@ config EFI_LOADER
if EFI_LOADER
config EFI_SETUP_EARLY
bool
default n
choice
prompt "Store for non-volatile UEFI variables"
default EFI_VARIABLE_FILE_STORE

View File

@ -34,6 +34,7 @@ obj-y += efi_memory.o
obj-y += efi_root_node.o
obj-y += efi_runtime.o
obj-y += efi_setup.o
obj-y += efi_string.o
obj-$(CONFIG_EFI_UNICODE_COLLATION_PROTOCOL2) += efi_unicode_collation.o
obj-y += efi_var_common.o
obj-y += efi_var_mem.o

View File

@ -3523,6 +3523,7 @@ static efi_status_t EFIAPI efi_disconnect_controller(
size_t number_of_children = 0;
efi_status_t r;
struct efi_object *efiobj;
bool sole_child;
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
child_handle);
@ -3545,16 +3546,18 @@ static efi_status_t EFIAPI efi_disconnect_controller(
}
/* Create list of child handles */
r = efi_get_child_controllers(efiobj,
driver_image_handle,
&number_of_children,
&child_handle_buffer);
if (r != EFI_SUCCESS)
return r;
sole_child = (number_of_children == 1);
if (child_handle) {
number_of_children = 1;
free(child_handle_buffer);
child_handle_buffer = &child_handle;
} else {
r = efi_get_child_controllers(efiobj,
driver_image_handle,
&number_of_children,
&child_handle_buffer);
if (r != EFI_SUCCESS)
return r;
}
/* Get the driver binding protocol */
@ -3579,7 +3582,7 @@ static efi_status_t EFIAPI efi_disconnect_controller(
}
}
/* Remove the driver */
if (!child_handle) {
if (!child_handle || sole_child) {
r = EFI_CALL(binding_protocol->stop(binding_protocol,
controller_handle,
0, NULL));

View File

@ -0,0 +1,36 @@
// SPDX-License-Identifier: GPL-2.0+
/*
* String functions
*
* Copyright (c) 2020 AKASHI Takahiro, Linaro Limited
*/
#include <common.h>
#include <charset.h>
/**
* efi_create_indexed_name - create a string name with an index
* @buffer: Buffer
* @name: Name string
* @index: Index
*
* Create a utf-16 string with @name, appending @index.
* For example, L"Capsule0001"
*
* The caller must ensure that the buffer has enough space for the resulting
* string including the trailing L'\0'.
*
* Return: A pointer to the next position after the created string
* in @buffer, or NULL otherwise
*/
u16 *efi_create_indexed_name(u16 *buffer, const char *name, unsigned int index)
{
u16 *p = buffer;
char index_buf[5];
utf8_utf16_strcpy(&p, name);
sprintf(index_buf, "%04X", index);
utf8_utf16_strcpy(&p, index_buf);
return p;
}

View File

@ -8,6 +8,7 @@
#include <common.h>
#include <charset.h>
#include <command.h>
#include <efi_loader.h>
#include <errno.h>
#include <log.h>
#include <malloc.h>
@ -594,6 +595,24 @@ static int unicode_test_u16_strsize(struct unit_test_state *uts)
}
UNICODE_TEST(unicode_test_u16_strsize);
#ifdef CONFIG_EFI_LOADER
static int unicode_test_efi_create_indexed_name(struct unit_test_state *uts)
{
u16 buf[16];
u16 const expected[] = L"Capsule0AF9";
u16 *pos;
memset(buf, 0xeb, sizeof(buf));
pos = efi_create_indexed_name(buf, "Capsule", 0x0af9);
ut_asserteq_mem(expected, buf, sizeof(expected));
ut_asserteq(pos - buf, u16_strnlen(buf, SIZE_MAX));
return 0;
}
UNICODE_TEST(unicode_test_efi_create_indexed_name);
#endif
int do_ut_unicode(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);