From patchwork Sun Mar 14 19:05:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 400113 Delivered-To: patch@linaro.org Received: by 2002:a02:8562:0:0:0:0:0 with SMTP id g89csp2862027jai; Sun, 14 Mar 2021 12:06:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz+8ZT582yJvMnXVz9q2+HRS6KIAoJ6ilv+bz98Ke4krWg6Y104vEqobMfxwn5+GPGZZ7Lm X-Received: by 2002:a17:906:b7d5:: with SMTP id fy21mr5071026ejb.153.1615748790415; Sun, 14 Mar 2021 12:06:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1615748790; cv=none; d=google.com; s=arc-20160816; b=t2RZUTS90xjV4Ic1u3+woa6qZVfchuwLlp0/Q5JC/qFXZ0U37kIyZLhvDIazI6woTN phVh2E9bPH2iQLCclGgCUAyXK9RygykiDXfUzopANL9QUVc7h71sz1dZ0aQGspq4Hd2s 5AfTa8gqPF91JEayj6w5QI+q2uGptqY6bE3+3JREq5k00mah7j1RfeL9c6EfP8I92TrX pmCK7rqLF4SzRAgwBqQtgRg2jh+mQVrUkjRUelZmwGdYGVrfBI5xfZuAmxTgI4zvnumG 5wwxXaVrs93NyhTuYwwWXIa1yXFCFOG7WKhAcPiGiVhOY6HOdyPwJ1fY3mhDrzHQceIU IYqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:list-subscribe:list-help:list-post:list-archive :list-unsubscribe:list-id:precedence:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=aucN0R1bTsCuusS52LQughd1Obv4V/vjNdPUbjUadNA=; b=vDnXuKFZs4BdFuTAwcTraqTtZkxKlPtw0i385Dgyua5OLXanm0WA1agl0RcoKMfXdb Vs4QBTbKUuTeTBEK62zthI+EjZKT37lNo9z/8JN1mcwOdg1KufjgFgNqC0cso+jTHEhP CF4K++3hNOv6Yw6hgE2suThJR/g7NzHmAK0mzZXf6W3XPeY4mY/J/wt/nftHueq4qEqK JreG8zrRlGe0Nsp3ggvFn/yuddp+W6pC2yPa/HzpwsnGCYnnL9Z3c3byCBdzm3SxVycY qNb3Z2o0UaBNJEz5strJvDWM5QDtouf1NjOxpePseIBuEk1/PmSq8E7UuuvED+Az95T2 EPdA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZWRERxsl; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from phobos.denx.de (phobos.denx.de. [2a01:238:438b:c500:173d:9f52:ddab:ee01]) by mx.google.com with ESMTPS id yj20si10146556ejb.318.2021.03.14.12.06.30 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 14 Mar 2021 12:06:30 -0700 (PDT) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZWRERxsl; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 2a01:238:438b:c500:173d:9f52:ddab:ee01 as permitted sender) smtp.mailfrom=u-boot-bounces@lists.denx.de; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id D205B82976; Sun, 14 Mar 2021 20:06:06 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ZWRERxsl"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id BEB998297D; Sun, 14 Mar 2021 20:06:03 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wr1-x42d.google.com (mail-wr1-x42d.google.com [IPv6:2a00:1450:4864:20::42d]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id A6FD082946 for ; Sun, 14 Mar 2021 20:05:58 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wr1-x42d.google.com with SMTP id f12so7578822wrx.8 for ; Sun, 14 Mar 2021 12:05:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=aucN0R1bTsCuusS52LQughd1Obv4V/vjNdPUbjUadNA=; b=ZWRERxsl8+ix/TqhWVNV88G2KzPvwwZazaZK6FvOO57ATDl17QGeQhESlhQoSsG3/V 9tIJTgKz8aHa3iE6xzvuJx99roMOektkWYWzk32AEpB/Or3skjSZjGTfK6b1n+7OLRJ+ yF38MJjXlTSL53MNJS+ReSQM/5n47jq3hfc+aFWCyFEmmkeXXVVS7k4gUz1LMOW9PFiD FU6d6XpOrG8eeLBWwzPIHjVZo2x98XbqZU71Lx1XpBJXHeJ+n8WjlgxW4ADCKhlkL1U4 1t34LyBPVSpmnfJlMFmL+0+fj0umbEu5p2dyb2af2PERMmZRjJNT3Tit03hncGM5EYk/ E+nA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=aucN0R1bTsCuusS52LQughd1Obv4V/vjNdPUbjUadNA=; b=CfLrsbX8m47BOxbSVpHhG3MeWfNJnwInPFPSk/eOL5OcxkkWrFk9/KLYjselpn+Tjb nNRMQrchuPcGbWF7fvbNKtWhJmPKey0XP8O+ZT/Y07IZ2tMrsfIKzElT+2VyqmOI6r28 GEczl/H2ydWq+pfuZBXVqaVBBkzNaYx2zRsUBYOkH7TI0/qxGeFSg38hKhwiUnyTmCUk 7ZnSQRyLKudo1C4X1XhI3Tte0rP45Hkonzk18sSSQooYJ5tKoig18Ct5PXqpZKrjfHtT ZutJgntexv0DRn50lTfPWquOTGJKJicjPSruCHj4NGbNiUBVrvyIlH5CEfSgABVA2sUm sbiw== X-Gm-Message-State: AOAM532mJ9ZIBEPJ6P2cLoo5N++gs5uT1+ESGYbrfEBr/Z5O3y8Ce9Fj tDaRn39ElF+XZUj5CDCglv6CjQ== X-Received: by 2002:a5d:404d:: with SMTP id w13mr24247390wrp.230.1615748758276; Sun, 14 Mar 2021 12:05:58 -0700 (PDT) Received: from localhost.localdomain (ppp-94-64-113-158.home.otenet.gr. [94.64.113.158]) by smtp.gmail.com with ESMTPSA id 3sm18718029wry.72.2021.03.14.12.05.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 14 Mar 2021 12:05:57 -0700 (PDT) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, Ilias Apalodimas , Alexander Graf , Sughosh Ganu , u-boot@lists.denx.de Subject: [PATCH 3/6 v3] efi_loader: Add helper functions for EFI Date: Sun, 14 Mar 2021 21:05:35 +0200 Message-Id: <20210314190541.129687-4-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210314190541.129687-1-ilias.apalodimas@linaro.org> References: <20210314190541.129687-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.4 at phobos.denx.de X-Virus-Status: Clean 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 --- include/efi_loader.h | 7 +++ lib/efi_loader/Makefile | 1 + lib/efi_loader/efi_file.c | 39 +++++++++++++ lib/efi_loader/efi_helper.c | 98 +++++++++++++++++++++++++++++++++ lib/efi_loader/efi_var_common.c | 33 +++++++++++ 5 files changed, 178 insertions(+) create mode 100644 lib/efi_loader/efi_helper.c -- 2.30.2 diff --git a/include/efi_loader.h b/include/efi_loader.h index eb11a8c7d4b1..25302628d8a8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -552,6 +552,11 @@ struct efi_simple_file_system_protocol *efi_simple_file_system( /* open file from device-path: */ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp); +efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size); + +/* get a device path from a Boot#### option */ +struct efi_device_path *efi_get_dp_from_boot(const efi_guid_t guid); + /** * efi_size_in_pages() - convert size in bytes to size in pages * @@ -717,6 +722,8 @@ efi_status_t EFIAPI efi_query_variable_info( u64 *remaining_variable_storage_size, u64 *maximum_variable_size); +void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size); + /* * See section 3.1.3 in the v2.7 UEFI spec for more details on * the layout of EFI_LOAD_OPTION. In short it is: diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile index 10b42e8847bf..da2741adecfa 100644 --- a/lib/efi_loader/Makefile +++ b/lib/efi_loader/Makefile @@ -23,6 +23,7 @@ endif obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o obj-$(CONFIG_CMD_BOOTEFI_BOOTMGR) += efi_bootmgr.o obj-y += efi_boottime.o +obj-y += efi_helper.o obj-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += efi_capsule.o obj-$(CONFIG_EFI_CAPSULE_FIRMWARE) += efi_firmware.o obj-y += efi_console.o diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 8ece8e71ee1c..bebcb520272a 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -409,6 +409,45 @@ static efi_status_t efi_get_file_size(struct file_handle *fh, return EFI_SUCCESS; } +/** + * efi_file_size() - Get the size of a file using an EFI file handle + * + * @handle: EFI file handle + * @size: buffer to fill in the discovered size + * + * Return: size of the file + */ +efi_status_t efi_file_size(struct efi_file_handle *fh, efi_uintn_t *size) +{ + struct efi_file_info *info = NULL; + efi_uintn_t bs = 0; + efi_status_t ret; + + *size = 0; + ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs, + info)); + if (ret != EFI_BUFFER_TOO_SMALL) { + ret = EFI_DEVICE_ERROR; + goto out; + } + + info = malloc(bs); + if (!info) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + ret = EFI_CALL(fh->getinfo(fh, (efi_guid_t *)&efi_file_info_guid, &bs, + info)); + if (ret != EFI_SUCCESS) + goto out; + + *size = info->file_size; + +out: + free(info); + return ret; +} + static efi_status_t file_read(struct file_handle *fh, u64 *buffer_size, void *buffer) { diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c new file mode 100644 index 000000000000..d03a7364615e --- /dev/null +++ b/lib/efi_loader/efi_helper.c @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#define LOG_CATEGORY LOGC_EFI +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * 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; +} diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index 1c7459266a38..b11ed91a74a4 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -9,6 +9,7 @@ #include #include #include +#include enum efi_secure_mode { EFI_MODE_SETUP, @@ -343,3 +344,35 @@ enum efi_auth_var_type efi_auth_var_get_type(u16 *name, const efi_guid_t *guid) } return EFI_AUTH_VAR_NONE; } + +/** + * efi_get_var() - read value of an EFI variable + * + * @name: variable name + * @start: vendor GUID + * @size: size of allocated buffer + * + * Return: buffer with variable data or NULL + */ +void *efi_get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size) +{ + efi_status_t ret; + void *buf = NULL; + + *size = 0; + ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) { + buf = malloc(*size); + if (!buf) + return NULL; + ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL); + } + + if (ret != EFI_SUCCESS) { + free(buf); + *size = 0; + return NULL; + } + + return buf; +}