Pull request for UEFI sub-system for v2019.07-rc2

This pull request provides error fixes for the handling of GPT partitions
 and for the UEFI subsystem.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEbcT5xx8ppvoGt20zxIHbvCwFGsQFAlzLSXQACgkQxIHbvCwF
 GsSdeQ/9HM7NELIDgo8lK9+v4i1oFLbfO0a/W8I1p2d8o19RKLKfDe9hE5fs5cmu
 Ky/qnGIfNbtv1YdJg9TNLWbdE9lrLRJVWXbDhG6rh99W8vDEhFwPMhwzmTsoyJnR
 H5qXgEpwqG7FYidiVWvN6J3MB9pZRn+Be6Rt28NUrM0QJWrJ9MPkN3/tHNbtYGbs
 jbsm/GDhTBVXLlOcOjXtJvrcC/W/fLyPEz9oR0POzOtKDAZPISfZhORwipnu3DAb
 WVzH1Slg7Icy7fRPJDFpQGwiefcuFngLShL6JP2tA4HcMVAhdhjDo+YYwR0vXoM5
 QfvrIE2hpNrOUhHkNrcYRWynHVZHnuoxdwdQpeBs3y0G8Ig1K0xvB5nwUGZhigzY
 qmOWZZoNt1IJByvZdS+gVa0Mx0akRF9tJy/Kou90acPuSRAbsAaEjeuP5umYqBhl
 o9isRLyc+jjfpS2WyRzy4vfIhmR+FA8BU7KPUF/GppA+q0ZplGizJ+a1M5WBZWMN
 JIjIMuYmbbHOjcfrksDfPCfE5WyS5QZyV7jyec8xAXe/cW045uqaeWV/215sr9hr
 dcJS6rKfYJ1CO5OSYjZCJJLKBbSoS/RE31iLBxRvOLjR0o8kJGm7IN//sTtVL7uJ
 OWRpeLVQ35JFAmDzr8LlEtDdkbTrPM5AMMUCie+SU8R7b+ldnwU=
 =GUpA
 -----END PGP SIGNATURE-----

Merge tag 'efi-2019-07-rc2' of git://git.denx.de/u-boot-efi

Pull request for UEFI sub-system for v2019.07-rc2

This pull request provides error fixes for the handling of GPT partitions
and for the UEFI subsystem.
This commit is contained in:
Tom Rini 2019-05-03 07:10:17 -04:00
commit 6e25cfe9a4
14 changed files with 204 additions and 68 deletions

View File

@ -297,18 +297,21 @@ static efi_status_t efi_install_fdt(const char *fdt_opt)
static efi_status_t do_bootefi_exec(efi_handle_t handle)
{
efi_status_t ret;
efi_uintn_t exit_data_size = 0;
u16 *exit_data = NULL;
/* Transfer environment variable as load options */
ret = set_load_options(handle, "bootargs");
if (ret != EFI_SUCCESS)
return ret;
/* we don't support much: */
env_set("efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported",
"{ro,boot}(blob)0000000000000000");
/* Call our payload! */
ret = EFI_CALL(efi_start_image(handle, NULL, NULL));
ret = EFI_CALL(efi_start_image(handle, &exit_data_size, &exit_data));
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
if (ret && exit_data) {
printf("## %ls\n", exit_data);
efi_free_pool(exit_data);
}
efi_restore_gd();
@ -361,7 +364,6 @@ static int do_efibootmgr(const char *fdt_opt)
}
ret = do_bootefi_exec(handle);
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
if (ret != EFI_SUCCESS)
return CMD_RET_FAILURE;
@ -476,7 +478,6 @@ static int do_bootefi_image(const char *image_opt, const char *fdt_opt)
goto out;
ret = do_bootefi_exec(handle);
printf("## Application terminated, r = %lu\n", ret & ~EFI_ERROR_MASK);
out:
if (mem_handle)

View File

