From patchwork Sun Jun 19 04:55:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582991 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747441mav; Sat, 18 Jun 2022 21:55:33 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vVWVvlHz6NNJ6I59LXmhuKD3z6NO/ohoSuF3FYdpcLr/A/TX5oe3rZW60c26ggARR0w0k8 X-Received: by 2002:a17:907:e91:b0:707:c7af:93aa with SMTP id ho17-20020a1709070e9100b00707c7af93aamr15896998ejc.382.1655614533012; Sat, 18 Jun 2022 21:55:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614533; cv=none; d=google.com; s=arc-20160816; b=RoN9EqYCimkR25NlGSRScvqJZX0/nROISbHXifV3RCTxFZjjKHHcW5LBbxuNTkK8un wLanVkKuGB9SxAe00axgFkwpPc7FPR9JKvahEz72oEVzs4aAD/D4T0gA96Q9AQaT22Zu Cgo2Aep/PVBnJGYvSjZ43WPQfOGISVwYQKjsnPdUpXqvoJ1uPcNbTO25yZgakd3qU8DQ RPa5SLbVjujKRFhaO6b6x7t8blkKNGuxM3gtbFNqj55oElnqtJhY/h91rVKjjyR2OUz8 VLkre7W8NvwsfdP+g5Gsna5X2Rn2mdME36hGPNe/2cp9Sb4mA9mKxLZWxujihMYXylA9 AygQ== 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=WU1FIAvj64o9s7UuJIaIDn0QkIa48MBrl4j4ORMKwTA=; b=O0rY0nupNNqjLDb15Wv+LbfLSI5OQkuPVfE+opLWANhvPzBFtc81D94YgLUyDIvowD VMBvJPG3Fm+OlXvIK1fe3Iyyp+kYOcbS/+45CA+Nsyi0ocVMCh/qzi7mJim4oTp66gLm KiWRpuYpIVKyz9uIiNsH2Q0czssvZRtt7nmt431rf4GcJGHugrI6IFuOPelwIXsZCLx5 GEj/9A4dyyUUNQLuLEYBEJZTn4aBUW+7GKHnr6AdiYl80QmMAPMMAqnxWALPJrA8JvgN mBz2iiIwwaZ87Nm03BgcpU0uTldK6bpy8GHp6JTI6/hG4shEPQCwACKfE8HLBCkHWnKn 6afw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sJyA6LAx; 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 ht20-20020a170907609400b006fec271359asi6524035ejc.57.2022.06.18.21.55.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:33 -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=sJyA6LAx; 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 C1EA88433F; Sun, 19 Jun 2022 06:55: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=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="sJyA6LAx"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 29D27843D8; Sun, 19 Jun 2022 06:55:23 +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-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) (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 C1F09842FA for ; Sun, 19 Jun 2022 06:55:20 +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-x1036.google.com with SMTP id g10-20020a17090a708a00b001ea8aadd42bso7468872pjk.0 for ; Sat, 18 Jun 2022 21:55:20 -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=WU1FIAvj64o9s7UuJIaIDn0QkIa48MBrl4j4ORMKwTA=; b=sJyA6LAxSfJraUdKtVBt4zlT3LA/UQOEq4iG0e941ElzzdZBVfZw9TBa/sr8JFMbRv oPlsXsYJIwrkD2IqQax9zSTmseAAFOYatPja4aTMuf494bI9mqIKvLFYs1out6PH+Wuw /sgHIPhHx5qEWQqE4WVepHJCnbL378K9nD1I2wEDiGqS7IRTVP0OL2yV+FBkNrwCZGEx CTOjoAgPTMKSl8/hGz5ilcf8YGWOec/oc0jx+CR+DSFFxch2V6yignWLVRWDB34YDGAw GJ8FgfkFPsF+DuQTk027cGt7YhAj+KV/3pyh4eSUTO/HWKQGjZQo9D3fKF+hzBpXtT3p puUw== 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=WU1FIAvj64o9s7UuJIaIDn0QkIa48MBrl4j4ORMKwTA=; b=i3qoDhXBenfzdmHKghScVsjCTxK+5BQdlCIp43UFhvAIg20ZBjueksP9JKq5c60L9Y 1hu9feTBgEuZDWApZTXTGUHqF9v/ZjqMeqJsYKewX5iOYpmxVdG9nqc0e8tPIC6UOo3A P4GL53ETL+Yau8FaLa7OSaaEKolaMqYOKVGxHrIi4+t98IKjiMBJ7Ey9caN6P5EPdjDG 0Yh4FVKiwPAef/zL/lgiMArgbGIVCeqqtO/N3HFChTygUYRDchjhphDHQHaughYw/w1Q x7i6xvdPFx+00BzK3GIMCQi+p16jvrsW7i76Bdof3aD7mveThHcnOqCk2lXSu/4q8Apk VH7g== X-Gm-Message-State: AJIora+zzkYWBjGJw5T0SKh/6YI9YKIjDJ3+dTjI4R6AkxrO4peC1bQh cmxoBn1NPNuGnPvyJRy2kOWyoMvzpi4iLQ== X-Received: by 2002:a17:902:7486:b0:16a:cfc:7f49 with SMTP id h6-20020a170902748600b0016a0cfc7f49mr8482415pll.135.1655614518941; Sat, 18 Jun 2022 21:55:18 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:18 -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 v8 1/9] efi_loader: expose END device path node Date: Sun, 19 Jun 2022 13:55:59 +0900 Message-Id: <20220619045607.1669-2-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 Reviewed-by: Heinrich Schuchardt Reviewed-by: Ilias Apalodimas --- No change in v8 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 Sun Jun 19 04:56:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582993 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747619mav; Sat, 18 Jun 2022 21:55:54 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tI2eEdWmJGtebJYBdoDJh43B2mEgwSP3j+GhpcCewt1+EIeQIOFWjHlFoiF8cKocZ7RPKn X-Received: by 2002:a17:906:54c3:b0:6ef:d07b:c8ec with SMTP id c3-20020a17090654c300b006efd07bc8ecmr15281089ejp.687.1655614554154; Sat, 18 Jun 2022 21:55:54 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614554; cv=none; d=google.com; s=arc-20160816; b=dqNm9HwQVQ4r6A46EOzNX3VlTYMTEW5SN7xbVygFEzjIi/DWKduJhVezbCMo7ee7xx z8nCxuHFhONoUgtuh3RQsXLiOMvxJOCLtlVOwtVcsMVCBlBmflH3xvUdVdDJytxzEzv/ 9n2npN0XkBaJoG/+aVeSPMNCRAa52Z23T8cGNtmiW0Gu/WcPNc5d0oB/K1ocVGIHAf/F bVhkFJf17iVsLBKKY0NRJNQU0Imv40T+yhToAfgwqII+qQeCIEUNbex0qccFFMIpzus2 erI325tEOiUJ7xYQTXMM8qTAlRJ8No66wx11SZBzoCbvgzhrFf21Nbq2Vg1g7rMb0BOZ 6Q4A== 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=hwv04G0BupojJ1fuQ/N6wHgYn1yRkKZg9z/lz6cz8aM=; b=WK8G1fcwKKZlpTZtGydafiNTGWthU3gdsREWrMrFK4aqRLFkN16Stu+anPeXYvuJ4+ spLiPglpPraabAhvop5MOdI3g08sW1yHxvPs9IfmZW+4hkVFxCh9XktNbhso8CHewDwz wzynp+vtBp3kmJfWEPz2LVZIRnKSJfoEW8McyZRPZUfYo7b9W4Z+VRRdep9GJ/5PmlKw FjAlnSlZ02bQVLowgRrTUmhfOH2rs6McGC0SzDcaQog+Ind1hQ0MgxXBXwCEdHe+HnYz IjG6LhDEakOb41dLDkzoCf0ZxzYaHHT/pInnygkXh8yGj8/c5y/EaDMLnCY1eejP7ySn DKvg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=SDmJGiFE; 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 gt11-20020a1709072d8b00b00711c832d377si5621753ejc.17.2022.06.18.21.55.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:54 -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=SDmJGiFE; 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 97FFA84400; Sun, 19 Jun 2022 06:55: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=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="SDmJGiFE"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id CF31F843EA; Sun, 19 Jun 2022 06:55:33 +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-x534.google.com (mail-pg1-x534.google.com [IPv6:2607:f8b0:4864:20::534]) (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 9746784400 for ; Sun, 19 Jun 2022 06:55: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-pg1-x534.google.com with SMTP id r66so1485269pgr.2 for ; Sat, 18 Jun 2022 21:55: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=hwv04G0BupojJ1fuQ/N6wHgYn1yRkKZg9z/lz6cz8aM=; b=SDmJGiFEzYkRyJtUPUGevztY4aurq/E6DLFD3rm97YZ2PebC3n0ix1eWFOCzWhz04w Aqhln5H3MmIUL0L/Ynt9M2T22LTAIeWY3lxbKNoFbVxp5gHYav3Ag47ONv81JtQ6pMej H6P68rmFzgtuyjt3SOf4yni5I5EVnRqgGCZZnrUUE17ePr2N5Ap4+3tOfAkibPFAjixN ijBBp/XtP8TzflnIK+eEru/j1K9DvDq+zEHrTWYZb9Lydeo7djvrqG/LT3laTWEEcls4 rRBgUVgAFN0wR6yU50qrKnQhBNYEtqss9hhjy6fJQmWRyDYdAt/Xxp0GMLCgCBSvdS2p 2DyA== 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=hwv04G0BupojJ1fuQ/N6wHgYn1yRkKZg9z/lz6cz8aM=; b=Ssv/4VC1KrZOHxCkW+LyFkyP5TRPxYuznaQtvUVaTmBCI/AvoMsRksGWfvkcmSlPQt zinPxz1v2N0lvQQJqjYHDIYBlJSBBcarrOX6tbN3G3uW+3WWQ75PFupQOiJgJ/3SE2HH 30uZ1cPVz3H1P2OYbzWjOZcfzI6p1ZufkZyCpGfPoOLWO50zoP2VZW5uimOleG7aM1mL QhFqonWVhA4dM6UbBDkYVFEoYM4tXrhH644xV4qHU1J2XkuJ8uXtASaJQu+EtuC9A9n4 r+1d/pgepOLmQ99mJHECV+PBZfs3YIjenPRqKY0eJIhi71ezA8AL9yj2J3Rdy1oymabp MvCA== X-Gm-Message-State: AJIora9TIfUIbAOt/ehOF94eRJPjPvZ2LvA2ai7kzWnpmRkEuItKqtlI 40Yd8n3oN97ZHryKHEJIQJRPGoSuElY4Uw== X-Received: by 2002:a63:1226:0:b0:405:dd6:52d2 with SMTP id h38-20020a631226000000b004050dd652d2mr16111098pgl.541.1655614524055; Sat, 18 Jun 2022 21:55:24 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:23 -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 , Huang Jianan , Roland Gaudig , Chris Morgan Subject: [PATCH v8 2/9] eficonfig: menu-driven addition of UEFI boot option Date: Sun, 19 Jun 2022 13:56:00 +0900 Message-Id: <20220619045607.1669-3-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 "eficonfig" command. The "eficonfig" 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_config.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 v8: - command name is change from "efimenu" to "eficonfig" - function and struct prefixes is changed to "eficonfig" - fix menu header string 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/eficonfig.c | 1270 +++++++++++++++++++++++++++++++++ include/efi_config.h | 91 +++ include/efi_loader.h | 40 ++ 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, 1578 insertions(+), 47 deletions(-) create mode 100644 cmd/eficonfig.c create mode 100644 include/efi_config.h diff --git a/cmd/Kconfig b/cmd/Kconfig index 09193b61b9..bb7f1d0463 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_EFICONFIG + bool "eficonfig - provide menu-driven uefi variables maintenance interface" + depends on CMD_BOOTEFI_BOOTMGR + help + Enable the 'eficonfig' command which provides the menu-driven UEFI + variable maintenance interface. + config CMD_EXCEPTION bool "exception - raise exception" depends on ARM || RISCV || SANDBOX || X86 diff --git a/cmd/Makefile b/cmd/Makefile index 5e43a1e022..0afa687e94 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_EFICONFIG) += eficonfig.o obj-$(CONFIG_CMD_ELF) += elf.o obj-$(CONFIG_CMD_EROFS) += erofs.o obj-$(CONFIG_HUSH_PARSER) += exit.o diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c new file mode 100644 index 0000000000..20747db115 --- /dev/null +++ b/cmd/eficonfig.c @@ -0,0 +1,1270 @@ +// 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 EFICONFIG_DESCRIPTION_MAX 32 +#define EFICONFIG_OPTIONAL_DATA_MAX 64 +#define EFICONFIG_EDIT_BOOT_OPTION_MENU_ENTRY 5 + +#define EFICONFIG_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 = + EFICONFIG_AUTO_GENERATED_ENTRY_GUID; + +struct eficonfig_boot_selection_data { + u16 bootorder_index; + int *selected; +}; + +struct eficonfig_filepath_info { + u16 *name; + struct list_head list; +}; + +/** + * struct eficonfig_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 eficonfig_boot_option { + struct eficonfig_select_file_info file_info; + unsigned int boot_index; + u16 *description; + u16 *optional_data; + bool edit_completed; +}; + +struct eficonfig_volume_entry_data { + struct eficonfig_select_file_info *file_info; + struct efi_simple_file_system_protocol *v; + struct efi_device_path *dp; +}; + +struct eficonfig_file_entry_data { + struct eficonfig_select_file_info *file_info; + bool is_directory; + u16 *file_name; +}; + +/** + * eficonfig_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 eficonfig_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 eficonfig_print_entry(void *data) +{ + struct eficonfig_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 eficonfig_display_statusline(struct menu *m) +{ + struct eficonfig_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 *eficonfig_choice_entry(void *data) +{ + int i; + int esc = 0; + struct eficonfig_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("eficonfig: this should not happen"); + return NULL; +} + +static void eficonfig_destroy(struct efimenu *efi_menu) +{ + struct eficonfig_entry *next; + struct eficonfig_entry *iter = efi_menu->first; + + while (iter) { + next = iter->next; + free(iter); + iter = next; + } + free(efi_menu->menu_header); + free(efi_menu); +} + +/** + * eficonfig_process_quit() - callback function for "Quit" entry + * + * @data: pointer to the data + * Return: status code + */ +efi_status_t eficonfig_process_quit(void *data) +{ + return EFI_ABORTED; +} + +/** + * eficonfig_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 eficonfig_process_common(const struct eficonfig_item *items, int count, + char *menu_header) +{ + u32 i; + efi_status_t ret; + struct menu *menu; + void *choice = NULL; + struct eficonfig_entry *entry; + struct efimenu *efi_menu; + struct eficonfig_entry *iter = NULL; + + if (count > EFICONFIG_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 eficonfig_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, eficonfig_display_statusline, + eficonfig_print_entry, eficonfig_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); + eficonfig_destroy(efi_menu); + + puts(ANSI_CLEAR_CONSOLE); + printf(ANSI_CURSOR_POSITION, 1, 1); + puts(ANSI_CURSOR_SHOW); + + return ret; +} + +static efi_status_t eficonfig_volume_selected(void *data) +{ + struct eficonfig_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 eficonfig_file_selected(void *data) +{ + struct eficonfig_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 eficonfig_filepath_info *iter; + struct list_head *pos, *n; + int is_last; + + memset(info->file_info->current_path, 0, EFICONFIG_FILE_PATH_BUF_SIZE); + list_for_each_safe(pos, n, &info->file_info->filepath_list) { + iter = list_entry(pos, struct eficonfig_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, + EFICONFIG_FILE_PATH_MAX); + u16_strlcat(info->file_info->current_path, u"\\", + EFICONFIG_FILE_PATH_MAX); + } + } else { + size_t new_len; + struct eficonfig_filepath_info *filepath; + + new_len = u16_strlen(info->file_info->current_path) + + u16_strlen(info->file_name); + if (new_len >= EFICONFIG_FILE_PATH_MAX) { + eficonfig_print_msg("File path is too long!"); + return EFI_INVALID_PARAMETER; + } + u16_strlcat(info->file_info->current_path, info->file_name, + EFICONFIG_FILE_PATH_MAX); + + filepath = calloc(1, sizeof(struct eficonfig_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 >= EFICONFIG_FILE_PATH_MAX) { + eficonfig_print_msg("Directory path is too long!"); + return EFI_INVALID_PARAMETER; + } + u16_strlcat(info->file_info->current_path, u"\\", + EFICONFIG_FILE_PATH_MAX); + } else { + info->file_info->file_selected = true; + } + } + return EFI_SUCCESS; +} + +static efi_status_t eficonfig_select_volume(struct eficonfig_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 eficonfig_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) { + eficonfig_print_msg("No block device found!"); + return ret; + } + + menu_item = calloc(count + 1, sizeof(struct eficonfig_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 eficonfig_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 eficonfig_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 = eficonfig_volume_selected; + iter->data = info; + iter++; + } + + iter->title = strdup("Quit"); + iter->func = eficonfig_process_quit; + iter->data = NULL; + count += 1; + + ret = eficonfig_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 eficonfig_select_file(struct eficonfig_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 eficonfig_item *menu_item, *iter; + + buf = calloc(1, sizeof(struct efi_file_info) + EFICONFIG_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? */ + eficonfig_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) + EFICONFIG_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 eficonfig_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 eficonfig_file_entry_data *info; + + len = sizeof(struct efi_file_info) + EFICONFIG_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 eficonfig_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 = eficonfig_file_selected; + iter->data = info; + iter++; + } + + /* add "Quit" entry */ + iter->title = "Quit"; + iter->func = eficonfig_process_quit; + iter->data = NULL; + count += 1; + + ret = eficonfig_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 eficonfig_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 eficonfig_boot_add_enter_description(void *data) +{ + u16 *tmp; + efi_status_t ret; + struct eficonfig_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, EFICONFIG_DESCRIPTION_MAX * sizeof(u16)); + if (!tmp) + return EFI_OUT_OF_RESOURCES; + + ret = efi_console_get_u16_string(cin, cout, tmp, + EFICONFIG_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 eficonfig_boot_add_optional_data(void *data) +{ + u16 *tmp; + efi_status_t ret; + struct eficonfig_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, EFICONFIG_OPTIONAL_DATA_MAX * sizeof(u16)); + ret = efi_console_get_u16_string(cin, cout, tmp, + EFICONFIG_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 eficonfig_boot_edit_save(void *data) +{ + struct eficonfig_boot_option *bo = data; + + if (u16_strlen(bo->description) == 0) { + eficonfig_print_msg("Boot Description is empty!"); + bo->edit_completed = false; + return EFI_NOT_READY; + } + if (u16_strlen(bo->file_info.current_path) == 0) { + eficonfig_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 eficonfig_boot_edit_quit(void *data) +{ + return EFI_ABORTED; +} + +/** + * eficonfig_select_file_handler() - handle user file selection + * + * @data: pointer to the data + * Return: status code + */ +efi_status_t eficonfig_select_file_handler(void *data) +{ + size_t len; + efi_status_t ret; + struct list_head *pos, *n; + struct efi_file_handle *root; + struct eficonfig_filepath_info *item; + struct eficonfig_select_file_info *file_info = data; + struct eficonfig_select_file_info *tmp = NULL; + + tmp = calloc(1, sizeof(struct eficonfig_select_file_info)); + if (!tmp) + return EFI_OUT_OF_RESOURCES; + + tmp->current_path = calloc(1, EFICONFIG_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, EFICONFIG_FILE_PATH_BUF_SIZE); + + ret = eficonfig_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 = eficonfig_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 >= EFICONFIG_FILE_PATH_MAX) ? (EFICONFIG_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 eficonfig_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 eficonfig_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 eficonfig_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 eficonfig_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 eficonfig_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, + eficonfig_entry_func func, struct eficonfig_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; +} + +/** + * eficonfig_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 + * @header_str: pointer to the header string + * Return: status code + */ +static efi_status_t eficonfig_show_boot_option(struct eficonfig_boot_option *bo, + char *header_str) +{ + u32 i, len; + u16 *file_name, *p; + struct eficonfig_item *menu_item, *iter; + efi_status_t ret = EFI_OUT_OF_RESOURCES; + char devname[BOOTMENU_DEVICE_NAME_MAX] = {0}; + + menu_item = calloc(EFICONFIG_EDIT_BOOT_OPTION_MENU_ENTRY, sizeof(struct eficonfig_item)); + if (!menu_item) + goto out; + + iter = menu_item; + + ret = create_boot_option_entry(bo, "Description: ", bo->description, + eficonfig_boot_add_enter_description, iter++); + if (ret != EFI_SUCCESS) + goto out; + + /* file name */ + eficonfig_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, + eficonfig_select_file_handler, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Optional Data: ", bo->optional_data, + eficonfig_boot_add_optional_data, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Save", NULL, + eficonfig_boot_edit_save, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = create_boot_option_entry(bo, "Quit", NULL, + eficonfig_boot_edit_quit, iter++); + if (ret != EFI_SUCCESS) + goto out; + + ret = eficonfig_process_common(menu_item, EFICONFIG_EDIT_BOOT_OPTION_MENU_ENTRY, + header_str); + +out: + iter = menu_item; + for (i = 0; i < EFICONFIG_EDIT_BOOT_OPTION_MENU_ENTRY; i++) { + free(iter->title); + iter++; + } + + free(file_name); + free(menu_item); + + return ret; +} + +/** + * eficonfig_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 + * @header_str: pointer to the header string + * Return : status code + */ +static efi_status_t eficonfig_edit_boot_option(u16 *varname, struct eficonfig_boot_option *bo, + u16 *description, const u8 *optional_data, + efi_uintn_t optional_data_size, + struct efi_device_path *dp, + char *header_str) +{ + 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, EFICONFIG_FILE_PATH_BUF_SIZE); + if (!bo->file_info.current_path) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + bo->description = calloc(1, EFICONFIG_DESCRIPTION_MAX * sizeof(u16)); + if (!bo->description) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + bo->optional_data = calloc(1, EFICONFIG_OPTIONAL_DATA_MAX * sizeof(u16)); + if (!bo->optional_data) { + ret = EFI_OUT_OF_RESOURCES; + goto out; + } + + if (description && u16_strlen(description) >= EFICONFIG_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 >= EFICONFIG_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 = eficonfig_show_boot_option(bo, header_str); + 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 = eficonfig_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 eficonfig_process_add_boot_option(void *data) +{ + u16 varname[9]; + efi_status_t ret; + struct eficonfig_boot_option *bo = NULL; + + bo = calloc(1, sizeof(struct eficonfig_boot_option)); + if (!bo) + return EFI_OUT_OF_RESOURCES; + + ret = eficonfig_get_unused_bootoption(varname, sizeof(varname), &bo->boot_index); + if (ret != EFI_SUCCESS) + return ret; + + ret = eficonfig_edit_boot_option(varname, bo, NULL, NULL, 0, NULL, + " ** Add Boot Option ** "); + if (ret != EFI_SUCCESS) + goto out; + + ret = eficonfig_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 eficonfig_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 eficonfig_item maintenance_menu_items[] = { + {"Add Boot Option", eficonfig_process_add_boot_option}, + {"Quit", eficonfig_process_quit}, +}; + +int do_eficonfig(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) +{ + efi_status_t ret; + + if (argc > 1) + return CMD_RET_USAGE; + + ret = efi_init_obj_list(); + if (ret != EFI_SUCCESS) { + log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n", + ret & ~EFI_ERROR_MASK); + + return CMD_RET_FAILURE; + } + + ret = eficonfig_init(); + if (ret != EFI_SUCCESS) + return CMD_RET_FAILURE; + + while (1) { + ret = eficonfig_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( + eficonfig, 1, 0, do_eficonfig, + "provide menu-driven UEFI variable maintenance interface", + "" +); diff --git a/include/efi_config.h b/include/efi_config.h new file mode 100644 index 0000000000..1b48e47c48 --- /dev/null +++ b/include/efi_config.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_CONFIG_H +#define _EFI_CONFIG_H + +#define EFICONFIG_ENTRY_NUM_MAX 99 +#define EFICONFIG_FILE_PATH_MAX 512 +#define EFICONFIG_FILE_PATH_BUF_SIZE (EFICONFIG_FILE_PATH_MAX * sizeof(u16)) + +typedef efi_status_t (*eficonfig_entry_func)(void *data); + +/** + * struct eficonfig_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 eficonfig_entry { + u32 num; + char *title; + char key[3]; + struct efimenu *efi_menu; + struct eficonfig_entry *next; + eficonfig_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 eficonfig_entry *first; +}; + +/** + * struct eficonfig_item - structure to construct eficonfig_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 eficonfig_item { + char *title; + eficonfig_entry_func func; + void *data; +}; + +/** + * struct eficonfig_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 eficonfig_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 eficonfig_print_msg(char *msg); +efi_status_t eficonfig_process_quit(void *data); +efi_status_t eficonfig_process_common(const struct eficonfig_item *items, int count, + char *menu_header); +efi_status_t eficonfig_select_file_handler(void *data); + +#endif diff --git a/include/efi_loader.h b/include/efi_loader.h index c6df29993c..365ce9493e 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 eficonfig_get_unused_bootoption(u16 *buf, + efi_uintn_t buf_size, u32 *index); +efi_status_t eficonfig_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/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 Sun Jun 19 04:56:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582992 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747528mav; Sat, 18 Jun 2022 21:55:43 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tf5GYk0O9WF8c3rS16i53xnGd79V/VLQp2NNQtEQsS61iyYgyPsqEMmsJdbZ1AJdqPw1gv X-Received: by 2002:a05:6402:524a:b0:431:51b3:bc7 with SMTP id t10-20020a056402524a00b0043151b30bc7mr22088577edd.5.1655614543382; Sat, 18 Jun 2022 21:55:43 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614543; cv=none; d=google.com; s=arc-20160816; b=d+PAVlhVpacyvPqY2YwVptEZ14dNzVf7fPaxeZ3vrabSIaXPRClBrV7M2gmRtuAOHz lGuxPZciUaMYEUVmrp8jt+GLadBvdvU3VN+nK2NJqlSNnvPmWLqkGQaEeDBHB4tQwU0P q+BTMdLOQksFm91WLcpo4PNdY5QQWP6ht9AFMixS8fTOSrXCL4f8Az6seTCJl4QMRBPq +epFHjHPezYHzRuQs1QC6cpU+wEffRWKdPo3FVD8Jhx7p7HgsCWk47H9NtYmpAfpxE3e ahwaJwUYotxWT0WTJRJ3ynsu/Z+q7X9uGgbB29B/7lqA212Eyjkn9iFFL2mYh9esa+E9 q/Rw== 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=nYx8vZ5x4OFbmDCnEM+s9ToINssm3sE7Ndp9yEDv5OY=; b=rkoWmmsVX+HnQLIa+h4dE92JctUTBBO4fs52B31KDF3Wci5eAF9UKmD9V+LOFOMWps Sfz5uqFQXn78Se2AArJK2vX996Hgb1KacICFkRkf74eFaeLIwcfXUMoGlOY5BNHaDiuu 8U2Iyc2z4D9t4+fn9vkvsRt0b+LaPtVPi/g8Ptei8j0/pgG676hgdPTvNcJXVaLtYCl6 iZ4L/JWKyCscIUkDuVXU6YutzqsGQgsyXOAu0Bvk6ZLVnGbiIcl4cAt/i4htqHP7KWZW mAnrAt4mVFDIdmMnNeNRkNVDzTqcgaiS6RWfXj7TNp3H19/S9JFrQO01YsqcmLuRkS12 kQaw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=KY1cfoAP; 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 bs8-20020a056402304800b004357f2f78adsi373409edb.614.2022.06.18.21.55.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:43 -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=KY1cfoAP; 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 982888440C; Sun, 19 Jun 2022 06:55: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=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="KY1cfoAP"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 3162A843F0; Sun, 19 Jun 2022 06:55:31 +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-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) (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 E52798440C for ; Sun, 19 Jun 2022 06:55:27 +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-x433.google.com with SMTP id u37so7496877pfg.3 for ; Sat, 18 Jun 2022 21:55:27 -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=nYx8vZ5x4OFbmDCnEM+s9ToINssm3sE7Ndp9yEDv5OY=; b=KY1cfoAPN2WVbOi3MDwH2478FwF8YwE5J41yC2wJF9rkrr8rO+ZGYlHFa8jJLAbDxZ qmRsLU46C9ZNvOLV8iQ3OXspFiX1+dB1GnlMrNs0OHQf7XY2usYMNT78saV2Ejwtc2LU CuUGcjn+CMZA1QpXSYfWtBxTek+eOA4lrpRA7uWGzDLOpomIvQFObNO4op/SiwOyjViD KDlDiAdgPWI7w9o887oRP/9odeHBo0NNcilVOMKv41JMARsJnhf07uYHbTzWxXJjtC8N QVgWTMQqJxWEntCTWg5AKPFkIFHrDr5Qu3an114K0iAYzNxcC5xsehOhXX7b/htawVTO bVsg== 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=nYx8vZ5x4OFbmDCnEM+s9ToINssm3sE7Ndp9yEDv5OY=; b=c4q0n9pUJP8L36xp4LAl0LAVcmM52QhxMBzxH0maPp8uNjPJrurxdW7iihn+ZpEgeF wtcOX5ach1tXU2Myvkr1En05/FQEdcwwjJiI3H+UtubASS2LaStQH7SbPAPv5dIIdEGW tq2aRHpWV3teFQ3moqQEMMYahNVPq46LWT1cDWRlHLHEiVJYZkI/hFL2iIQ4y9jysZSN cwdq6eI+3PGBYLFPybPmZwBOzyv+ICHXmKmaXPiAGYu9oicGPsbxHDiosEBONpDDuGZf /qlpIeW8p2XN0bYbP3b9glAufik6JlDFJbn6cj/qgvT0Xlq3L/i6+lVI1tnLk7LR9WK7 f6Fg== X-Gm-Message-State: AJIora9dHATCzGCeoyxWSxKWTjm3qltvpRP4gzWidLqiAEAIl/MdhJvZ LPqkcbrs2y3tRqVyueCzA2RpA1HbDmkaAA== X-Received: by 2002:a63:7d49:0:b0:408:c70a:9496 with SMTP id m9-20020a637d49000000b00408c70a9496mr15559091pgn.616.1655614527251; Sat, 18 Jun 2022 21:55:27 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:26 -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 v8 3/9] eficonfig: add "Edit Boot Option" menu entry Date: Sun, 19 Jun 2022 13:56:01 +0900 Message-Id: <20220619045607.1669-4-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 --- Changes in v8: - fix menu header string - fix function and structure prefix to "eficonfig" Newly created in v7 cmd/eficonfig.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 20747db115..0a58b83ea3 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1197,6 +1197,177 @@ out: return ret; } +static efi_status_t eficonfig_process_boot_selected(void *data) +{ + struct eficonfig_boot_selection_data *info = data; + + if (info) + *info->selected = info->bootorder_index; + + return EFI_SUCCESS; +} + +static efi_status_t eficonfig_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 eficonfig_item *menu_item, *iter; + + menu_item = calloc(count + 1, sizeof(struct eficonfig_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 eficonfig_boot_selection_data *info; + + info = calloc(1, sizeof(struct eficonfig_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 = eficonfig_process_boot_selected; + iter->data = info; + iter++; + actual_count++; + } + free(load_option); + } + + /* add "Quit" entry */ + iter->title = strdup("Quit"); + iter->func = eficonfig_process_quit; + iter->data = NULL; + actual_count += 1; + + ret = eficonfig_process_common(menu_item, actual_count, " ** Select Boot Option **"); + +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 eficonfig_process_edit_boot_option(void *data) +{ + u16 *bootorder; + efi_status_t ret; + efi_uintn_t num, size; + struct eficonfig_boot_option *bo = NULL; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) { + eficonfig_print_msg("BootOrder is not defined!"); + 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 = eficonfig_show_boot_selection(bootorder, num, &selected); + if (ret != EFI_SUCCESS) + break; + + bo = calloc(1, sizeof(struct eficonfig_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 = eficonfig_edit_boot_option(varname, bo, lo.label, lo.optional_data, + size, lo.file_path, + " ** Edit Boot Option ** "); + + 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 eficonfig_init(void) { efi_status_t ret; @@ -1230,6 +1401,7 @@ static efi_status_t eficonfig_init(void) static const struct eficonfig_item maintenance_menu_items[] = { {"Add Boot Option", eficonfig_process_add_boot_option}, + {"Edit Boot Option", eficonfig_process_edit_boot_option}, {"Quit", eficonfig_process_quit}, }; From patchwork Sun Jun 19 04:56:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582994 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747712mav; Sat, 18 Jun 2022 21:56:06 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sa/lNjCrLUUWAMSzEd5li67+nqWD6ckpvd68yvTy6QyrQTQucPObzOPk+6vL3Rz0/NfTlF X-Received: by 2002:a17:907:8c1a:b0:715:73d2:df36 with SMTP id ta26-20020a1709078c1a00b0071573d2df36mr16089707ejc.256.1655614566339; Sat, 18 Jun 2022 21:56:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614566; cv=none; d=google.com; s=arc-20160816; b=p9GqVnY0exFjZsJNL68MK2PcyaMKZdZyA69cU5YeodClnJvPH5hl/LzmwHW2vPawVd 6Cienr30n2zERXwx1zbXFdak7fzVB23E9z15qeN31H/7vBis89f/ef0kDpSb3ou/mMWO rl58j9CiHRddbv7Ud7DZLBCNp/Q6fEprBGWRcTRC3+M4yj24wXctX0Pta6YuVu931qti tENRt1HoxnJGLJDF+8zDfhO6hjJR4w1fqTsSCxoDCZc0IoddMbzkxxEh7QZzu2y+lqAB MtPv3R1GpqLX2nmkEt+GwbcoKCe83midYKR0Mef2/tbbI3JnIdt+ElGwNF5Johkly/lR Bl0g== 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=xGDO0Ssq9nrgzeMOiIso7MdOflludZaZXVG91BZi/aM=; b=Marebx2MFxJempWdNyKGjZk6cx3Cp1SVFVyx9oXqfgd12lB0evMtese5qLewr++2TF H614mfxtbaJRPF+UerP8yaQzieDTtjFJePy1tqOfzT7/r0OPgzB2c5Q5/82rqbUEQyz8 NG+IHo39SQ2c3qJav9HZw6+M/Asq4QNLZ2lKyF9VMElgNoTR8yBi22bcOe55JhgfCn63 I83JQgavpDAjn2WmmIsAFasANq+kQsBsqJX2OeNNVQYMPBkk9E6lDH3saPk8A4F9XMIC xiiyYxFaUTRBcXO2j0SLpc8+au6lYUYCUF2t0T9Jhx9MH3rU//rrMCOjphkCcOBks991 B0iw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=sScbIOcT; 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 mp35-20020a1709071b2300b007174e91f206si12131561ejc.217.2022.06.18.21.56.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:06 -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=sScbIOcT; 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 A4A4384428; Sun, 19 Jun 2022 06:55: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="sScbIOcT"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 34F73843EA; Sun, 19 Jun 2022 06:55: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-pf1-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) (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 CF38E843F0 for ; Sun, 19 Jun 2022 06:55:31 +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-x433.google.com with SMTP id p14so1818742pfh.6 for ; Sat, 18 Jun 2022 21:55:31 -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=xGDO0Ssq9nrgzeMOiIso7MdOflludZaZXVG91BZi/aM=; b=sScbIOcTQB7oQfHm7SsOYA/lP+Sp6cJqJZAoGsUl7WuEcX9bnU/XNqYSsLzVqeKxWs b74kdGB5uDICmzZzgiwNKkBH2hw2N2l/sEEGAg5xTU25Qw9u2VRnrYQHdRIdgzAUHNgp aVd4ImZhuMsRfoJ8uSzEuxFF5YvqWLy7+Eu5RZIhazrHlbDFV6ynFXjBKiZB3UKQkpLS dS64byzPrrQkEi+3zwJ/9X/Y3pXL+hO+eMEVyAAe8HVaTSdfpla6svOTS0bvMGfzwPje R2rc/ny9+qadUORR3tQtV7XZXsOsOfYeuo7J+FJFIHbM0uBPYYRP4fKoKFFX5ftlcNMT oh8Q== 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=xGDO0Ssq9nrgzeMOiIso7MdOflludZaZXVG91BZi/aM=; b=pyOu2kAW2AIZ0Je3Ml4iXd3vbzX1jR5znws8gtOukxDTkxdvkDJcDeQtT8dRlO/oGP UDBYn/Z6+NCrbd/wXXqtQ6uQu84du/9GRbVypLrK85iF10u+H05HwMWfgLXX9Wgp0tBx vQJR//jptmGfZhTs1WJLOltIEhIFYYY4YIG9d6R5WGK359uqsFtrS7pymI3u19sFEweq qgUyUvphCuhohlQdW7VmQfk9GI2TXgOWPt81ae4C0ZQ3K6X/CKFZ5lGiV60aFtNPf0oN TZ9iR8F3Fl4QyT/6L5GvUsNuIx1wRPR9/TSJ2Mjv60u8ho/ntW1iUWF6CDP0MGOCSpvy 5F9w== X-Gm-Message-State: AJIora9DT8S+jhHrw8iLgGyMSKWWeuUedFkmSyxvlSk30xlQoT3iCP1L Gje8qgOJIAsu1BlSSRpUcDB5wKezLb/ltA== X-Received: by 2002:a63:2a0c:0:b0:3fc:9b04:541d with SMTP id q12-20020a632a0c000000b003fc9b04541dmr16241110pgq.546.1655614529967; Sat, 18 Jun 2022 21:55:29 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:29 -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 v8 4/9] menu: add KEY_PLUS and KEY_MINUS handling Date: Sun, 19 Jun 2022 13:56:02 +0900 Message-Id: <20220619045607.1669-5-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 Reviewed-by: Heinrich Schuchardt --- No change in v8 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 Sun Jun 19 04:56:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582995 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747812mav; Sat, 18 Jun 2022 21:56:17 -0700 (PDT) X-Google-Smtp-Source: AGRyM1soaE7nAM8jKjC0AdZ1y7l8IDixZ87wY8sXPnpb7UG45kzEQVWIEXIhxQCekBbPHvUrO0rV X-Received: by 2002:a05:6402:278d:b0:42e:d3d5:922e with SMTP id b13-20020a056402278d00b0042ed3d5922emr21507743ede.154.1655614577450; Sat, 18 Jun 2022 21:56:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614577; cv=none; d=google.com; s=arc-20160816; b=NdNULIfUXahCpeKvV+oCQgGKC/aXasqPLBh1NOefCDrKN9TN1loC3QDq5fR2oNWvni M7yKp6fKMmO3pC//0l7aZExMaKTS56RjvpzyvlSEn4PUNq4gxI+rtmsw2ncyg/AOQDNG 8+bHtM3SLwCpiN/BlMuzBBf43ISPZZkjs/Fl0Wwq5MV/HjntsBsjkcnCCXk0pDFvVkZ3 LUe+K4rXnMtq4XbS2TKLgrXztipG88a+lasXNh4meFziowwk0FfYv0P2idec8Ay/PzJZ tCQNVdGNSPDzGxwIB7VkFTPfWmK+coT0YYp0U9q4daWXm+yx6B2B3+Fpg75G4PdTkfqe 2jrA== 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=dH2Omd+FOGUahna8c2sg9Zk7CsJFHXCucHARzyj27Cc=; b=GsMSvKUF1NLQ0KILlLt0CLxFNsAQIipa25UfFYWH5OHvpKXwYIkTvKPpIgpv/S+Pj5 ZvP5PWXc2hUpNYevFH1VfhwOlw/tjp1Iiq7HK+ReW83dxCvxxDBR0OVcdg0QweyCTIGb B7+6EPZQBIxstKwlq9Q4bn+0eBWbJLtK2X8mmBwq27ru8XlEwi+E0zhwxiL2uWHYoQ7B YQ52bxy+DHqb6hYCcD2yNOSG5LUbJmMYnSQ6WD2ARVPUwJs1uRxG0NTiZV/mYXgSOfri HCquCq2VkWoX1A9aSq3KaqVd4Yn+erf1wQr1rr/mHte2m4KETmlqmz6TNpfo1O++PfYH PskQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=zoLILLeZ; 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 b17-20020a056402351100b0043135bbd7b3si11290045edd.606.2022.06.18.21.56.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:17 -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=zoLILLeZ; 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 95EEE84445; Sun, 19 Jun 2022 06:55: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="zoLILLeZ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C1C8284441; Sun, 19 Jun 2022 06:55: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-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) (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 EFA5B843EA for ; Sun, 19 Jun 2022 06:55:34 +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-x42e.google.com with SMTP id x4so1157425pfq.2 for ; Sat, 18 Jun 2022 21:55:34 -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=dH2Omd+FOGUahna8c2sg9Zk7CsJFHXCucHARzyj27Cc=; b=zoLILLeZfh3STqrkb4NY05KxT/PPimmmNOSCcD3qaOTBoDOMYWJQMq41pzq764o1K3 QRe5c7lck4uvYvOy28vax0LGVRsWdN3gmkzxH+itB8sFvDBErRCUKAzqtVCSb5j3efSm +WqazYUiHLogwoL14OOmMNKDn1MpEHzn7vRErfhIkxc+CpO6Z85E2qp8eNQohudp9PtA lewtW05XNP+sME2jqYJm9rmyrSCAok+y2xCMLyxlIxva7Wwmp3+GoY+xrEluOgNTLYru QXbwmk/tSvkfLr8UlG6UKFQrXbB9YRzbyfQHaIeL/b2HtS5lCHdrgoAXmI97HWJZbMi/ QiPg== 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=dH2Omd+FOGUahna8c2sg9Zk7CsJFHXCucHARzyj27Cc=; b=F8wYJLyR5DPZYqYZHD8KkWaJWrEeZwrXadmnVGJO8197Sn8d50Xwx1dWeDyn5e83h3 0DMzeTrC4Cr2o3SYYPgHpyVDoYSyRs5qR8/juSC46TG5Ved61EYzKBwX9RiFjxO5Mpgw V5J1T7Yy3GJU0Ssy0ssLUB0Xvz5H28q5nvR9TG5msg+qQKV/7m4p5LkTvnnRtLLacVQI 5WbGNK12a95uQ3JHpEOvr7x0wF3Nn+lqUWwzILPj3QpULyf5cl2qH7S36fcgq5QZRRAI EdM8LLKVgXZQHjlP2X6qG2u+K62oI5iH4PpUJT/89EGsc2JD31399DrJaSzPufuCFdqP GXCg== X-Gm-Message-State: AJIora8/TF+ceHFpO+V4E9Hgv0A9IHMoUoYqtrWKUCJ86SbvW4PpYveG gHoOHCsjAHtArYRZtV+QdX1It/KWKexyYw== X-Received: by 2002:a05:6a00:114e:b0:4c8:55f7:faad with SMTP id b14-20020a056a00114e00b004c855f7faadmr18347510pfm.86.1655614533160; Sat, 18 Jun 2022 21:55:33 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:32 -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 v8 5/9] eficonfig: add "Change Boot Order" menu entry Date: Sun, 19 Jun 2022 13:56:03 +0900 Message-Id: <20220619045607.1669-6-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 v8: - add "Save" and "Quit" entries Changes in v7: - use UP/DOWN and PLUS/MINUS key to change to order no update in v6: cmd/eficonfig.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 237 insertions(+) diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 0a58b83ea3..c4a18e6a2a 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -70,6 +70,13 @@ struct eficonfig_file_entry_data { u16 *file_name; }; +struct eficonfig_boot_order { + u32 num; + u16 *description; + u32 prev_index; + struct list_head list; +}; + /** * eficonfig_print_msg() - print message * @@ -1368,6 +1375,235 @@ out: return ret; } +static void eficonfig_display_change_boot_order(struct list_head *bo_list, + struct efimenu *efi_menu) +{ + bool reverse; + struct list_head *pos, *n; + struct eficonfig_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 eficonfig_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 eficonfig_choice_change_boot_order(struct list_head *bo_list, + struct efimenu *efi_menu) +{ + int esc = 0; + struct list_head *pos, *n; + struct eficonfig_boot_order *tmp; + enum bootmenu_key key = KEY_NONE; + struct eficonfig_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 eficonfig_boot_order, list); + if (entry->num == efi_menu->active) + break; + } + tmp = list_entry(pos->prev, struct eficonfig_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 - 3) { + list_for_each_safe(pos, n, bo_list) { + entry = list_entry(pos, struct eficonfig_boot_order, list); + if (entry->num == efi_menu->active) + break; + } + tmp = list_entry(pos->next, struct eficonfig_boot_order, list); + entry->num++; + tmp->num--; + list_del(&entry->list); + list_add(&entry->list, &tmp->list); + + ++efi_menu->active; + } + return EFI_NOT_READY; + case KEY_DOWN: + if (efi_menu->active < efi_menu->count - 1) + ++efi_menu->active; + return EFI_NOT_READY; + case KEY_SELECT: + /* "Save" */ + if (efi_menu->active == efi_menu->count - 2) + return EFI_SUCCESS; + + /* "Quit" */ + if (efi_menu->active == efi_menu->count - 1) + return EFI_ABORTED; + + break; + case KEY_QUIT: + return EFI_ABORTED; + default: + break; + } + } +} + +static efi_status_t eficonfig_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 eficonfig_boot_order *entry; + struct efimenu efi_menu; + + bootorder = efi_get_var(u"BootOrder", &efi_global_variable_guid, &size); + if (!bootorder) { + eficonfig_print_msg("BootOrder is not defined!"); + 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 eficonfig_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); + } + + /* add "Save" and "Quit" entries */ + entry = calloc(1, sizeof(struct eficonfig_boot_order)); + if (!entry) + goto out; + + entry->num = i++; + entry->description = u16_strdup(u"Save"); + entry->prev_index = 0; + list_add_tail(&entry->list, &bo_list); + + entry = calloc(1, sizeof(struct eficonfig_boot_order)); + if (!entry) + goto out; + + entry->num = i++; + entry->description = u16_strdup(u"Quit"); + entry->prev_index = 0; + list_add_tail(&entry->list, &bo_list); + + efi_menu.delay = -1; + efi_menu.active = 0; + efi_menu.count = i; + + while (1) { + eficonfig_display_change_boot_order(&bo_list, &efi_menu); + + ret = eficonfig_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 eficonfig_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 eficonfig_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 eficonfig_init(void) { efi_status_t ret; @@ -1402,6 +1638,7 @@ static efi_status_t eficonfig_init(void) static const struct eficonfig_item maintenance_menu_items[] = { {"Add Boot Option", eficonfig_process_add_boot_option}, {"Edit Boot Option", eficonfig_process_edit_boot_option}, + {"Change Boot Order", eficonfig_process_change_boot_order}, {"Quit", eficonfig_process_quit}, }; From patchwork Sun Jun 19 04:56:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582996 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747890mav; Sat, 18 Jun 2022 21:56:27 -0700 (PDT) X-Google-Smtp-Source: AGRyM1sVwm2EuhuLr3F85dOMzbpGNakey1+JpuKJnDkwwd8Wl72wX2bHaAALfccSeNB6u7fESk4l X-Received: by 2002:a17:906:7d47:b0:715:7ec3:e3ad with SMTP id l7-20020a1709067d4700b007157ec3e3admr15547795ejp.12.1655614587145; Sat, 18 Jun 2022 21:56:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614587; cv=none; d=google.com; s=arc-20160816; b=o4XGpYuTYF/wDfKZXrB7LZVbJFpiSrhzEjVGNzuch9ZoZuZK3Hq2Z7jRiCP3EvNUDW UxG5+2qZMmt+tLlDS0fFBSLL943k1xArLubzSpsfbGA+5j3peRhbvj/qGVLfW1sJlur+ sXpNSK7d+FY2HkOdXsLRca62haSpafwHrnPdPyo6Krpw2xGjLgMYLFlZlTJ+cWeQCcS/ jgyPxgoFyG08DdfyGiZYA2ur3p+C9L5V5WiNjvBidCNDg/pwhNMKSm7tbfEArJxRT731 AFUtUhpgYCaZ3FX+QGc6qKuGQ7TriWZLEcxoMuTDQwKAO7yIniu6BDDg/r3BWMYOqBBh KcbA== 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=iTOxfZlVU0Xa89lgD5gK34/B0lo21WpnQfbNL9AbyVA=; b=1BjC/C7cPIJsiXShtdMNc3immZ8gEM+v6CtRwOczC4uEVcxVaKmK+UhO0wDghL8FlQ 1290bpwiw5CzrwZIZOTb8InNQH8cHleLjUCnLf2Ij+IjpHxZIFgjtto537DcVw5Ei/Gb UFxW38KOXjWIIWUS3QvY0r8kPSMWBDJ6OUk76OHlu1ksropdXMfW9/oNKzjnRKtHt0t1 ZNzYPXUsX93+AiSKeJAX2eHYhVT2K9eYUju7OhZQa9CdvL+kvgH3+6xdzA5fozxHxfMG eeDzC1SA4P36rtGmeFazVhloFTXHPX7cC7fe045NVVGLjL2D2LlTAuNOD59YRLo7mf9b whag== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=TakptvWb; 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 l25-20020a056402345900b004357fb1ea9bsi5644edc.436.2022.06.18.21.56.26 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:27 -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=TakptvWb; 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 A81E484435; Sun, 19 Jun 2022 06:55: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="TakptvWb"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id AA8ED8442B; Sun, 19 Jun 2022 06:55:40 +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-x42e.google.com (mail-pf1-x42e.google.com [IPv6:2607:f8b0:4864:20::42e]) (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 140C3843F0 for ; Sun, 19 Jun 2022 06:55:38 +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-x42e.google.com with SMTP id f18so2156580pfq.9 for ; Sat, 18 Jun 2022 21:55:37 -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=iTOxfZlVU0Xa89lgD5gK34/B0lo21WpnQfbNL9AbyVA=; b=TakptvWbQ6gP7D3G1r9Pu65uDVCU5djQf1b0Nu6qwaAh3twyWlbvdRy6b3v9kCXl16 LTAuXVbFoEjREuJ4x0VCrBemzZSBC9p5IgUG4aha3OmUQPMTe8WFcbC/n7JefETCvm1M aU6+exa69kQGKGnW1ns4JKq84hkUDY9obkLq+n9hxl/dG3HCl7+9uSZq+Rgml7vYl+nJ gcIlS55PA0XKxGeWlhd3Lue5sVtuSDSXGjalNNrqgJtG3ReueFsurpe/DyMunPC8ShhG RVZqvvCxBuOE8+CQl+iywE4fBd9T4zY/24ci4YPh4ZHm3XrOeaWyiZqVF/U5BYXGSCxB XsXg== 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=iTOxfZlVU0Xa89lgD5gK34/B0lo21WpnQfbNL9AbyVA=; b=2nnYoOHaKfdfDjxcmQ6N6NWFpNgl+qbiYGXjuw13KxC4MS/UMIqKqHgGNV5oZQUYWE T8QBXyNn5HnM7so9WjcQGamVQazc+23XB61j9D7ZzZ5TFL4EudMveegKfRC9k+wLaONb kj6Y9kQOXbNeJUZ38InMn3pNsXUshQWYMY+DOhOKwS+c191gboE3LWhwA35Iz5NWCySt HkabMyLpT44Zzq+jLMmsF56NZ4PduOID9Zmp5kSc78CkWqJZwB/2hkmKdmw++TGwBCRs JIEoWmNMFskzNMMIuAZ2wBGw7SiB0cHMqB2tgMATLvqyTUMMJLDwNmnilq1Z3EBV6dbi 2L8A== X-Gm-Message-State: AJIora/ueDXHsPDZI47EZqL9luioTXhaPfpbJY2sSROJ1Y/GYP/b73uP SoDvSlGa9aB1Z910CFTQHNfoFgj8lQAYAQ== X-Received: by 2002:aa7:80c2:0:b0:524:c3c2:5993 with SMTP id a2-20020aa780c2000000b00524c3c25993mr16270654pfn.1.1655614536239; Sat, 18 Jun 2022 21:55:36 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:35 -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 v8 6/9] eficonfig: add "Delete Boot Option" menu entry Date: Sun, 19 Jun 2022 13:56:04 +0900 Message-Id: <20220619045607.1669-7-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 v8: - function and structure prefix is changed to "eficonfig" Changes in v7: - to stay the boot order list after user delete the entry no update in v6: changes in v5: cmd/eficonfig.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/cmd/eficonfig.c b/cmd/eficonfig.c index 0ba70bb10f..b8907f36dc 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1604,6 +1604,67 @@ 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 eficonfig_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) { + eficonfig_print_msg("BootOrder is not defined!"); + ret = EFI_NOT_FOUND; + return ret; + } + + num = size / sizeof(u16); + ret = eficonfig_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 eficonfig_init(void) { efi_status_t ret; @@ -1639,6 +1700,7 @@ static const struct eficonfig_item maintenance_menu_items[] = { {"Add Boot Option", eficonfig_process_add_boot_option}, {"Edit Boot Option", eficonfig_process_edit_boot_option}, {"Change Boot Order", eficonfig_process_change_boot_order}, + {"Delete Boot Option", eficonfig_process_delete_boot_option}, {"Quit", eficonfig_process_quit}, }; From patchwork Sun Jun 19 04:56:05 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582997 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp747956mav; Sat, 18 Jun 2022 21:56:37 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tdT/vAw3WRuepweo9XRzW59saw0xkoZh3gdDHbSFTbECI+SnuO6ecosigOeM/sjoMaEKEZ X-Received: by 2002:a05:6402:3805:b0:435:61d8:8da0 with SMTP id es5-20020a056402380500b0043561d88da0mr12471033edb.63.1655614597794; Sat, 18 Jun 2022 21:56:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614597; cv=none; d=google.com; s=arc-20160816; b=cZ3Ou+bNI/P1hoZ2fAIVXrN50a/+V6UIHVA8g2BKYiDgomjBi8C9z++AWzHuGRR4sc Uz2onHETEFsvun4jZ3mZjZuUhrRPY0F/2Niu07sjvG+EdsMLbRKMzvNkRO8B8qiSOrKX bemwYIjK3xmo+TUq9d1JhGwGtx11oDNFVfs0cilbGJ37Uw8jymnYPM/shFezuFmOH8Z2 GNQvBz+BdOlI7Tmy5+X+GIkdCrknx8F8YBcBFJx0EmvP9/C/M57xYnFq7Gfp8Bj+cQYR 7KQI1xox+C0nM+p8CDQ00XY/0VStsTJsC6qY+UpQTCwsFJl6GWXUAe9hXERLlJ2Q+nif 52qQ== 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=QlryWEK/zFnaJpuvn5ISHkFFzYqXoIkdwWKrBtbCX78=; b=l+wD/7w/h6IGAi2FNLIUalpN+2+nAK9K0LVIOucVKFcceTyuDNaS9FosnFt+9h5o+g vjZU8hmeLczB6gfu3ix/d2ESecNM0XguvEWg3KjTWtULunXFp2vIIW0bM/5SeMJzA012 LMkn4twR9mRCNIlZM8uLcqGCgvJSIPXPFESgbmtY0uzRQgKRjnpU1Qtph5ZbtJKshBPz FlcAZFgFULwF2m/AaAFKrLs2FXNWylxIRYIJx9bqh2k+tt3nshM2kVm2/hfFo8vPqtWv fEZhopaDCOwmGb6rKFuQ9VSLKhCeFya0ydzOlqQGL3itDfrACmp7CO2qImA3/tXLVCgx 9Erg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=LTpGjGWV; 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 qw15-20020a1709066a0f00b00711f5c9d6cfsi10323875ejc.829.2022.06.18.21.56.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:37 -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=LTpGjGWV; 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 8959484456; Sun, 19 Jun 2022 06:55:46 +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="LTpGjGWV"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 7EF028445A; Sun, 19 Jun 2022 06:55:44 +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-x536.google.com (mail-pg1-x536.google.com [IPv6:2607:f8b0:4864:20::536]) (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 63E56843F0 for ; Sun, 19 Jun 2022 06:55: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-pg1-x536.google.com with SMTP id l4so7411552pgh.13 for ; Sat, 18 Jun 2022 21:55: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=QlryWEK/zFnaJpuvn5ISHkFFzYqXoIkdwWKrBtbCX78=; b=LTpGjGWVb2jasg3FQUVAUdqPAZ/bWWzWawDgKVt7X8IA5bsDteF4yPPM+TD7MYPktJ lUKpH2U0dsbEdYHxieN1CtUUVfSfgPHbcUQgTJJTC8bgmeLl9Tvs6nxyBh/DR4Z/FUJI D5AWYw/uVveQGq11jJZsU2Y71IlQ7qCPp/EkqNdrHG7HE1xr1a/0LT9kcUB8y2f9aAcB UDSps6KPzbmlk8BlqXtH7DUl2JMs8bzg+K3m1nAGyWCgtIDv4Hxi4tQNN4bqIQ+drR3Q VRucGh+OXft/lwH2vL7fj8MMorEep5GHec8meoTx8WBz66gUTMqZ614QuEoDkw92njlx OdHA== 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=QlryWEK/zFnaJpuvn5ISHkFFzYqXoIkdwWKrBtbCX78=; b=1LCp6+agpH6XqqYCsaAVX3rULUb7jP1s5ZqPCsWmwmUYuMpQ/4OOmpgEDubVgs5bQl MB/yMnltyhojh/gDti0kv/13lT/CQVUm5KRNB425Y/7P6jRbzIawgcG5W/KkrtHZk33F e9k6NVuCfALW0L0iH0oiP3+fy53krD5Kk0FMaqvk9Bw943Rwqo0ulzO/XPew9T0J7X/n uicJZ6Jb215mNbmO6QvR7EBieeLwRYAHD06nx3DQu/LvFYtvAwojU9/X+MlTz91I6MWe VpMHU5lI5NjdwXZEQKFuF181WeL3Jt0/cn/aTtZI9TGNLo151VxrV4KEUoBxaJW7k5tG 9yZQ== X-Gm-Message-State: AJIora/MxZOmrt3ytiou9vnUY6O7cAYQE88d0dLM0MRy8SCaP8DrZbZM cj1bY25ewsxJMzDsuLN1FvUbQWDEd/ODhw== X-Received: by 2002:a05:6a00:230a:b0:505:a8ac:40e7 with SMTP id h10-20020a056a00230a00b00505a8ac40e7mr18073385pfh.11.1655614539510; Sat, 18 Jun 2022 21:55:39 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55: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 Subject: [PATCH v8 7/9] bootmenu: add removable media entries Date: Sun, 19 Jun 2022 13:56:05 +0900 Message-Id: <20220619045607.1669-8-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 v8: - function and structure prefix is changed to "eficonfig" 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 cmd/bootmenu.c | 99 +++++++++++++++++++++++++- cmd/eficonfig.c | 131 +++++++++++++++++++++++++++++++++++ include/efi_loader.h | 20 ++++++ lib/efi_loader/efi_bootmgr.c | 4 ++ 4 files changed, 251 insertions(+), 3 deletions(-) diff --git a/cmd/bootmenu.c b/cmd/bootmenu.c index 704d36debe..3b4294f7c5 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 eficonfig_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 eficonfig_media_boot_option)); + if (!opt) + goto out; + + /* enumerate all devices supporting EFI_SIMPLE_FILE_SYSTEM_PROTOCOL */ + ret = eficonfig_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 = eficonfig_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 = eficonfig_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 = eficonfig_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/eficonfig.c b/cmd/eficonfig.c index c87b04cc87..e62f5e41a4 100644 --- a/cmd/eficonfig.c +++ b/cmd/eficonfig.c @@ -1665,6 +1665,137 @@ static efi_status_t eficonfig_process_delete_boot_option(void *data) return ret; } +efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_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 eficonfig_delete_invalid_boot_option(struct eficonfig_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 eficonfig_init(void) { efi_status_t ret; diff --git a/include/efi_loader.h b/include/efi_loader.h index 365ce9493e..9909c58f0b 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 eficonfig_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 eficonfig_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 eficonfig_get_unused_bootoption(u16 *buf, efi_uintn_t buf_size, u32 *index); efi_status_t eficonfig_append_bootorder(u16 index); +efi_status_t eficonfig_enumerate_boot_option(struct eficonfig_media_boot_option *opt, + efi_handle_t *volume_handles, efi_status_t count); +efi_status_t eficonfig_delete_invalid_boot_option(struct eficonfig_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); diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 93f6590530..224571957c 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -245,6 +245,10 @@ static efi_status_t try_load_entry(u16 n, efi_handle_t *handle, } /* Set load options */ + if (size >= sizeof(efi_guid_t) && + !guidcmp(lo.optional_data, &efi_guid_bootmenu_auto_generated)) + size = 0; + if (size) { *load_options = malloc(size); if (!*load_options) { From patchwork Sun Jun 19 04:56:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582998 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp748018mav; Sat, 18 Jun 2022 21:56:48 -0700 (PDT) X-Google-Smtp-Source: AGRyM1vcx5sNixVpkd9L5V7rSsSqki4DpFlynkmGUHlv03w/ZA6e3YOsY6Z6R+rQkLywPVsoqUS1 X-Received: by 2002:a17:906:6a26:b0:718:e1a9:b86b with SMTP id qw38-20020a1709066a2600b00718e1a9b86bmr15423718ejc.271.1655614608544; Sat, 18 Jun 2022 21:56:48 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614608; cv=none; d=google.com; s=arc-20160816; b=fxoHFfQknv9UFatLYI61RYSQYGNy+73o2y4ckqiVLKBr3Hcq9qzb8YvwUN2NV455XJ e0y9N++q70aVfb3fvqdm7LyLfts/IzCS+DvFPZjXNSP8VvDkC1T1eSeEJ+tzxpVsBSQt QdLwp78iH4Bs0uuhNT0E0GhU3yIu7/p5JRjhh5jvDvHnbvNrjY171FCUjh/XZa2GUHah RXrbFZh2TwfD2zLOS3AJ0E24Yyc/atuSay9VZQFy4Mok4ZLIhEnxXh/VMLmeN5o/ykC9 ua0KCXCSgJao/ZHpWItmIOQB2oIlpAh7gnF/qPCUzwpgGSczV0ZmGb6sFG743W3T+lfX FxWw== 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=EukiBs851NPSRHrvq1HxR29QEPHc03UA7I255m3KpHU=; b=CLvOU1sBtzEcKfnXIzxa+eD/Yivm0OEss9DBIOqLmLN5rQWyytLjza6sJ950fYPhHc 26wbMrH9ewZD5kJXUQEaNW9qjC+cG0dOxcRdWNiT/wlRsY8MBGXJ0xzkutSSxXRTkany vnu5KsYN3dgtiXy7GSH1mLMCKA2fU7V38D7mTtZAtRtZsanUW1ubX4RJcTBGHWj+VOOY 0DoZncHyBcX6T9vOwjs8aC36VZkHtRAoyOSvyGA0irmfLmvQxdcZhmVndbIxYQyFi+yq Q/ffA3rEorlxvGp33gQxavXnlxUyEMyf7F3ivssUpEuUJO+Mi+WPU/1aZ6RTngTQB6xQ /lUw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=I3K4n1Dk; 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 ga11-20020a1709070c0b00b006ff49b183e9si7227190ejc.971.2022.06.18.21.56.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:48 -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=I3K4n1Dk; 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 827C98445C; Sun, 19 Jun 2022 06:55:50 +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="I3K4n1Dk"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id C96C38445A; Sun, 19 Jun 2022 06:55: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-pl1-x635.google.com (mail-pl1-x635.google.com [IPv6:2607:f8b0:4864:20::635]) (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 27BBA84453 for ; Sun, 19 Jun 2022 06:55: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=masahisa.kojima@linaro.org Received: by mail-pl1-x635.google.com with SMTP id d5so7039676plo.12 for ; Sat, 18 Jun 2022 21:55:44 -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=EukiBs851NPSRHrvq1HxR29QEPHc03UA7I255m3KpHU=; b=I3K4n1DkLzLBv+H1OJnfhrA5CnDSQDtwQ71+4HBSrMFnoQhR4rbEF+CWisYqqdYy7D fpvXy+KabTwtjue8EIyFt8Q0Ukr5aGk1a1RcWHte028kCEMRbgprQVYCtnvHNL5zai9A i9ZfL21x+imSqtFxcf5qKRQQaYfGh7g4Qmyof4gRwS2u0jsX9AxIzpZAJ55kA7GCwxED v6AvxLwFat47xZa6cCm6RyaaKybId9QEkycbbrODqUYmtIHDr1P58RcsAx2tZ6FiIero 7mIrHAp/j09CCuM+mb+8T7xNWVccRKg5+zkXhe/gG0syqTqxuibRrP40GbiSA+k7k7mx 9aUw== 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=EukiBs851NPSRHrvq1HxR29QEPHc03UA7I255m3KpHU=; b=Pu7Jly/A4nVnhr4Qs5X8DhXl6czOatrv4HDya9KKN1l5KhrucifHUvJHF2F99+9SC5 9yTWuSMoj+viylmgSVG1zsvwmXT1MSDRj2TCz7aA/PtqCubjknDiuJ5vgdILLVyKWEVK gLHLQs0KGOczlUKDLANX7teobMMNGULvfwdD2nxKeLgUVTgPSeJ7sZgaFnZDPdzc8EBy SXokgSSypBVlOT8Gt/poDysf+kq1d7PzhR/Iqkh5CMeUzzsygaYDlDtdQjbGUc3/vJhe joPmDK5dXbA/WKEmkHl0/5JLBL0gb2ugH3ZVWeNrXL4/E4cVNVU4ulvjybwzFPc4Hv+u Q/Hw== X-Gm-Message-State: AJIora9b6I0IiKh9YfyRM3m2ZgkVIJJ0hF8pvk8wTyzFT/DHtPSsTu4q E+O0t7lC/VG5NL3iGJqLQe/tYPXBhwKTBg== X-Received: by 2002:a17:90b:682:b0:1e3:142:a562 with SMTP id m2-20020a17090b068200b001e30142a562mr29792033pjz.91.1655614542274; Sat, 18 Jun 2022 21:55:42 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:42 -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 v8 8/9] doc:bootmenu: add description for UEFI boot support Date: Sun, 19 Jun 2022 13:56:06 +0900 Message-Id: <20220619045607.1669-9-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 --- No change in v8 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 Sun Jun 19 04:56:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Masahisa Kojima X-Patchwork-Id: 582999 Delivered-To: patch@linaro.org Received: by 2002:a05:7000:7814:0:0:0:0 with SMTP id b20csp748082mav; Sat, 18 Jun 2022 21:56:59 -0700 (PDT) X-Google-Smtp-Source: AGRyM1tOvPMc9JtC0qhk1e9sU8XpL6F5g9OLGZWerkg1TlYvkq9/tLd5oPXXUS8Tn7kfbGJvFfM5 X-Received: by 2002:a05:6402:1741:b0:433:4e4d:bfb4 with SMTP id v1-20020a056402174100b004334e4dbfb4mr21811424edx.7.1655614619235; Sat, 18 Jun 2022 21:56:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1655614619; cv=none; d=google.com; s=arc-20160816; b=j5BYXCKII1tMwOSooC9G0RCI/NchmvpMXlgNVnS2uT7UnZRq0gZuw/C+HaPDxUuAaH lxEXr6RX0D5KSglZEJSuqiQ/X0kWF/EDapSdipiW4B29IiP5adq9zXFg14dUmB5UN81s ZEe8nmYQqcBwjUUXvFjoDfXdPcpV/muSlJyDu5wyf+FsZH0Y0cogR4mNvekWXlWuZQNV hw1/2m7E9QmB6rYBL0a7+e4/lDIVUuRMVkTdni6mEz1naocq1y+yRsRvgGPjUfGJMP3w V5hqG/4lSurw6Mt6LfP89vJXiBfpobEX2emqa9kb54Uy5UXEA7eV69jSlmp0P5VlX0MR Wb0g== 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=yl0fOm9Dk2mQNW3V9MRAGwieU68f5bxzBQQLRqELvcE=; b=I0Jt2Zt2PROFO2SAyc8iF/R4BMhXZp7kJDm8zfoBVG+7sYw4mhYcmbBQv2rnr2dp07 SuSWB2yFi0tC1v1ssgiK8Y3YZiX4mXIB1cmYL0l1MprCZ+rAOTy6mg8ksE6iJQWe+Was 6NNY9aKzpMw3BfxKneRLEW3lqTwVyg4Ih8XzyjFP2Ff2AwM45evqESWQU5P+hzOMZSRt vCkUj2whguWOogh0JgwTDak6zmsjx+YMW77rzwqR/wTVG0yXWXszpYejh2coG9/YOAGI 9jOiSw1HFPGodGLKg9xXpiBxKZM78cSUXukqYiL4wXrmQiDv0mNJ//QGICw2Xne3EkgA rWag== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=a8vE5VJv; 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 gs24-20020a170906f19800b006e01f1d9677si4631850ejb.532.2022.06.18.21.56.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:56:59 -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=a8vE5VJv; 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 986CE84466; Sun, 19 Jun 2022 06:55:52 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="a8vE5VJv"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1AFDE84463; Sun, 19 Jun 2022 06:55:51 +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-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) (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 0639A84460 for ; Sun, 19 Jun 2022 06:55: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=masahisa.kojima@linaro.org Received: by mail-pj1-x1035.google.com with SMTP id h34-20020a17090a29a500b001eb01527d9eso6586790pjd.3 for ; Sat, 18 Jun 2022 21:55:47 -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=yl0fOm9Dk2mQNW3V9MRAGwieU68f5bxzBQQLRqELvcE=; b=a8vE5VJv39NRMLu4M3w8xYllPBzHStQIps53fR+pnPUadRQxcO52TJvngChfKymSJ6 vA3abjpFUYtWuvtdKac1UqnPnHhpo5iN0be02RCZv7sgChxj0i8BJdjzUueq6hHtIkMU yN23+uNO5SrpHxkiUr7QcJb/qfZQjXuwyR9qVGciTadZu5gPGCBaKgUYWY6OtZAcO90m WFc8ccF0m2P+i7go1yS0Kg0u6XtsPaC1+WhjE/4MrGddk3TqfHAsEgjwKB44fnCej2fs lrDdHv21WHRyVJUde+TeclFhk0S97L2YmvNUYxVHqcDLhKr83ixpgRrkvpDZGaiX6Amj d60A== 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=yl0fOm9Dk2mQNW3V9MRAGwieU68f5bxzBQQLRqELvcE=; b=17WVd5vF9h8hG5PV1yu/dW9qbshKnQkt/FPIstv80cPZFnfMRnjK99NTNS7BAeUfRK YFm2zjOcUHYI/BlQxeQJXU2PoTj47wZcyUJyC0n2cVYKnjR9vCfQB2Rn2FOLk6snZk1F J6M+MY9aHguGQZ1Ti8gTs0vKVmzKjuZp+K2UovjmXZ/E+Clh9BCk1UPYClFqkXoJC9Pz dNbilhruZaVr4037pCCYfQIUhUfRUFrJCADA6owoqGV6AXyTpK0kooiTvRqHafp7ZVbt dPyJ2Ry2buBjD+kg6ASzqZJoG8I0ElwjX8aCijAGz3V9MzDLseL05gApL+FiO6HgWHbT DEjA== X-Gm-Message-State: AJIora+7RBAHGXkdzaNLmhJbz4HQ6GQ5BbSRKKYI5g9wwhAj/ooAUgOJ 8DaxDziahSr5wo0Z2ghJftBR9C9+ISxRFg== X-Received: by 2002:a17:90a:6444:b0:1ea:b662:c12e with SMTP id y4-20020a17090a644400b001eab662c12emr19701315pjm.199.1655614546106; Sat, 18 Jun 2022 21:55:46 -0700 (PDT) Received: from localhost.localdomain ([240d:1a:cf7:5800:82fa:5bff:fe4b:26b1]) by smtp.gmail.com with ESMTPSA id 9-20020aa79149000000b00518424f8922sm6381848pfi.77.2022.06.18.21.55.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Jun 2022 21:55:45 -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?= , Patrick Delaunay , Roland Gaudig Subject: [PATCH v8 9/9] doc:eficonfig: add documentation for eficonfig command Date: Sun, 19 Jun 2022 13:56:07 +0900 Message-Id: <20220619045607.1669-10-masahisa.kojima@linaro.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20220619045607.1669-1-masahisa.kojima@linaro.org> References: <20220619045607.1669-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 eficonfig command. Signed-off-by: Masahisa Kojima --- Changes in v8: - command name is changed from "efimenu" to "eficonfig" Newly created in v7 doc/usage/cmd/eficonfig.rst | 50 +++++++++++++++++++++++++++++++++++++ doc/usage/index.rst | 1 + 2 files changed, 51 insertions(+) create mode 100644 doc/usage/cmd/eficonfig.rst diff --git a/doc/usage/cmd/eficonfig.rst b/doc/usage/cmd/eficonfig.rst new file mode 100644 index 0000000000..93b2df306d --- /dev/null +++ b/doc/usage/cmd/eficonfig.rst @@ -0,0 +1,50 @@ +.. SPDX-License-Identifier: GPL-2.0+ +.. (C) Copyright 2022, Masahisa Kojima + +eficonfig command +================= + +Synopsis +-------- +:: + + eficonfig + +Description +----------- + +The "eficonfig" command uses U-Boot menu interface and privides +a menu-driven UEFI variable maintenance feature. +The "eficonfig" 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 "eficonfig" command is enabled by:: + + CONFIG_CMD_EFICONFIG=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 "eficonfig":: + + CONFIG_USE_PREBOOT=y + CONFIG_PREBOOT="setenv bootmenu_0 UEFI Maintenance Menu=eficonfig" + +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..106dbfa1b2 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -33,6 +33,7 @@ Shell commands cmd/cbsysinfo cmd/conitrace cmd/echo + cmd/eficonfig cmd/env cmd/event cmd/exception