Pull request for efi-2023-01-rc5

UEFI:
 
 * Improve parameter checking in efi_get_next_variable_name_mem()
 * Fix a bugs in management of security database via the eficonfig command
 
 Other:
 
 * Allow sound command to play multiple sounds
 -----BEGIN PGP SIGNATURE-----
 
 iQJWBAABCABAFiEEK7wKXt3/btL6/yA+hO4vgnE3U0sFAmOh4MsiHGhlaW5yaWNo
 LnNjaHVjaGFyZHRAY2Fub25pY2FsLmNvbQAKCRCE7i+CcTdTS6WLEADGtNSMvG+x
 qNBH+2jZc8PnslzXY3FfugSpk29FOFKj4SHwt3p/Du1VPhw1KHWl5gOYTTw/GizI
 t7yfHavyttzUuHoCa2uKUTYN6RDTCHUgzpyGaXCuh89ls1xilzq3YxVcQ9RYeKM1
 lmNIC9rGmTxsWui5VgczkrBzsp8gBj2hs0C+nqJIP+JPGQT1XlA5KXmECsZn8+fi
 GRvGuuflSDzszHOdRClzrtWNt6kLTpNu8D6UormIrTGrHSdDBwO9QFXOyt9qOnA+
 /aboHSd5Oc5BApatTUtRwGoxm0Jm7hujA1EhX6wDsILE/+zMXjmsXS/mbRegYFXY
 Xzu/Wif4ARexECMe0zxHPHf+VA8QYi9QmELzic8Xen5WzHSRBVQd8BtLK/1ItYDT
 LrgPtoyY5eWd3gcjlhgimPPUEqsK45aYXftsv7NcH8K64Yj7UolJL1fcJm8tMkHt
 0ziiO4ZKZjJkJc4c4XUkWQadCnjqDciJkWfAp922PjoV2jBbf7EtNaynUnsiM/R8
 C4oZ7bD1m5gVFLvDsJ9OBy6qHdwRJTn/ETG5H8BlIJ60I9ZZxT4VoUqit+1HQjLx
 zvH98T8OM/N6d/+Q1fJvKg1QIQQxKHnExYBUBn/WxbeWupVe6K77C7TRE7HTz0tO
 A+VslTXg5i2XB1SfFrvvF7EpUtX/kqMOMQ==
 =d09r
 -----END PGP SIGNATURE-----

Merge tag 'efi-2023-01-rc5' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request for efi-2023-01-rc5

UEFI:

* Improve parameter checking in efi_get_next_variable_name_mem()
* Fix a bugs in management of security database via the eficonfig command

Other:

* Allow sound command to play multiple sounds
This commit is contained in:
Tom Rini 2022-12-20 12:50:38 -05:00
commit 1154e965d0
11 changed files with 225 additions and 84 deletions

View file