@ -11,6 +11,7 @@
#include <efi_loader.h>
#include <environment.h>
#include <exports.h>
#include <hexdump.h>
#include <malloc.h>
#include <search.h>
#include <linux/ctype.h>
@ -545,7 +546,10 @@ static int do_efi_boot_add(cmd_tbl_t *cmdtp, int flag,
+ sizeof(struct efi_device_path); /* for END */
/* optional data */
lo.optional_data = (u8 *)(argc == 6 ? "" : argv[6]);
if (argc < 6)
lo.optional_data = NULL;
else
lo.optional_data = (const u8 *)argv[6];
size = efi_serialize_load_option(&lo, (u8 **)&data);
if (!size) {
@ -615,12 +619,13 @@ static int do_efi_boot_rm(cmd_tbl_t *cmdtp, int flag,
/**
* show_efi_boot_opt_data() - dump UEFI load option
*
* @id: Load option number
* @data: Value of UEFI load option variable
* @id: load option number
* @data: value of UEFI load option variable
* @size: size of the boot option
*
* Decode the value of UEFI load option variable and print information.
*/
static void show_efi_boot_opt_data(int id, void *data)
static void show_efi_boot_opt_data(int id, void *data, size_t size)
{
struct efi_load_option lo;
char *label, *p;
@ -638,7 +643,7 @@ static void show_efi_boot_opt_data(int id, void *data)
utf16_utf8_strncpy(&p, lo.label, label_len16);
printf("Boot%04X:\n", id);
printf("\tattributes: %c%c%c (0x%08x)\n",
printf(" attributes: %c%c%c (0x%08x)\n",
/* ACTIVE */
lo.attributes & LOAD_OPTION_ACTIVE ? 'A' : '-',
/* FORCE RECONNECT */
@ -646,14 +651,16 @@ static void show_efi_boot_opt_data(int id, void *data)
/* HIDDEN */
lo.attributes & LOAD_OPTION_HIDDEN ? 'H' : '-',
lo.attributes);
printf("\tlabel: %s\n", label);
printf(" label: %s\n", label);
dp_str = efi_dp_str(lo.file_path);
printf("\tfile_path: %ls\n", dp_str);
printf(" file_path: %ls\n", dp_str);
efi_free_pool(dp_str);
printf("\tdata: %s\n", lo.optional_data);
printf(" data:\n");
print_hex_dump(" ", DUMP_PREFIX_OFFSET, 16, 1,
lo.optional_data, size + (u8 *)data -
(u8 *)lo.optional_data, true);
free(label);
}
@ -686,13 +693,24 @@ static void show_efi_boot_opt(int id)
data));
}
if (ret == EFI_SUCCESS)
show_efi_boot_opt_data(id, data);
show_efi_boot_opt_data(id, data, size);
else if (ret == EFI_NOT_FOUND)
printf("Boot%04X: not found\n", id);
free(data);
}
static int u16_tohex(u16 c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
/* not hexadecimal */
return -1;
}
/**
* show_efi_boot_dump() - dump all UEFI load options
*
@ -709,38 +727,58 @@ static void show_efi_boot_opt(int id)
static int do_efi_boot_dump(cmd_tbl_t *cmdtp, int flag,
int argc, char * const argv[])
{
char regex[256];
char * const regexlist[] = {regex};
char *variables = NULL, *boot, *value;
int len;
int id;
u16 *var_name16, *p;
efi_uintn_t buf_size, size;
efi_guid_t guid;
int id, i, digit;
efi_status_t ret;
if (argc > 1)
return CMD_RET_USAGE;
snprintf(regex, 256, "efi_.*-.*-.*-.*-.*_Boot[0-9A-F]+");
/* TODO: use GetNextVariableName? */
len = hexport_r(&env_htab, '\n', H_MATCH_REGEX | H_MATCH_KEY,
&variables, 0, 1, regexlist);
if (!len)
return CMD_RET_SUCCESS;
if (len < 0)
buf_size = 128;
var_name16 = malloc(buf_size);
if (!var_name16)
return CMD_RET_FAILURE;
boot = variables;
while (*boot) {
value = strstr(boot, "Boot") + 4;
id = (int)simple_strtoul(value, NULL, 16);
show_efi_boot_opt(id);
boot = strchr(boot, '\n');
if (!*boot)
var_name16[0] = 0;
for (;;) {
size = buf_size;
ret = EFI_CALL(efi_get_next_variable_name(&size, var_name16,
&guid));
if (ret == EFI_NOT_FOUND)
break;
boot++;
if (ret == EFI_BUFFER_TOO_SMALL) {
buf_size = size;
p = realloc(var_name16, buf_size);
if (!p) {
free(var_name16);
return CMD_RET_FAILURE;
}
var_name16 = p;
ret = EFI_CALL(efi_get_next_variable_name(&size,
var_name16,
&guid));
}
if (ret != EFI_SUCCESS) {
free(var_name16);
return CMD_RET_FAILURE;
}
if (memcmp(var_name16, L"Boot", 8))
continue;
for (id = 0, i = 0; i < 4; i++) {
digit = u16_tohex(var_name16[4 + i]);
if (digit < 0)
break;
id = (id << 4) + digit;
}
if (i == 4 && !var_name16[8])
show_efi_boot_opt(id);
}
free(variables);
free(var_name16);
return CMD_RET_SUCCESS;
}

