All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ilias Apalodimas <ilias.apalodimas@linaro.org>
To: 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	[thread overview]
Message-ID: <20201228122440.316403-3-ilias.apalodimas@linaro.org> (raw)
In-Reply-To: <20201228122440.316403-1-ilias.apalodimas@linaro.org>

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 <ilias.apalodimas@linaro.org>
---
 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

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 <efi.h>
+#include <efi_api.h>
+
+/*
+ * @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 <common.h>
+#include <env.h>
+#include <malloc.h>
+#include <dm.h>
+#include <fs.h>
+#include <efi_helper.h>
+#include <efi_loader.h>
+#include <efi_variable.h>
+
+/**
+ * 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;
+}
-- 
2.30.0.rc2

  parent reply	other threads:[~2020-12-28 12:24 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-12-28 12:24 [PATCH 0/6] Change logic of EFI LoadFile2 protocol for initrd loading Ilias Apalodimas
2020-12-28 12:24 ` [PATCH 1/6] efi_loader: remove unconditional initialization of file2 protocol for initrd Ilias Apalodimas
2020-12-28 12:24 ` Ilias Apalodimas [this message]
2020-12-28 14:49   ` [PATCH 2/6] efi_loader: Introduce helper functions for EFI Heinrich Schuchardt
2020-12-28 22:06     ` Ilias Apalodimas
2020-12-28 12:24 ` [PATCH 3/6] efi_loader: Replace config option with EFI variable for initrd loading Ilias Apalodimas
2020-12-28 13:10   ` Ilias Apalodimas
2020-12-28 14:55   ` Heinrich Schuchardt
2020-12-28 22:03     ` Ilias Apalodimas
2020-12-28 12:24 ` [PATCH 4/6] efi_loader: Remove unused headers from efi_load_initrd.c Ilias Apalodimas
2020-12-28 15:06   ` Heinrich Schuchardt
2020-12-28 15:08   ` [PATCH] " Heinrich Schuchardt
2020-12-28 12:24 ` [PATCH 5/6] efi_selftest: Modify self-tests for initrd loading Ilias Apalodimas
2020-12-28 12:24 ` [PATCH 6/6] efi_loader: bootmgr: use get_var from efi_helper file Ilias Apalodimas

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201228122440.316403-3-ilias.apalodimas@linaro.org \
    --to=ilias.apalodimas@linaro.org \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.