@ -1683,7 +1683,7 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
u32 i;
u16 *bootorder;
efi_status_t ret;
u16 *var_name16 = NULL, *p;
u16 *var_name16 = NULL;
efi_uintn_t num, size, buf_size;
struct efimenu *efi_menu;
struct list_head *pos, *n;
@ -1718,24 +1718,12 @@ static efi_status_t eficonfig_show_boot_selection(unsigned int *selected)
int index;
efi_guid_t guid;
size = buf_size;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
if (ret == EFI_NOT_FOUND)
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = size;
p = realloc(var_name16, buf_size);
if (!p) {
free(var_name16);
return EFI_OUT_OF_RESOURCES;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
}
if (ret != EFI_SUCCESS) {
free(var_name16);
return ret;
}
if (ret != EFI_SUCCESS)
goto out;
if (efi_varname_is_load_option(var_name16, &index)) {
/* If the index is included in the BootOrder, skip it */
if (search_bootorder(bootorder, num, index, NULL))
@ -2026,7 +2014,7 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
u32 i;
char *title;
efi_status_t ret;
u16 *var_name16 = NULL, *p;
u16 *var_name16 = NULL;
efi_uintn_t size, buf_size;
/* list the load option in the order of BootOrder variable */
@ -2054,19 +2042,9 @@ static efi_status_t eficonfig_create_change_boot_order_entry(struct efimenu *efi
break;
size = buf_size;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
if (ret == EFI_NOT_FOUND)
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = size;
p = realloc(var_name16, buf_size);
if (!p) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&size, var_name16, &guid);
}
if (ret != EFI_SUCCESS)
goto out;
@ -2332,14 +2310,15 @@ out:
efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_option *opt,
efi_status_t count)
{
u32 i;
efi_uintn_t size;
void *load_option;
u32 i, list_size = 0;
struct efi_load_option lo;
u16 *var_name16 = NULL, *p;
u16 *var_name16 = NULL;
u16 varname[] = u"Boot####";
efi_status_t ret = EFI_SUCCESS;
efi_uintn_t varname_size, buf_size;
u16 *delete_index_list = NULL, *p;
efi_uintn_t buf_size;
buf_size = 128;
var_name16 = malloc(buf_size);
@ -2352,24 +2331,18 @@ efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_op
efi_guid_t guid;
efi_uintn_t tmp;
varname_size = buf_size;
ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid);
if (ret == EFI_NOT_FOUND)
ret = efi_next_variable_name(&buf_size, &var_name16, &guid);
if (ret == EFI_NOT_FOUND) {
/*
* EFI_NOT_FOUND indicates we retrieved all EFI variables.
* This should be treated as success.
*/
ret = EFI_SUCCESS;
break;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = varname_size;
p = realloc(var_name16, buf_size);
if (!p) {
free(var_name16);
return EFI_OUT_OF_RESOURCES;
}
var_name16 = p;
ret = efi_get_next_variable_name_int(&varname_size, var_name16, &guid);
}
if (ret != EFI_SUCCESS) {
free(var_name16);
return ret;
}
if (ret != EFI_SUCCESS)
goto out;
if (!efi_varname_is_load_option(var_name16, &index))
continue;
@ -2383,8 +2356,8 @@ efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_op
if (ret != EFI_SUCCESS)
goto next;
if (size >= sizeof(efi_guid_bootmenu_auto_generated)) {
if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) {
if (size >= sizeof(efi_guid_bootmenu_auto_generated) &&
!guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) {
for (i = 0; i < count; i++) {
if (opt[i].size == tmp &&
memcmp(opt[i].lo, load_option, tmp) == 0) {
@ -2393,20 +2366,37 @@ efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_media_boot_op
}
}
/*
* The entire list of variables must be retrieved by
* efi_get_next_variable_name_int() before deleting the invalid
* boot option, just save the index here.
*/
if (i == count) {
ret = delete_boot_option(i);
if (ret != EFI_SUCCESS) {
free(load_option);
p = realloc(delete_index_list, sizeof(u32) *
(list_size + 1));
if (!p) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
}
}
delete_index_list = p;
delete_index_list[list_size++] = index;
}
}
next:
free(load_option);
}
/* delete all invalid boot options */
for (i = 0; i < list_size; i++) {
ret = delete_boot_option(delete_index_list[i]);
if (ret != EFI_SUCCESS)
goto out;
}
out:
free(var_name16);
free(delete_index_list);
return ret;
}

View file

