Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/812123/?format=api
{ "id": 812123, "url": "http://patchwork.ozlabs.org/api/patches/812123/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/patch/20170910112149.21358-24-robdclark@gmail.com/", "project": { "id": 18, "url": "http://patchwork.ozlabs.org/api/projects/18/?format=api", "name": "U-Boot", "link_name": "uboot", "list_id": "u-boot.lists.denx.de", "list_email": "u-boot@lists.denx.de", "web_url": null, "scm_url": null, "webscm_url": null, "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20170910112149.21358-24-robdclark@gmail.com>", "list_archive_url": null, "date": "2017-09-10T11:21:40", "name": "[U-Boot,v2,14/21] efi_loader: efi variable support", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "cb753a2966cb1e0e7561cb0b1e8b1836cbb1923c", "submitter": { "id": 18760, "url": "http://patchwork.ozlabs.org/api/people/18760/?format=api", "name": "Rob Clark", "email": "robdclark@gmail.com" }, "delegate": { "id": 3400, "url": "http://patchwork.ozlabs.org/api/users/3400/?format=api", "username": "agraf", "first_name": "Alexander", "last_name": "Graf", "email": "agraf@suse.de" }, "mbox": "http://patchwork.ozlabs.org/project/uboot/patch/20170910112149.21358-24-robdclark@gmail.com/mbox/", "series": [ { "id": 2383, "url": "http://patchwork.ozlabs.org/api/series/2383/?format=api", "web_url": "http://patchwork.ozlabs.org/project/uboot/list/?series=2383", "date": "2017-09-10T11:21:17", "name": "efi_loader: enough UEFI for standard distro boot", "version": 2, "mbox": "http://patchwork.ozlabs.org/series/2383/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/812123/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/812123/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<u-boot-bounces@lists.denx.de>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@bilbo.ozlabs.org", "Authentication-Results": [ "ozlabs.org;\n\tspf=none (mailfrom) smtp.mailfrom=lists.denx.de\n\t(client-ip=81.169.180.215; helo=lists.denx.de;\n\tenvelope-from=u-boot-bounces@lists.denx.de;\n\treceiver=<UNKNOWN>)", "ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"UmFky+pD\"; dkim-atps=neutral" ], "Received": [ "from lists.denx.de (dione.denx.de [81.169.180.215])\n\tby ozlabs.org (Postfix) with ESMTP id 3xqpz65SCcz9sNV\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSun, 10 Sep 2017 21:40:50 +1000 (AEST)", "by lists.denx.de (Postfix, from userid 105)\n\tid 8B2BBC21F79; Sun, 10 Sep 2017 11:32:25 +0000 (UTC)", "from lists.denx.de (localhost [IPv6:::1])\n\tby lists.denx.de (Postfix) with ESMTP id 0EDBFC21F1A;\n\tSun, 10 Sep 2017 11:30:28 +0000 (UTC)", "by lists.denx.de (Postfix, from userid 105)\n\tid 96CB2C21E0F; Sun, 10 Sep 2017 11:23:54 +0000 (UTC)", "from mail-qk0-f193.google.com (mail-qk0-f193.google.com\n\t[209.85.220.193])\n\tby lists.denx.de (Postfix) with ESMTPS id 05DE5C21F44\n\tfor <u-boot@lists.denx.de>; Sun, 10 Sep 2017 11:23:46 +0000 (UTC)", "by mail-qk0-f193.google.com with SMTP id d70so3978394qkc.1\n\tfor <u-boot@lists.denx.de>; Sun, 10 Sep 2017 04:23:45 -0700 (PDT)", "from localhost ([2601:184:4780:aac0:25f8:dd96:a084:785a])\n\tby smtp.gmail.com with ESMTPSA id\n\ty11sm4256526qkb.20.2017.09.10.04.23.42\n\t(version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256);\n\tSun, 10 Sep 2017 04:23:43 -0700 (PDT)" ], "X-Spam-Checker-Version": "SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de", "X-Spam-Level": "", "X-Spam-Status": "No, score=-0.0 required=5.0 tests=FREEMAIL_FROM,\n\tRCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL,\n\tT_DKIM_INVALID\n\tautolearn=unavailable autolearn_force=no version=3.4.0", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=from:to:cc:subject:date:message-id:in-reply-to:references;\n\tbh=TcXSVnkuzNuuhq/qGicmO35MPEloXzfvi9hiWlZsjUI=;\n\tb=UmFky+pD+5SPxnZQ0DY7+TqrqH+FnhqXsWMOChxeNmPuSDaQYwiX0YB4uiWEZkTN2u\n\ta9reXp0StRrBpPa3aetgGXDZX853P8obAN1ESSsXIzSpK5z7/8QJpcpCY7A4Lpvo3ega\n\t2JVZ/gLwokSRh8NFSZwae8ogZUEdhWwK6e1kjTjmxAIr4zlDWA5lVm0qTBAJlOCbi/v6\n\tJ0IGHPQoDfur3pxcLCQ8LGbLMFF3iRONMfqkcpKkSjxvI+qkRkWCgQLprpiDDusGWDe4\n\ti9CN+TiHjoInpiuQHFoPTBluzkPRluZkAPuYzv7eFCfgLduPBJq8OHMGAq8tAmNt+pmZ\n\tBBrQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n\t:references;\n\tbh=TcXSVnkuzNuuhq/qGicmO35MPEloXzfvi9hiWlZsjUI=;\n\tb=qTS171OqzZOshSnNIftjQg3vl1Y7pzfwDZkIaKk5ZyGasI31rKnrrxT39EYGPHAVzx\n\t8+cFVI5CXRnVklb7ELCJX11jEnNNskgOmsXVCbY8PA/zzEQHoN+ulNiqitGAI46ZTiJT\n\tIdxK9UNkMEUXP2f9bh7BQ94i0Yh016jr4gj/Fcte/vep6DenDw7CyHZpXf97aRF7zopX\n\t48MeubQLeViChghj8KknUDY5ezif4KtDzIjdRaKTuEsf7xkXB+3kyiA/wwNbBVJiMOR9\n\tBxaFyk6kAxiQbp9oDPNyxQbFG5J9ZxhP80Gk/mAB01+fi+Jzyh7obwJqZkzl5IZHs8bf\n\tCRpg==", "X-Gm-Message-State": "AHPjjUjMn9ttkqIsQMtgmHY8A4MLbPVGLu7o9mfXyM64JX/UDQddGw7L\n\tQ1Y73PI8B5omiANRtcg=", "X-Google-Smtp-Source": "AOwi7QAX4c9r/0NHDjdN5mAMo8nnj9Zl9Wy2km1IB3EYUfU7TQ8JEGu9dhak3VwXzWvvHrvQ1SaMYQ==", "X-Received": "by 10.55.43.65 with SMTP id r62mr11445393qkh.250.1505042624503; \n\tSun, 10 Sep 2017 04:23:44 -0700 (PDT)", "From": "Rob Clark <robdclark@gmail.com>", "To": "U-Boot Mailing List <u-boot@lists.denx.de>", "Date": "Sun, 10 Sep 2017 07:21:40 -0400", "Message-Id": "<20170910112149.21358-24-robdclark@gmail.com>", "X-Mailer": "git-send-email 2.13.5", "In-Reply-To": "<20170910112149.21358-1-robdclark@gmail.com>", "References": "<20170910112149.21358-1-robdclark@gmail.com>", "Cc": "Heinrich Schuchardt <xypron.glpk@gmx.de>", "Subject": "[U-Boot] [PATCH v2 14/21] efi_loader: efi variable support", "X-BeenThere": "u-boot@lists.denx.de", "X-Mailman-Version": "2.1.18", "Precedence": "list", "List-Id": "U-Boot discussion <u-boot.lists.denx.de>", "List-Unsubscribe": "<https://lists.denx.de/options/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=unsubscribe>", "List-Archive": "<http://lists.denx.de/pipermail/u-boot/>", "List-Post": "<mailto:u-boot@lists.denx.de>", "List-Help": "<mailto:u-boot-request@lists.denx.de?subject=help>", "List-Subscribe": "<https://lists.denx.de/listinfo/u-boot>,\n\t<mailto:u-boot-request@lists.denx.de?subject=subscribe>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=\"utf-8\"", "Content-Transfer-Encoding": "base64", "Errors-To": "u-boot-bounces@lists.denx.de", "Sender": "\"U-Boot\" <u-boot-bounces@lists.denx.de>" }, "content": "Add EFI variable support, mapping to u-boot environment variables.\nVariables are pretty important for setting up boot order, among other\nthings. If the board supports saveenv, then it will be called in\nExitBootServices() to persist variables set by the efi payload. (For\nexample, fallback.efi configuring BootOrder and BootXXXX load-option\nvariables.)\n\nVariables are *not* currently exposed at runtime, post ExitBootServices.\nOn boards without a dedicated device for storage, which the loaded OS\nis not trying to also use, this is rather tricky. One idea, at least\nfor boards that can persist RAM across reboot, is to keep a \"journal\"\nof modified variables in RAM, and then turn halt into a reboot into\nu-boot, plus store variables, plus halt. Whatever the solution, it\nlikely involves some per-board support.\n\nMapping between EFI variables and u-boot variables:\n\n efi_$guid_$varname = {attributes}(type)value\n\nFor example:\n\n efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=\n \"{ro,boot,run}(blob)0000000000000000\"\n efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=\n \"(blob)00010000\"\n\nThe attributes are a comma separated list of these possible\nattributes:\n\n + ro - read-only\n + boot - boot-services access\n + run - runtime access\n\nNOTE: with current implementation, no variables are available after\nExitBootServices, and all are persisted (if possible).\n\nIf not specified, the attributes default to \"{boot}\".\n\nThe required type is one of:\n\n + utf8 - raw utf8 string\n + blob - arbitrary length hex string\n\nSigned-off-by: Rob Clark <robdclark@gmail.com>\n---\n cmd/bootefi.c | 4 +\n include/efi.h | 19 +++\n include/efi_loader.h | 10 ++\n lib/efi_loader/Makefile | 2 +-\n lib/efi_loader/efi_boottime.c | 6 +\n lib/efi_loader/efi_runtime.c | 17 ++-\n lib/efi_loader/efi_variable.c | 335 ++++++++++++++++++++++++++++++++++++++++++\n 7 files changed, 388 insertions(+), 5 deletions(-)\n create mode 100644 lib/efi_loader/efi_variable.c", "diff": "diff --git a/cmd/bootefi.c b/cmd/bootefi.c\nindex 0980088668..d3ae33e25b 100644\n--- a/cmd/bootefi.c\n+++ b/cmd/bootefi.c\n@@ -181,6 +181,10 @@ static unsigned long do_bootefi_exec(void *efi, void *fdt,\n \t\tgoto exit;\n \t}\n \n+\t/* we don't support much: */\n+\tenv_set(\"efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported\",\n+\t\t\"{ro,boot}(blob)0000000000000000\");\n+\n \t/* Call our payload! */\n \tdebug(\"%s:%d Jumping to 0x%lx\\n\", __func__, __LINE__, (long)entry);\n \ndiff --git a/include/efi.h b/include/efi.h\nindex ddd2b96417..04e83220b4 100644\n--- a/include/efi.h\n+++ b/include/efi.h\n@@ -324,6 +324,25 @@ extern char image_base[];\n /* Start and end of U-Boot image (for payload) */\n extern char _binary_u_boot_bin_start[], _binary_u_boot_bin_end[];\n \n+/*\n+ * Variable Attributes\n+ */\n+#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001\n+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002\n+#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004\n+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008\n+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010\n+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020\n+#define EFI_VARIABLE_APPEND_WRITE\t0x0000000000000040\n+\n+#define EFI_VARIABLE_MASK\t(EFI_VARIABLE_NON_VOLATILE | \\\n+\t\t\t\tEFI_VARIABLE_BOOTSERVICE_ACCESS | \\\n+\t\t\t\tEFI_VARIABLE_RUNTIME_ACCESS | \\\n+\t\t\t\tEFI_VARIABLE_HARDWARE_ERROR_RECORD | \\\n+\t\t\t\tEFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \\\n+\t\t\t\tEFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \\\n+\t\t\t\tEFI_VARIABLE_APPEND_WRITE)\n+\n /**\n * efi_get_sys_table() - Get access to the main EFI system table\n *\ndiff --git a/include/efi_loader.h b/include/efi_loader.h\nindex b0c1e8fb78..9eee62dc9c 100644\n--- a/include/efi_loader.h\n+++ b/include/efi_loader.h\n@@ -277,6 +277,16 @@ efi_status_t __efi_runtime EFIAPI efi_get_time(\n \t\t\tstruct efi_time_cap *capabilities);\n void efi_get_time_init(void);\n \n+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,\n+\t\tefi_guid_t *vendor, u32 *attributes,\n+\t\tunsigned long *data_size, void *data);\n+efi_status_t EFIAPI efi_get_next_variable(\n+\t\tunsigned long *variable_name_size,\n+\t\ts16 *variable_name, efi_guid_t *vendor);\n+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,\n+\t\tefi_guid_t *vendor, u32 attributes,\n+\t\tunsigned long data_size, void *data);\n+\n #else /* defined(EFI_LOADER) && !defined(CONFIG_SPL_BUILD) */\n \n /* Without CONFIG_EFI_LOADER we don't have a runtime section, stub it out */\ndiff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile\nindex cce92cfeb5..f58cb13337 100644\n--- a/lib/efi_loader/Makefile\n+++ b/lib/efi_loader/Makefile\n@@ -16,7 +16,7 @@ always := $(efiprogs-y)\n obj-$(CONFIG_CMD_BOOTEFI_HELLO) += helloworld_efi.o\n obj-y += efi_image_loader.o efi_boottime.o efi_runtime.o efi_console.o\n obj-y += efi_memory.o efi_device_path_to_text.o efi_device_path.o\n-obj-y += efi_file.o\n+obj-y += efi_file.o efi_variable.o\n obj-$(CONFIG_LCD) += efi_gop.o\n obj-$(CONFIG_DM_VIDEO) += efi_gop.o\n obj-$(CONFIG_PARTITIONS) += efi_disk.o\ndiff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c\nindex ec40f41bcb..c406ff82ff 100644\n--- a/lib/efi_loader/efi_boottime.c\n+++ b/lib/efi_loader/efi_boottime.c\n@@ -8,6 +8,7 @@\n \n #include <common.h>\n #include <efi_loader.h>\n+#include <environment.h>\n #include <malloc.h>\n #include <asm/global_data.h>\n #include <libfdt_env.h>\n@@ -942,6 +943,11 @@ static efi_status_t EFIAPI efi_exit_boot_services(void *image_handle,\n {\n \tEFI_ENTRY(\"%p, %ld\", image_handle, map_key);\n \n+#if defined(CONFIG_CMD_SAVEENV) && !defined(CONFIG_ENV_IS_NOWHERE)\n+\t/* save any EFI variables that have been written: */\n+\tenv_save();\n+#endif\n+\n \tboard_quiesce_devices();\n \n \t/* Fix up caches for EFI payloads if necessary */\ndiff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c\nindex ad7f3754bd..2f95c766ac 100644\n--- a/lib/efi_loader/efi_runtime.c\n+++ b/lib/efi_loader/efi_runtime.c\n@@ -184,7 +184,16 @@ static const struct efi_runtime_detach_list_struct efi_runtime_detach_list[] = {\n \t\t/* Clean up system table */\n \t\t.ptr = &systab.boottime,\n \t\t.patchto = NULL,\n-\t},\n+\t}, {\n+\t\t.ptr = &efi_runtime_services.get_variable,\n+\t\t.patchto = &efi_device_error,\n+\t}, {\n+\t\t.ptr = &efi_runtime_services.get_next_variable,\n+\t\t.patchto = &efi_device_error,\n+\t}, {\n+\t\t.ptr = &efi_runtime_services.set_variable,\n+\t\t.patchto = &efi_device_error,\n+\t}\n };\n \n static bool efi_runtime_tobedetached(void *p)\n@@ -382,9 +391,9 @@ struct efi_runtime_services __efi_runtime_data efi_runtime_services = {\n \t.set_wakeup_time = (void *)&efi_unimplemented,\n \t.set_virtual_address_map = &efi_set_virtual_address_map,\n \t.convert_pointer = (void *)&efi_invalid_parameter,\n-\t.get_variable = (void *)&efi_device_error,\n-\t.get_next_variable = (void *)&efi_device_error,\n-\t.set_variable = (void *)&efi_device_error,\n+\t.get_variable = efi_get_variable,\n+\t.get_next_variable = efi_get_next_variable,\n+\t.set_variable = efi_set_variable,\n \t.get_next_high_mono_count = (void *)&efi_device_error,\n \t.reset_system = &efi_reset_system_boottime,\n };\ndiff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c\nnew file mode 100644\nindex 0000000000..5569b3d3f0\n--- /dev/null\n+++ b/lib/efi_loader/efi_variable.c\n@@ -0,0 +1,335 @@\n+/*\n+ * EFI utils\n+ *\n+ * Copyright (c) 2017 Rob Clark\n+ *\n+ * SPDX-License-Identifier: GPL-2.0+\n+ */\n+\n+#include <malloc.h>\n+#include <charset.h>\n+#include <efi_loader.h>\n+\n+#define READ_ONLY BIT(31)\n+\n+/*\n+ * Mapping between EFI variables and u-boot variables:\n+ *\n+ * efi_$guid_$varname = {attributes}(type)value\n+ *\n+ * For example:\n+ *\n+ * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_OsIndicationsSupported=\n+ * \"{ro,boot,run}(blob)0000000000000000\"\n+ * efi_8be4df61-93ca-11d2-aa0d-00e098032b8c_BootOrder=\n+ * \"(blob)00010000\"\n+ *\n+ * The attributes are a comma separated list of these possible\n+ * attributes:\n+ *\n+ * + ro - read-only\n+ * + boot - boot-services access\n+ * + run - runtime access\n+ *\n+ * NOTE: with current implementation, no variables are available after\n+ * ExitBootServices, and all are persisted (if possible).\n+ *\n+ * If not specified, the attributes default to \"{boot}\".\n+ *\n+ * The required type is one of:\n+ *\n+ * + utf8 - raw utf8 string\n+ * + blob - arbitrary length hex string\n+ *\n+ * Maybe a utf16 type would be useful to for a string value to be auto\n+ * converted to utf16?\n+ */\n+\n+#define MAX_VAR_NAME 31\n+#define MAX_NATIVE_VAR_NAME \\\n+\t(strlen(\"efi_xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx_\") + \\\n+\t\t(MAX_VAR_NAME * MAX_UTF8_PER_UTF16))\n+\n+static int hex(unsigned char ch)\n+{\n+\tif (ch >= 'a' && ch <= 'f')\n+\t\treturn ch-'a'+10;\n+\tif (ch >= '0' && ch <= '9')\n+\t\treturn ch-'0';\n+\tif (ch >= 'A' && ch <= 'F')\n+\t\treturn ch-'A'+10;\n+\treturn -1;\n+}\n+\n+static const char *hex2mem(u8 *mem, const char *hexstr, int count)\n+{\n+\tmemset(mem, 0, count/2);\n+\n+\tdo {\n+\t\tint nibble;\n+\n+\t\t*mem = 0;\n+\n+\t\tif (!count || !*hexstr)\n+\t\t\tbreak;\n+\n+\t\tnibble = hex(*hexstr);\n+\t\tif (nibble < 0)\n+\t\t\tbreak;\n+\n+\t\t*mem = nibble;\n+\t\tcount--;\n+\t\thexstr++;\n+\n+\t\tif (!count || !*hexstr)\n+\t\t\tbreak;\n+\n+\t\tnibble = hex(*hexstr);\n+\t\tif (nibble < 0)\n+\t\t\tbreak;\n+\n+\t\t*mem = (*mem << 4) | nibble;\n+\t\tcount--;\n+\t\thexstr++;\n+\t\tmem++;\n+\n+\t} while (1);\n+\n+\tif (*hexstr)\n+\t\treturn hexstr;\n+\n+\treturn NULL;\n+}\n+\n+static char *mem2hex(char *hexstr, const u8 *mem, int count)\n+{\n+\tstatic const char hexchars[] = \"0123456789abcdef\";\n+\n+\twhile (count-- > 0) {\n+\t\tu8 ch = *mem++;\n+\t\t*hexstr++ = hexchars[ch >> 4];\n+\t\t*hexstr++ = hexchars[ch & 0xf];\n+\t}\n+\n+\treturn hexstr;\n+}\n+\n+static efi_status_t efi_to_native(char *native, s16 *variable_name,\n+\t\tefi_guid_t *vendor)\n+{\n+\tsize_t len;\n+\n+\tlen = utf16_strlen((u16 *)variable_name);\n+\tif (len >= MAX_VAR_NAME)\n+\t\treturn EFI_DEVICE_ERROR;\n+\n+\tnative += sprintf(native, \"efi_%pUl_\", vendor);\n+\tnative = (char *)utf16_to_utf8((u8 *)native, (u16 *)variable_name, len);\n+\t*native = '\\0';\n+\n+\treturn EFI_SUCCESS;\n+}\n+\n+static const char *prefix(const char *str, const char *prefix)\n+{\n+\tsize_t n = strlen(prefix);\n+\tif (!strncmp(prefix, str, n))\n+\t\treturn str + n;\n+\treturn NULL;\n+}\n+\n+/* parse attributes part of variable value, if present: */\n+static const char *parse_attr(const char *str, u32 *attrp)\n+{\n+\tu32 attr = 0;\n+\tchar sep = '{';\n+\n+\tif (*str != '{') {\n+\t\t*attrp = EFI_VARIABLE_BOOTSERVICE_ACCESS;\n+\t\treturn str;\n+\t}\n+\n+\twhile (*str == sep) {\n+\t\tconst char *s;\n+\n+\t\tstr++;\n+\n+\t\tif ((s = prefix(str, \"ro\"))) {\n+\t\t\tattr |= READ_ONLY;\n+\t\t} else if ((s = prefix(str, \"boot\"))) {\n+\t\t\tattr |= EFI_VARIABLE_BOOTSERVICE_ACCESS;\n+\t\t} else if ((s = prefix(str, \"run\"))) {\n+\t\t\tattr |= EFI_VARIABLE_RUNTIME_ACCESS;\n+\t\t} else {\n+\t\t\tprintf(\"invalid attribute: %s\\n\", str);\n+\t\t\tbreak;\n+\t\t}\n+\n+\t\tstr = s;\n+\t\tsep = ',';\n+\t}\n+\n+\tstr++;\n+\n+\t*attrp = attr;\n+\n+\treturn str;\n+}\n+\n+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetVariable.28.29 */\n+efi_status_t EFIAPI efi_get_variable(s16 *variable_name,\n+\t\tefi_guid_t *vendor, u32 *attributes,\n+\t\tunsigned long *data_size, void *data)\n+{\n+\tchar native_name[MAX_NATIVE_VAR_NAME + 1];\n+\tefi_status_t ret;\n+\tunsigned long in_size;\n+\tconst char *val, *s;\n+\tu32 attr;\n+\n+\tEFI_ENTRY(\"%p %p %p %p %p\", variable_name, vendor, attributes,\n+\t\t data_size, data);\n+\n+\tif (!variable_name || !vendor || !data_size)\n+\t\treturn EFI_EXIT(EFI_INVALID_PARAMETER);\n+\n+\tret = efi_to_native(native_name, variable_name, vendor);\n+\tif (ret)\n+\t\treturn EFI_EXIT(ret);\n+\n+\tdebug(\"%s: get '%s'\\n\", __func__, native_name);\n+\n+\tval = env_get(native_name);\n+\tif (!val)\n+\t\treturn EFI_EXIT(EFI_NOT_FOUND);\n+\n+\tval = parse_attr(val, &attr);\n+\n+\tin_size = *data_size;\n+\n+\tif ((s = prefix(val, \"(blob)\"))) {\n+\t\tunsigned len = strlen(s);\n+\n+\t\t/* two characters per byte: */\n+\t\tlen = DIV_ROUND_UP(len, 2);\n+\t\t*data_size = len;\n+\n+\t\tif (in_size < len)\n+\t\t\treturn EFI_EXIT(EFI_BUFFER_TOO_SMALL);\n+\n+\t\tif (!data)\n+\t\t\treturn EFI_EXIT(EFI_INVALID_PARAMETER);\n+\n+\t\tif (hex2mem(data, s, len * 2))\n+\t\t\treturn EFI_EXIT(EFI_DEVICE_ERROR);\n+\n+\t\tdebug(\"%s: got value: \\\"%s\\\"\\n\", __func__, s);\n+\t} else if ((s = prefix(val, \"(utf8)\"))) {\n+\t\tunsigned len = strlen(s) + 1;\n+\n+\t\t*data_size = len;\n+\n+\t\tif (in_size < len)\n+\t\t\treturn EFI_EXIT(EFI_BUFFER_TOO_SMALL);\n+\n+\t\tif (!data)\n+\t\t\treturn EFI_EXIT(EFI_INVALID_PARAMETER);\n+\n+\t\tmemcpy(data, s, len);\n+\t\t((char *)data)[len] = '\\0';\n+\n+\t\tdebug(\"%s: got value: \\\"%s\\\"\\n\", __func__, (char *)data);\n+\t} else {\n+\t\tdebug(\"%s: invalid value: '%s'\\n\", __func__, val);\n+\t\treturn EFI_EXIT(EFI_DEVICE_ERROR);\n+\t}\n+\n+\tif (attributes)\n+\t\t*attributes = attr & EFI_VARIABLE_MASK;\n+\n+\treturn EFI_EXIT(EFI_SUCCESS);\n+}\n+\n+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#GetNextVariableName.28.29 */\n+efi_status_t EFIAPI efi_get_next_variable(\n+\t\tunsigned long *variable_name_size,\n+\t\ts16 *variable_name, efi_guid_t *vendor)\n+{\n+\tEFI_ENTRY(\"%p %p %p\", variable_name_size, variable_name, vendor);\n+\n+\treturn EFI_EXIT(EFI_DEVICE_ERROR);\n+}\n+\n+/* http://wiki.phoenix.com/wiki/index.php/EFI_RUNTIME_SERVICES#SetVariable.28.29 */\n+efi_status_t EFIAPI efi_set_variable(s16 *variable_name,\n+\t\tefi_guid_t *vendor, u32 attributes,\n+\t\tunsigned long data_size, void *data)\n+{\n+\tchar native_name[MAX_NATIVE_VAR_NAME + 1];\n+\tefi_status_t ret = EFI_SUCCESS;\n+\tchar *val, *s;\n+\tu32 attr;\n+\n+\tEFI_ENTRY(\"%p %p %x %lu %p\", variable_name, vendor, attributes,\n+\t\t data_size, data);\n+\n+\tif (!variable_name || !vendor)\n+\t\treturn EFI_EXIT(EFI_INVALID_PARAMETER);\n+\n+\tret = efi_to_native(native_name, variable_name, vendor);\n+\tif (ret)\n+\t\treturn EFI_EXIT(ret);\n+\n+#define ACCESS_ATTR (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)\n+\n+\tif ((data_size == 0) || !(attributes & ACCESS_ATTR)) {\n+\t\t/* delete the variable: */\n+\t\tenv_set(native_name, NULL);\n+\t\treturn EFI_EXIT(EFI_SUCCESS);\n+\t}\n+\n+\tval = env_get(native_name);\n+\tif (val) {\n+\t\tparse_attr(val, &attr);\n+\n+\t\tif (attr & READ_ONLY)\n+\t\t\treturn EFI_EXIT(EFI_WRITE_PROTECTED);\n+\t}\n+\n+\tval = malloc(2 * data_size + strlen(\"{ro,run,boot}(blob)\") + 1);\n+\tif (!val)\n+\t\treturn EFI_EXIT(EFI_OUT_OF_RESOURCES);\n+\n+\ts = val;\n+\n+\t/* store attributes: */\n+\tattributes &= (EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS);\n+\ts += sprintf(s, \"{\");\n+\twhile (attributes) {\n+\t\tu32 attr = 1 << (ffs(attributes) - 1);\n+\n+\t\tif (attr == EFI_VARIABLE_BOOTSERVICE_ACCESS)\n+\t\t\ts += sprintf(s, \"boot\");\n+\t\telse if (attr == EFI_VARIABLE_RUNTIME_ACCESS)\n+\t\t\ts += sprintf(s, \"run\");\n+\n+\t\tattributes &= ~attr;\n+\t\tif (attributes)\n+\t\t\ts += sprintf(s, \",\");\n+\t}\n+\ts += sprintf(s, \"}\");\n+\n+\t/* store payload: */\n+\ts += sprintf(s, \"(blob)\");\n+\ts = mem2hex(s, data, data_size);\n+\t*s = '\\0';\n+\n+\tdebug(\"%s: setting: %s=%s\\n\", __func__, native_name, val);\n+\n+\tif (env_set(native_name, val))\n+\t\tret = EFI_DEVICE_ERROR;\n+\n+\tfree(val);\n+\n+\treturn EFI_EXIT(ret);\n+}\n", "prefixes": [ "U-Boot", "v2", "14/21" ] }