u-boot/lib/efi_loader/efi_helper.c
Ilias Apalodimas 37c3ca5c0b efi_loader: Add helper functions for EFI
A following patch introduces a different logic for loading initrd's
based on the EFI_LOAD_FILE2_PROTOCOL.
Since similar logic can be applied in the future for other system files
(i.e DTBs), let's add some helper functions which will retrieve and
parse file paths stored in EFI variables.

Signed-off-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
2021-03-25 20:14:25 +01:00

99 lines
2.3 KiB
C

// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright (c) 2020, Linaro Limited
*/
#define LOG_CATEGORY LOGC_EFI
#include <common.h>
#include <env.h>
#include <malloc.h>
#include <dm.h>
#include <fs.h>
#include <efi_load_initrd.h>
#include <efi_loader.h>
#include <efi_variable.h>
/**
* efi_create_current_boot_var() - Return Boot#### name were #### is replaced by
* the value of BootCurrent
*
* @var_name: variable name
* @var_name_size: size of var_name
*
* Return: Status code
*/
static efi_status_t efi_create_current_boot_var(u16 var_name[],
size_t var_name_size)
{
efi_uintn_t boot_current_size;
efi_status_t ret;
u16 boot_current;
u16 *pos;
boot_current_size = sizeof(boot_current);
ret = efi_get_variable_int(L"BootCurrent",
&efi_global_variable_guid, NULL,
&boot_current_size, &boot_current, NULL);
if (ret != EFI_SUCCESS)
goto out;
pos = efi_create_indexed_name(var_name, var_name_size, "Boot",
boot_current);
if (!pos) {
ret = EFI_OUT_OF_RESOURCES;
goto out;
}
out:
return ret;
}
/**
* efi_get_dp_from_boot() - Retrieve and return a device path from an EFI
* Boot### variable.
* A boot option may contain an array of device paths.
* We use a VenMedia() with a specific GUID to identify
* the usage of the array members. This function is
* used to extract a specific device path
*
* @guid: vendor GUID of the VenMedia() device path node identifying the
* device path
*
* Return: device path or NULL. Caller must free the returned value
*/
struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid)
{
struct efi_device_path *file_path = NULL;
struct efi_device_path *tmp = NULL;
struct efi_load_option lo;
void *var_value = NULL;
efi_uintn_t size;
efi_status_t ret;
u16 var_name[16];
ret = efi_create_current_boot_var(var_name, sizeof(var_name));
if (ret != EFI_SUCCESS)
return NULL;
var_value = efi_get_var(var_name, &efi_global_variable_guid, &size);
if (!var_value)
return NULL;
ret = efi_deserialize_load_option(&lo, var_value, &size);
if (ret != EFI_SUCCESS)
goto out;
tmp = efi_dp_from_lo(&lo, &size, guid);
if (!tmp)
goto out;
/* efi_dp_dup will just return NULL if efi_dp_next is NULL */
file_path = efi_dp_dup(efi_dp_next(tmp));
out:
efi_free_pool(tmp);
free(var_value);
return file_path;
}