Pull request for UEFI sub-system for v2019.10-rc4 (5)
This patch set fixes errors in the UEFI sub-system and adds a function to compare u16 strings which is prerequisite for further patches. -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAl2FpJ0ACgkQxIHbvCwF GsQJeQ/8Cp+wGxLlQnXHyMjEh89+7qG6XQv9P6OCwrhkg5k1Qjl7V1adDgTn6snR UTP0RRyMwtW7sQ5Tqk2jr5SDlRF8CZV2HZNQMebVPCm2gqiXkZYHGr3CcY6U0z8s UMb6PyNjEZCMtY6GgEGRsAFrGl3+eFqOFOLvTSk/Y+36vLaTXRYpn2WRLkHpattA rBhnqgljLZN6uf5nsQDUkrvW/s/hY4cq5QVLv1wKhH014CUrCxHlhyzkYqspEBT+ Biwmhu/XEz2qKthghw4QyZ5zCn/iMFfLnV8cHXYbd0KP643jKWWRGR+4qW/MjfBp BMH+tHTEZCG7F7w6bPefjGlGeidLQFgF0nU8ZXRLcxn3K1uTnZaa4wu9ZKPT4dAj Ucrtf1XAXwxnDIQccJ7lxsTWf1Prp8yl53Eb0HJTcLPSeqwAudca0+dbushxRj7F 6LUtuBgtIEkBTp5EB3Y84JyNPHwBihneD9NIlPMWud6e1jDHVshvgLDSM1hepvWf 2oDdCm/o5PGYVC+S9DWpHno2pGhOQfxzHAewyQc11IT1/n99UthOnTNdBDRM+/9M 0uDUHzMBZQ+l7jB9RgcK20hY2PWQ3lOP9nvrKFo3dvoXf/0Jd3ywjTkMcDrbBuYK IlWO2lnOpCTfpgKXD+V15hlsmXwVMk/08xgXqk14gJ//L5QbiaU= =SXhW -----END PGP SIGNATURE----- Merge tag 'efi-2019-10-rc4-5' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi Pull request for UEFI sub-system for v2019.10-rc4 (5) This patch set fixes errors in the UEFI sub-system and adds a function to compare u16 strings which is prerequisite for further patches.
This commit is contained in:
commit
390183b581
8 changed files with 171 additions and 39 deletions
|
@ -168,6 +168,21 @@ s32 utf_to_lower(const s32 code);
|
|||
*/
|
||||
s32 utf_to_upper(const s32 code);
|
||||
|
||||
/*
|
||||
* u16_strncmp() - compare two u16 string
|
||||
*
|
||||
* @s1: first string to compare
|
||||
* @s2: second string to compare
|
||||
* @n: maximum number of u16 to compare
|
||||
* Return: 0 if the first n u16 are the same in s1 and s2
|
||||
* < 0 if the first different u16 in s1 is less than the
|
||||
* corresponding u16 in s2
|
||||
* > 0 if the first different u16 in s1 is greater than the
|
||||
* corresponding u16 in s2
|
||||
*/
|
||||
int u16_strncmp(const u16 *s1, const u16 *s2, size_t n);
|
||||
#define u16_strcmp(s1, s2) u16_strncmp((s1), (s2), SIZE_MAX)
|
||||
|
||||
/**
|
||||
* u16_strlen - count non-zero words
|
||||
*
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#define U_BOOT_GUID \
|
||||
EFI_GUID(0xe61d73b9, 0xa384, 0x4acc, \
|
||||
0xae, 0xab, 0x82, 0xe8, 0x28, 0xf3, 0x62, 0x8b)
|
||||
/* GUID used as host device on sandbox */
|
||||
#define U_BOOT_HOST_DEV_GUID \
|
||||
EFI_GUID(0xbbe4e671, 0x5773, 0x4ea1, \
|
||||
0x9a, 0xab, 0x3a, 0x7d, 0xbf, 0x40, 0xc4, 0x82)
|
||||
|
||||
/* Root node */
|
||||
extern efi_handle_t efi_root;
|
||||
|
@ -121,6 +125,10 @@ uint16_t *efi_dp_str(struct efi_device_path *dp);
|
|||
|
||||
/* GUID of the U-Boot root node */
|
||||
extern const efi_guid_t efi_u_boot_guid;
|
||||
#ifdef CONFIG_SANDBOX
|
||||
/* GUID of U-Boot host device on sandbox */
|
||||
extern const efi_guid_t efi_guid_host_dev;
|
||||
#endif
|
||||
/* GUID of the EFI_BLOCK_IO_PROTOCOL */
|
||||
extern const efi_guid_t efi_block_io_guid;
|
||||
extern const efi_guid_t efi_global_variable_guid;
|
||||
|
|
|
@ -335,6 +335,31 @@ s32 utf_to_upper(const s32 code)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* u16_strncmp() - compare two u16 string
|
||||
*
|
||||
* @s1: first string to compare
|
||||
* @s2: second string to compare
|
||||
* @n: maximum number of u16 to compare
|
||||
* Return: 0 if the first n u16 are the same in s1 and s2
|
||||
* < 0 if the first different u16 in s1 is less than the
|
||||
* corresponding u16 in s2
|
||||
* > 0 if the first different u16 in s1 is greater than the
|
||||
* corresponding u16 in s2
|
||||
*/
|
||||
int u16_strncmp(const u16 *s1, const u16 *s2, size_t n)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
for (; n; --n, ++s1, ++s2) {
|
||||
ret = *s1 - *s2;
|
||||
if (ret || !*s1)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t u16_strlen(const void *in)
|
||||
{
|
||||
const char *pos = in;
|
||||
|
|
|
@ -3499,7 +3499,6 @@ static efi_status_t EFIAPI efi_disconnect_controller(
|
|||
efi_handle_t *child_handle_buffer = NULL;
|
||||
size_t number_of_children = 0;
|
||||
efi_status_t r;
|
||||
size_t stop_count = 0;
|
||||
struct efi_object *efiobj;
|
||||
|
||||
EFI_ENTRY("%p, %p, %p", controller_handle, driver_image_handle,
|
||||
|
@ -3539,32 +3538,35 @@ static efi_status_t EFIAPI efi_disconnect_controller(
|
|||
(void **)&binding_protocol,
|
||||
driver_image_handle, NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL));
|
||||
if (r != EFI_SUCCESS)
|
||||
if (r != EFI_SUCCESS) {
|
||||
r = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
/* Remove the children */
|
||||
if (number_of_children) {
|
||||
r = EFI_CALL(binding_protocol->stop(binding_protocol,
|
||||
controller_handle,
|
||||
number_of_children,
|
||||
child_handle_buffer));
|
||||
if (r == EFI_SUCCESS)
|
||||
++stop_count;
|
||||
if (r != EFI_SUCCESS) {
|
||||
r = EFI_DEVICE_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
/* Remove the driver */
|
||||
if (!child_handle)
|
||||
if (!child_handle) {
|
||||
r = EFI_CALL(binding_protocol->stop(binding_protocol,
|
||||
controller_handle,
|
||||
0, NULL));
|
||||
if (r == EFI_SUCCESS)
|
||||
++stop_count;
|
||||
if (r != EFI_SUCCESS) {
|
||||
r = EFI_DEVICE_ERROR;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
EFI_CALL(efi_close_protocol(driver_image_handle,
|
||||
&efi_guid_driver_binding_protocol,
|
||||
driver_image_handle, NULL));
|
||||
|
||||
if (stop_count)
|
||||
r = EFI_SUCCESS;
|
||||
else
|
||||
r = EFI_NOT_FOUND;
|
||||
r = EFI_SUCCESS;
|
||||
out:
|
||||
if (!child_handle)
|
||||
free(child_handle_buffer);
|
||||
|
|
|
@ -12,8 +12,13 @@
|
|||
#include <mmc.h>
|
||||
#include <efi_loader.h>
|
||||
#include <part.h>
|
||||
#include <sandboxblockdev.h>
|
||||
#include <asm-generic/unaligned.h>
|
||||
|
||||
#ifdef CONFIG_SANDBOX
|
||||
const efi_guid_t efi_guid_host_dev = U_BOOT_HOST_DEV_GUID;
|
||||
#endif
|
||||
|
||||
/* template END node: */
|
||||
static const struct efi_device_path END = {
|
||||
.type = DEVICE_PATH_TYPE_END,
|
||||
|
@ -445,6 +450,16 @@ static unsigned dp_size(struct udevice *dev)
|
|||
case UCLASS_MMC:
|
||||
return dp_size(dev->parent) +
|
||||
sizeof(struct efi_device_path_sd_mmc_path);
|
||||
#endif
|
||||
#ifdef CONFIG_SANDBOX
|
||||
case UCLASS_ROOT:
|
||||
/*
|
||||
* Sandbox's host device will be represented
|
||||
* as vendor device with extra one byte for
|
||||
* device number
|
||||
*/
|
||||
return dp_size(dev->parent)
|
||||
+ sizeof(struct efi_device_path_vendor) + 1;
|
||||
#endif
|
||||
default:
|
||||
return dp_size(dev->parent);
|
||||
|
@ -505,6 +520,24 @@ static void *dp_fill(void *buf, struct udevice *dev)
|
|||
#ifdef CONFIG_BLK
|
||||
case UCLASS_BLK:
|
||||
switch (dev->parent->uclass->uc_drv->id) {
|
||||
#ifdef CONFIG_SANDBOX
|
||||
case UCLASS_ROOT: {
|
||||
/* stop traversing parents at this point: */
|
||||
struct efi_device_path_vendor *dp = buf;
|
||||
struct blk_desc *desc = dev_get_uclass_platdata(dev);
|
||||
|
||||
dp_fill(buf, dev->parent);
|
||||
dp = buf;
|
||||
++dp;
|
||||
dp->dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE;
|
||||
dp->dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR;
|
||||
dp->dp.length = sizeof(*dp) + 1;
|
||||
memcpy(&dp->guid, &efi_guid_host_dev,
|
||||
sizeof(efi_guid_t));
|
||||
dp->vendor_data[0] = desc->devnum;
|
||||
return &dp->vendor_data[1];
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_IDE
|
||||
case UCLASS_IDE: {
|
||||
struct efi_device_path_atapi *dp =
|
||||
|
|
|
@ -424,17 +424,17 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
|
|||
efi_uintn_t data_size, const void *data)
|
||||
{
|
||||
char *native_name = NULL, *val = NULL, *s;
|
||||
const char *old_val;
|
||||
size_t old_size;
|
||||
efi_status_t ret = EFI_SUCCESS;
|
||||
u32 attr;
|
||||
|
||||
EFI_ENTRY("\"%ls\" %pUl %x %zu %p", variable_name, vendor, attributes,
|
||||
data_size, data);
|
||||
|
||||
/* TODO: implement APPEND_WRITE */
|
||||
if (!variable_name || !*variable_name || !vendor ||
|
||||
((attributes & EFI_VARIABLE_RUNTIME_ACCESS) &&
|
||||
!(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS)) ||
|
||||
(attributes & EFI_VARIABLE_APPEND_WRITE)) {
|
||||
!(attributes & EFI_VARIABLE_BOOTSERVICE_ACCESS))) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
@ -445,35 +445,51 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
|
|||
|
||||
#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)
|
||||
|
||||
if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
|
||||
/* delete the variable: */
|
||||
env_set(native_name, NULL);
|
||||
ret = EFI_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
old_val = env_get(native_name);
|
||||
if (old_val) {
|
||||
old_val = parse_attr(old_val, &attr);
|
||||
|
||||
val = env_get(native_name);
|
||||
if (val) {
|
||||
parse_attr(val, &attr);
|
||||
|
||||
/* We should not free val */
|
||||
val = NULL;
|
||||
/* check read-only first */
|
||||
if (attr & READ_ONLY) {
|
||||
ret = EFI_WRITE_PROTECTED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* attributes won't be changed
|
||||
* TODO: take care of APPEND_WRITE once supported
|
||||
*/
|
||||
if (attr != attributes) {
|
||||
if ((data_size == 0) || !(attributes & ACCESS_ATTR)) {
|
||||
/* delete the variable: */
|
||||
env_set(native_name, NULL);
|
||||
ret = EFI_SUCCESS;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* attributes won't be changed */
|
||||
if (attr != (attributes & ~EFI_VARIABLE_APPEND_WRITE)) {
|
||||
ret = EFI_INVALID_PARAMETER;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (attributes & EFI_VARIABLE_APPEND_WRITE) {
|
||||
if (!prefix(old_val, "(blob)")) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
goto out;
|
||||
}
|
||||
old_size = strlen(old_val);
|
||||
} else {
|
||||
old_size = 0;
|
||||
}
|
||||
} else {
|
||||
if ((data_size == 0) || !(attributes & ACCESS_ATTR) ||
|
||||
(attributes & EFI_VARIABLE_APPEND_WRITE)) {
|
||||
/* delete, but nothing to do */
|
||||
ret = EFI_NOT_FOUND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
old_size = 0;
|
||||
}
|
||||
|
||||
val = malloc(2 * data_size + strlen("{ro,run,boot,nv}(blob)") + 1);
|
||||
val = malloc(old_size + 2 * data_size
|
||||
+ strlen("{ro,run,boot,nv}(blob)") + 1);
|
||||
if (!val) {
|
||||
ret = EFI_OUT_OF_RESOURCES;
|
||||
goto out;
|
||||
|
@ -481,10 +497,7 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
|
|||
|
||||
s = val;
|
||||
|
||||
/*
|
||||
* store attributes
|
||||
* TODO: several attributes are not supported
|
||||
*/
|
||||
/* store attributes */
|
||||
attributes &= (EFI_VARIABLE_NON_VOLATILE |
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS);
|
||||
|
@ -505,8 +518,13 @@ efi_status_t EFIAPI efi_set_variable(u16 *variable_name,
|
|||
}
|
||||
s += sprintf(s, "}");
|
||||
|
||||
if (old_size)
|
||||
/* APPEND_WRITE */
|
||||
s += sprintf(s, old_val);
|
||||
else
|
||||
s += sprintf(s, "(blob)");
|
||||
|
||||
/* store payload: */
|
||||
s += sprintf(s, "(blob)");
|
||||
s = bin2hex(s, data, data_size);
|
||||
*s = '\0';
|
||||
|
||||
|
|
|
@ -21,6 +21,9 @@ static const efi_guid_t guid_vendor0 =
|
|||
static const efi_guid_t guid_vendor1 =
|
||||
EFI_GUID(0xff629290, 0x1fc1, 0xd73f,
|
||||
0x8f, 0xb1, 0x32, 0xf9, 0x0c, 0xa0, 0x42, 0xea);
|
||||
static const efi_guid_t guid_global =
|
||||
EFI_GUID(0x8be4df61, 0x93ca, 0x11d2,
|
||||
0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c);
|
||||
|
||||
/*
|
||||
* Setup unit test.
|
||||
|
@ -116,7 +119,7 @@ static int execute(void)
|
|||
EFI_VARIABLE_APPEND_WRITE,
|
||||
7, v + 8);
|
||||
if (ret != EFI_SUCCESS) {
|
||||
efi_st_todo("SetVariable(APPEND_WRITE) failed\n");
|
||||
efi_st_error("SetVariable(APPEND_WRITE) failed\n");
|
||||
} else {
|
||||
len = EFI_ST_MAX_DATA_SIZE;
|
||||
ret = runtime->get_variable(L"efi_st_var1", &guid_vendor1,
|
||||
|
@ -131,6 +134,21 @@ static int execute(void)
|
|||
if (memcmp(data, v, len))
|
||||
efi_st_todo("GetVariable returned wrong value\n");
|
||||
}
|
||||
/* Append variable 2 */
|
||||
ret = runtime->set_variable(L"efi_none", &guid_vendor1,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_APPEND_WRITE,
|
||||
15, v);
|
||||
if (ret != EFI_NOT_FOUND)
|
||||
efi_st_error("SetVariable(APPEND_WRITE) with size 0 to non-existent variable returns wrong code\n");
|
||||
/* Append variable 3 */
|
||||
ret = runtime->set_variable(L"PlatformLangCodes", &guid_global,
|
||||
EFI_VARIABLE_BOOTSERVICE_ACCESS |
|
||||
EFI_VARIABLE_RUNTIME_ACCESS |
|
||||
EFI_VARIABLE_APPEND_WRITE,
|
||||
15, v);
|
||||
if (ret != EFI_WRITE_PROTECTED)
|
||||
efi_st_todo("SetVariable(APPEND_WRITE) to read-only variable returns wrong code\n");
|
||||
/* Enumerate variables */
|
||||
boottime->set_mem(&guid, 16, 0);
|
||||
*varname = 0;
|
||||
|
|
|
@ -567,6 +567,19 @@ static int unicode_test_utf_to_upper(struct unit_test_state *uts)
|
|||
}
|
||||
UNICODE_TEST(unicode_test_utf_to_upper);
|
||||
|
||||
static int unicode_test_u16_strncmp(struct unit_test_state *uts)
|
||||
{
|
||||
ut_assert(u16_strncmp(L"abc", L"abc", 3) == 0);
|
||||
ut_assert(u16_strncmp(L"abcdef", L"abcghi", 3) == 0);
|
||||
ut_assert(u16_strncmp(L"abcdef", L"abcghi", 6) < 0);
|
||||
ut_assert(u16_strncmp(L"abcghi", L"abcdef", 6) > 0);
|
||||
ut_assert(u16_strcmp(L"abc", L"abc") == 0);
|
||||
ut_assert(u16_strcmp(L"abcdef", L"deghi") < 0);
|
||||
ut_assert(u16_strcmp(L"deghi", L"abcdef") > 0);
|
||||
return 0;
|
||||
}
|
||||
UNICODE_TEST(unicode_test_u16_strncmp);
|
||||
|
||||
int do_ut_unicode(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
|
||||
{
|
||||
struct unit_test *tests = ll_entry_start(struct unit_test, unicode_test);
|
||||
|
|
Loading…
Reference in a new issue