@ -72,6 +72,28 @@ static bool file_have_auth_header(void *buf, efi_uintn_t size)
return true;
}
/**
* file_is_null_key() - check the file is an authenticated and signed null key
*
* @auth: pointer to the file
* @size: file size
* @null_key: pointer to store the result
* Return: status code
*/
static efi_status_t file_is_null_key(struct efi_variable_authentication_2 *auth,
efi_uintn_t size, bool *null_key)
{
efi_uintn_t auth_size =
sizeof(auth->time_stamp) + auth->auth_info.hdr.dwLength;
if (size < auth_size)
return EFI_INVALID_PARAMETER;
*null_key = (size == auth_size);
return EFI_SUCCESS;
}
/**
* eficonfig_process_enroll_key() - enroll key into signature database
*
@ -84,6 +106,7 @@ static efi_status_t eficonfig_process_enroll_key(void *data)
char *buf = NULL;
efi_uintn_t size;
efi_status_t ret;
bool null_key = false;
struct efi_file_handle *f = NULL;
struct efi_device_path *full_dp = NULL;
struct eficonfig_select_file_info file_info;
@ -149,13 +172,24 @@ static efi_status_t eficonfig_process_enroll_key(void *data)
goto out;
}
ret = file_is_null_key((struct efi_variable_authentication_2 *)buf,
size, &null_key);
if (ret != EFI_SUCCESS) {
eficonfig_print_msg("ERROR! Invalid file format.");
goto out;
}
attr = EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
/* PK can enroll only one certificate */
if (u16_strcmp(data, u"PK")) {
/*
* PK can enroll only one certificate.
* The signed null key is used to clear KEK, db and dbx.
* EFI_VARIABLE_APPEND_WRITE attribute must not be set in these cases.
*/
if (u16_strcmp(data, u"PK") && !null_key) {
efi_uintn_t db_size = 0;
/* check the variable exists. If exists, add APPEND_WRITE attribute */

View file

@ -39,26 +39,39 @@ static int do_play(struct cmd_tbl *cmdtp, int flag, int argc,
int ret = 0;
int msec = 1000;
int freq = 400;
if (argc > 1)
msec = dectoul(argv[1], NULL);
if (argc > 2)
freq = dectoul(argv[2], NULL);
bool first = true;
ret = uclass_first_device_err(UCLASS_SOUND, &dev);
if (!ret)
if (ret)
goto err;
--argc;
++argv;
while (argc || first) {
first = false;
if (argc && *argv[0] != '-') {
msec = dectoul(argv[0], NULL);
--argc;
++argv;
}
if (argc && *argv[0] != '-') {
freq = dectoul(argv[0], NULL);
--argc;
++argv;
}
ret = sound_beep(dev, msec, freq);
if (ret) {
if (ret)
goto err;
}
return 0;
err:
printf("Sound device failed to play (err=%d)\n", ret);
return CMD_RET_FAILURE;
}
return 0;
}
static struct cmd_tbl cmd_sound_sub[] = {
U_BOOT_CMD_MKENT(init, 0, 1, do_init, "", ""),
U_BOOT_CMD_MKENT(play, 2, 1, do_play, "", ""),
U_BOOT_CMD_MKENT(play, INT_MAX, 1, do_play, "", ""),
};
/* process sound command */
@ -83,8 +96,10 @@ static int do_sound(struct cmd_tbl *cmdtp, int flag, int argc,
}
U_BOOT_CMD(
sound, 4, 1, do_sound,
sound, INT_MAX, 1, do_sound,
"sound sub-system",
"init - initialise the sound driver\n"
"sound play [len [freq]] - play a sound for len ms at freq Hz\n"
"sound play [[[-q|-s] len [freq]] ...] - play sounds\n"
" len - duration in ms\n"
" freq - frequency in Hz\n"
);

View file

@ -78,7 +78,7 @@ variable and how to specify a vendor GUID:
=>
Configuration
=============
-------------
UEFI variables are only supported if CONFIG_CMD_NVEDIT_EFI=y. The value of UEFI
variables can only be displayed if CONFIG_HEXDUMP=y.

View file

@ -10,12 +10,12 @@ Synopsis
::
sound init
sound play [len [freq]]
sound play [[len freq] ...] [len [freq]]
Description
-----------
The *sound* command is used to play a beep sound.
The *sound* command is used to play one or multiple beep sounds.
sound init
initializes the sound driver.
@ -30,6 +30,25 @@ len
freq
frequency of the sound in Hz, defaults to 400 Hz
Examples
--------
Beep at 400 Hz for 1000 ms::
sound play
Beep at 400 Hz for 600 ms::
sound play 600
Beep at 500 Hz for 600 ms::
sound play 600 500
Play melody::
sound play 500 1047 500 880 500 0 500 1047 500 880 500 0 500 784 500 698 500 784 1000 698
Configuration
-------------

View file

@ -708,6 +708,8 @@ int algo_to_len(const char *algo);
int efi_link_dev(efi_handle_t handle, struct udevice *dev);
int efi_unlink_dev(efi_handle_t handle);
bool efi_varname_is_load_option(u16 *var_name16, int *index);
efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf,
efi_guid_t *guid);
/**
* efi_size_in_pages() - convert size in bytes to size in pages

View file

@ -268,7 +268,8 @@ const efi_guid_t *efi_auth_var_get_guid(const u16 *name);
* efi_get_next_variable_name_mem() - Runtime common code across efi variable
* implementations for GetNextVariable()
* from the cached memory copy
* @variable_name_size: size of variable_name buffer in byte
*
* @variable_name_size: size of variable_name buffer in bytes
* @variable_name: name of uefi variable's name in u16
* @vendor: vendor's guid
*

View file

@ -223,3 +223,37 @@ bool efi_varname_is_load_option(u16 *var_name16, int *index)
return false;
}
/**
* efi_next_variable_name() - get next variable name
*
* This function is a wrapper of efi_get_next_variable_name_int().
* If efi_get_next_variable_name_int() returns EFI_BUFFER_TOO_SMALL,
* @size and @buf are updated by new buffer size and realloced buffer.
*
* @size: pointer to the buffer size
* @buf: pointer to the buffer
* @guid: pointer to the guid
* Return: status code
*/
efi_status_t efi_next_variable_name(efi_uintn_t *size, u16 **buf, efi_guid_t *guid)
{
u16 *p;
efi_status_t ret;
efi_uintn_t buf_size = *size;
ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
if (ret == EFI_NOT_FOUND)
return ret;
if (ret == EFI_BUFFER_TOO_SMALL) {
p = realloc(*buf, buf_size);
if (!p)
return EFI_OUT_OF_RESOURCES;
*buf = p;
*size = buf_size;
ret = efi_get_next_variable_name_int(&buf_size, *buf, guid);
}
return ret;
}

View file

@ -315,14 +315,14 @@ efi_get_next_variable_name_mem(efi_uintn_t *variable_name_size,
u16 *variable_name, efi_guid_t *vendor)
{
struct efi_var_entry *var;
efi_uintn_t old_size;
efi_uintn_t len, old_size;
u16 *pdata;
if (!variable_name_size || !variable_name || !vendor)
return EFI_INVALID_PARAMETER;
if (u16_strnlen(variable_name, *variable_name_size) ==
*variable_name_size)
len = *variable_name_size >> 1;
if (u16_strnlen(variable_name, len) == len)
return EFI_INVALID_PARAMETER;
if (!efi_var_mem_find(vendor, variable_name, &var) && *variable_name)

View file

@ -141,6 +141,41 @@ static int execute(void)
return EFI_ST_FAILURE;
}
/* Enumerate variables */
ret = runtime->get_next_variable_name(NULL, u"efi_st_var1", &guid);
if (ret != EFI_INVALID_PARAMETER) {
efi_st_error("GetNextVariableName missing parameter check\n");
return EFI_ST_FAILURE;
}
len = 24;
ret = runtime->get_next_variable_name(&len, NULL, &guid);
if (ret != EFI_INVALID_PARAMETER) {
efi_st_error("GetNextVariableName missing parameter check\n");
return EFI_ST_FAILURE;
}
len = 24;
ret = runtime->get_next_variable_name(&len, u"efi_st_var1", NULL);
if (ret != EFI_INVALID_PARAMETER) {
efi_st_error("GetNextVariableName missing parameter check\n");
return EFI_ST_FAILURE;
}
len = 1;
ret = runtime->get_next_variable_name(&len, u"", &guid);
if (ret != EFI_INVALID_PARAMETER) {
efi_st_error("GetNextVariableName missing parameter check\n");
return EFI_ST_FAILURE;
}
len = 16;
ret = runtime->get_next_variable_name(&len, u"efi_st_var1", &guid);
if (ret != EFI_INVALID_PARAMETER) {
efi_st_error("GetNextVariableName missing parameter check\n");
return EFI_ST_FAILURE;
}
boottime->set_mem(&guid, 16, 0);
*varname = 0;
flag = 0;

View file

@ -67,6 +67,17 @@ static int unicode_test_u16_strlen(struct unit_test_state *uts)
}
UNICODE_TEST(unicode_test_u16_strlen);
static int unicode_test_u16_strnlen(struct unit_test_state *uts)
{
ut_asserteq(0, u16_strnlen(c1, 0));
ut_asserteq(4, u16_strnlen(c1, 4));
ut_asserteq(6, u16_strnlen(c1, 6));
ut_asserteq(6, u16_strnlen(c1, 7));
return 0;
}
UNICODE_TEST(unicode_test_u16_strnlen);
static int unicode_test_u16_strdup(struct unit_test_state *uts)
{
u16 *copy = u16_strdup(c4);