View File

@ -876,21 +876,21 @@ U_BOOT_CMD(gpt, CONFIG_SYS_MAXARGS, 1, do_gpt,
" Example usage:\n"
" gpt write mmc 0 $partitions\n"
" gpt verify mmc 0 $partitions\n"
" read <interface> <dev>\n"
" - read GPT into a data structure for manipulation\n"
" guid <interface> <dev>\n"
" gpt guid <interface> <dev>\n"
" - print disk GUID\n"
" guid <interface> <dev> <varname>\n"
" gpt guid <interface> <dev> <varname>\n"
" - set environment variable to disk GUID\n"
" Example usage:\n"
" gpt guid mmc 0\n"
" gpt guid mmc 0 varname\n"
#ifdef CONFIG_CMD_GPT_RENAME
"gpt partition renaming commands:\n"
"gpt swap <interface> <dev> <name1> <name2>\n"
" gpt read <interface> <dev>\n"
" - read GPT into a data structure for manipulation\n"
" gpt swap <interface> <dev> <name1> <name2>\n"
" - change all partitions named name1 to name2\n"
" and vice-versa\n"
"gpt rename <interface> <dev> <part> <name>\n"
" gpt rename <interface> <dev> <part> <name>\n"
" - rename the specified partition\n"
" Example usage:\n"
" gpt swap mmc 0 foo bar\n"

View File

@ -291,8 +291,11 @@ static int append_value(char **bufp, size_t *sizep, char *data)
if (!tmp_buf)
return -1;
if (hex2bin((u8 *)tmp_buf, data, len) < 0)
if (hex2bin((u8 *)tmp_buf, data, len) < 0) {
printf("Error: illegal hexadecimal string\n");
free(tmp_buf);
return -1;
}
value = tmp_buf;
} else { /* string */

View File

@ -209,6 +209,8 @@ int get_disk_guid(struct blk_desc * dev_desc, char *guid)
guid_bin = gpt_head->disk_guid.b;
uuid_bin_to_str(guid_bin, guid, UUID_STR_FORMAT_GUID);
/* Remember to free pte */
free(gpt_pte);
return 0;
}
@ -696,6 +698,10 @@ int gpt_verify_headers(struct blk_desc *dev_desc, gpt_header *gpt_head,
__func__);
return -1;
}
/* Free pte before allocating again */
free(*gpt_pte);
if (is_gpt_valid(dev_desc, (dev_desc->lba - 1),
gpt_head, gpt_pte) != 1) {
printf("%s: *** ERROR: Invalid Backup GPT ***\n",

View File

@ -207,12 +207,17 @@ struct efi_object {
* struct efi_loaded_image_obj - handle of a loaded image
*
* @header: EFI object header
* @exit_status: exit status passed to Exit()
* @exit_data_size: exit data size passed to Exit()
* @exit_data: exit data passed to Exit()
* @exit_jmp: long jump buffer for returning form started image
* @entry: entry address of the relocated image
*/
struct efi_loaded_image_obj {
struct efi_object header;
efi_status_t exit_status;
efi_uintn_t *exit_data_size;
u16 **exit_data;
struct jmp_buf_data exit_jmp;
EFIAPI efi_status_t (*entry)(efi_handle_t image_handle,
struct efi_system_table *st);
@ -560,7 +565,7 @@ struct efi_load_option {
u16 file_path_length;
u16 *label;
struct efi_device_path *file_path;
u8 *optional_data;
const u8 *optional_data;
};
void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data);

View File

@ -16,7 +16,7 @@
#define EFI_ST_SUCCESS 0
#define EFI_ST_FAILURE 1
#define EFI_ST_SUCCESS_STR L"SUCCESS"
/*
* Prints a message.
*/

View File

@ -53,19 +53,20 @@ void efi_deserialize_load_option(struct efi_load_option *lo, u8 *data)
*/
unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
{
unsigned long label_len, option_len;
unsigned long label_len;
unsigned long size;
u8 *p;
label_len = (u16_strlen(lo->label) + 1) * sizeof(u16);
option_len = strlen((char *)lo->optional_data);
/* total size */
size = sizeof(lo->attributes);
size += sizeof(lo->file_path_length);
size += label_len;
size += lo->file_path_length;
size += option_len + 1;
if (lo->optional_data)
size += (utf8_utf16_strlen((const char *)lo->optional_data)
+ 1) * sizeof(u16);
p = malloc(size);
if (!p)
return 0;
@ -84,10 +85,10 @@ unsigned long efi_serialize_load_option(struct efi_load_option *lo, u8 **data)
memcpy(p, lo->file_path, lo->file_path_length);
p += lo->file_path_length;
memcpy(p, lo->optional_data, option_len);
p += option_len;
*(char *)p = '\0';
if (lo->optional_data) {
utf8_utf16_strcpy((u16 **)&p, (const char *)lo->optional_data);
p += sizeof(u16); /* size of trailing \0 */
}
return size;
}

View File

@ -423,10 +423,12 @@ static efi_status_t EFIAPI efi_free_pool_ext(void *buffer)
}
/**
* efi_add_handle() - add a new object to the object list
* @obj: object to be added
* efi_add_handle() - add a new handle to the object list
*
* The protocols list is initialized. The object handle is set.
* @handle: handle to be added
*
* The protocols list is initialized. The handle is added to the list of known
* UEFI objects.
*/
void efi_add_handle(efi_handle_t handle)
{
@ -618,7 +620,7 @@ efi_status_t efi_create_event(uint32_t type, efi_uintn_t notify_tpl,
}
if ((type & (EVT_NOTIFY_WAIT | EVT_NOTIFY_SIGNAL)) &&
(is_valid_tpl(notify_tpl) != EFI_SUCCESS))
(!notify_function || is_valid_tpl(notify_tpl) != EFI_SUCCESS))
return EFI_INVALID_PARAMETER;
evt = calloc(1, sizeof(struct efi_event));
@ -2626,6 +2628,9 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
efi_is_direct_boot = false;
image_obj->exit_data_size = exit_data_size;
image_obj->exit_data = exit_data;
/* call the image! */
if (setjmp(&image_obj->exit_jmp)) {
/*
@ -2669,6 +2674,41 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle,
return EFI_CALL(systab.boottime->exit(image_handle, ret, 0, NULL));
}
/**
* efi_update_exit_data() - fill exit data parameters of StartImage()
*
* @image_obj image handle
* @exit_data_size size of the exit data buffer
* @exit_data buffer with data returned by UEFI payload
* Return: status code
*/
static efi_status_t efi_update_exit_data(struct efi_loaded_image_obj *image_obj,
efi_uintn_t exit_data_size,
u16 *exit_data)
{
efi_status_t ret;
/*
* If exit_data is not provided to StartImage(), exit_data_size must be
* ignored.
*/
if (!image_obj->exit_data)
return EFI_SUCCESS;
if (image_obj->exit_data_size)
*image_obj->exit_data_size = exit_data_size;
if (exit_data_size && exit_data) {
ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA,
exit_data_size,
(void **)image_obj->exit_data);
if (ret != EFI_SUCCESS)
return ret;
memcpy(*image_obj->exit_data, exit_data, exit_data_size);
} else {
image_obj->exit_data = NULL;
}
return EFI_SUCCESS;
}
/**
* efi_exit() - leave an EFI application or driver
* @image_handle: handle of the application or driver that is exiting
@ -2709,6 +2749,15 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle,
if (ret != EFI_SUCCESS)
goto out;
/* Exit data is only foreseen in case of failure. */
if (exit_status != EFI_SUCCESS) {
ret = efi_update_exit_data(image_obj, exit_data_size,
exit_data);
/* Exiting has priority. Don't return error to caller. */
if (ret != EFI_SUCCESS)
EFI_PRINT("%s: out of memory\n", __func__);
}
/* Make sure entry/exit counts for EFI world cross-overs match */
EFI_EXIT(exit_status);

View File

@ -452,7 +452,7 @@ efi_status_t efi_free_pages(uint64_t memory, efi_uintn_t pages)
uint64_t r = 0;
/* Sanity check */
if (!memory || (memory & EFI_PAGE_MASK)) {
if (!memory || (memory & EFI_PAGE_MASK) || !pages) {
printf("%s: illegal free 0x%llx, 0x%zx\n", __func__,
memory, pages);
return EFI_INVALID_PARAMETER;

View File

@ -79,6 +79,7 @@ out:
*/
efi_status_t efi_init_obj_list(void)
{
u64 os_indications_supported = 0; /* None */
efi_status_t ret = EFI_SUCCESS;
/* Initialize once only */
@ -90,6 +91,16 @@ efi_status_t efi_init_obj_list(void)
if (ret != EFI_SUCCESS)
goto out;
/* Indicate supported features */
ret = EFI_CALL(efi_set_variable(L"OsIndicationsSupported",
&efi_global_variable_guid,
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS,
sizeof(os_indications_supported),
&os_indications_supported));
if (ret != EFI_SUCCESS)
goto out;
/* Initialize system table */
ret = efi_initialize_system_table();
if (ret != EFI_SUCCESS)

View File

@ -9,7 +9,7 @@
*/
#include <common.h>
#include <efi_api.h>
#include <efi_selftest.h>
static efi_guid_t loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
@ -66,15 +66,22 @@ efi_status_t EFIAPI efi_main(efi_handle_t handle,
struct efi_system_table *systable)
{
struct efi_simple_text_output_protocol *con_out = systable->con_out;
efi_status_t ret = EFI_UNSUPPORTED;
efi_status_t ret;
u16 text[] = EFI_ST_SUCCESS_STR;
con_out->output_string(con_out, L"EFI application calling Exit\n");
if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS)
if (check_loaded_image_protocol(handle, systable) != EFI_SUCCESS) {
con_out->output_string(con_out,
L"Loaded image protocol missing\n");
ret = EFI_NOT_FOUND;
goto out;
}
/* The return value is checked by the calling test */
systable->boottime->exit(handle, ret, 0, NULL);
/* This return value is expected by the calling test */
ret = EFI_UNSUPPORTED;
out:
systable->boottime->exit(handle, ret, sizeof(text), text);
/*
* This statement should not be reached.

View File

@ -123,6 +123,9 @@ static int execute(void)
{
efi_status_t ret;
efi_handle_t handle;
efi_uintn_t exit_data_size = 0;
u16 *exit_data = NULL;
u16 expected_text[] = EFI_ST_SUCCESS_STR;
ret = boottime->load_image(false, image_handle, NULL, image,
img.length, &handle);
@ -130,11 +133,21 @@ static int execute(void)
efi_st_error("Failed to load image\n");
return EFI_ST_FAILURE;
}
ret = boottime->start_image(handle, NULL, NULL);
ret = boottime->start_image(handle, &exit_data_size, &exit_data);
if (ret != EFI_UNSUPPORTED) {
efi_st_error("Wrong return value from application\n");
return EFI_ST_FAILURE;
}
if (!exit_data || exit_data_size != sizeof(expected_text) ||
efi_st_memcmp(exit_data, expected_text, sizeof(expected_text))) {
efi_st_error("Incorrect exit data\n");
return EFI_ST_FAILURE;
}
ret = boottime->free_pool(exit_data);
if (ret != EFI_SUCCESS) {
efi_st_error("Failed to free exit data\n");
return EFI_ST_FAILURE;
}
return EFI_ST_SUCCESS;
}

View File

@ -238,6 +238,8 @@ void gen_rand_uuid(unsigned char *uuid_bin)
unsigned int *ptr = (unsigned int *)&uuid;
int i;
srand(get_ticks() + rand());
/* Set all fields randomly */
for (i = 0; i < sizeof(struct uuid) / sizeof(*ptr); i++)
*(ptr + i) = cpu_to_be32(rand());