From patchwork Mon Jun 13 09:38:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581411 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1797731max; Mon, 13 Jun 2022 02:38:36 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzYKY9InqDpIu/KJrKk+PtsVQy6YjJ4zVkW6HLi/2/0F6G1JLpxKRlQtXFr8YGFayB8L/th X-Received: by 2002:a05:6e02:1b8f:b0:2d1:b707:3022 with SMTP id h15-20020a056e021b8f00b002d1b7073022mr33457560ili.71.1655113116845; Mon, 13 Jun 2022 02:38:36 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113116; cv=none; d=google.com; s=arc-20160816; b=c7C2IQMysry76vyXwl0CoJ5UirWB/nfAGcElJrzBk2kas8zbfYFwhRVEUiqz882ytj p3Po9IfPcTf1Y8NYX2ZgpnJpdvTbTM80LlOESs942XVC1UOdU8C+X+I+iMrzg/wg3/ld hV4daJgv2Cw/RXBdYXDbk+fJgDfXFSfyMvSFh8NOHmq+cqdSu6fPGF0LVyiwwQEc5j33 iZpcMpiKksf+2L7vwVP+3EfJK+oz3PBf0pUEe23ev3TCWLvjcUxruC8MQ9KpcfFK4Dy0 41zW88CpI646mjk9lhBTjJW4wdrYnwZoVfr6fvpaLqfb80LosYMXV4h+kMM9uqXR/jIo E9ww== 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=X6aMr3BDdux3VY3eAJb7ZV/iL097awoz6J+eOVjDX2M=; b=oePNSGqwd761FtGud/dQmEocFXZd7fATDwwhEQx6fHSUxp4Imx5Dov0uQtpzM6Cbb2 3JAYTLB077gCFJUi/sd4D24q1z2jY21oH/1mjMSiFFRo9Zx9txBG56Fz14pzAyx5BunX p7UIlmTnKiU0Kii1mt6Zok2VMq90p2YoP3x9bPw+bcr42sgxdwbZGPSBqWqZ8v/RpERY p7t9F9teQLx/MpGYmspkR0mDEAqowoxA4qUquIxh8fooa77jTlwQv08DDRepG/Fh7Imo GXQm/8xCcBmdo2P3bBNwyieQGI/vLnr0la91eAtEvxRRaYECj93U9Rp6FXMuihYfAF6L zWoQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=VeglpB0W; 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 u20-20020a056638135400b0032ec51298fesi11662769jad.13.2022.06.13.02.38.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:36 -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=VeglpB0W; 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 9DD408442B; Mon, 13 Jun 2022 11:38:23 +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="VeglpB0W"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 57EBC842E6; Mon, 13 Jun 2022 11:38:21 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pg1-x532.google.com (mail-pg1-x532.google.com [IPv6:2607:f8b0:4864:20::532]) (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 2BEF6842E6 for ; Mon, 13 Jun 2022 11:38:18 +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-x532.google.com with SMTP id h192so5066734pgc.4 for ; Mon, 13 Jun 2022 02:38:18 -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=X6aMr3BDdux3VY3eAJb7ZV/iL097awoz6J+eOVjDX2M=; b=VeglpB0WsTsLdOfStFw4pdYIrk1ew59iF8lmG/F6LToJe9dbia9j8A9d8twxlXiUvk KlIuzHR5/svDTWGgmGjv6tJMuOwSK0yOehTURFeC3O20l7vfPF3xgjUY8HsVDOzOjyJs 9LvJH6P37sOty51YsEWYcCyHBgYYSIVcLnVe3y4HcTbyXbFy2mSh9HxyrRfDA22hFcv9 mEtHxzgKxvwy6XktEvgDFCTcTfnOmihk0Z8NJOqZEj5DPoQ315ucZOppMmMfDwy/vS3a EnUo7vvb4YKI81s+5JhEn+BpVSmSncvxO3Lt9KJW2J1R4XZQPH2xmQs2V/t+EPbLMCq/ ZTAg== 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=X6aMr3BDdux3VY3eAJb7ZV/iL097awoz6J+eOVjDX2M=; b=M7afJTs1H5zQYbT7nwIhvr1LjychBskpbxjI+KjruAjnXNvPv7V6JkQo214YHfDeTr TiJqwHotv+TQ2YA9jw5oW9sRnmcP0IsXofHNDVwNyEx1SfG1QhCb0K+ti96Gfm1Rl01f Ti+p1a53h3/Iv8+Sj4aYKQrymOt2lYT4aNevAavsriJ+Blr70iA1NKGFSIJlvExA5KS0 4oOASkIcIEmRwuTQIEFnQ2QzHg0aXD9UV99fCnt12nz9I1gZSo2fI6IuDJznBzz7mdWj 3IR6gd3nK/1WCxD7gqrEKq8WGaLZifcscLW6yx5OX5rWQBzUYv7KcqdFoBGiI+NDD+jZ Wb/Q== X-Gm-Message-State: AOAM530Mzi4Pk7kHnjcpgksG7/gn/IbQDO9YzKBYYTnUSamzfxBYPT5p qdl922fAgjj7fXpffpzU8/IrrS+aa2CLpA== X-Received: by 2002:a65:6499:0:b0:3fc:dcaa:ad62 with SMTP id e25-20020a656499000000b003fcdcaaad62mr50762918pgv.63.1655113096141; Mon, 13 Jun 2022 02:38:16 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:15 -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 v7 1/9] efi_loader: expose END device path node Date: Mon, 13 Jun 2022 18:38:45 +0900 Message-Id: <20220613093853.23865-2-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 exposes the END device path node. Signed-off-by: Masahisa Kojima --- Newly created in v7 include/efi_loader.h | 3 +++ lib/efi_loader/efi_device_path.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/efi_loader.h b/include/efi_loader.h index f6651e2c60..c6df29993c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -798,6 +798,9 @@ ssize_t efi_dp_check_length(const struct efi_device_path *dp, (((_dp)->type == DEVICE_PATH_TYPE_##_type) && \ ((_dp)->sub_type == DEVICE_PATH_SUB_TYPE_##_subtype)) +/* template END node: */ +extern const struct efi_device_path END; + /* Indicate supported runtime services */ efi_status_t efi_init_runtime_supported(void); diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 50a988c561..4798cec622 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -30,7 +30,7 @@ const efi_guid_t efi_guid_virtio_dev = U_BOOT_VIRTIO_DEV_GUID; #endif /* template END node: */ -static const struct efi_device_path END = { +const struct efi_device_path END = { .type = DEVICE_PATH_TYPE_END, .sub_type = DEVICE_PATH_SUB_TYPE_END, .length = sizeof(END), From patchwork Mon Jun 13 09:38:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581414 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798086max; Mon, 13 Jun 2022 02:39:17 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx1kXvYIWFrv3ns1sQzVWyBYyeDcR/DPUlzQmNKxYetBC3yvcAnUMDOoeCZaBzOszvwbaP0 X-Received: by 2002:a05:6602:2e08:b0:669:fba7:9346 with SMTP id o8-20020a0566022e0800b00669fba79346mr593098iow.31.1655113157766; Mon, 13 Jun 2022 02:39:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113157; cv=none; d=google.com; s=arc-20160816; b=DqZ+/r89OhOGW7F7ndN6W6p2i0l+4lP1FUrN+c5LiqyJscS7sOFkHkS4tLnxGZK1ev iwLFbyg0Yte1amMUnAIb07jv1O9lbOh/uwUuDiD3BwMJcjQxWMuD6JuiYZcIzpZXKbAz CErKCjw/dTJ+ifsLMVBzAs3sSdGBV4mKpXF93ASd81zwXBCAzhNfN2eUY2rqbM+nDaN8 sbfKxCLC5lBcTvugu0wTjqrSDcfofm6nkX9PZU3HcyHhN1vEcwSFfSh4KyqIWsdCy5om tB3C3t1DC498pQDkjGg9VNxOd3ltqQ+wppcWxByQztx8+f5b61VySIbRL7jjisqldz8Y VlHQ== 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=Dye33uhrE/3oEiVBMKDisWyjnDvhlYQFjiozxQBv2zE=; b=qp6SSd0mRfbWHTIaZiznEP+XRtXeC6hfVjCFfkRFHlrb9ickCfK2+C2XD+PjZPAmoA onIADNXUXXH7WdUFcQu0POYGp/Ia8gK54fmGJfi0bj6bG0Td0Tj382X3hd/QT9+2maAs UV8dANmRrl6vNYi92JRiW7Jzv6167qxdxJsyJ2TCaXJSVEXcRUYrATbFr4EJ3lq3jsso kWRYjEpNC+WjvfIG2eYfXfNa8Il1PoLXgY5h+9HDOHgBRoy+a+/gkgvA0rrWthWvaZWv N/qSDN6qwO19zgwtWC0ng9t+cgVOqILc02awMqwu4y4rpdFxjxNHX4c1+AIaiKezLTrD 0bHQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="L/LeZeB8"; 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 g15-20020a92cdaf000000b002d35f89023esi8892678ild.94.2022.06.13.02.39.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:39:17 -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="L/LeZeB8"; 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 EA3BD84442; Mon, 13 Jun 2022 11:38:39 +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="L/LeZeB8"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3E15C84271; Mon, 13 Jun 2022 11:38:36 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1031.google.com (mail-pj1-x1031.google.com [IPv6:2607:f8b0:4864:20::1031]) (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 3E0BD84433 for ; Mon, 13 Jun 2022 11:38:24 +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-pj1-x1031.google.com with SMTP id g10-20020a17090a708a00b001ea8aadd42bso5445704pjk.0 for ; Mon, 13 Jun 2022 02:38:24 -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=Dye33uhrE/3oEiVBMKDisWyjnDvhlYQFjiozxQBv2zE=; b=L/LeZeB80ikwGBqwHJB1pgI/Mk3LjiJinrRRy/wbMlL0XXuQzenzuSZM5GU47ZcUb1 Zo/G8/wcPJI7dpp9ZdM/vsqv1Wvnrg3flz2yfMluP3+axzT2/6sUzZ3sLuHNX+A7wko1 jar5oO5eUNQ9YIh+QQ+TS5qrDgDzsSCR10IGrqlFvAHBAmGk4xRIZ8u0XYlPRI+sxRGy z5/JryxNVnZ4c0/kpG5OYdvmcKr4McBBx1gGh9/baCyzmlfn2nsX+/5woG3rQz4SSnGY byeI9hu0E+qfJAq1CYyKu7fczFzzpdP1zrfKXMz6vZaWFvDike53TfigIPwjBat/V2pN O5Yw== 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=Dye33uhrE/3oEiVBMKDisWyjnDvhlYQFjiozxQBv2zE=; b=f8CHxu/oYa3zp5TjhpL40nKR9niGYAuSjaPp6BCtmzf4yIQO+brEW3GuvfclM7xsqv x1Is9GgO8uSQEKd297Wyt0LXD4zAlBeTJHcYWwb/gQsO34qIq0wrWyKWmtOrutqzSkYm xjL0bcpNzpCRa5xMjBXiRGZ/5iKePREUgUzhQpPy4fhFTdk1ylf+jChdwSCtkPf9YRDQ C+IlU2lTJrUEJAzadCPKjO/ZrK9L6lUHKfH8v5Qnr3UwLh0cL1bxVq9JsTOL8XbHigNV rW1v6G9By8TxR0Xn64bO+a9vK62ByLUIaEmdOgoEV1Rouccc8SBhQ0JsvCQx1tfDw5Ow 004Q== X-Gm-Message-State: AOAM530FIxqmfpzByGoaD4ITEXatV9LYD/R+bzpqbHDnHhnN5uGqUY/Q X0oErgxcIwCfvWvwhkgjBQp2XvZPX8va4w== X-Received: by 2002:a17:902:e353:b0:168:9a78:25cb with SMTP id p19-20020a170902e35300b001689a7825cbmr24894682plc.13.1655113101523; Mon, 13 Jun 2022 02:38:21 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:21 -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 , Michal Simek , Ovidiu Panait , Ashok Reddy Soma , Roland Gaudig , Ramon Fried , Thomas Huth , Kever Yang , Huang Jianan , Chris Morgan Subject: [PATCH v7 2/9] efimenu: menu-driven addition of UEFI boot option Date: Mon, 13 Jun 2022 18:38:46 +0900 Message-Id: <20220613093853.23865-3-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 add the "efimenu" command. The "efimenu" command implements the menu-driven UEFI boot option maintenance feature. This commit implements the addition of new boot option. User can select the block device volume having efi_simple_file_system_protocol and select the file corresponding to the Boot#### variable. User can also enter the description and optional_data of the BOOT#### variable in utf8. This commit adds "include/efi_menu.h", it contains the common definition to be used from other menus such as UEFI Secure Boot key management. Signed-off-by: Masahisa Kojima --- Changes in v7: - add "efimenu" command and uefi variable maintenance code moved into cmd/efimenu.c - create include/efimenu.h to define the common definition for the other menu such as UEFI Secure Boot key management - update boot option edit UI, user can select description, file, and optional_data to edit in the same menu like following. ** Edit Boot Option ** Description: debian File: virtio 0:1/EFI\debian\grubaa64.efi Optional Data: test Save Quit - remove exit parameter from efimenu_process_common() - menu title type is changed from u16 to char - efimenu_process_common() add menu title string - reduce printf/puts function call for displaying the menu - efi_console_get_u16_string() accept 0 length to allow optional_data is empty - efi_console_get_u16_string() the "size" parameter name is changes to "count" - efimenu is now designed to maintain the UEFI variables, remove autoboot related code - remove one empty line before "Quit" entry - efimenu_init() processes only the first time Changes in v6: - fix typos - modify volume name to match U-Boot syntax - compile in CONFIG_EFI_LOADER=n and CONFIG_CMD_BOOTEFI_BOOTMGR=n - simplify u16_strncmp() usage - support "a\b.efi" file path, use link list to handle filepath - modify length check condition - UEFI related menu items only appears with CONFIG_AUTOBOOT_MENU_SHOW=y Changes in v5: - remove forward declarations - add const qualifier for menu items - fix the possible unaligned access for directory info access - split into three commit 1)add boot option 2) delete boot option 3)change boot order This commit is 1)add boot option. - fix file name buffer allocation size, it should be EFI_BOOTMENU_FILE_PATH_MAX * sizeof(u16) - fix wrong size checking for file selection Chanes in v4: - UEFI boot option maintenance menu is integrated into bootmenu - display the simplified volume name(e.g. usb0:1, nvme1:2) for the volume selection - instead of extending lib/efi_loader/efi_bootmgr.c, newly create lib/efi_loader/efi_bootmenu_maintenance.c and implement boot variable maintenance into it. Changes in RFC v3: not included in v3 series Changes in RFC v2: - enable utf8 user input for boot option name - create lib/efi_loader/efi_console.c::efi_console_get_u16_string() for utf8 user input handling - use u16_strlcat instead of u16_strcat - remove the EFI_CALLs, and newly create or expose the following xxx_int() functions. efi_locate_handle_buffer_int(), efi_open_volume_int(), efi_file_open_int(), efi_file_close_int(), efi_file_read_int() and efi_file_setpos_int(). Note that EFI_CALLs still exist for EFI_DEVICE_PATH_TO_TEXT_PROTOCOL and EFI_SIMPLE_TEXT_INPUT/OUTPUT_PROTOCOL - use efi_search_protocol() instead of calling locate_protocol() to get the device_path_to_text_protocol interface. - remove unnecessary puts(ANSI_CLEAR_LINE), this patch is still depends on puts(ANSI_CLEAR_CONSOLE) - skip SetVariable() if the bootorder is not changed cmd/Kconfig | 7 + cmd/Makefile | 1 + cmd/efimenu.c | 1255 +++++++++++++++++++++++++++++++++ include/efi_loader.h | 40 ++ include/efi_menu.h | 91 +++ lib/efi_loader/efi_boottime.c | 52 +- lib/efi_loader/efi_console.c | 78 ++ lib/efi_loader/efi_disk.c | 11 + lib/efi_loader/efi_file.c | 75 +- 9 files changed, 1563 insertions(+), 47 deletions(-) create mode 100644 cmd/efimenu.c create mode 100644 include/efi_menu.h diff --git a/cmd/Kconfig b/cmd/Kconfig index 09193b61b9..3c3944c545 100644 --- a/cmd/Kconfig +++ b/cmd/Kconfig @@ -1870,6 +1870,13 @@ config CMD_EFIDEBUG particularly for managing boot parameters as well as examining various EFI status for debugging. +config CMD_EFIMENU + bool "provide menu-driven uefi variables maintenance feature" + depends on CMD_BOOTEFI_BOOTMGR + help + Enable the 'efimenu' command which provides the menu-driven UEFI + variable maintenance feature. + config CMD_EXCEPTION bool "exception - raise exception" depends on ARM || RISCV || SANDBOX || X86 diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e022..b8ae08f961 100644 --- a/cmd/Makefile +++ b/cmd/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_ENV_IS_IN_EEPROM) += eeprom.o obj-$(CONFIG_CMD_EEPROM) += eeprom.o obj-$(CONFIG_EFI) += efi.o obj-$(CONFIG_CMD_EFIDEBUG) += efidebug.o +obj-$(CONFIG_CMD_EFIMENU) += efimenu.o obj-$(CONFIG_CMD_ELF) += elf.o obj-$(CONFIG_CMD_EROFS) += erofs.o obj-$(CONFIG_HUSH_PARSER) += exit.o diff --git a/cmd/efimenu.c b/cmd/efimenu.c new file mode 100644 index 0000000000..fce08900db --- /dev/null +++ b/cmd/efimenu.c @@ -0,0 +1,1255 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Menu-driven UEFI Variable maintenance + * + * Copyright (c) 2022 Masahisa Kojima, Linaro Limited + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct efi_simple_text_input_protocol *cin; +static struct efi_simple_text_output_protocol *cout; + +#define EFIMENU_DESCRIPTION_MAX 32 +#define EFIMENU_OPTIONAL_DATA_MAX 64 +#define EFIMENU_EDIT_BOOT_OPTION_MENU_ENTRY 5 + +#define EFIMENU_AUTO_GENERATED_ENTRY_GUID \ + EFI_GUID(0x38c1acc1, 0x9fc0, 0x41f0, \ + 0xb9, 0x01, 0xfa, 0x74, 0xd6, 0xd6, 0xe4, 0xde) +const efi_guid_t efi_guid_bootmenu_auto_generated = + EFIMENU_AUTO_GENERATED_ENTRY_GUID; + +struct efimenu_boot_selection_data { + u16 bootorder_index; + int *selected; +}; + +struct efimenu_filepath_info { + u16 *name; + struct list_head list; +}; + +/** + * struct efimenu_boot_option - structure to be used for uefi boot option update + * + * @file_info: user selected file info + * @boot_index: index of the uefi BootOrder variable + * @description: pointer to the description string + * @optional_data: pointer to the optional_data + * @edit_completed: flag indicates edit complete + */ +struct efimenu_boot_option { + struct efimenu_select_file_info file_info; + unsigned int boot_index; + u16 *description; + u16 *optional_data; + bool edit_completed; +}; + +struct efimenu_volume_entry_data { + struct efimenu_select_file_info *file_info; + struct efi_simple_file_system_protocol *v; + struct efi_device_path *dp; +}; + +struct efimenu_file_entry_data { + struct efimenu_select_file_info *file_info; + bool is_directory; + u16 *file_name; +}; + +/** + * efimenu_print_msg() - print message + * + * display the message to the user, user proceeds the screen + * with ENTER key press. + * + * @items: pointer to the structure of each menu entry + * @count: the number of menu entry + * @menu_header: pointer to the menu header string + * Return: status code + */ +void efimenu_print_msg(char *msg) +{ + char c; + + puts(ANSI_CURSOR_HIDE); + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 3, 4); + printf(msg); + + /* Flush input */ + while (tstc()) + getchar(); + + printf("\n\n Press ENTER to continue"); + while (1) { + while (!tstc()) { + WATCHDOG_RESET(); + mdelay(10); + } + c = getchar(); + if (c == '\r') + break; + } +} + +static void efimenu_print_entry(void *data) +{ + struct efimenu_entry *entry = data; + int reverse = (entry->efi_menu->active == entry->num); + + /* TODO: support scroll or page for many entries */ + + /* + * Move cursor to line where the entry will be drawn (entry->count) + * First 3 lines(menu header) + one empty line + */ + printf(ANSI_CURSOR_POSITION " ", entry->num + 4, 1); + + if (reverse) + puts(ANSI_COLOR_REVERSE); + + printf("%s", entry->title); + + if (reverse) + puts(ANSI_COLOR_RESET); +} + +static void efimenu_display_statusline(struct menu *m) +{ + struct efimenu_entry *entry; + + if (menu_default_choice(m, (void *)&entry) < 0) + return; + + printf(ANSI_CURSOR_POSITION + "\n%s\n" + ANSI_CURSOR_POSITION + "\n" + " Press UP/DOWN to move, ENTER to select, ESC/CTRL+C to quit", + 0, 1, entry->efi_menu->menu_header, entry->efi_menu->count + 5, 1); +} + +static char *efimenu_choice_entry(void *data) +{ + int i; + int esc = 0; + struct efimenu_entry *iter; + enum bootmenu_key key = KEY_NONE; + struct efimenu *efi_menu = data; + + while (1) { + bootmenu_loop((struct bootmenu_data *)efi_menu, &key, &esc); + + switch (key) { + case KEY_UP: + if (efi_menu->active > 0) + --efi_menu->active; + /* no menu key selected, regenerate menu */ + return NULL; + case KEY_DOWN: + if (efi_menu->active < efi_menu->count - 1) + ++efi_menu->active; + /* no menu key selected, regenerate menu */ + return NULL; + case KEY_SELECT: + iter = efi_menu->first; + for (i = 0; i < efi_menu->active; ++i) + iter = iter->next; + return iter->key; + case KEY_QUIT: + /* Quit by choosing the last entry */ + iter = efi_menu->first; + while (iter->next) + iter = iter->next; + return iter->key; + default: + break; + } + } + + /* never happens */ + debug("efi menu: this should not happen"); + return NULL; +} + +static void efimenu_destroy(struct efimenu *efi_menu) +{ + struct efimenu_entry *next; + struct efimenu_entry *iter = efi_menu->first; + + while (iter) { + next = iter->next; + free(iter); + iter = next; + } + free(efi_menu->menu_header); + free(efi_menu); +} + +/** + * efimenu_process_quit() - callback function for "Quit" entry + * + * @data: pointer to the data + * Return: status code + */ +efi_status_t efimenu_process_quit(void *data) +{ + return EFI_ABORTED; +} + +/** + * efimenu_process_common() - main handler for uefi menu + * + * Construct the structures required to show the menu, then handle + * the user input intracting with u-boot menu functions. + * + * @items: pointer to the structure of each menu entry + * @count: the number of menu entry + * @menu_header: pointer to the menu header string + * Return: status code + */ +efi_status_t efimenu_process_common(const struct efimenu_item *items, int count, + char *menu_header) +{ + u32 i; + efi_status_t ret; + struct menu *menu; + void *choice = NULL; + struct efimenu_entry *entry; + struct efimenu *efi_menu; + struct efimenu_entry *iter = NULL; + + if (count > EFIMENU_ENTRY_NUM_MAX) + return EFI_OUT_OF_RESOURCES; + + efi_menu = calloc(1, sizeof(struct efimenu)); + if (!efi_menu) + return EFI_OUT_OF_RESOURCES; + + efi_menu->delay = -1; + efi_menu->active = 0; + efi_menu->first = NULL; + + if (menu_header) { + efi_menu->menu_header = strdup(menu_header); + if (!efi_menu->menu_header) { + free(efi_menu); + return EFI_OUT_OF_RESOURCES; + } + } + + for (i = 0; i < count; i++) { + entry = calloc(1, sizeof(struct efimenu_entry)); + if (!entry) { + ret = EFI_LOAD_ERROR; + goto out; + } + + entry->num = i; + entry->title = items->title; + sprintf(entry->key, "%d", i); + entry->efi_menu = efi_menu; + entry->func = items->func; + entry->data = items->data; + entry->next = NULL; + + if (!iter) + efi_menu->first = entry; + else + iter->next = entry; + + iter = entry; + items++; + } + efi_menu->count = count; + + menu = menu_create(NULL, 0, 1, efimenu_display_statusline, + efimenu_print_entry, efimenu_choice_entry, + efi_menu); + if (!menu) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + + for (entry = efi_menu->first; entry; entry = entry->next) { + if (!menu_item_add(menu, entry->key, entry)) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + } + + menu_default_set(menu, efi_menu->first->key); + + puts(ANSI_CURSOR_HIDE); + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 1, 1); + + if (menu_get_choice(menu, &choice)) { + entry = choice; + if (entry->func) + ret = entry->func(entry->data); + } + +out: + menu_destroy(menu); + efimenu_destroy(efi_menu); + + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 1, 1); + puts(ANSI_CURSOR_SHOW); + + return ret; +} + +static efi_status_t efimenu_volume_selected(void *data) +{ + struct efimenu_volume_entry_data *info = data; + + if (info) { + info->file_info->current_volume = info->v; + info->file_info->dp_volume = info->dp; + } + + return EFI_SUCCESS; +} + +static efi_status_t efimenu_file_selected(void *data) +{ + struct efimenu_file_entry_data *info = data; + + if (!info) + return EFI_INVALID_PARAMETER; + + if (u16_strcmp(info->file_name, u".") == 0 && + u16_strlen(info->file_name) == 1) { + /* stay current path */ + } else if (u16_strcmp(info->file_name, u"..") == 0 && + u16_strlen(info->file_name) == 2) { + struct efimenu_filepath_info *iter; + struct list_head *pos, *n; + int is_last; + + memset(info->file_info->current_path, 0, EFIMENU_FILE_PATH_BUF_SIZE); + list_for_each_safe(pos, n, &info->file_info->filepath_list) { + iter = list_entry(pos, struct efimenu_filepath_info, list); + + is_last = list_is_last(&iter->list, &info->file_info->filepath_list); + if (is_last) { + list_del(&iter->list); + free(iter->name); + free(iter); + break; + } + u16_strlcat(info->file_info->current_path, iter->name, + EFIMENU_FILE_PATH_MAX); + u16_strlcat(info->file_info->current_path, u"\\", + EFIMENU_FILE_PATH_MAX); + } + } else { + size_t new_len; + struct efimenu_filepath_info *filepath; + + new_len = u16_strlen(info->file_info->current_path) + + u16_strlen(info->file_name); + if (new_len >= EFIMENU_FILE_PATH_MAX) { + efimenu_print_msg("File path is too long!"); + return EFI_INVALID_PARAMETER; + } + u16_strlcat(info->file_info->current_path, info->file_name, + EFIMENU_FILE_PATH_MAX); + + filepath = calloc(1, sizeof(struct efimenu_filepath_info)); + if (!filepath) + return EFI_OUT_OF_RESOURCES; + + filepath->name = u16_strdup(info->file_name); + if (!filepath->name) { + free(filepath); + return EFI_OUT_OF_RESOURCES; + } + list_add_tail(&filepath->list, &info->file_info->filepath_list); + + if (info->is_directory) { + /* + * Remainig buffer should have enough space to contain u"\\" and + * at least one character for file name + */ + if (new_len + 2 >= EFIMENU_FILE_PATH_MAX) { + efimenu_print_msg("Directory path is too long!"); + return EFI_INVALID_PARAMETER; + } + u16_strlcat(info->file_info->current_path, u"\\", + EFIMENU_FILE_PATH_MAX); + } else { + info->file_info->file_selected = true; + } + } + return EFI_SUCCESS; +} + +static efi_status_t efimenu_select_volume(struct efimenu_select_file_info *file_info) +{ + u32 i; + efi_status_t ret; + efi_uintn_t count; + struct efi_handler *handler; + struct efi_device_path *device_path; + efi_handle_t *volume_handles = NULL; + struct efimenu_item *menu_item, *iter; + struct efi_simple_file_system_protocol *v; + + ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid, + NULL, &count, (efi_handle_t **)&volume_handles); + if (ret != EFI_SUCCESS) + return ret; + + menu_item = calloc(count + 1, sizeof(struct efimenu_item)); + if (!menu_item) { + efi_free_pool(volume_handles); + return EFI_OUT_OF_RESOURCES; + } + + iter = menu_item; + for (i = 0; i < count; i++) { + char *devname; + struct efi_block_io *block_io; + struct efimenu_volume_entry_data *info; + + ret = efi_search_protocol(volume_handles[i], + &efi_simple_file_system_protocol_guid, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&v, efi_root, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&device_path, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&block_io, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + info = calloc(1, sizeof(struct efimenu_volume_entry_data)); + if (!info) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + devname = calloc(1, BOOTMENU_DEVICE_NAME_MAX); + if (!devname) { + free(info); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + efi_disk_get_device_name(block_io, devname, BOOTMENU_DEVICE_NAME_MAX); + + info->v = v; + info->dp = device_path; + info->file_info = file_info; + iter->title = devname; + iter->func = efimenu_volume_selected; + iter->data = info; + iter++; + } + + iter->title = strdup("Quit"); + iter->func = efimenu_process_quit; + iter->data = NULL; + count += 1; + + ret = efimenu_process_common(menu_item, count, " ** Select Volume **"); + +out: + iter = menu_item; + for (i = 0; i < count; i++, iter++) { + free(iter->data); + free(iter->title); + } + + free(menu_item); + + efi_free_pool(volume_handles); + + return ret; +} + +static efi_status_t efimenu_select_file(struct efimenu_select_file_info *file_info, + struct efi_file_handle *root) +{ + u32 i; + u32 count = 0; + efi_uintn_t len; + efi_status_t ret; + struct efi_file_handle *f; + struct efi_file_info *buf; + struct efimenu_item *menu_item, *iter; + + buf = calloc(1, sizeof(struct efi_file_info) + EFIMENU_FILE_PATH_BUF_SIZE); + if (!buf) + return EFI_OUT_OF_RESOURCES; + + while (!file_info->file_selected) { + count = 0; + + ret = efi_file_open_int(root, &f, file_info->current_path, EFI_FILE_MODE_READ, 0); + if (ret != EFI_SUCCESS) { + /* TODO: need to fileter out non-FAT partition? */ + efimenu_print_msg("Reading volume failed! Please make sure the selected\n" + " volume is FAT12/FAT16/FAT32 partition."); + ret = EFI_ABORTED; + goto out; + } + + /* calculate directory information total count */ + for (;;) { + len = sizeof(struct efi_file_info) + EFIMENU_FILE_PATH_BUF_SIZE; + ret = efi_file_read_int(f, &len, buf); + if (ret != EFI_SUCCESS || len == 0) + break; + + count++; + } + + menu_item = calloc(count + 1, sizeof(struct efimenu_item)); + if (!menu_item) { + efi_file_close_int(f); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + /* read directory and construct menu structure */ + efi_file_setpos_int(f, 0); + iter = menu_item; + for (i = 0; i < count; i++) { + char *name, *p; + int name_len; + struct efimenu_file_entry_data *info; + + len = sizeof(struct efi_file_info) + EFIMENU_FILE_PATH_BUF_SIZE; + ret = efi_file_read_int(f, &len, buf); + if (ret != EFI_SUCCESS || len == 0) + goto err; + + info = calloc(1, sizeof(struct efimenu_file_entry_data)); + if (!info) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + + if (buf->attribute & EFI_FILE_DIRECTORY) { + /* append u'/' at the end of directory name */ + name_len = utf16_utf8_strlen(buf->file_name) + 2; + name = calloc(1, name_len); + if (!name) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + p = name; + utf16_utf8_strcpy(&p, buf->file_name); + name[u16_strlen(buf->file_name)] = u'/'; + + info->is_directory = true; + } else { + name_len = utf16_utf8_strlen(buf->file_name) + 1; + name = calloc(1, name_len); + if (!name) { + ret = EFI_OUT_OF_RESOURCES; + goto err; + } + p = name; + utf16_utf8_strcpy(&p, buf->file_name); + } + + info->file_name = u16_strdup(buf->file_name); + info->file_info = file_info; + iter->title = name; + iter->func = efimenu_file_selected; + iter->data = info; + iter++; + } + + /* add "Quit" entry */ + iter->title = "Quit"; + iter->func = efimenu_process_quit; + iter->data = NULL; + count += 1; + + ret = efimenu_process_common(menu_item, count, " ** Select File **"); +err: + efi_file_close_int(f); + iter = menu_item; + for (i = 0; i < count - 1; i++, iter++) { + free(((struct efimenu_file_entry_data *)(iter->data))->file_name); + free(iter->title); + free(iter->data); + } + + free(menu_item); + + if (ret != EFI_SUCCESS) + break; + } + +out: + free(buf); + return ret; +} + +static efi_status_t efimenu_boot_add_enter_description(void *data) +{ + u16 *tmp; + efi_status_t ret; + struct efimenu_boot_option *bo = data; + + printf(ANSI_CLEAR_CONSOLE + ANSI_CURSOR_POSITION + "\n ** Edit Description **\n" + "\n" + " enter description: " + ANSI_CURSOR_POSITION + " Press ENTER to complete, ESC/CTRL+C to quit", + 0, 1, 8, 1); + + tmp = calloc(1, EFIMENU_DESCRIPTION_MAX * sizeof(u16)); + if (!tmp) + return EFI_OUT_OF_RESOURCES; + + ret = efi_console_get_u16_string(cin, cout, tmp, + EFIMENU_DESCRIPTION_MAX, NULL, 4, 22); + if (ret == EFI_SUCCESS) + u16_strcpy(bo->description, tmp); + + free(tmp); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + +static efi_status_t efimenu_boot_add_optional_data(void *data) +{ + u16 *tmp; + efi_status_t ret; + struct efimenu_boot_option *bo = data; + + printf(ANSI_CLEAR_CONSOLE + ANSI_CURSOR_POSITION + "\n ** Edit Optional Data **\n" + "\n" + " enter optional data:" + ANSI_CURSOR_POSITION + " Press ENTER to complete, ESC/CTRL+C to quit", + 0, 1, 8, 1); + + tmp = calloc(1, EFIMENU_OPTIONAL_DATA_MAX * sizeof(u16)); + ret = efi_console_get_u16_string(cin, cout, tmp, + EFIMENU_OPTIONAL_DATA_MAX, NULL, 4, 24); + + if (ret == EFI_SUCCESS) + u16_strcpy(bo->optional_data, tmp); + + free(tmp); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + +static efi_status_t efimenu_boot_edit_save(void *data) +{ + struct efimenu_boot_option *bo = data; + + if (u16_strlen(bo->description) == 0) { + efimenu_print_msg("Boot Description is empty!"); + bo->edit_completed = false; + return EFI_NOT_READY; + } + if (u16_strlen(bo->file_info.current_path) == 0) { + efimenu_print_msg("File is not selected!"); + bo->edit_completed = false; + return EFI_NOT_READY; + } + + bo->edit_completed = true; + + return EFI_SUCCESS; +} + +static efi_status_t efimenu_boot_edit_quit(void *data) +{ + return EFI_ABORTED; +} + +/** + * efimenu_select_file_handler() - handle user file selection + * + * @data: pointer to the data + * Return: status code + */ +efi_status_t efimenu_select_file_handler(void *data) +{ + size_t len; + efi_status_t ret; + struct list_head *pos, *n; + struct efi_file_handle *root; + struct efimenu_filepath_info *item; + struct efimenu_select_file_info *file_info = data; + struct efimenu_select_file_info *tmp = NULL; + + tmp = calloc(1, sizeof(struct efimenu_select_file_info)); + if (!tmp) + return EFI_OUT_OF_RESOURCES; + + tmp->current_path = calloc(1, EFIMENU_FILE_PATH_BUF_SIZE); + if (!tmp->current_path) { + free(tmp); + return EFI_OUT_OF_RESOURCES; + } + INIT_LIST_HEAD(&tmp->filepath_list); + + while (!tmp->file_selected) { + tmp->current_volume = NULL; + memset(tmp->current_path, 0, EFIMENU_FILE_PATH_BUF_SIZE); + + ret = efimenu_select_volume(tmp); + if (ret != EFI_SUCCESS) + goto out; + + if (!tmp->current_volume) + return EFI_INVALID_PARAMETER; + + ret = efi_open_volume_int(tmp->current_volume, &root); + if (ret != EFI_SUCCESS) + goto out; + + ret = efimenu_select_file(tmp, root); + if (ret == EFI_ABORTED) + continue; + if (ret != EFI_SUCCESS) + goto out; + } + +out: + if (ret == EFI_SUCCESS) { + len = u16_strlen(tmp->current_path); + len = (len >= EFIMENU_FILE_PATH_MAX) ? (EFIMENU_FILE_PATH_MAX - 1) : len; + memcpy(file_info->current_path, tmp->current_path, len * sizeof(u16)); + file_info->current_path[len] = u'\0'; + file_info->current_volume = tmp->current_volume; + file_info->dp_volume = tmp->dp_volume; + } + + list_for_each_safe(pos, n, &tmp->filepath_list) { + item = list_entry(pos, struct efimenu_filepath_info, list); + list_del(&item->list); + free(item->name); + free(item); + } + free(tmp->current_path); + free(tmp); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + +efi_status_t efimenu_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size, + unsigned int *index) +{ + u32 i; + efi_status_t ret; + efi_uintn_t size; + + if (buf_size < u16_strsize(u"Boot####")) + return EFI_BUFFER_TOO_SMALL; + + for (i = 0; i <= 0xFFFF; i++) { + size = 0; + efi_create_indexed_name(buf, buf_size, "Boot", i); + ret = efi_get_variable_int(buf, &efi_global_variable_guid, + NULL, &size, NULL, NULL); + if (ret == EFI_BUFFER_TOO_SMALL) + continue; + else + break; + } + + if (i > 0xFFFF) + return EFI_OUT_OF_RESOURCES; + + *index = i; + + return EFI_SUCCESS; +} + +static efi_status_t efimenu_set_boot_option(u16 *varname, struct efi_device_path *dp, + u16 *label, char *optional_data) +{ + void *p = NULL; + efi_status_t ret; + efi_uintn_t size; + struct efi_load_option lo; + + lo.file_path = dp; + lo.file_path_length = efi_dp_size(dp) + sizeof(END); + lo.attributes = LOAD_OPTION_ACTIVE; + lo.optional_data = optional_data; + lo.label = label; + + size = efi_serialize_load_option(&lo, (u8 **)&p); + if (!size) + return EFI_INVALID_PARAMETER; + + ret = efi_set_variable_int(varname, &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, p, false); + free(p); + + return ret; +} + +efi_status_t efimenu_append_bootorder(u16 index) +{ + u16 *bootorder; + efi_status_t ret; + u16 *new_bootorder = NULL; + efi_uintn_t last, size, new_size; + + /* append new boot option */ + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + last = size / sizeof(u16); + new_size = size + sizeof(u16); + new_bootorder = calloc(1, new_size); + if (!new_bootorder) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + memcpy(new_bootorder, bootorder, size); + new_bootorder[last] = index; + + ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + new_size, new_bootorder, false); + if (ret != EFI_SUCCESS) + goto out; + +out: + free(bootorder); + free(new_bootorder); + + return ret; +} + +static efi_status_t efimenu_convert_dp_to_device_name(struct efi_device_path *dp, + char *buf, int size) +{ + u32 i; + efi_status_t ret; + struct efi_handler *handler; + efi_uintn_t count, dp_size, iter_dp_size; + efi_handle_t *volume_handles = NULL; + struct efi_device_path *iter_dp; + + if (!dp || !buf || !size) + return EFI_INVALID_PARAMETER; + + ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid, + NULL, &count, (efi_handle_t **)&volume_handles); + if (ret != EFI_SUCCESS) + return ret; + + dp_size = efi_dp_size(dp); + + for (i = 0; i < count; i++) { + struct efi_block_io *block_io; + + ret = efi_search_protocol(volume_handles[i], + &efi_simple_file_system_protocol_guid, &handler); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&iter_dp, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&block_io, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + iter_dp_size = efi_dp_size(iter_dp); + if (dp_size == iter_dp_size) { + if (memcmp(dp, iter_dp, dp_size) == 0) { + efi_disk_get_device_name(block_io, buf, size); + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +static efi_status_t create_boot_option_entry(void *data, char *title, u16 *val, + efimenu_entry_func func, struct efimenu_item *iter) +{ + u32 len; + char *p; + + len = strlen(title) + 1; + if (val) + len += utf16_utf8_strlen(val); + iter->title = calloc(1, len); + if (!iter->title) + return EFI_OUT_OF_RESOURCES; + + strcpy(iter->title, title); + if (val) { + p = iter->title + strlen(title); + utf16_utf8_strcpy(&p, val); + } + + iter->func = func; + iter->data = data; + + return EFI_SUCCESS; +} + +/** + * efimenu_show_boot_option() - prepare menu entry for editing boot option + * + * Construct the structures to create edit boot option menu + * + * @bo: pointer to the boot option + * Return: status code + */ +static efi_status_t efimenu_show_boot_option(struct efimenu_boot_option *bo) +{ + u32 i, len; + u16 *file_name, *p; + struct efimenu_item *menu_item, *iter; + efi_status_t ret = EFI_OUT_OF_RESOURCES; + char devname[BOOTMENU_DEVICE_NAME_MAX] = {0}; + + menu_item = calloc(EFIMENU_EDIT_BOOT_OPTION_MENU_ENTRY, sizeof(struct efimenu_item)); + if (!menu_item) + goto out; + + iter = menu_item; + + ret = create_boot_option_entry(bo, "Description: ", bo->description, + efimenu_boot_add_enter_description, iter++); + if (ret != EFI_SUCCESS) + goto out; + + /* file name */ + efimenu_convert_dp_to_device_name(bo->file_info.dp_volume, devname, + BOOTMENU_DEVICE_NAME_MAX); + /* + * efi_convert_device_path_to_text() automatically adds u'/' at the beginning of + * file name, add manually u'/' at the last of device name if there is no u'/' + * at bo->file_info.current_path[0]. + */ + if (bo->file_info.current_path[0] != u'\0' && bo->file_info.current_path[0] != u'/') + strlcat(devname, "/", BOOTMENU_DEVICE_NAME_MAX); + + len = strlen(devname); + len += utf16_utf8_strlen(bo->file_info.current_path) + 1; + file_name = calloc(1, len * sizeof(u16)); + if (!file_name) + goto out; + + p = file_name; + utf8_utf16_strcpy(&p, devname); + u16_strlcat(file_name, bo->file_info.current_path, len); + ret = create_boot_option_entry(&bo->file_info, "File: ", file_name, + efimenu_select_file_handler, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Optional Data: ", bo->optional_data, + efimenu_boot_add_optional_data, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Save", NULL, + efimenu_boot_edit_save, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Quit", NULL, + efimenu_boot_edit_quit, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = efimenu_process_common(menu_item, EFIMENU_EDIT_BOOT_OPTION_MENU_ENTRY, + " ** Edit Boot Option ** "); + +out: + iter = menu_item; + for (i = 0; i < EFIMENU_EDIT_BOOT_OPTION_MENU_ENTRY; i++) { + free(iter->title); + iter++; + } + + free(file_name); + free(menu_item); + + return ret; +} + +/** + * efimenu_edit_boot_option() - prepare boot option structure for editing + * + * Construct the boot option structure and copy the existing value + * + * @varname: pointer to the uefi variable name + * @bo: pointer to the boot option + * @description: pointer to the description + * @optional_data: pointer to the optional_data + * @optional_data_size: optional_data_size + * @dp: pointer to the device path + * Return : status code + */ +static efi_status_t efimenu_edit_boot_option(u16 *varname, struct efimenu_boot_option *bo, + u16 *description, const u8 *optional_data, + efi_uintn_t optional_data_size, + struct efi_device_path *dp) +{ + size_t len; + char *buf = NULL; + efi_status_t ret; + char *iter = NULL; + char *tmp = NULL, *p; + efi_uintn_t dp_size, fp_size; + struct efi_device_path *device_dp = NULL; + struct efi_device_path_file_path *fp; + + bo->file_info.current_path = calloc(1, EFIMENU_FILE_PATH_BUF_SIZE); + if (!bo->file_info.current_path) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + bo->description = calloc(1, EFIMENU_DESCRIPTION_MAX * sizeof(u16)); + if (!bo->description) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + bo->optional_data = calloc(1, EFIMENU_OPTIONAL_DATA_MAX * sizeof(u16)); + if (!bo->optional_data) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + if (description && u16_strlen(description) >= EFIMENU_DESCRIPTION_MAX) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (description) + u16_strcpy(bo->description, description); + + if (dp) { + u16 *file_str; + struct efi_device_path *file_dp = NULL; + + efi_dp_split_file_path(dp, &device_dp, &file_dp); + bo->file_info.dp_volume = device_dp; + file_str = efi_dp_str(file_dp); + u16_strcpy(bo->file_info.current_path, file_str); + efi_free_pool(file_dp); + efi_free_pool(file_str); + } + + if (optional_data && optional_data_size >= EFIMENU_OPTIONAL_DATA_MAX * sizeof(u16)) { + ret = EFI_INVALID_PARAMETER; + goto out; + } + if (optional_data && optional_data_size > 0) + memcpy(bo->optional_data, optional_data, optional_data_size); + + while (1) { + ret = efimenu_show_boot_option(bo); + if (ret == EFI_SUCCESS && bo->edit_completed) + break; + if (ret == EFI_NOT_READY) + continue; + if (ret != EFI_SUCCESS) + goto out; + } + + dp_size = efi_dp_size(bo->file_info.dp_volume); + fp_size = sizeof(struct efi_device_path) + + ((u16_strlen(bo->file_info.current_path) + 1) * sizeof(u16)); + buf = calloc(1, dp_size + fp_size + sizeof(END)); + if (!buf) + goto out; + + iter = buf; + memcpy(iter, bo->file_info.dp_volume, dp_size); + iter += dp_size; + + fp = (struct efi_device_path_file_path *)iter; + fp->dp.type = DEVICE_PATH_TYPE_MEDIA_DEVICE; + fp->dp.sub_type = DEVICE_PATH_SUB_TYPE_FILE_PATH; + fp->dp.length = (u16)fp_size; + u16_strcpy(fp->str, bo->file_info.current_path); + iter += fp_size; + *((struct efi_device_path *)iter) = END; + + len = utf16_utf8_strlen(bo->optional_data) + 1; + tmp = calloc(1, len); + if (!tmp) + goto out; + p = tmp; + utf16_utf8_strncpy(&p, bo->optional_data, u16_strlen(bo->optional_data)); + + ret = efimenu_set_boot_option(varname, (struct efi_device_path *)buf, + bo->description, tmp); + if (ret != EFI_SUCCESS) + goto out; + +out: + free(tmp); + free(buf); + free(bo->optional_data); + free(bo->description); + free(bo->file_info.current_path); + efi_free_pool(device_dp); + + return ret; +} + +static efi_status_t efimenu_process_add_boot_option(void *data) +{ + u16 varname[9]; + efi_status_t ret; + struct efimenu_boot_option *bo = NULL; + + bo = calloc(1, sizeof(struct efimenu_boot_option)); + if (!bo) + return EFI_OUT_OF_RESOURCES; + + ret = efimenu_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index); + if (ret != EFI_SUCCESS) + return ret; + + ret = efimenu_edit_boot_option(varname, bo, NULL, NULL, 0, NULL); + if (ret != EFI_SUCCESS) + goto out; + + ret = efimenu_append_bootorder((u16)bo->boot_index); + if (ret != EFI_SUCCESS) + goto out; + +out: + free(bo); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_SUCCESS : ret; + + return ret; +} + +static efi_status_t efimenu_init(void) +{ + efi_status_t ret; + static bool init; + struct efi_handler *handler; + + if (!init) { + ret = efi_search_protocol(efi_root, &efi_guid_text_input_protocol, &handler); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_protocol_open(handler, (void **)&cin, efi_root, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_search_protocol(efi_root, &efi_guid_text_output_protocol, &handler); + if (ret != EFI_SUCCESS) + return ret; + + ret = efi_protocol_open(handler, (void **)&cout, efi_root, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + return ret; + } + + init = true; + + return ret; +} + +static const struct efimenu_item maintenance_menu_items[] = { + {"Add Boot Option", efimenu_process_add_boot_option}, + {"Quit", efimenu_process_quit}, +}; + +int do_efimenu(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + efi_status_t ret; + + if (argc > 1) + return CMD_RET_USAGE; + + ret = efimenu_init(); + if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + + while (1) { + ret = efimenu_process_common(maintenance_menu_items, + ARRAY_SIZE(maintenance_menu_items), + " ** UEFI Maintenance Menu **"); + if (ret == EFI_ABORTED) + break; + } + + return CMD_RET_SUCCESS; +} + +U_BOOT_CMD( + efimenu, 1, 0, do_efimenu, + "provide menu-driven UEFI variable maintenance feature", + "" +); diff --git a/include/efi_loader.h b/include/efi_loader.h index c6df29993c..44d8ba9bf8 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -226,6 +226,9 @@ const char *__efi_nesting_dec(void); #define EFI_CACHELINE_SIZE 128 #endif +/* max bootmenu title size for volume selection */ +#define BOOTMENU_DEVICE_NAME_MAX 16 + /* Key identifying current memory map */ extern efi_uintn_t efi_memory_map_key; @@ -249,6 +252,9 @@ extern const struct efi_hii_string_protocol efi_hii_string; uint16_t *efi_dp_str(struct efi_device_path *dp); +/* GUID for the auto generated boot menu entry */ +extern const efi_guid_t efi_guid_bootmenu_auto_generated; + /* GUID of the U-Boot root node */ extern const efi_guid_t efi_u_boot_guid; #ifdef CONFIG_SANDBOX @@ -314,6 +320,9 @@ extern const efi_guid_t efi_guid_firmware_management_protocol; extern const efi_guid_t efi_esrt_guid; /* GUID of the SMBIOS table */ extern const efi_guid_t smbios_guid; +/*GUID of console */ +extern const efi_guid_t efi_guid_text_input_protocol; +extern const efi_guid_t efi_guid_text_output_protocol; extern char __efi_runtime_start[], __efi_runtime_stop[]; extern char __efi_runtime_rel_start[], __efi_runtime_rel_stop[]; @@ -883,6 +892,8 @@ efi_status_t efi_set_load_options(efi_handle_t handle, void *load_options); efi_status_t efi_bootmgr_load(efi_handle_t *handle, void **load_options); +efi_status_t efi_bootmenu_show_maintenance_menu(void); + /** * struct efi_image_regions - A list of memory regions * @@ -1054,4 +1065,33 @@ efi_status_t efi_esrt_populate(void); efi_status_t efi_load_capsule_drivers(void); efi_status_t platform_get_eventlog(struct udevice *dev, u64 *addr, u32 *sz); + +efi_status_t efi_locate_handle_buffer_int(enum efi_locate_search_type search_type, + const efi_guid_t *protocol, void *search_key, + efi_uintn_t *no_handles, efi_handle_t **buffer); + +efi_status_t efi_open_volume_int(struct efi_simple_file_system_protocol *this, + struct efi_file_handle **root); +efi_status_t efi_file_open_int(struct efi_file_handle *this, + struct efi_file_handle **new_handle, + u16 *file_name, u64 open_mode, + u64 attributes); +efi_status_t efi_file_close_int(struct efi_file_handle *file); +efi_status_t efi_file_read_int(struct efi_file_handle *this, + efi_uintn_t *buffer_size, void *buffer); +efi_status_t efi_file_setpos_int(struct efi_file_handle *file, u64 pos); + +typedef efi_status_t (*efi_console_filter_func)(struct efi_input_key *key); +efi_status_t efi_console_get_u16_string + (struct efi_simple_text_input_protocol *cin, + struct efi_simple_text_output_protocol *cout, + u16 *buf, efi_uintn_t count, efi_console_filter_func filer_func, + int row, int col); + +efi_status_t efimenu_get_unused_bootoption(u16 *buf, + efi_uintn_t buf_size, u32 *index); +efi_status_t efimenu_append_bootorder(u16 index); + +efi_status_t efi_disk_get_device_name(struct efi_block_io *this, char *buf, int size); + #endif /* _EFI_LOADER_H */ diff --git a/include/efi_menu.h b/include/efi_menu.h new file mode 100644 index 0000000000..35d29cb509 --- /dev/null +++ b/include/efi_menu.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Menu-driven UEFI Variable maintenance + * + * Copyright (c) 2022 Masahisa Kojima, Linaro Limited + */ + +#ifndef _EFI_MENU_H +#define _EFI_MENU_H + +#define EFIMENU_ENTRY_NUM_MAX 99 +#define EFIMENU_FILE_PATH_MAX 512 +#define EFIMENU_FILE_PATH_BUF_SIZE (EFIMENU_FILE_PATH_MAX * sizeof(u16)) + +typedef efi_status_t (*efimenu_entry_func)(void *data); + +/** + * struct efimenu_entry - menu entry structure + * + * @num: menu entry index + * @title: title of entry + * @key: unique key + * @efi_menu: pointer to the menu structure + * @next: pointer to the next entry + * @func: callback function to be called when this entry is selected + * @data: data to be passed to the callback function + */ +struct efimenu_entry { + u32 num; + char *title; + char key[3]; + struct efimenu *efi_menu; + struct efimenu_entry *next; + efimenu_entry_func func; + void *data; +}; + +/** + * struct efimenu - efi menu structure + * + * @delay: delay for autoboot + * @active: active menu entry index + * @count: total count of menu entry + * @menu_header: menu header string + * @first: pointer to the first menu entry + */ +struct efimenu { + int delay; + int active; + int count; + char *menu_header; + struct efimenu_entry *first; +}; + +/** + * struct efimenu_item - structure to construct efimenu_entry + * + * @title: title of entry + * @func: callback function to be called when this entry is selected + * @data: data to be passed to the callback function + */ +struct efimenu_item { + char *title; + efimenu_entry_func func; + void *data; +}; + +/** + * struct efimenu_select_file_info - structure to be used for file selection + * + * @current_volume: pointer to the efi_simple_file_system_protocol + * @dp_volume: pointer to device path of the selected device + * @current_path: pointer to the selected file path string + * @file_selectred: flag indicates file selecting status + * @filepath_list: list_head structure for file path list + */ +struct efimenu_select_file_info { + struct efi_simple_file_system_protocol *current_volume; + struct efi_device_path *dp_volume; + u16 *current_path; + struct list_head filepath_list; + bool file_selected; +}; + +void efimenu_print_msg(char *msg); +efi_status_t efimenu_process_quit(void *data); +efi_status_t efimenu_process_common(const struct efimenu_item *items, int count, + char *menu_header); +efi_status_t efimenu_select_file_handler(void *data); + +#endif diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 4da64b5d29..1233418e77 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -2453,6 +2453,35 @@ static efi_status_t EFIAPI efi_protocols_per_handle( return EFI_EXIT(EFI_SUCCESS); } +efi_status_t efi_locate_handle_buffer_int(enum efi_locate_search_type search_type, + const efi_guid_t *protocol, void *search_key, + efi_uintn_t *no_handles, efi_handle_t **buffer) +{ + efi_status_t r; + efi_uintn_t buffer_size = 0; + + if (!no_handles || !buffer) { + r = EFI_INVALID_PARAMETER; + goto out; + } + *no_handles = 0; + *buffer = NULL; + r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, + *buffer); + if (r != EFI_BUFFER_TOO_SMALL) + goto out; + r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size, + (void **)buffer); + if (r != EFI_SUCCESS) + goto out; + r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, + *buffer); + if (r == EFI_SUCCESS) + *no_handles = buffer_size / sizeof(efi_handle_t); +out: + return r; +} + /** * efi_locate_handle_buffer() - locate handles implementing a protocol * @search_type: selection criterion @@ -2474,30 +2503,13 @@ efi_status_t EFIAPI efi_locate_handle_buffer( efi_uintn_t *no_handles, efi_handle_t **buffer) { efi_status_t r; - efi_uintn_t buffer_size = 0; EFI_ENTRY("%d, %pUs, %p, %p, %p", search_type, protocol, search_key, no_handles, buffer); - if (!no_handles || !buffer) { - r = EFI_INVALID_PARAMETER; - goto out; - } - *no_handles = 0; - *buffer = NULL; - r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, - *buffer); - if (r != EFI_BUFFER_TOO_SMALL) - goto out; - r = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, buffer_size, - (void **)buffer); - if (r != EFI_SUCCESS) - goto out; - r = efi_locate_handle(search_type, protocol, search_key, &buffer_size, - *buffer); - if (r == EFI_SUCCESS) - *no_handles = buffer_size / sizeof(efi_handle_t); -out: + r = efi_locate_handle_buffer_int(search_type, protocol, search_key, + no_handles, buffer); + return EFI_EXIT(r); } diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index 60a3fc85ac..ca8e38b8eb 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -5,6 +5,7 @@ * Copyright (c) 2016 Alexander Graf */ +#include #include #include #include @@ -1312,3 +1313,80 @@ out_of_memory: printf("ERROR: Out of memory\n"); return r; } + +/** + * efi_console_get_u16_string() - get user input string + * + * @cin: protocol interface to EFI_SIMPLE_TEXT_INPUT_PROTOCOL + * @cout: protocol interface to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL + * @buf: buffer to store user input string in UTF16 + * @count: number of u16 string including NULL terminator that buf has + * @filter_func: callback to filter user input + * @row: row number to locate user input form + * @col: column number to locate user input form + * Return: status code + */ +efi_status_t efi_console_get_u16_string(struct efi_simple_text_input_protocol *cin, + struct efi_simple_text_output_protocol *cout, + u16 *buf, efi_uintn_t count, + efi_console_filter_func filter_func, + int row, int col) +{ + efi_status_t ret; + efi_uintn_t len = 0; + struct efi_input_key key; + + printf(ANSI_CURSOR_POSITION, row, col); + puts(ANSI_CLEAR_LINE_TO_END); + puts(ANSI_CURSOR_SHOW); + + ret = EFI_CALL(cin->reset(cin, false)); + if (ret != EFI_SUCCESS) + return ret; + + for (;;) { + do { + ret = EFI_CALL(cin->read_key_stroke(cin, &key)); + mdelay(10); + } while (ret == EFI_NOT_READY); + + if (key.unicode_char == u'\b') { + if (len > 0) + buf[--len] = u'\0'; + + printf(ANSI_CURSOR_POSITION, row, col); + ret = EFI_CALL(cout->output_string(cout, buf)); + if (ret != EFI_SUCCESS) + return ret; + + puts(ANSI_CLEAR_LINE_TO_END); + continue; + } else if (key.unicode_char == u'\r') { + buf[len] = u'\0'; + return EFI_SUCCESS; + } else if (key.unicode_char == 0x3 || key.scan_code == 23) { + return EFI_ABORTED; + } else if (key.unicode_char < 0x20) { + /* ignore control codes other than Ctrl+C, '\r' and '\b' */ + continue; + } else if (key.scan_code != 0) { + /* only accept single ESC press for cancel */ + continue; + } + + if (filter_func) { + if (filter_func(&key) != EFI_SUCCESS) + continue; + } + + if (len >= (count - 1)) + continue; + + buf[len] = key.unicode_char; + len++; + printf(ANSI_CURSOR_POSITION, row, col); + ret = EFI_CALL(cout->output_string(cout, buf)); + if (ret != EFI_SUCCESS) + return ret; + } +} diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c index 1e82f52dc0..efc2f20ff0 100644 --- a/lib/efi_loader/efi_disk.c +++ b/lib/efi_loader/efi_disk.c @@ -778,3 +778,14 @@ efi_status_t efi_disk_init(void) return EFI_SUCCESS; } + +efi_status_t efi_disk_get_device_name(struct efi_block_io *this, char *buf, int size) +{ + struct efi_disk_obj *diskobj; + + diskobj = container_of(this, struct efi_disk_obj, ops); + + snprintf(buf, size, "%s %d:%d", diskobj->ifname, diskobj->dev_index, diskobj->part); + + return EFI_SUCCESS; +} diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 7a7077e6d0..c96a7f7ca3 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -246,10 +246,10 @@ error: return NULL; } -static efi_status_t efi_file_open_int(struct efi_file_handle *this, - struct efi_file_handle **new_handle, - u16 *file_name, u64 open_mode, - u64 attributes) +efi_status_t efi_file_open_int(struct efi_file_handle *this, + struct efi_file_handle **new_handle, + u16 *file_name, u64 open_mode, + u64 attributes) { struct file_handle *fh = to_fh(this); efi_status_t ret; @@ -369,11 +369,17 @@ static efi_status_t file_close(struct file_handle *fh) return EFI_SUCCESS; } -static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file) +efi_status_t efi_file_close_int(struct efi_file_handle *file) { struct file_handle *fh = to_fh(file); + + return file_close(fh); +} + +static efi_status_t EFIAPI efi_file_close(struct efi_file_handle *file) +{ EFI_ENTRY("%p", file); - return EFI_EXIT(file_close(fh)); + return EFI_EXIT(efi_file_close_int(file)); } static efi_status_t EFIAPI efi_file_delete(struct efi_file_handle *file) @@ -562,8 +568,8 @@ static efi_status_t dir_read(struct file_handle *fh, u64 *buffer_size, return EFI_SUCCESS; } -static efi_status_t efi_file_read_int(struct efi_file_handle *this, - efi_uintn_t *buffer_size, void *buffer) +efi_status_t efi_file_read_int(struct efi_file_handle *this, + efi_uintn_t *buffer_size, void *buffer) { struct file_handle *fh = to_fh(this); efi_status_t ret = EFI_SUCCESS; @@ -773,24 +779,11 @@ out: return EFI_EXIT(ret); } -/** - * efi_file_setpos() - set current position in file - * - * This function implements the SetPosition service of the EFI file protocol. - * See the UEFI spec for details. - * - * @file: file handle - * @pos: new file position - * Return: status code - */ -static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, - u64 pos) +efi_status_t efi_file_setpos_int(struct efi_file_handle *file, u64 pos) { struct file_handle *fh = to_fh(file); efi_status_t ret = EFI_SUCCESS; - EFI_ENTRY("%p, %llu", file, pos); - if (fh->isdir) { if (pos != 0) { ret = EFI_UNSUPPORTED; @@ -812,6 +805,28 @@ static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, fh->offset = pos; error: + return ret; +} + +/** + * efi_file_setpos() - set current position in file + * + * This function implements the SetPosition service of the EFI file protocol. + * See the UEFI spec for details. + * + * @file: file handle + * @pos: new file position + * Return: status code + */ +static efi_status_t EFIAPI efi_file_setpos(struct efi_file_handle *file, + u64 pos) +{ + efi_status_t ret = EFI_SUCCESS; + + EFI_ENTRY("%p, %llu", file, pos); + + ret = efi_file_setpos_int(file, pos); + return EFI_EXIT(ret); } @@ -1138,17 +1153,23 @@ struct efi_file_handle *efi_file_from_path(struct efi_device_path *fp) return f; } +efi_status_t efi_open_volume_int(struct efi_simple_file_system_protocol *this, + struct efi_file_handle **root) +{ + struct file_system *fs = to_fs(this); + + *root = file_open(fs, NULL, NULL, 0, 0); + + return EFI_SUCCESS; +} + static efi_status_t EFIAPI efi_open_volume(struct efi_simple_file_system_protocol *this, struct efi_file_handle **root) { - struct file_system *fs = to_fs(this); - EFI_ENTRY("%p, %p", this, root); - *root = file_open(fs, NULL, NULL, 0, 0); - - return EFI_EXIT(EFI_SUCCESS); + return EFI_EXIT(efi_open_volume_int(this, root)); } struct efi_simple_file_system_protocol * From patchwork Mon Jun 13 09:38:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581412 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1797850max; Mon, 13 Jun 2022 02:38:49 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy1Ry1Kh0wn2D720f5S0Pu48qlM9iAcc3qDj03Zii25y3onPikOO8itNMjxrebcl/bD+4w9 X-Received: by 2002:a05:6638:13cc:b0:331:7c5e:6124 with SMTP id i12-20020a05663813cc00b003317c5e6124mr25440253jaj.83.1655113129795; Mon, 13 Jun 2022 02:38:49 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113129; cv=none; d=google.com; s=arc-20160816; b=dFCvXqd8FxxL16E7cwFMiGfqz5k4IwxNl4ZCwOa/owgFsvfttZknRPInX+6eUMdxRv jcSs2gOwX7fFoWEdIVoZs1IP4xJWgLbhATMDA66JQMQvPpkqwwKkkCALkJrit2QclDN/ FzI1bTYBX3xEIJt0UAUisBqMRMBk+1sPeFykHGuxeUtKk0FXkaUt4IsEIn9EHu6ri5Hu xRguNp0NfanpIX3XFN0Hrprg6wmjcdHdxC5RcGR4AFuFFkBIW0PO1IKX+ueCzdxjs4bC dayq0r7C082DpD/vSF7AO38LL1h5iNKFNiuxSTt1MhDSckdCuaV0ht5nh1t5Zxbm6SnW sefA== 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=IykigmOgQXbpm1uZ4F94KFNVdQgAZf3SDno6DR/ENqI=; b=CD5+OTh9hcLnUE1+votmCD1c5uEVYkdRUmlJngn7/4a2k8wq/HSvefPODxHAtdHKkB GhLxM9tlUCyauefdJSMHZqHhqfaBMkm1nIcjDH/rH8bWGWk4jYG0hfrOAKldPyMeXtr0 YhXvZGCBCbBTfJruBJMufsMdTRFg2WedWT0iBIShZntS88Io4UBOkaVwDqIAtR5+301W farVjvVY/NvyWYb5XD1o4aefWMjPo3EMoXPF6hj/zC6IMfkl+TeeT1jK2iqjIiqMn5GD CQTPPUgNJvuTf7BnOKmKwvvT33TIcAwmLtZ5AItCAOGOMgGeDb9E8yVzk46xiWCjwPJG DLsg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=cdQIPEtI; 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 k25-20020a6b6f19000000b00665e06dd40esi7519100ioc.96.2022.06.13.02.38.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:49 -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=cdQIPEtI; 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 2DC1784447; Mon, 13 Jun 2022 11:38:33 +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="cdQIPEtI"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 8F68784442; Mon, 13 Jun 2022 11:38:30 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x102d.google.com (mail-pj1-x102d.google.com [IPv6:2607:f8b0:4864:20::102d]) (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 895C284439 for ; Mon, 13 Jun 2022 11:38:26 +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-pj1-x102d.google.com with SMTP id o6-20020a17090a0a0600b001e2c6566046so8335999pjo.0 for ; Mon, 13 Jun 2022 02:38:26 -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=IykigmOgQXbpm1uZ4F94KFNVdQgAZf3SDno6DR/ENqI=; b=cdQIPEtIZ7d36dKyyCsDzCuYnqWD1pS026+aolTErnqW/fMEV+UcJFPyL+VBEckxuv ciWxRHJnqUoCzK66D5ocfIsemgdS/WC7GXcGi+kCWw+C5mvOZWjpOzsC3NwICRcrAetB 3zdX29G14qn5jyTXX1LgMMcksFPeyF6olM6PA/Cf7e3ZKTwfgw/W1lzOU7Baffdudhnf BCA+CaKkr1nMp5CJLbSk0iPuyKaHJ9zt3m4Uipv3WFYkYeuBL+K9GSos3DHrtPUbykzE VEtDR6mpsxY2WRSgWlSKP/R+1/N/6PwVL5L45baofdWnUsLlkAMKgs1H/yL1ZEfsMAaO cdkQ== 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=IykigmOgQXbpm1uZ4F94KFNVdQgAZf3SDno6DR/ENqI=; b=CMpp4ZJE94H6aTOkROYixursa7bml8zalSpw+zavTO9MaolzLI6VBmMZNTdlVolDig DnVLPcEWVbb6P8fKoqkdc1+UL102u8CgAO2Yd+3/ngNqXkrrgT57gcj1tPcJaVJBbH0+ mWnxliDuFy9HJAF4CwhBXaF7mCOWRIL4oxgxQCcg5sE5dOa6+/qUs7DmfAZ1Fk6Mp+Mu rym2a/+sGrfzir5gDHV6F420kYgK2QXuuJQmzNRrooc6vECNNl/uA7n2wwTjw7u1BKA3 /5ujM+3lbooOd7ULWrg8DvQPf4lrBPN5aG2UntnNx84E7KstokzWZqT4Nv55SM/JilTJ hWQw== X-Gm-Message-State: AOAM531eyV0ZiS/RELOYTIR2t0M0bRZab1S0qxny3ucBUX/2rcPtznUn LdV/UI3gTbtRSLleMmgByh67TNmG59Si1Q== X-Received: by 2002:a17:903:32c4:b0:167:6e6f:204b with SMTP id i4-20020a17090332c400b001676e6f204bmr43480245plr.117.1655113104708; Mon, 13 Jun 2022 02:38:24 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:24 -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 v7 3/9] efimenu: add "Edit Boot Option" menu entry Date: Mon, 13 Jun 2022 18:38:47 +0900 Message-Id: <20220613093853.23865-4-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 menu entry to edit the existing BOOT#### variable contents. User selects the item from the boot option list, then user can edit the description, file path and optional_data. Note that automatically generated boot option entry by bootmenu to suppport the removable media device is filtered out and user can not edit the automatically generated entry. Signed-off-by: Masahisa Kojima --- Newly created in v7 cmd/efimenu.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) diff --git a/cmd/efimenu.c b/cmd/efimenu.c index fce08900db..918e9dffa2 100644 --- a/cmd/efimenu.c +++ b/cmd/efimenu.c @@ -1190,6 +1190,175 @@ out: return ret; } +static efi_status_t efimenu_process_boot_selected(void *data) +{ + struct efimenu_boot_selection_data *info = data; + + if (info) + *info->selected = info->bootorder_index; + + return EFI_SUCCESS; +} + +static efi_status_t efimenu_show_boot_selection(u16 *bootorder, efi_uintn_t count, + int *selected) +{ + u32 i; + efi_status_t ret; + efi_uintn_t size, actual_count = 0; + void *load_option; + struct efi_load_option lo; + u16 varname[] = u"Boot####"; + struct efimenu_item *menu_item, *iter; + + menu_item = calloc(count + 1, sizeof(struct efimenu_item)); + if (!menu_item) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + iter = menu_item; + for (i = 0; i < count; i++) { + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[i]); + 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); + continue; + } + + if (size >= sizeof(efi_guid_t) && + !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) { + /* + * auto generated entry has GUID in optional_data, + * skip auto generated entry because it will be generated + * again even if it is edited or deleted. + */ + free(load_option); + continue; + } + + if (lo.attributes & LOAD_OPTION_ACTIVE) { + char *buf, *p; + struct efimenu_boot_selection_data *info; + + info = calloc(1, sizeof(struct efimenu_boot_selection_data)); + if (!info) { + free(load_option); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + buf = calloc(1, utf16_utf8_strlen(lo.label) + 1); + if (!buf) { + free(load_option); + free(info); + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + p = buf; + utf16_utf8_strcpy(&p, lo.label); + info->bootorder_index = i; + info->selected = selected; + iter->title = buf; + iter->func = efimenu_process_boot_selected; + iter->data = info; + iter++; + actual_count++; + } + free(load_option); + } + + /* add "Quit" entry */ + iter->title = strdup("Quit"); + iter->func = efimenu_process_quit; + iter->data = NULL; + actual_count += 1; + + ret = efimenu_process_common(menu_item, actual_count, " ** Select Boot Order **"); + +out: + iter = menu_item; + for (i = 0; i < actual_count; i++, iter++) { + free(iter->title); + free(iter->data); + } + + free(menu_item); + + return ret; +} + +static efi_status_t efimenu_process_edit_boot_option(void *data) +{ + u16 *bootorder; + efi_status_t ret; + efi_uintn_t num, size; + struct efimenu_boot_option *bo = NULL; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) { + ret = EFI_NOT_FOUND; + return ret; + } + + num = size / sizeof(u16); + while (1) { + int selected; + void *load_option; + struct efi_load_option lo; + u16 varname[] = u"Boot####"; + + ret = efimenu_show_boot_selection(bootorder, num, &selected); + if (ret != EFI_SUCCESS) + break; + + bo = calloc(1, sizeof(struct efimenu_boot_option)); + if (!bo) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + bo->boot_index = selected; + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[selected]); + load_option = efi_get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) { + free(bo); + ret = EFI_NOT_FOUND; + goto out; + } + + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) { + free(bo); + free(load_option); + goto out; + } + + ret = efimenu_edit_boot_option(varname, bo, lo.label, lo.optional_data, + size, lo.file_path); + + free(load_option); + free(bo); + if (ret != EFI_SUCCESS && ret != EFI_ABORTED) + break; + } + +out: + free(bootorder); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + static efi_status_t efimenu_init(void) { efi_status_t ret; @@ -1223,6 +1392,7 @@ static efi_status_t efimenu_init(void) static const struct efimenu_item maintenance_menu_items[] = { {"Add Boot Option", efimenu_process_add_boot_option}, + {"Edit Boot Option", efimenu_process_edit_boot_option}, {"Quit", efimenu_process_quit}, }; From patchwork Mon Jun 13 09:38:48 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581413 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1797941max; Mon, 13 Jun 2022 02:39:03 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwHywaH0wjbNdjSyaBN5f2FFSCI2GGsBp8sn/jlTGCqsXxgYlFV3JeSwPcCvgSfehvPO6vS X-Received: by 2002:a92:c6d2:0:b0:2d7:9848:232f with SMTP id v18-20020a92c6d2000000b002d79848232fmr5306463ilm.93.1655113143432; Mon, 13 Jun 2022 02:39:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113143; cv=none; d=google.com; s=arc-20160816; b=sSdQYJ5+sG1TjqUiOOzy0J9hEawaoGhRoy0vSStc/jfXPYxRpvOKsKxAZihLhu0bKd i0iD9jlMbAGbkQWzqWmBjM1FDqc/EKgjoHf2NWmv7VCOOSeIZJjkV6dUgQ1pneiEzFze 8wvYaOrBfVM6vKHhYB3iVDmPKpz3GSA6qTU1c8S7vMeE060YklbNT/adSZanf+i4cdl5 sMiWpjS620cnh7G1yPbr0bEGGgSb87J18cuyGdB/DDJJBUzU49g+Sas7V1ZV1W1dx9qG TDlxfQ18rgjOgk1AvnyuR575SBDWxq0wJLCIAGpuF8oNmRwNim9uknDvI98YH87jetyf pzfw== 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=lCT5fFxp+Oc7GgXT1+Rsu1/IAKOKVEKIidJZFtei3KE=; b=HQmz6urJQfPOE8XVz5hBbY04BJSuNQR0KaIALBQuuwGMOWjuoPGRkRGpSLZK7CZx/P opRLvylwVDqjlElQYpYyMDJeua50gM5BWx8Ue/KClQW38y5w9jYc8bAw1ORHT8BLJl0c mtXd3n9dbxxj/+n5icUKhJzPPsQ5LCAFz5S7XplfF2TJ1icZ0ZXGzeRbkkIyaZlNQpfY Euo/aVF5haB/8ua/7K9aGZaWJgE1D+x5FHz3VxD0fghrJHAWRQWTFQCXR+Z80ooSthLT klfDOs/rUDitIfxcuTwFbn2zf1xhuA3p9P0XdbJ3NxYEgfemSTAgrSXNYE/HJMfsWqAt aUqg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=hwstSP0u; 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 u21-20020a022e55000000b003241174840csi6045557jae.111.2022.06.13.02.39.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:39:03 -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=hwstSP0u; 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 E023284433; Mon, 13 Jun 2022 11:38:36 +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="hwstSP0u"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2F68E84441; Mon, 13 Jun 2022 11:38:34 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) (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 89CBD8443F for ; Mon, 13 Jun 2022 11:38:29 +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-pj1-x102a.google.com with SMTP id k5-20020a17090a404500b001e8875e6242so5384110pjg.5 for ; Mon, 13 Jun 2022 02:38:29 -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=lCT5fFxp+Oc7GgXT1+Rsu1/IAKOKVEKIidJZFtei3KE=; b=hwstSP0u1Sp6hodXgSakH7sQ8FpWLdN5sQ5fP2KHxyFOvdVBGJY0b4NSfEyaJ2nWhj nBZpdpVL4GsflRNDdFW4ky7NdYIxdT9PvH83xQv99cTZEHctd+O+irWPjNA52WiT2ubP PsS8feiFk5Nnfbg4WTu3fGvj/BD0hOQpxmnRXKaa8Ivn0REN4dH/oMvmoQFQIqQ35SHS 6CPs3UYW/eO0/vh7pnO4nZYUDwxQ+UAbnh0GB2kDsZwfkJVA/5sj1y0F1Hpo72qe+N7R i5ArO2xaITvr3lplThqPFEgL1CzmqyoGySXf54nP6yvS1NmNZvwFynnjQhqP/IswN2Es iU7Q== 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=lCT5fFxp+Oc7GgXT1+Rsu1/IAKOKVEKIidJZFtei3KE=; b=Sc6rAdjln6H+6HolBbkWhNOc/MrkwHqhDpyrKTLP1DMFF1El8eZEDmmR1/HwkZnvMp bpv0f3uXzol9+QzkgIOsMvifFvrei1XshTzsIBS62epuOsBmeAY4FbJFWLA7nXTEpWGF w3UPJE1F7CJhNcEUFuGtSTO2X/1ier3YMRS3jFUBD8mCDjuh6YGD359ta7c749pMfB/D ocJE7a1ZfIMcMUn4EKYyOc1C01AAD+zIgDigF0QQ0agSH2xThx69BjNU7jN/GX+dR+Cb hu0Ra7BVHgFWD0tMWfHMEpg8ZHcfZFTnIaFOc4z6ixJ1XBOHK/k+26gK4LmxPs+6cnv+ BGTQ== X-Gm-Message-State: AOAM530MdX+G7uSkKVv/c0/lV/+e+NxND/S8BCQBMhMXgCBymluGjXGU o/ylf4K2jRFni/wvte3/jQBNrNAr/CfPiw== X-Received: by 2002:a17:903:11cc:b0:168:eae:da4a with SMTP id q12-20020a17090311cc00b001680eaeda4amr29520270plh.21.1655113107521; Mon, 13 Jun 2022 02:38:27 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:27 -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 v7 4/9] menu: add KEY_PLUS and KEY_MINUS handling Date: Mon, 13 Jun 2022 18:38:48 +0900 Message-Id: <20220613093853.23865-5-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 is preparation to support menu-driven UEFI BootOrder variable updated by KEY_PLUS and KEY_MINUS. Signed-off-by: Masahisa Kojima --- Newly created in v7 common/menu.c | 6 ++++++ include/menu.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/common/menu.c b/common/menu.c index 3e876b55b3..3470f95a98 100644 --- a/common/menu.c +++ b/common/menu.c @@ -548,4 +548,10 @@ void bootmenu_loop(struct bootmenu_data *menu, /* ^C was pressed */ if (c == 0x3) *key = KEY_QUIT; + + if (c == '+') + *key = KEY_PLUS; + + if (c == '-') + *key = KEY_MINUS; } diff --git a/include/menu.h b/include/menu.h index e74616cae8..4c32e74ce9 100644 --- a/include/menu.h +++ b/include/menu.h @@ -48,6 +48,8 @@ enum bootmenu_key { KEY_DOWN, KEY_SELECT, KEY_QUIT, + KEY_PLUS, + KEY_MINUS, }; void bootmenu_autoboot_loop(struct bootmenu_data *menu, From patchwork Mon Jun 13 09:38:49 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581415 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798236max; Mon, 13 Jun 2022 02:39:31 -0700 (PDT) X-Google-Smtp-Source: ABdhPJx+S4cyejI92TudHloCK7EtSmM2ga1spkYrfuPHdDxe3/A/MlVgL0PQF4jRh8PgqhH6npT1 X-Received: by 2002:a05:6638:328a:b0:333:f1fe:79bc with SMTP id f10-20020a056638328a00b00333f1fe79bcmr2069161jav.170.1655113171734; Mon, 13 Jun 2022 02:39:31 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113171; cv=none; d=google.com; s=arc-20160816; b=tZ2aq4K4hj+5PfDROxvOlogDT2yC42HUQKZOjGGDJDNYWzydtYc0fZG4X8VkqEDL1s kkr4pMcP6o85+wQXB8tbLPwTQlLz1EFXWPbRiUjHYBlvoiTQeW0ARZOtvMrf4ThzyPsb ULN2oAxbjL8G0cN80vjzVQgK70dC+yhJFIw9/lu6Nhn/cqTRb0Rt+Wa1vO/QPvObIq6S 4/34Qe7wwFH9LvQeiXnxiXQjjSVDH7xXZFV7+fl7SllMmZ9wDa95tZE2za3Tq1nn1G/+ S23LpiuqFCGMTZcVfukQr1If56n3T8R4eANtwaX4fachNFoY6Z7eHQLJNGS9owNNCodm UqeQ== 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=ipqYrDgdo+rU6I5+nXrw9+NuktsvngSgJ2DIkqyEAr0=; b=DuLz5d25XLjBfMf8TVQPhtwU8a1bny+MWiCC996rHLnPmcnVqpuu3iFz6LnlCGDxai azJItvIjCPBX97rzZUyeKqMae1+8nS4ubpiQyKSftopJpYgVIePQhRcP2112wkL08nD+ PfP5yavS1pC21tvJ08XqGYoTiSTvZy7dLGGhKbiPrlmAmc39luCMcTfiJa/Dg1Q8k5co rz3h7uBo5T8h4nfoFreIo2KflSfE1xbRoxm1BkCNax8D7QgIo/YCukFzGmj8i+pVkCY6 POiSSW30FVZFt5TVb6/pwQWkPplJRlgAUC4lOf8Lhy98IO7ue00fvI3cGijAhkNOA+WV LTXA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=N6pmFh89; 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 10-20020a056e0216ca00b002cde0eaf204si8798700ilx.15.2022.06.13.02.39.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:39:31 -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=N6pmFh89; 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 3018284455; Mon, 13 Jun 2022 11:38:42 +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="N6pmFh89"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3327984434; Mon, 13 Jun 2022 11:38:37 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pf1-x42d.google.com (mail-pf1-x42d.google.com [IPv6:2607:f8b0: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 7E01C84442 for ; Mon, 13 Jun 2022 11:38:32 +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-pf1-x42d.google.com with SMTP id 187so5250181pfu.9 for ; Mon, 13 Jun 2022 02:38:32 -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=ipqYrDgdo+rU6I5+nXrw9+NuktsvngSgJ2DIkqyEAr0=; b=N6pmFh89V1sF3KjHxfatVKvUjrCNs/ZE97Rw0BdBSVQo35EuV4VuqKcyoJ+SplmbXj RBxtbI2+pIQhxQo74UvWWFboTAP7aSJH+6x/vuOV3qQ6I/Axw6Iq9tB1rL1d/sASMLff mvhYG1m0wfNcnLdSKWv5xfQ6PJx7oxDJpi+9n/kFBO/7vwrz8W4RK0UKSa6DzpxQxl5K l/RVNff9zEHVOXBX1GXlHqPHTfA7AxRYXxexSj9OGHMt970zNC3pvtoo47CpRUle1gRs HcEavXvG0TdAvlLnGlkjodBEf14Fbq5SiZ6RLRFlWvtOPgngc0lNVmnh1vgP/0O8SRhH tDWA== 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=ipqYrDgdo+rU6I5+nXrw9+NuktsvngSgJ2DIkqyEAr0=; b=HjcjvIxGuefGUI2zGWV84DTGHpkdOmUh871k0nYuqiqxOTgsnTzOOxhUF9ZbK2EZJB 0JXTeP89E8ZTp8yUBaUA1CRbcxNEGLyl7vFVffd9swULsE/swPeIsoOMB5oLyQH3v5bX 296D3IDxbY3fNx/g289QNTme1lmrMzt7pf1lu2wRBZ/ZAQkRY7Lvr+TJrOsD9RnCOt4E IuZDIKFcsUcl2DvsIVbuaXnLMphEixzBSC4RyivlCK/E2t9ceIrmRgTnHWCh4tN5PnxJ LayajuYdJCcncQ3etlhwQR9WE//iTzGQ10v25S0iTTt0meqxFX5zun/2AFBpfx4HbRUU GEgA== X-Gm-Message-State: AOAM530FTWeosVoZrPt0K43W45wTBjo5tFh1LpVAPDBGYe6XFdmLB47g fb8ftDKen1FQgTwOW+GC9M0w6geDH4YSiA== X-Received: by 2002:a62:7cd2:0:b0:51b:9ba6:a028 with SMTP id x201-20020a627cd2000000b0051b9ba6a028mr65986838pfc.24.1655113110643; Mon, 13 Jun 2022 02:38:30 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:30 -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 v7 5/9] efimenu: add "Change Boot Order" menu entry Date: Mon, 13 Jun 2022 18:38:49 +0900 Message-Id: <20220613093853.23865-6-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 menu entry to update UEFI BootOrder variable. User moves the entry with UP/DOWN key, changes the order with PLUS/MINUS key, then finalizes the order by ENTER key. The U-Boot menu framework is well designed for static menu, this commit implements the own menu display and key handling for dynamically change the order of menu entry. Signed-off-by: Masahisa Kojima --- Changes in v7: - use UP/DOWN and PLUS/MINUS key to change to order no update in v6: cmd/efimenu.c | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/cmd/efimenu.c b/cmd/efimenu.c index 918e9dffa2..1be483a082 100644 --- a/cmd/efimenu.c +++ b/cmd/efimenu.c @@ -70,6 +70,13 @@ struct efimenu_file_entry_data { u16 *file_name; }; +struct efimenu_boot_order { + u32 num; + u16 *description; + u32 prev_index; + struct list_head list; +}; + /** * efimenu_print_msg() - print message * @@ -1359,6 +1366,205 @@ out: return ret; } +static void efimenu_display_change_boot_order(struct list_head *bo_list, + struct efimenu *efi_menu) +{ + bool reverse; + struct list_head *pos, *n; + struct efimenu_boot_order *entry; + + printf(ANSI_CLEAR_CONSOLE + ANSI_CURSOR_POSITION + "\n ** Change Boot Order **\n" + ANSI_CURSOR_POSITION + "\n" + " Press UP/DOWN to move, +/- to change order\n ENTER to complete, ESC/CTRL+C to quit" + ANSI_CURSOR_POSITION, + 0, 1, efi_menu->count + 5, 1, 4, 1); + + /* draw boot order list */ + list_for_each_safe(pos, n, bo_list) { + entry = list_entry(pos, struct efimenu_boot_order, list); + reverse = (entry->num == efi_menu->active); + puts(" "); + if (reverse) + puts(ANSI_COLOR_REVERSE); + + printf("%ls\n", entry->description); + + if (reverse) + puts(ANSI_COLOR_RESET); + } +} + +static efi_status_t efimenu_choice_change_boot_order(struct list_head *bo_list, + struct efimenu *efi_menu) +{ + int esc = 0; + struct list_head *pos, *n; + struct efimenu_boot_order *tmp; + enum bootmenu_key key = KEY_NONE; + struct efimenu_boot_order *entry; + + while (1) { + bootmenu_loop(NULL, &key, &esc); + + switch (key) { + case KEY_PLUS: + if (efi_menu->active > 0) { + list_for_each_safe(pos, n, bo_list) { + entry = list_entry(pos, struct efimenu_boot_order, list); + if (entry->num == efi_menu->active) + break; + } + tmp = list_entry(pos->prev, struct efimenu_boot_order, list); + entry->num--; + tmp->num++; + list_del(&tmp->list); + list_add(&tmp->list, &entry->list); + } + fallthrough; + case KEY_UP: + if (efi_menu->active > 0) + --efi_menu->active; + return EFI_NOT_READY; + case KEY_MINUS: + if (efi_menu->active < efi_menu->count - 1) { + list_for_each_safe(pos, n, bo_list) { + entry = list_entry(pos, struct efimenu_boot_order, list); + if (entry->num == efi_menu->active) + break; + } + tmp = list_entry(pos->next, struct efimenu_boot_order, list); + entry->num++; + tmp->num--; + list_del(&entry->list); + list_add(&entry->list, &tmp->list); + } + fallthrough; + case KEY_DOWN: + if (efi_menu->active < efi_menu->count - 1) + ++efi_menu->active; + return EFI_NOT_READY; + case KEY_SELECT: + return EFI_SUCCESS; + case KEY_QUIT: + return EFI_ABORTED; + default: + break; + } + } +} + +static efi_status_t efimenu_process_change_boot_order(void *data) +{ + u32 i; + u16 *bootorder; + efi_status_t ret; + efi_uintn_t num, size; + struct list_head bo_list; + struct list_head *pos, *n; + struct efimenu_boot_order *entry; + struct efimenu efi_menu; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) { + ret = EFI_NOT_FOUND; + return ret; + } + + INIT_LIST_HEAD(&bo_list); + + num = size / sizeof(u16); + for (i = 0; i < num; i++) { + void *load_option; + struct efi_load_option lo; + u16 varname[] = u"Boot####"; + + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[i]); + load_option = efi_get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) { + ret = EFI_NOT_FOUND; + goto out; + } + + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) { + free(load_option); + goto out; + } + + entry = calloc(1, sizeof(struct efimenu_boot_order)); + if (!entry) { + free(load_option); + goto out; + } + entry->num = i; + entry->description = u16_strdup(lo.label); + entry->prev_index = i; + list_add_tail(&entry->list, &bo_list); + + free(load_option); + } + + efi_menu.delay = -1; + efi_menu.active = 0; + efi_menu.count = num; + + while (1) { + efimenu_display_change_boot_order(&bo_list, &efi_menu); + + ret = efimenu_choice_change_boot_order(&bo_list, &efi_menu); + if (ret == EFI_SUCCESS) { + u32 i = 0; + u16 *new_bootorder; + + /* update the BootOrder variable */ + size = num * sizeof(u16); + new_bootorder = calloc(1, size); + if (!new_bootorder) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + list_for_each_safe(pos, n, &bo_list) { + entry = list_entry(pos, struct efimenu_boot_order, list); + new_bootorder[i] = bootorder[entry->prev_index]; + i++; + } + + ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, new_bootorder, false); + + free(new_bootorder); + goto out; + } else if (ret == EFI_NOT_READY) { + continue; + } else { + goto out; + } + } + +out: + list_for_each_safe(pos, n, &bo_list) { + entry = list_entry(pos, struct efimenu_boot_order, list); + list_del(&entry->list); + free(entry->description); + free(entry); + } + + free(bootorder); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + static efi_status_t efimenu_init(void) { efi_status_t ret; @@ -1393,6 +1599,7 @@ static efi_status_t efimenu_init(void) static const struct efimenu_item maintenance_menu_items[] = { {"Add Boot Option", efimenu_process_add_boot_option}, {"Edit Boot Option", efimenu_process_edit_boot_option}, + {"Change Boot Order", efimenu_process_change_boot_order}, {"Quit", efimenu_process_quit}, }; From patchwork Mon Jun 13 09:38:50 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581416 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798357max; Mon, 13 Jun 2022 02:39:45 -0700 (PDT) X-Google-Smtp-Source: ABdhPJy/0Jt32olLbFPB8vabvY+6TxqHM1T1Qfxda+9kY8urAZI5UYy90pup3ucNdn+amQA8mmLi X-Received: by 2002:a05:6602:26d1:b0:669:734a:4c8a with SMTP id g17-20020a05660226d100b00669734a4c8amr16044843ioo.209.1655113185792; Mon, 13 Jun 2022 02:39:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113185; cv=none; d=google.com; s=arc-20160816; b=BjnXDPMZ6c99KHCgPUH+lHehAo+af4fQ7Gwxz+/jRCgVygnx0Y3BCngR7ey4PE6+hr RQgwHlXGK54W/pTJGDEe8XN2a289ThJoF7h+AxFuBNKDG39OWr2kIvVdLdX8kSfFmEaI GRxqRqNWvGimHWsbO4HqQJKPZx4asNfnuQhohYIS2YT5augR0DTUhi0PLO6Gyogo2he7 3XzBghKEnd4Ilvx9zHfP3f3WpCy/VJI2jgqLBCyHM5a61DbsRvrEc6gRVaBGdWr2nAZa u/rCTxU7kDXtsbD6XNnfWv1Kh1o9IJ3hTFt9xbJiaTWgkb2V+U5s6qRdzUvTWZjT/VWL lLow== 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=wzS9GCSvOtEaOWH68WUJ5XdcnFyLi3UNyKkWlC/jMmA=; b=TWcLVLPvYtje7Wt4LTpvSAtQ90PxY7K16+ElKMI2YFciDgovBtu+c6Z7GMHRNf3D0Q 5uH5lyc+gxmSrcs15YcWW2jF6/92uSDnZGpwGjlNAtZNZIac4RMQBgqoQn1UxS7esf0c 6baDNOb+hf6vx/AOgyq0/NxbPpy1n0P+BHWZUt4wgbSZEbSjaniQvUyU3l+fNl5qpem9 h9+DNH298wUVQDFxaXxmZDIIHjeaEvbbKDzk6DPT1ZguVhyISP4UMSVzmWiTKpbTVehj /iTjydJbwwcmfAgmIBuorUoXAfjZDtXvDkJf3pWl6TCdr6X7cmhvrODldr/Shv+9a1XG jBRQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=fgb9rZIn; 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 h5-20020a92c265000000b002d3da8d76cfsi8834202ild.156.2022.06.13.02.39.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:39:45 -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=fgb9rZIn; 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 8AD518444C; Mon, 13 Jun 2022 11:38:44 +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="fgb9rZIn"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AF5178443E; Mon, 13 Jun 2022 11:38:38 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1032.google.com (mail-pj1-x1032.google.com [IPv6:2607:f8b0:4864:20::1032]) (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 D969A84411 for ; Mon, 13 Jun 2022 11:38:35 +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-pj1-x1032.google.com with SMTP id k12-20020a17090a404c00b001eaabc1fe5dso2431386pjg.1 for ; Mon, 13 Jun 2022 02:38:35 -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=wzS9GCSvOtEaOWH68WUJ5XdcnFyLi3UNyKkWlC/jMmA=; b=fgb9rZInOSUYG5jvGnxsOUiX2sEbeTOh0FRNj+u8JMQVViQ8K7hD1RcZDfEqLz5vSx d/R4sgzHYGwvpihdVcpo/JUZm9f5vKdYx8/Y/i+xXRAt1SNgcQrPqvbMZAwQ8K55TyhX ooWKVVuZFLEw8GpatDTPZWGckDtfZfsQhVvjpYZZH5EyomzQLDbCvwh9l9SKgnZJvMAk ATrEJhF2sA+fRpp9ZkB5x3RAJAsjbMFfiuUwB1QE2pAu8YEB/euWL5mv6wQ4HCWxmhd/ 5rjlNDtXKRI5ZS3GfMcxnT3CGJw34GVgtqWYRaBBhjHTOmwy4npswnOR27uWKGUL0AvJ i2lA== 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=wzS9GCSvOtEaOWH68WUJ5XdcnFyLi3UNyKkWlC/jMmA=; b=tEQ9KMFVkY1gOvEttyudTJs+xp7PoqW5zkV1moSfvd97O7XepWNvJmTuct1yTT8MwR PuPRYE2b3TmBd8EYUSBDDrSVPvMKdtZxbm9aiaktkeSEl6ylaSHftxlDl/KtKeH9MJvw V+J0Ij7ZDixWCJH3cVTLk0eLwgkGjOkVJsPXpLC2yImbqeb/edS8eyAnvXnWO3Iawju5 wmyAULo3DEmqnaV2xTAE7O/rBN6uocjZalXzWBVXDK7VULu06+OJCqgvOgC7dfadvsXx r7IIL8c/9WSis1pTLDQAZ1feuKSu608G0g8C+Gy9tGWwXcBR5usHBQjjFifJixb9/81A n5uQ== X-Gm-Message-State: AOAM533FA+FptKckYJMCRsp+qD8PrTbk1TVNMjd3u8e3l/eJrdh0PgiD UyTY8pMK8hu6/wgo67/AtLiHL/62znry+Q== X-Received: by 2002:a17:902:bd05:b0:15f:19a0:95ed with SMTP id p5-20020a170902bd0500b0015f19a095edmr57540878pls.31.1655113113837; Mon, 13 Jun 2022 02:38:33 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:33 -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 v7 6/9] efimenu: add "Delete Boot Option" menu entry Date: Mon, 13 Jun 2022 18:38:50 +0900 Message-Id: <20220613093853.23865-7-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 menu entry to delete the UEFI boot option. User moves the entry with UP/DOWN key, changes, then presses ENTER key to delete the selected boot option. Signed-off-by: Masahisa Kojima --- Changes in v7: - to stay the boot order list after user delete the entry no update in v6: changes in v5: - split into the separate patch cmd/efimenu.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/cmd/efimenu.c b/cmd/efimenu.c index 1be483a082..1c97f265ca 100644 --- a/cmd/efimenu.c +++ b/cmd/efimenu.c @@ -1565,6 +1565,66 @@ out: return ret; } +static efi_status_t delete_boot_option(u16 *bootorder, u16 index, efi_uintn_t size) +{ + u16 varname[9]; + efi_status_t ret; + efi_uintn_t num; + + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[index]); + ret = efi_set_variable_int(varname, &efi_global_variable_guid, + 0, 0, NULL, false); + if (ret != EFI_SUCCESS) { + log_err("delete boot option(%ls) failed\n", varname); + return ret; + } + + /* update BootOrder */ + num = size / sizeof(u16); + memmove(&bootorder[index], &bootorder[index + 1], + (num - index - 1) * sizeof(u16)); + size -= sizeof(u16); + ret = efi_set_variable_int(u"BootOrder", &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + size, bootorder, false); + + return ret; +} + +static efi_status_t efimenu_process_delete_boot_option(void *data) +{ + int selected; + u16 *bootorder; + efi_status_t ret; + efi_uintn_t num, size; + + while (1) { + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) { + ret = EFI_NOT_FOUND; + return ret; + } + + num = size / sizeof(u16); + ret = efimenu_show_boot_selection(bootorder, num, &selected); + if (ret == EFI_SUCCESS) + ret = delete_boot_option(bootorder, selected, size); + + if (ret != EFI_SUCCESS) + break; + } + + free(bootorder); + + /* to stay the parent menu */ + ret = (ret == EFI_ABORTED) ? EFI_NOT_READY : ret; + + return ret; +} + static efi_status_t efimenu_init(void) { efi_status_t ret; @@ -1600,6 +1660,7 @@ static const struct efimenu_item maintenance_menu_items[] = { {"Add Boot Option", efimenu_process_add_boot_option}, {"Edit Boot Option", efimenu_process_edit_boot_option}, {"Change Boot Order", efimenu_process_change_boot_order}, + {"Delete Boot Option", efimenu_process_delete_boot_option}, {"Quit", efimenu_process_quit}, }; From patchwork Mon Jun 13 09:38:51 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581417 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798468max; Mon, 13 Jun 2022 02:39:56 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyDLQhTuUX4PQ7eSqWiYrlvHzxGfHbXyo3sWQ35Y27XeCPUGr0Hlmal32j5oJHQPqSgyUrq X-Received: by 2002:a05:6602:29c3:b0:669:25e5:72d2 with SMTP id z3-20020a05660229c300b0066925e572d2mr24981729ioq.206.1655113196408; Mon, 13 Jun 2022 02:39:56 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113196; cv=none; d=google.com; s=arc-20160816; b=T2cxpN5/Kg9XNeLVv7c8n2guxQ0R/dOY1EgBeEe/u+gd0l3qN//xI5exSQpNR5csvo lbN2ZVAVK3fFWwKORXqV5WWjCcf7WLOCWFpKYVkXua1Lxbn+dygbSQY/RmAsiMKUW7Yk yeX9fyEdYCnYUE8t53ikKgftUjFfYB8RtLvLXY/e9VnPhaCAuhJWe3saf39bs0mrQXTz Q7oJJKdjrDpR6B55X0HFHvnDCOzZhK5FvoV7xLt74OE6lRW9GO9hFzaFBFrfjfba50CR f2M5yTyjjW2bdos8nsuOgYgmucaO7nPTZmEdPqQRz3D1Oj/0CJwyk5j9LzYujwLeksEf avvg== 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=EjMMDCSdUiI22k9F0bDeabFjESPgWRSfO/UwCp7fPG4=; b=kAeWs+WkDZCc5BaEjvTh+b0xNARY69T0JSwCTzZPFI1kjyW/1HvXmZsbucRfCmy3wY lTl73+lwmWR/fpD5by6hlXQX/Hl6IZk1U4y75GgbbFQAqXy1TSDd08+PNJfEPPPonieX i6rt2B56XLQcOYq/5c0SeRe5j1Fx90AB27znLVhxU3DsfxhAiPQECK4IZqHYVoqSuxgC OTOIb1uzF43uqC7tF3KlqVbwz8JCOcoaneEZwN16/c2prPef+QX0g9BQ+TIXgioUQ63I D7ugK82uArSxa8+W7A8fXnmcrfarKzK+dPVSzYf9e3UyeUGxnV+twRJpJRhKUySiATGt LW/Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b="LxmKwu+/"; 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 j18-20020a056e020ef200b002d3f8fd9c49si6715047ilk.128.2022.06.13.02.39.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:39:56 -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="LxmKwu+/"; 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 764988444E; Mon, 13 Jun 2022 11:38:48 +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="LxmKwu+/"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id DDC2B84459; Mon, 13 Jun 2022 11:38:42 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) (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 1ADFF8437A for ; Mon, 13 Jun 2022 11:38:39 +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-pl1-x62d.google.com with SMTP id n18so4642259plg.5 for ; Mon, 13 Jun 2022 02:38:39 -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=EjMMDCSdUiI22k9F0bDeabFjESPgWRSfO/UwCp7fPG4=; b=LxmKwu+/KQ/Bkl58ZqPpvjxv/oLTWHPLShsWSO6grp0hEVjLVpqyWTsz0B//kURIXq 2gSjs9hny9083zq8oD/NBrG5f8ziwkALUxWL/IGEV+gLiwJFPptGRTJx48z8N78OJCI6 4fHcSgoXAWyHZ/e2DXpmAV4/Kdliny9lBZ5+Y7EZX5503AG57HHEfYbfvvkD1z1L5v7N rPuqQp+8kShUlMBYsviavERWPFUfqp120z5DcKPDXcAaTHudgvGaOYFPqER0mWoUoMra 5ldIK3vTHYneNHeNmXnLWNqv7rdvd6rydqQe7uZa/vpel7V0nAi/QZzf1nhjtFgYcqgd nhpw== 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=EjMMDCSdUiI22k9F0bDeabFjESPgWRSfO/UwCp7fPG4=; b=eNninfQsXBfGaURWERUCU33NamebZRsOMup5HoVZ/updVUMLYdxLVYG9Vp1vYstELQ twaPA0hNAs0tIhydAS+HNeCAmX4V8LQISoSWQwkpmmhHH/XAp1yHbzBsbdHiDCaOgXTy 6l8Wh6kZYGGUtUD0Zp/+Df99P3NiU4LKBK53ajJse2lxiyWTOPuapciR+i4FVNDQnbIB VlOYq+fX2GsM4IE5lCnJjsUerqPHKsObBh7WSHaNnmX2Ty8Xam6VZRYCBkgyjomWML/f hvrv0vcrWKZ44VAhyjcb/w+HF41L+44mxkjTyI52AO9F5pJsrvbxP8ZRvj0NgNLExqtY r8nQ== X-Gm-Message-State: AOAM530PU/r/GawWggOHZjwyWsv5iueXYj/DsbFl+IWlXv5E1ehqYH4U ThoFWNd22/Ber6sk6v+ZRoskOMCpKStc0g== X-Received: by 2002:a17:90b:314a:b0:1e8:5362:5620 with SMTP id ip10-20020a17090b314a00b001e853625620mr14779359pjb.9.1655113117230; Mon, 13 Jun 2022 02:38:37 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:36 -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 v7 7/9] bootmenu: add removable media entries Date: Mon, 13 Jun 2022 18:38:51 +0900 Message-Id: <20220613093853.23865-8-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 UEFI specification requires booting from removal media using a architecture-specific default image name such as BOOTAA64.EFI. This commit adds the removable media entries into bootmenu, so that user can select the removable media and boot with default image. The bootmenu automatically enumerates the possible bootable media devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL, add it as new UEFI boot option(BOOT####) and update BootOrder variable. This automatically generated UEFI boot option has the dedicated guid in the optional_data to distinguish it from the UEFI boot option user adds manually. This optional_data is removed when the efi bootmgr loads the selected UEFI boot option. This commit also provides the BOOT#### variable maintenance feature. Depending on the system hardware setup, some devices may not exist at a later system boot, so bootmenu checks the available device in each bootmenu invocation and automatically removes the BOOT#### variable corrensponding to the non-existent media device. Signed-off-by: Masahisa Kojima --- Changes in v7: - rename prepare_media_device_entry() to generate_media_device_boot_option() Changes in v6: - optional_data size is changed to 16bytes - check the load option size before comparison - remove guid included in optional_data of auto generated entry when loading Changes in v5: - Return EFI_SUCCESS if there is no BootOrder defined - correctly handle the case if no removable device found - use guid to identify the automatically generated entry by bootmenu Newly created in v4 cmd/bootmenu.c | 99 +++++++++++++++++++++++++++++++- cmd/efimenu.c | 131 +++++++++++++++++++++++++++++++++++++++++++ include/efi_loader.h | 20 +++++++ 3 files changed, 247 insertions(+), 3 deletions(-) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 704d36debe..49544864b1 100644 --- a/cmd/bootmenu.c +++ b/cmd/bootmenu.c @@ -221,6 +221,89 @@ static int prepare_bootmenu_entry(struct bootmenu_data *menu, } #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) +/** + * generate_media_device_boot_option() - generate the media device boot option + * + * This function enumerates all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL + * and generate the bootmenu entries. + * This function also provide the BOOT#### variable maintenance for + * the media device entries. + * - Automatically create the BOOT#### variable for the newly detected device, + * this BOOT#### variable is distinguished by the special GUID + * stored in the EFI_LOAD_OPTION.optional_data + * - If the device is not attached to the system, the associated BOOT#### variable + * is automatically deleted. + * + * Return: status code + */ +static efi_status_t generate_media_device_boot_option(void) +{ + u32 i; + efi_status_t ret; + efi_uintn_t count; + efi_handle_t *volume_handles = NULL; + struct efimenu_media_boot_option *opt = NULL; + + ret = efi_locate_handle_buffer_int(BY_PROTOCOL, &efi_simple_file_system_protocol_guid, + NULL, &count, (efi_handle_t **)&volume_handles); + if (ret != EFI_SUCCESS) + return ret; + + opt = calloc(count, sizeof(struct efimenu_media_boot_option)); + if (!opt) + goto out; + + /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ + ret = efimenu_enumerate_boot_option(opt, volume_handles, count); + if (ret != EFI_SUCCESS) + goto out; + + /* + * System hardware configuration may vary depending on the user setup. + * The boot option is automatically added by the bootmenu. + * If the device is not attached to the system, the boot option needs + * to be deleted. + */ + ret = efimenu_delete_invalid_boot_option(opt, count); + if (ret != EFI_SUCCESS) + goto out; + + /* add non-existent boot option */ + for (i = 0; i < count; i++) { + u32 boot_index; + u16 var_name[9]; + + if (!opt[i].exist) { + ret = efimenu_get_unused_bootoption(var_name, sizeof(var_name), + &boot_index); + if (ret != EFI_SUCCESS) + goto out; + + ret = efi_set_variable_int(var_name, &efi_global_variable_guid, + EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_RUNTIME_ACCESS, + opt[i].size, opt[i].lo, false); + if (ret != EFI_SUCCESS) + goto out; + + ret = efimenu_append_bootorder(boot_index); + if (ret != EFI_SUCCESS) + goto out; + } + } + +out: + if (opt) { + for (i = 0; i < count; i++) + free(opt[i].lo); + } + free(opt); + efi_free_pool(volume_handles); + + return ret; +} + /** * prepare_uefi_bootorder_entry() - generate the uefi bootmenu entries * @@ -342,9 +425,19 @@ static struct bootmenu_data *bootmenu_create(int delay) #if (CONFIG_IS_ENABLED(CMD_BOOTEFI_BOOTMGR)) if (i < MAX_COUNT - 1) { - ret = prepare_uefi_bootorder_entry(menu, &iter, &i); - if (ret < 0 && ret != -ENOENT) - goto cleanup; + efi_status_t efi_ret; + + /* + * UEFI specification requires booting from removal media using + * a architecture-specific default image name such as BOOTAA64.EFI. + */ + efi_ret = generate_media_device_boot_option(); + if (efi_ret != EFI_SUCCESS && efi_ret != EFI_NOT_FOUND) + goto cleanup; + + ret = prepare_uefi_bootorder_entry(menu, &iter, &i); + if (ret < 0 && ret != -ENOENT) + goto cleanup; } #endif diff --git a/cmd/efimenu.c b/cmd/efimenu.c index 1c97f265ca..21571e9334 100644 --- a/cmd/efimenu.c +++ b/cmd/efimenu.c @@ -1625,6 +1625,137 @@ static efi_status_t efimenu_process_delete_boot_option(void *data) return ret; } +efi_status_t efimenu_enumerate_boot_option(struct efimenu_media_boot_option *opt, + efi_handle_t *volume_handles, efi_status_t count) +{ + u32 i; + struct efi_handler *handler; + efi_status_t ret = EFI_SUCCESS; + + for (i = 0; i < count; i++) { + char *optional_data; + u16 *dev_name, *p; + struct efi_load_option lo; + struct efi_block_io *block_io; + char buf[BOOTMENU_DEVICE_NAME_MAX]; + struct efi_device_path *device_path; + + ret = efi_search_protocol(volume_handles[i], &efi_guid_device_path, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&device_path, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + ret = efi_search_protocol(volume_handles[i], &efi_block_io_guid, &handler); + if (ret != EFI_SUCCESS) + continue; + ret = efi_protocol_open(handler, (void **)&block_io, + efi_root, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) + continue; + + efi_disk_get_device_name(block_io, buf, BOOTMENU_DEVICE_NAME_MAX); + dev_name = calloc(1, (strlen(buf) + 1) * sizeof(u16)); + if (!dev_name) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + p = dev_name; + utf8_utf16_strncpy(&p, buf, strlen(buf)); + + lo.label = dev_name; + lo.attributes = LOAD_OPTION_ACTIVE; + lo.file_path = device_path; + lo.file_path_length = efi_dp_size(device_path) + sizeof(END); + /* + * Set the dedicated guid to optional_data, it is used to identify + * the boot option that automatically generated by the bootmenu. + * efi_serialize_load_option() expects optional_data is null-terminated + * utf8 string, so set the "1234567" string to allocate enough space + * to store guid, instead of realloc the load_option. + */ + lo.optional_data = "1234567"; + opt[i].size = efi_serialize_load_option(&lo, (u8 **)&opt[i].lo); + if (!opt[i].size) { + ret = EFI_OUT_OF_RESOURCES; + free(dev_name); + goto out; + } + /* set the guid */ + optional_data = (char *)opt[i].lo + (opt[i].size - u16_strsize(u"1234567")); + memcpy(optional_data, &efi_guid_bootmenu_auto_generated, sizeof(efi_guid_t)); + free(dev_name); + } + +out: + return ret; +} + +efi_status_t efimenu_delete_invalid_boot_option(struct efimenu_media_boot_option *opt, + efi_status_t count) +{ + u16 *bootorder; + u32 i, j; + efi_status_t ret; + efi_uintn_t num, size, bootorder_size; + void *load_option; + struct efi_load_option lo; + u16 varname[] = u"Boot####"; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &bootorder_size); + if (!bootorder) + return EFI_SUCCESS; /* BootOrder is not defined, nothing to do */ + + num = bootorder_size / sizeof(u16); + for (i = 0; i < num;) { + efi_uintn_t tmp; + + efi_create_indexed_name(varname, sizeof(varname), + "Boot", bootorder[i]); + load_option = efi_get_var(varname, &efi_global_variable_guid, &size); + if (!load_option) + goto next; + + tmp = size; + ret = efi_deserialize_load_option(&lo, load_option, &size); + if (ret != EFI_SUCCESS) + goto next; + + if (size >= sizeof(efi_guid_bootmenu_auto_generated)) { + if (guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated) == 0) { + for (j = 0; j < count; j++) { + if (opt[j].size == tmp && + memcmp(opt[j].lo, load_option, tmp) == 0) { + opt[j].exist = true; + break; + } + } + + if (j == count) { + ret = delete_boot_option(bootorder, i, bootorder_size); + if (ret != EFI_SUCCESS) { + free(load_option); + goto out; + } + + num--; + bootorder_size -= sizeof(u16); + free(load_option); + continue; + } + } + } +next: + free(load_option); + i++; + } + +out: + return ret; +} + static efi_status_t efimenu_init(void) { efi_status_t ret; diff --git a/include/efi_loader.h b/include/efi_loader.h index 44d8ba9bf8..eab6cb5ecd 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -943,6 +943,22 @@ struct efi_signature_store { struct x509_certificate; struct pkcs7_message; +/** + * struct efimenu_media_boot_option - boot option for (removable) media device + * + * This structure is used to enumerate possible boot option + * + * @lo: Serialized load option data + * @size: Size of serialized load option data + * @exist: Flag to indicate the load option already exists + * in Non-volatile load option + */ +struct efimenu_media_boot_option { + void *lo; + efi_uintn_t size; + bool exist; +}; + bool efi_signature_lookup_digest(struct efi_image_regions *regs, struct efi_signature_store *db, bool dbx); @@ -1091,6 +1107,10 @@ efi_status_t efi_console_get_u16_string efi_status_t efimenu_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size, u32 *index); efi_status_t efimenu_append_bootorder(u16 index); +efi_status_t efimenu_enumerate_boot_option(struct efimenu_media_boot_option *opt, + efi_handle_t *volume_handles, efi_status_t count); +efi_status_t efimenu_delete_invalid_boot_option(struct efimenu_media_boot_option *opt, + efi_status_t count); efi_status_t efi_disk_get_device_name(struct efi_block_io *this, char *buf, int size); From patchwork Mon Jun 13 09:38:52 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581418 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798592max; Mon, 13 Jun 2022 02:40:10 -0700 (PDT) X-Google-Smtp-Source: ABdhPJz6QAk9Lx73ApQCxBB8i3sNemk/mRIAHHPW92r5gOcvUpTZeOBYseau6DYUltmPAfJnLGcQ X-Received: by 2002:a92:cd41:0:b0:2d6:6553:db13 with SMTP id v1-20020a92cd41000000b002d66553db13mr14190976ilq.307.1655113210256; Mon, 13 Jun 2022 02:40:10 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113210; cv=none; d=google.com; s=arc-20160816; b=EsuZb9yrvqkAHPA+2aQkxh4JT38fCE8+pq/+tVgth7Tirg0dVoaXfmh3TnXnUe+a1h 6KmtaVMksLjavBpVQ6Vq8f9fGJBFt0kHzlwl/PeOfHlxx/BaO3wmYtoAPEiuAKuHIr+l hW5pJPvFItiqpWuPcDYO4nJqpZKqn0t7SUx48KxCNswwZUKcJme/ASDhEsXvy5gmg80d JuTS/ix5PyTzzuUlVLmpaJKc1fR+G3l8mF0r7u8A/ZM+GnWJmkw1SJ7q+lio0bJ9xzPY Awyx0SHv0+LFISY2X9+VvMVWanyapQpmgN+sdH3yk8k1GX8xg9Q/pH9FOwXk8WR3NTKj g83Q== 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=TcgkC7dSbCLJEWpbkUsU5xZrZM5AddVBeoyH2icwoeI=; b=sVWrsbwfnoO7rTMV6ZB4a2ZG1suHkS4PknlUdNbm4xEBN8eY+N3tUBW3mZNszYZywV krmrfjmrNpcn8y0Af30KexWKNSAMCflWAuBIb0kUTsakDOKPhyZfFK4RO4Hl/gJPjax4 Pp7Fyp9+90Vhl6U9WTfCoYyJbbD7ZCaMR+yG0ujbvfm+Ve1B9pMC58yL0WKIpn+hWYON zNJgjjqiAcv4NaPEsCwlvhGJSkvQqtfrzzYX4J7Z3N+MK6MC/TSIliS+dguCe0ZlZ70x xO2FJCC8gTci8t4G49t9LSeowIuUYymaCNbjvzB940XZs5ZM+o2+Mx5d6V+G2mYLjxgJ H16Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=Fkfg09FB; 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 w7-20020a056e02190700b002d3dce14046si9949930ilu.173.2022.06.13.02.40.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:40:10 -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=Fkfg09FB; 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 A7D1A8445E; Mon, 13 Jun 2022 11:38:51 +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="Fkfg09FB"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 9A2208445F; Mon, 13 Jun 2022 11:38:46 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x1034.google.com (mail-pj1-x1034.google.com [IPv6:2607:f8b0:4864:20::1034]) (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 EEC8084451 for ; Mon, 13 Jun 2022 11:38:41 +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-pj1-x1034.google.com with SMTP id v11-20020a17090a4ecb00b001e2c5b837ccso8296433pjl.3 for ; Mon, 13 Jun 2022 02:38:41 -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=TcgkC7dSbCLJEWpbkUsU5xZrZM5AddVBeoyH2icwoeI=; b=Fkfg09FBDV3xBkcqiqs8WpIqaAWty+IZnxCk4q9ZF8tCvOCxjfmic9uSlKAZKgjWaL XwvgqU58I8PubCHcj8Zjjby+80CcPXQjY6fhfqGL6M5bt7c3NCYKtKVOwCviwXWZR5+b 23ARwp13ZBN0jNFflheMZsPgmP3E6d6EiP3Vt1nolPTi3cbaSaJxll602MfXTbXQ/BvA chptysjfsEAB2Fq13GNINO66quT6JchS5+1lKH+PY2kyyqJ1Xea0NTpGN021aFez3UnD eJlK2FZPdv+K97SxR5ZK2384R12i4wOje3K6np+GJDp3fwDdZ60dI2ySMowQnygkMVDb uqVA== 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=TcgkC7dSbCLJEWpbkUsU5xZrZM5AddVBeoyH2icwoeI=; b=kZCD+HUAKTxqS3Wl+RketIw1chIOAG4i0dQL1Yzakxw0MIS57HqRr6Cyx+Rv9IRyIS flZl8OttN+0Tpn0U6sIRybZtGdSq+rOVozpDkqUspU5txujftQ7bC54HWrlPy84h/8Jm 3wHb5BCx1W/yDLFk4wGxo72Nx7DDWKn5lrJNovQ334WuBtIRiNoOsu6AFvypaWUmKGCq kRW7kFjGcZwdeA6hzH/wu3BT3M989m6pGPSLin6U3N5DsaW/h7/WCjC3NHGjkawBvU4g kkvozBGxGp1zBHKbcBrdYFsMCuP06OC+jaR/3vzFHgI3chUno59XWTQgoi2RALxsu3SX 8/EA== X-Gm-Message-State: AOAM5330Vdr7XCnalDSB7PdNhZ0O1ZQ58O0q3rckyq3Vxcxpe9iBRe1P 2Jwj8hQ1LROCjl09ycsp/eE4Ln6Cc4wosg== X-Received: by 2002:a17:902:6845:b0:168:b675:39e2 with SMTP id f5-20020a170902684500b00168b67539e2mr17250941pln.33.1655113120027; Mon, 13 Jun 2022 02:38:40 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:39 -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 , Bin Meng Subject: [PATCH v7 8/9] doc:bootmenu: add description for UEFI boot support Date: Mon, 13 Jun 2022 18:38:52 +0900 Message-Id: <20220613093853.23865-9-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 The bootmenu enumerates the UEFI boot options for boot device selection. This commit adds the description how the UEFI boot work in bootmenu. This commit also adds "Synopsis", "Description" and "Configuration" sections to follow the U-Boot command documentation format. Signed-off-by: Masahisa Kojima --- Changes in v7: - update the description what bootmenu do for uefi-related boot menu - add default behavior when user exits from bootmenu Changes in v6: - remove distro boot related contents because the distro boot support in bootmenu is dropped - update uefi entry example - add [delay] argument of bootmenu command - add description to enable uefi boot entry Changes in v5: - follow the cmd documentation format same as other command, add "Synopsis", "Description" add "Configuration" sections Newly created in v4 doc/usage/cmd/bootmenu.rst | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/doc/usage/cmd/bootmenu.rst b/doc/usage/cmd/bootmenu.rst index 9430f8c9aa..69435090a2 100644 --- a/doc/usage/cmd/bootmenu.rst +++ b/doc/usage/cmd/bootmenu.rst @@ -4,6 +4,15 @@ bootmenu command ================ +Synopsis +-------- +:: + + bootmenu [delay] + +Description +----------- + The "bootmenu" command uses U-Boot menu interfaces and provides a simple mechanism for creating menus with different boot items. The cursor keys "Up" and "Down" are used for navigation through @@ -79,6 +88,55 @@ The above example will be rendered as below:: The selected menu entry will be highlighted - it will have inverted background and text colors. +UEFI boot variable enumeration +'''''''''''''''''''''''''''''' +If enabled, the bootmenu command will automatically generate and add +UEFI-related boot menu entries for the following items. + + * possible bootable media with default file names + * user-defined UEFI boot options + +The bootmenu automatically enumerates the possible bootable +media devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. +This auto generated entry is named as " :" format. +(e.g. "usb 0:1") + +The bootmenu displays the UEFI-related menu entries in order of "BootOrder". +When the user selects the UEFI boot menu entry, the bootmenu sets +the selected boot variable index to "BootNext" without non-volatile attribute, +then call the uefi boot manager with the command "bootefi bootmgr". + +Example bootmenu is as below:: + + *** U-Boot Boot Menu *** + + mmc 0:1 + mmc 0:2 + debian + nvme 0:1 + ubuntu + nvme 0:2 + usb 0:2 + U-Boot console + +Default behavior when user exits from the bootmenu +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +User can exit from bootmenu by selecting the last entry +"U-Boot console"/"Quit" or ESC/CTRL+C key. + +When the CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is disabled, +user exits from the bootmenu and returns to the U-Boot console. + +When the CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, user can not +enter the U-Boot console. When the user exits from the bootmenu, +the bootmenu invokes the following default behabior. + + * if CONFIG_CMD_BOOTEFI_BOOTMGR is enabled, execute "bootefi bootmgr" command + * "bootefi bootmgr" fails or is not enabled, then execute "run bootcmt" command. + +Configuration +------------- + The "bootmenu" command is enabled by:: CONFIG_CMD_BOOTMENU=y @@ -88,3 +146,19 @@ To run the bootmenu at startup add these additional settings:: CONFIG_AUTOBOOT_KEYED=y CONFIG_BOOTDELAY=30 CONFIG_AUTOBOOT_MENU_SHOW=y + +UEFI boot variable enumeration is enabled by:: + + CONFIG_CMD_BOOTEFI_BOOTMGR=y + +To improve the product security, entering U-Boot console from bootmenu +can be disabled by:: + + CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE=y + +To scan the discoverable devices connected to the buses such as +USB and PCIe prior to bootmenu showing up, CONFIG_PREBOOT can be +used to run the command before showing the bootmenu, i.e.:: + + CONFIG_USE_PREBOOT=y + CONFIG_PREBOOT="pci enum; usb start; scsi scan; nvme scan; virtio scan" From patchwork Mon Jun 13 09:38:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 581419 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:5806:0:0:0:0 with SMTP id j6csp1798722max; Mon, 13 Jun 2022 02:40:24 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyLWZx0J5uMwr51VuSuy0hmZvcKHP6COqVfCeea7QxI/6NFHuvHAlCjNXdoIn+2yOcHbcHm X-Received: by 2002:a05:6602:2d49:b0:645:dcf0:3151 with SMTP id d9-20020a0566022d4900b00645dcf03151mr27322794iow.61.1655113224570; Mon, 13 Jun 2022 02:40:24 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655113224; cv=none; d=google.com; s=arc-20160816; b=onRvwaCHq9oJdKVNlmStyRoQa/nYfmjwA++SjEg+nECjpfaGIPusf5qetwy3DGpHIe brShNpQTgyiVZpS8m3NuIREr7lqnkISWSZGhLw1HBXRYpV5GzmS2IPEbLpdD2yZRfzPo p8i5/O7Cyf58E2P/JXJy+69cENsXSNOm2bmg48QQxNkNXPphPcD+LoQDdYZayduquIQg ZyrEzHrDbirq4LS6066iIbIIgbjIvMl65SdvgV1pkX3e+Rd5vEkiVi9c+depN5/30j4g ucSN5xE/G2mDHc0aR8Hz2VWEm2XsSYZUNiS6DerJer+QeJ3tQCpJcM4fm4WhmA+HAK0v bmmw== 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=lUl7+80BIIqbkhzwp48a89+25+AUrwntSybviCws/jA=; b=kxB+Ve14LKsxlENq3WCaNZ2VZv0mjFTBi2Hn6zpFmfVqV5KE5C/GYHnyzaS9xRlU1T KIl6+05ukZ/gMpn0hhag0t7bNaUf00usmFP4/O/0tPXY25ZACdWJeTz2w7tlnr1MDQQ3 Jqn2XdHCt0k9fm+S4XBpxEP02AHVfcaqleZEMqOzxSVjnZca+i7WdGGyDA2GOP7bKkfE k3B3tgJnZgIWKdT7Nuo4IspBogIQJIOa1v96jNem+rer9J2aPxtvCwI4IFtqaos5MXs5 ZiH0TsG3Hz4W9ErFH1TZVPV/W5hMIobnRVCicEbCykLGzdBzRfPuC4mpgKwOLCAzIcsu 5f2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=pJ2YGHQz; 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 u20-20020a05663825d400b003320950b662si10374015jat.103.2022.06.13.02.40.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:40:24 -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=pJ2YGHQz; 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 8EAB484462; Mon, 13 Jun 2022 11:38:53 +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="pJ2YGHQz"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 5052884459; Mon, 13 Jun 2022 11:38:50 +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, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-pj1-x102c.google.com (mail-pj1-x102c.google.com [IPv6:2607:f8b0:4864:20::102c]) (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 B76E28445D for ; Mon, 13 Jun 2022 11:38:45 +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-pj1-x102c.google.com with SMTP id q12-20020a17090a304c00b001e2d4fb0eb4so8289835pjl.4 for ; Mon, 13 Jun 2022 02:38:45 -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=lUl7+80BIIqbkhzwp48a89+25+AUrwntSybviCws/jA=; b=pJ2YGHQzb+5s7LDaUX6R46+t/NtrlJySfbfwZnZgeKW2uVgevKnERUigWdVmF0HBSx 1NbDvqmuGk2gpOmnt1jCobbl+Zw3rybQLNB2DjbvpqtFB/LAZEelFgHHHsglurtEE3ar xG5idNXGG5E6a/loU2+RDFDRM3B5wcerJwxKtVXjJjXVxWewPR9y+CJ2DrXzvV7Q5F9i ztE38j3w1m2TxoVVVbsTDG+ZFeX1TSM2f96lcZJMYsgzyp7+a4x1ZYGiz6MzP/IWfORu FZ1hjfalL0lY+oTsfGJhAD1AGCnh+SzEVYzBgJLyP1cBaqeQas01+M8YZLLIIjT5AYCl VPFg== 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=lUl7+80BIIqbkhzwp48a89+25+AUrwntSybviCws/jA=; b=Cn2yg030bj0Bfi3gPy1HIpEEFG1eFmVsUT8wsaicAnPrKwRRfDG2CiaE/EhuvN5Py+ 9gmooD5M/BsNKywQbPsgalFckjLDfHXFco5PLDn7YIfIedotNje2DCPc/0odi37KjE7+ oihm3cL9hGPQL1XuV9GzGm05vFnReWMvnac5pwmCjX9unjNzxsahyY5kr4ao7SZjfSRk kIQDCcgueU+omXc72SXhfw28sE+eSAKZWicDZtDGnDXvGJ9/hHxAYOky2JLb58ZItzXC R54vTH8ZDmOZzpOXiUzj3ehQ2amQ0JN4AON/8pzFQhhXlHSW8+sfueULMd99F7/ligDB UMvw== X-Gm-Message-State: AOAM533MzxIwQKyIEGirlcMuINWML8q+WqHtczhxjElIQKW6qkDyOPw6 J3AYju1ZfQQpAjdD+lE0Uk96ov8jZgU9ew== X-Received: by 2002:a17:90a:f2cb:b0:1e8:8ac2:bcdd with SMTP id gt11-20020a17090af2cb00b001e88ac2bcddmr14570732pjb.219.1655113123648; Mon, 13 Jun 2022 02:38:43 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id q6-20020a170902a3c600b00163f7935772sm4629227plb.46.2022.06.13.02.38.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 13 Jun 2022 02:38:43 -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 , Bin Meng , =?utf-8?q?Marek_Beh=C3=BAn?= , Sean Anderson Subject: [PATCH v7 9/9] doc:efimenu: add documentation for efimenu command Date: Mon, 13 Jun 2022 18:38:53 +0900 Message-Id: <20220613093853.23865-10-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220613093853.23865-1-masahisa.kojima@linaro.org> References: <20220613093853.23865-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 Add documentation for efimenu command. Signed-off-by: Masahisa Kojima --- Newly created in v7 doc/usage/cmd/efimenu.rst | 50 +++++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 2 files changed, 51 insertions(+) create mode 100644 doc/usage/cmd/efimenu.rst diff --git a/doc/usage/cmd/efimenu.rst b/doc/usage/cmd/efimenu.rst new file mode 100644 index 0000000000..2bf4f9266e --- /dev/null +++ b/doc/usage/cmd/efimenu.rst @@ -0,0 +1,50 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. (C) Copyright 2022, Masahisa Kojima + +efimenu command +================ + +Synopsis +-------- +:: + + efimenu + +Description +----------- + +The "efimenu" command uses U-Boot menu interface and privides +a menu-driven UEFI variable maintenance feature. +The "efimenu" has the following menu entries. + +Add Boot Option + Add new UEFI Boot Option. + User can edit description, file path, and optional_data. + +Edit Boot Option + Edit the existing UEFI Boot Option + User can edit description, file path, and optional_data. + +Change Boot Order + Change the order of UEFI BootOrder variable. + +Delete Boot Option + Delete the UEFI Boot Option + +Configuration +------------- + +The "efimenu" command is enabled by:: + + CONFIG_CMD_EFIMENU=y + +If CONFIG_BOOTMENU_DISABLE_UBOOT_CONSOLE is enabled, user can not enter +U-Boot console. In this case, bootmenu can be used to invoke "efimenu":: + + CONFIG_USE_PREBOOT=y + CONFIG_PREBOOT="setenv bootmenu_0 UEFI Maintenance Menu=efimenu" + +See also +-------- +* :doc:`bootmenu` provides a simple mechanism for creating menus with different boot items + diff --git a/doc/usage/index.rst b/doc/usage/index.rst index c03f4aef9e..053631a746 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -33,6 +33,7 @@ Shell commands cmd/cbsysinfo cmd/conitrace cmd/echo + cmd/efimenu cmd/env cmd/event cmd/exception