From patchwork Mon Dec 28 12:24:34 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 352612 Delivered-To: patch@linaro.org Received: by 2002:a02:85a7:0:0:0:0:0 with SMTP id d36csp9705901jai; Mon, 28 Dec 2020 04:25:12 -0800 (PST) X-Google-Smtp-Source: ABdhPJyLKQY3+odllwEfJfRE8S4xzaWVN/zvIGvs+gz0pIWoSqMSZYaIBlg/p2Pb/vrogiwjlZp4 X-Received: by 2002:a05:6402:94c:: with SMTP id h12mr42058228edz.268.1609158312522; Mon, 28 Dec 2020 04:25:12 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609158312; cv=none; d=google.com; s=arc-20160816; b=eZL1Om44HSwkq6sTZJW0jYKL2LDOXPczFqLabsPVnDyriH8pJrZlhtLQeh5HX5GSRU D1qFl3zEUSL3f1h1EvlLb/pX0BNRekQzeTx1whJkJzpTIg4cOakq2gIRxtAmT/m7dcnT YUI321xhcZi4IQ4Zk1Of6Sz9wjfm5Fnu4xz4clvnxTvGTgWXy034qeqF5JY3U2V/CHk0 sXcpCo62yLQ2LPxb9iJ64PZWv1HCZLhogt+tImYhnu9ZYW/a5O41BhFaltzSOSiFrYAZ bJ+hA+lH4z01e2Kh++1dQxIH/8tv1OUhTrq6xKB6+Kx161kulxP+x6FfiWLO5oQBMYwo +GOQ== 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=Rvmf4NtYbsV4B+CR9AaY2V5Uo9GQ0IZzE+k4WrEsISI=; b=vw7wdJcRbSQVvDtZOq53idawsZg2vHl18b5x/6k/bbrPTkHwlD+/P1VGQkICxoCLNK nFNl/b4icBf5T2PT9Fh89BA+XWnzQ3TZ/qhW7IlIblPzZzcIROZnmnvZqIHA+Qvy89mO fc1R66abln6JFHYrWAzi8rFeIA3JTODY6KGRa8hGFeCQ3Ayx9tAweFJAO+g/Xfx9L1Mw htbDMxelGKNsK6YV/GdH6HZeBZdhMZcVHJEtxFdgIWyNc9yE2672v/rS4jUloXnS59uD JLJ0Iw7Aa9g2ZJEtU0ob5qSBXxv7mQx61m7N3eR0t6NW5fqLD/Xp8zX/j9aivDez+vJi lX5Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZjDJ4CFC; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 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. [85.214.62.61]) by mx.google.com with ESMTPS id lz16si17623947ejb.373.2020.12.28.04.25.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Dec 2020 04:25:12 -0800 (PST) Received-SPF: pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 as permitted sender) client-ip=85.214.62.61; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=ZjDJ4CFC; spf=pass (google.com: domain of u-boot-bounces@lists.denx.de designates 85.214.62.61 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 E4C1F8244B; Mon, 28 Dec 2020 13:25:07 +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="ZjDJ4CFC"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2B67D8241C; Mon, 28 Dec 2020 13:24:53 +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,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x335.google.com (mail-wm1-x335.google.com [IPv6:2a00:1450:4864:20::335]) (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 05F3D82409 for ; Mon, 28 Dec 2020 13:24:48 +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-wm1-x335.google.com with SMTP id 3so9664921wmg.4 for ; Mon, 28 Dec 2020 04:24:48 -0800 (PST) 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=Rvmf4NtYbsV4B+CR9AaY2V5Uo9GQ0IZzE+k4WrEsISI=; b=ZjDJ4CFCUe1FknrozsTet9oXp2ZVejGc1XQZoxGeBkCI6PLbkcvEmTT0FGcVgpTFnb cAFH64ekE9qje+1fIwZ6orU5SJ6+7W/gmc2WF9pHlu+9Pw9JrPXzPr0Itnqck6yRYo1N R0KtnPm0NIK61VWkSutr9XVkaiWuhCDn21U+93KcMVCpBTIsOwu73+mrSmyNKIr3Q+ff Tvr0BkbxNEbkeMKnm9MNM7rr8QOzN4nFn581mu9OPmP9SxAUTqhsmyFOxzUzhrS6Fyoi vjtBAyuJYxJGqFYcLvjtTkvrMNC63SvuBXLZ2pdCOXT7f2LSHVHHVjhZwXUq5s99S44f U1fA== 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=Rvmf4NtYbsV4B+CR9AaY2V5Uo9GQ0IZzE+k4WrEsISI=; b=JkXeLdfPm/WT7LSvRCl7GZT/+bIcNGNDDkSfQh+4fbmMzHnQIM81DiqQKjNFHcR9t2 ySbdO4sBDq0sHBpVRKeEPZssAox4icT3rJ0IX4EPYuvHYiYxViiUDxSvYHWPvLd7/JfK YvIedEe3wuoXisnuVLREiQu7FoRcQM9cMY25k+qOZ7JmeE5sijBtmlDwaBEFGA8Xx5K9 e7bZifiGM9SX9Jwt4iSRE1dbOyVY5XE77Vj7AXlWbeBQ/TN1OYU4+tBLLHVVw+LfOIUJ ENuwiNUXTS5Qzd+ZZ2NGMTOuIyiB9zafwCmjrMZf6Ff4skQqMDI1M26S62L2d8+YkbIe oA7Q== X-Gm-Message-State: AOAM530xgTdW4aPkLBXB3s2WY4Z9P86ZzgxUbAQ3SUpEzPJV4DB0rzjT jyT6P666UaB7D1BylHeosMABhw== X-Received: by 2002:a7b:cc0f:: with SMTP id f15mr20375006wmh.29.1609158288539; Mon, 28 Dec 2020 04:24:48 -0800 (PST) Received: from localhost.localdomain (athedsl-4484548.home.otenet.gr. [94.71.57.204]) by smtp.gmail.com with ESMTPSA id w21sm18710321wmi.45.2020.12.28.04.24.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 28 Dec 2020 04:24:48 -0800 (PST) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, ard.biesheuvel@arm.com, Ilias Apalodimas , Alexander Graf , u-boot@lists.denx.de Subject: [PATCH 2/6] efi_loader: Introduce helper functions for EFI Date: Mon, 28 Dec 2020 14:24:34 +0200 Message-Id: <20201228122440.316403-3-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.30.0.rc2 In-Reply-To: <20201228122440.316403-1-ilias.apalodimas@linaro.org> References: <20201228122440.316403-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.3 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 device paths via EFI variables. Signed-off-by: Ilias Apalodimas --- include/efi_helper.h | 29 ++++++ lib/efi_loader/efi_helper.c | 189 ++++++++++++++++++++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 include/efi_helper.h create mode 100644 lib/efi_loader/efi_helper.c -- 2.30.0.rc2 diff --git a/include/efi_helper.h b/include/efi_helper.h new file mode 100644 index 000000000000..d76e24e0f57d --- /dev/null +++ b/include/efi_helper.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#if !defined _EFI_HELPER_H_ +#define _EFI_HELPER_H + +#include +#include + +/* + * @dev: device string i.e 'mmc' + * @part: partition string i.e '0:2' + * @filename: name of the file + */ +struct load_file_info { + char dev[32]; + char part[16]; + char filename[256]; +}; + +loff_t get_file_size(const struct load_file_info *file_loc, + efi_status_t *status); +efi_status_t efi_get_fp_from_var(const u16 *name, u16 start, + struct load_file_info *loc); +void *get_var(u16 *name, const efi_guid_t *vendor, efi_uintn_t *size); + +#endif diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c new file mode 100644 index 000000000000..4cf1f8abed30 --- /dev/null +++ b/lib/efi_loader/efi_helper.c @@ -0,0 +1,189 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2020, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * get_file_size() - retrieve the size of initramfs, set efi status on error + * + * @dev: device to read from, e.g. "mmc" + * @part: device partition, e.g. "0:1" + * @file: name of file + * @status: EFI exit code in case of failure + * + * Return: size of file + */ +loff_t get_file_size(const struct load_file_info *info, efi_status_t *status) +{ + loff_t sz = 0; + int ret; + + ret = fs_set_blk_dev(info->dev, info->part, FS_TYPE_ANY); + if (ret) { + *status = EFI_NO_MEDIA; + goto out; + } + + ret = fs_size(info->filename, &sz); + if (ret) { + sz = 0; + *status = EFI_NOT_FOUND; + goto out; + } + +out: + return sz; +} + +/* + * string_to_load_args() - Fill in a struct load_file_info with the file info + * parsed from an EFI variable + * + * @args: value of the EFI variable i.e "mmc 0 initrd" + * @info: struct to fill in with file specific info + * + * Return: Status code + */ +static efi_status_t string_to_load_args(char *args, struct load_file_info *info) +{ + efi_status_t status = EFI_SUCCESS; + char *p; + + /* + * expect a string with three space separated parts: + * - block device type, e.g. "mmc" + * - device and partition identifier, e.g. "0:1" + * - file path on the block device, e.g. "/boot/initrd.cpio.gz" + */ + p = strsep(&args, " "); + if (!p) { + status = EFI_NO_MEDIA; + goto out; + } + strncpy(info->dev, p, sizeof(info->dev)); + + p = strsep(&args, " "); + if (!p) { + status = EFI_NO_MEDIA; + goto out; + } + strncpy(info->part, p, sizeof(info->part)); + + p = strsep(&args, " "); + if (!p) { + status = EFI_NOT_FOUND; + goto out; + } + strncpy(info->filename, p, sizeof(info->filename)); + +out: + return status; +} + +/** + * 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 *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); + ret = efi_get_variable_int(name, vendor, NULL, size, buf, NULL); + } + + if (ret != EFI_SUCCESS) { + free(buf); + *size = 0; + return NULL; + } + + return buf; +} + +/** + * efi_get_fp_from_var() - Retrieve a file path from an EFI variable + * + * @name: variable name + * @start: start replacing from + * @info: struct to fill in with file specific info + */ +efi_status_t efi_get_fp_from_var(const u16 *name, u16 start, + struct load_file_info *info) +{ + u16 hexmap[] = L"0123456789ABCDEF"; + efi_uintn_t boot_order_size; + void *var_value = NULL; + u16 *name_dup = NULL; + efi_uintn_t size; + efi_status_t ret; + u16 boot_order; + + memset(info, 0, sizeof(*info)); + + /* make sure we have enough space for replacements */ + if (u16_strsize(name) < sizeof(*name) * start + u16_strsize(L"####")) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + boot_order_size = sizeof(boot_order); + ret = efi_get_variable_int(L"BootCurrent", + &efi_global_variable_guid, NULL, + &boot_order_size, &boot_order, NULL); + if (ret != EFI_SUCCESS) + goto out; + + name_dup = u16_strdup(name); + if (!name_dup) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + /* Match name variable to BootCurrent */ + name_dup[start] = hexmap[(boot_order & 0xf000) >> 12]; + name_dup[start + 1] = hexmap[(boot_order & 0x0f00) >> 8]; + name_dup[start + 2] = hexmap[(boot_order & 0x00f0) >> 4]; + name_dup[start + 3] = hexmap[(boot_order & 0x000f) >> 0]; + + var_value = get_var(name_dup, &efi_global_variable_guid, &size); + if (!var_value) { + ret = EFI_NOT_FOUND; + goto out; + } + + ret = string_to_load_args(var_value, info); + if (ret != EFI_SUCCESS) + goto out; + + if (fs_set_blk_dev(info->dev, info->part, FS_TYPE_ANY)) { + ret = EFI_NO_MEDIA; + goto out; + } + + if (!fs_exists(info->filename)) { + ret = EFI_NOT_FOUND; + goto out; + } + +out: + free(var_value); + free(name_dup); + return ret; +}