From patchwork Thu Apr 28 08:09:42 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 567136 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:6886:0:0:0:0 with SMTP id m6csp5233477map; Thu, 28 Apr 2022 01:13:11 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwH5AdwFTK0WZnudFR8diFQzZ0aEbgWjhLClk+v/a0hg1nEYnot9snn/w8TPbeZToUzXsdJ X-Received: by 2002:a17:907:d8d:b0:6df:b214:392a with SMTP id go13-20020a1709070d8d00b006dfb214392amr30776184ejc.669.1651133591004; Thu, 28 Apr 2022 01:13:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1651133590; cv=none; d=google.com; s=arc-20160816; b=Acn80u3xN6A05Tmk3XmA76C4pEJdAAPiUh3reY9a6mLRR81H8DHAe0PwoaKhR692sD wn+mKzd/8Gzt6vWbZRvEpDl0EQ57jywI+9y/fwGp/ND+BY1QTi0Q35FngQgah5dkvqeS /m6NyOROep1elRCrl+5oFdGYC9sLwfsfXUoUgtNrEFcJKULeE+dQWHT5xmxoDvjIg+T0 t/reO2YnPE0Lg831e7hGzAhsUO9drSgycT2lH+oK0Mps5X0xLRPyWpuRDEOJmPv/FePQ MLqOzOhXqprQ85afV+hrQWKFlXcrEX9mukNnJmuM3JZfVoBQlLo5eToQsYrdmutTumst C/CQ== 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:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=Xe69R6FDlBovFEuSAtFxJhquUkinf9gjFq4OL2sJCZs=; b=C5fo4rtnn6l0+Okc+4srIjUYEIu7D2iXaMk7k5++0DfxZjHJjHzzQKXPn+1xypfcL2 B4VmFM7j0QiwWAojqaRZZeapJ2B0Nm9oKXmCsNJgYr9WbJIt7sahcRGxpmpYJbappdXL S7v8PE+C2AqKW98IVxFSznOn+E5BGeFxS7sZwlCeZiwh7Di0WzrgS9nPrOzAvwtQ8jqY czoh7IJcBeAuWbS+y8UKSXiLFa/jHCkBmureeBfvI8PcDwxaHa/W1RCfr6dRC0nUeYvM zSETPREWywXpZD+GWOSpt92HxgpjZswR64iWY3W1qF19mhXnWXH0sPzGwmhsFVFMlTY0 T+Wg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=phKCLtJz; 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 gn40-20020a1709070d2800b006f3a2a7fd95si3420089ejc.636.2022.04.28.01.13.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 01:13:10 -0700 (PDT) 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=phKCLtJz; 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 94E5583EFB; Thu, 28 Apr 2022 10:11:52 +0200 (CEST) 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="phKCLtJz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 50B5E81D4B; Thu, 28 Apr 2022 10:11:16 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) (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 1A5F983E17 for ; Thu, 28 Apr 2022 10:11:03 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=masahisa.kojima@linaro.org Received: by mail-pg1-x52f.google.com with SMTP id bg9so3373735pgb.9 for ; Thu, 28 Apr 2022 01:11:03 -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; bh=Xe69R6FDlBovFEuSAtFxJhquUkinf9gjFq4OL2sJCZs=; b=phKCLtJzIyp4LDl1UqWppGRYhOlMCPVlWQ+TG+hlEPrEYmINc7e9Had+aX1ximZrPo z2BXcTo7i7mRO01Ypah+q+hCi3u/5qoFYA9pa7b2SHF92CBlwVBoRaoOEDn1P2djfwzK AAKFjl8xcC8x8XZNUMvFGAsWhkAEL9lj22+fbumTyOY+habNeYZ8TtcdIhQah2b2/Pce 9Ec13a1mGKaRvrt3wLJEw1vYbaP9QgmNSfkfvNV35boGZMNPbKRbt3PXrE6MXCQrcpWY XIe1gA87G+NpYyHF9u4/2F1lfTh428xt27qUloS2Qfr8XlKZMztcCmBZ4cbwB2sg51Ug kKbA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xe69R6FDlBovFEuSAtFxJhquUkinf9gjFq4OL2sJCZs=; b=DxZALAXTSKEac2tO4fmHWrJ1VZaIiZUGpTYXXmw/HLZEYQYnQ+HcEdNXhdBMQfF5KM 7I0XAnvq1x9s140r6LcAGMx7zkaPwVbHzM2sZMldg/xEsjVm535kudx3epAUnUuMC+Sp vybcnTloZkXb/qfXWCt5PtOQIhJPhl9dxWArFrnGP4EjJj3b/SFoGgyPywvt/EmX4ilS rDWryPcUnSiO5u9YUZbqL8JQVq3CZj+ummDi2tDOUeyuV4T3uahOpnKPlg5d25i3kZ+W j41L6tYJD35pU51PiMQqQdJvRtWbsFtt+2MgQ43ZtjdfMQo4CC7jXvXT7IMXvI9URK4D 6Pqw== X-Gm-Message-State: AOAM533BC09+jN4e6UPQTDXq+XD3J4FsyWl4exBFA5L45RBHE+Y8rsBC 9K7jGv1+OMQ2xdf4yiQqnj6t5DpHZ+ApFg== X-Received: by 2002:a63:195f:0:b0:399:1f0e:a21d with SMTP id 31-20020a63195f000000b003991f0ea21dmr26823935pgz.393.1651133461177; Thu, 28 Apr 2022 01:11:01 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id b15-20020a17090a7acf00b001cd4989ff5fsm5684259pjl.38.2022.04.28.01.10.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Apr 2022 01:11:00 -0700 (PDT) From: Masahisa Kojima To: u-boot@lists.denx.de Cc: Heinrich Schuchardt , Ilias Apalodimas , Simon Glass , Takahiro Akashi , Francois Ozog , Mark Kettenis , Masahisa Kojima Subject: [PATCH v5 09/17] bootmenu: add UEFI boot entry into bootmenu Date: Thu, 28 Apr 2022 17:09:42 +0900 Message-Id: <20220428080950.23509-10-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220428080950.23509-1-masahisa.kojima@linaro.org> References: <20220428080950.23509-1-masahisa.kojima@linaro.org> X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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.103.5 at phobos.denx.de X-Virus-Status: Clean This commit adds the UEFI related menu entries into the bootmenu. User can select which UEFI "Boot####" option to execute from bootmenu, then bootmenu sets the "BootNext" UEFI variable and invoke efi bootmgr. The efi bootmgr will handle the "BootNext" UEFI variable. If the "BootNext" UEFI variable is preset and efi bootmgr is enabled, bootmenu invokes efi bootmgr to handle "BootNext" as first priority. The UEFI boot entry has the "UEFI BOOTXXXX" prefix as below. *** U-Boot Boot Menu *** UEFI BOOT0000 : debian UEFI BOOT0001 : ubuntu Signed-off-by: Masahisa Kojima --- Changes in v5: - split into the separate patch - add function description comment - remove non-volatile attribute for BootNext variable to minimize the access to the non-volatile storage cmd/bootmenu.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 154 insertions(+), 1 deletion(-) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 15ad621c9f..da688e6213 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,6 +30,7 @@ enum boot_type { BOOTMENU_TYPE_NONE = 0, BOOTMENU_TYPE_BOOTMENU, + BOOTMENU_TYPE_UEFI_BOOT_OPTION, }; struct bootmenu_entry { @@ -85,6 +88,8 @@ static void bootmenu_print_entry(void *data) if (entry->type == BOOTMENU_TYPE_BOOTMENU) printf("bootmenu_%02d : %ls", entry->bootorder, entry->title); + else if (entry->type == BOOTMENU_TYPE_UEFI_BOOT_OPTION) + printf("UEFI BOOT%04X : %ls", entry->bootorder, entry->title); else printf("%ls", entry->title); @@ -371,6 +376,95 @@ static int prepare_bootmenu_entry(struct bootmenu_data *menu, return 1; } +/** + * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries + * + * This function read the "BootOrder" UEFI variable + * and generate the bootmenu entries in the order of "BootOrder". + * + * @menu: pointer to the bootmenu structure + * @current: pointer to the last bootmenu entry list + * @index: pointer to the index of the last bootmenu entry, + * the number of uefi entry is added by this function + * Return: 1 on success, negative value on error + */ +static int prepare_uefi_bootorder_entry(struct bootmenu_data *menu, + struct bootmenu_entry **current, + unsigned short int *index) +{ + u16 *bootorder; + efi_status_t ret; + unsigned short j; + efi_uintn_t num, size; + void *load_option; + struct efi_load_option lo; + u16 varname[] = u"Boot####"; + unsigned short int i = *index; + struct bootmenu_entry *entry = NULL; + struct bootmenu_entry *iter = *current; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) + return -ENOENT; + + num = size / sizeof(u16); + for (j = 0; j < num; j++) { + entry = malloc(sizeof(struct bootmenu_entry)); + if (!entry) + return -ENOMEM; + + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[j]); + load_option = efi_get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) + continue; + + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) { + log_warning("Invalid load option for %ls\n", varname); + free(load_option); + free(entry); + continue; + } + + if (lo.attributes & LOAD_OPTION_ACTIVE) { + entry->title = u16_strdup(lo.label); + if (!entry->title) { + free(load_option); + free(entry); + free(bootorder); + return -ENOMEM; + } + entry->command = strdup("bootefi bootmgr"); + sprintf(entry->key, "%d", i); + entry->num = i; + entry->menu = menu; + entry->type = BOOTMENU_TYPE_UEFI_BOOT_OPTION; + entry->bootorder = bootorder[j]; + entry->next = NULL; + + if (!iter) + menu->first = entry; + else + iter->next = entry; + + iter = entry; + i++; + } + + free(load_option); + + if (i == MAX_COUNT - 1) + break; + } + + free(bootorder); + *index = i; + *current = iter; + + return 1; +} + static struct bootmenu_data *bootmenu_create(int delay) { int ret; @@ -396,6 +490,14 @@ static struct bootmenu_data *bootmenu_create(int delay) if (ret < 0) goto cleanup; + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { + if (i < MAX_COUNT - 1) { + ret = prepare_uefi_bootorder_entry(menu, &iter, &i); + if (ret < 0 && ret != -ENOENT) + goto cleanup; + } + } + /* Add U-Boot console entry at the end */ if (i <= MAX_COUNT - 1) { entry = malloc(sizeof(struct bootmenu_entry)); @@ -473,6 +575,31 @@ static void menu_display_statusline(struct menu *m) puts(ANSI_CLEAR_LINE); } +static void handle_uefi_bootnext(void) +{ + u16 bootnext; + efi_status_t ret; + efi_uintn_t size; + + /* Initialize EFI drivers */ + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + + return; + } + + /* If UEFI BootNext variable is set, boot the BootNext load option */ + size = sizeof(u16); + ret = efi_get_variable_int(u"BootNext", + &efi_global_variable_guid, + NULL, &size, &bootnext, NULL); + if (ret == EFI_SUCCESS) + /* BootNext does exist here, try to boot */ + run_command("bootefi bootmgr", 0); +} + static void bootmenu_show(int delay) { int init = 0; @@ -482,8 +609,12 @@ static void bootmenu_show(int delay) struct menu *menu; struct bootmenu_data *bootmenu; struct bootmenu_entry *iter; + efi_status_t efi_ret = EFI_SUCCESS; char *option, *sep; + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) + handle_uefi_bootnext(); + /* If delay is 0 do not create menu, just run first entry */ if (delay == 0) { option = bootmenu_getoption(0); @@ -532,6 +663,27 @@ static void bootmenu_show(int delay) command = strdup(iter->command); } + /* + * If the selected entry is UEFI BOOT####, set the BootNext variable. + * Then uefi bootmgr is invoked by the preset command in iter->command. + */ + if (IS_ENABLED(CONFIG_CMD_BOOTEFI_BOOTMGR)) { + if (iter->type == BOOTMENU_TYPE_UEFI_BOOT_OPTION) { + /* + * UEFI specification requires BootNext variable needs non-volatile + * attribute, but this BootNext is only used inside of U-Boot and + * removed by efi bootmgr once BootNext is processed. + * So this BootNext can be volatile. + */ + efi_ret = efi_set_variable_int(u"BootNext", &efi_global_variable_guid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + sizeof(u16), &iter->bootorder, false); + if (efi_ret != EFI_SUCCESS) + goto cleanup; + } + } + cleanup: menu_destroy(menu); bootmenu_destroy(bootmenu); @@ -545,7 +697,8 @@ cleanup: if (title && command) { debug("Starting entry '%ls'\n", title); free(title); - run_command(command, 0); + if (efi_ret == EFI_SUCCESS) + run_command(command, 0); free(command); }