From patchwork Wed Dec 30 15:07:18 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ilias Apalodimas X-Patchwork-Id: 355276 Delivered-To: patch@linaro.org Received: by 2002:a02:85a7:0:0:0:0:0 with SMTP id d36csp11404045jai; Wed, 30 Dec 2020 07:08:52 -0800 (PST) X-Google-Smtp-Source: ABdhPJxdNGcCbmV/VaRsZiBp59a2jMOY5JQz10rtn1+bkG4iFslY4djfJAFaQx+49LOE3LJtgXxJ X-Received: by 2002:a05:6402:3048:: with SMTP id bu8mr50989309edb.49.1609340932660; Wed, 30 Dec 2020 07:08:52 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1609340932; cv=none; d=google.com; s=arc-20160816; b=vLoJ5yNaYBbfosL+GDmmGrdz6j+vAMdPt19gOTCAvQ1RsoBnvECWztPWIdUxa5xThR q5gjzWHb+maAwDel/zUKCalEs5RKX+mWIcpbenTTbhVMl9ZwL//u28llePQpnYXTpfhg jzOJPNf+M3O5eLeJw4DZxqhuLzdIoNC6l1PnU+dQoFulGSQwundC8S0Ze0TkQNOli/m8 SNpfodlm8itX0B2ya9H8hznBY5GQ1ZZGMibHID36ha7+USZNxYZtzrGsSr+xLSKWjqnh QSE1ku32NALWFD8JKqzVtHsHCUFDC6fJmiCKS0RCtQdX0K6kDcdodayA2nGwq12PEcaP DW0A== 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:content-transfer-encoding :mime-version:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=X96u6EoOrgEIPVFvysoAV+fvMN1BK+7emh0RCN4v4nA=; b=00E9Mg440+bdeb8ZS4FJD3G4SxTgbcMLthqExMwyuLvzzK6zO+t3YhKZYBZjnks6kc whYbTRaEUkEwgJ3hViBrwvRxqwn/0OoHuuK5UmdkLqnBiIz0shq9Zn8YldvKTBdUYhaM FdU4KIXnaBdyDgheUwpoHHbKIThPS66bbgIW5tkZdgjVlgFMoxbaULh50qRS6CB62WG4 /XAQrNJsZROC5IFID0vEKZGoxC8yetpjW4tmbG7YcGSPzYFRH9Ey1q+raEPoadzDdt5s YmYTokjgMQHpCoK25Xmbn/Qz/O/38kDF6zDfuZZIFCCUVUYYJMnyLDE2POgmHeYHn9YV wN2w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=pgfuppBJ; 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 f15si21510120ejr.2.2020.12.30.07.08.52 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 07:08:52 -0800 (PST) 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=pgfuppBJ; 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 5EE6782636; Wed, 30 Dec 2020 16:08:09 +0100 (CET) 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="pgfuppBJ"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 208AF82626; Wed, 30 Dec 2020 16:07:50 +0100 (CET) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE autolearn=ham autolearn_force=no version=3.4.2 Received: from mail-wm1-x32b.google.com (mail-wm1-x32b.google.com [IPv6:2a00:1450:4864:20::32b]) (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 34F7C82623 for ; Wed, 30 Dec 2020 16:07:44 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=ilias.apalodimas@linaro.org Received: by mail-wm1-x32b.google.com with SMTP id k10so5176910wmi.3 for ; Wed, 30 Dec 2020 07:07:44 -0800 (PST) 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 :mime-version:content-transfer-encoding; bh=X96u6EoOrgEIPVFvysoAV+fvMN1BK+7emh0RCN4v4nA=; b=pgfuppBJkdBAvtnSPsE4euXJtuI6teCoqvm4ZWwlQbVqBEhp+T2Ebt1d26OiG6X3QK +04I56a9XUouZzn40LOc4/poNTERue6Hrw7ENCqQ1ugnS2Mu3o4jjCrJ1JXvbM1wsBIG 13WTr6H3Q8zBu3i5/m7w2pm+aVHSGczL+fk/zoLEcCunlC7EibqFwxrkr3ZkjFYF1KKg 50AuXxObWCWanfu9QbePP4+E9c2MM/tuzpgwvoQCo5HxNn/YEy2s/XZ1Mr1UXw6mc9pH 8uv/DzGLM+mHBquKaDyCoSxJwrTfXJmCU2hZGKUZrnEfcgDhAeoOjEdZT46Df1GwvRTO QGNQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=X96u6EoOrgEIPVFvysoAV+fvMN1BK+7emh0RCN4v4nA=; b=X1aoxT38ZnLxkf45c3cCDgu9HA5iYm5QJnC3MUpfQeZh1FzdqG/yw2Wwru9MBr7pYh Y1qXQ3HPOSSGoESIuFuzwFE1E6Dsbzv/Y5XdGb3zhbDM/wlERSHkHQ0kFIEjDIUze3pR MlFhjN5hH3hpIlCY8C18iPQ3jW8QgCSXKZUXOGnsHA1RCkKjAVflHC4vgFtmZBeTT1k1 8KkSBpPA7pjEQ1PhghOGb+UxiJ/2QtQu/R1ijAbWoeCdoA4hAylSZj597E3np+tcmMCT sJKUm/BtiGWbngNYDrx29TVbZ5AAcQ9kLcA54xRZZxN3pH4uumOJpBBfyAjy4/U6CO9x 9QoA== X-Gm-Message-State: AOAM531U2tcu4dvCkCKUSFi8PfmlD6XFY254CidYsRKzmIRU6Uzm6tzo NSC3EgWZ/qTv4LDREoReYLf9fw== X-Received: by 2002:a1c:7c09:: with SMTP id x9mr8077696wmc.98.1609340863787; Wed, 30 Dec 2020 07:07:43 -0800 (PST) Received: from localhost.localdomain (athedsl-4484548.home.otenet.gr. [94.71.57.204]) by smtp.gmail.com with ESMTPSA id k10sm62062721wrq.38.2020.12.30.07.07.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 30 Dec 2020 07:07:43 -0800 (PST) From: Ilias Apalodimas To: xypron.glpk@gmx.de Cc: takahiro.akashi@linaro.org, ard.biesheuvel@arm.com, Ilias Apalodimas , Alexander Graf , u-boot@lists.denx.de Subject: [PATCH 6/8 v2] efi_loader: Replace config option with EFI variable for initrd loading Date: Wed, 30 Dec 2020 17:07:18 +0200 Message-Id: <20201230150722.154663-7-ilias.apalodimas@linaro.org> X-Mailer: git-send-email 2.30.0 In-Reply-To: <20201230150722.154663-1-ilias.apalodimas@linaro.org> References: <20201230150722.154663-1-ilias.apalodimas@linaro.org> MIME-Version: 1.0 X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 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.102.3 at phobos.denx.de X-Virus-Status: Clean Up to now we install EFI_LOAD_FILE2_PROTOCOL to load an initrd unconditionally. Although we correctly return various EFI exit codes depending on the file status (i.e EFI_NO_MEDIA, EFI_NOT_FOUND etc), the kernel loader, only falls back to the cmdline interpreted initrd if the protocol is not installed. This creates a problem for EFI installers, since they won't be able to load their own initrd and continue the installation. It also makes the feature hard to use, since we can either have a single initrd or we have to recompile u-boot if the filename changes. So let's introduce a different logic that will decouple the initrd path from the config option we currently have. When the EFI application is launched through the bootmgr, we'll try to match the BootCurrent value to an Initrd#### EFI variable. e.g Boot0000 -> Initrd0000, Boot0010 -> Initrd0010 etc. The Initrd#### EFI variable is expected to include the full file path, i.e 'mmc 0:1 initrd'. If the file is found, we'll install the appropriate protocol so the kernel's efi-stub can use it and load our initrd. If the file is not found the kernel will still try to load an initrd parsing the kernel cmdline, since the protocol won't be installed. This opens up another path using U-Boot and defines a new boot flow. A user will be able to control the kernel/initrd pairs without explicit cmdline args or GRUB. So we can base the whole boot flow on the Boot#### and Initrd#### paired values. Suggested-by: Heinrich Schuchardt Signed-off-by: Ilias Apalodimas --- cmd/bootefi.c | 13 +++++ include/efi_loader.h | 2 +- lib/efi_loader/Kconfig | 13 ++--- lib/efi_loader/efi_load_initrd.c | 93 ++++++++++---------------------- 4 files changed, 46 insertions(+), 75 deletions(-) -- 2.30.0 diff --git a/cmd/bootefi.c b/cmd/bootefi.c index fdf909f8da2c..0234b0df2258 100644 --- a/cmd/bootefi.c +++ b/cmd/bootefi.c @@ -377,6 +377,19 @@ static int do_efibootmgr(void) return CMD_RET_FAILURE; } + /* efi_exit() will delete all protocols and the handle itself on exit */ + if (IS_ENABLED(CONFIG_EFI_LOAD_FILE2_INITRD)) { + ret = efi_initrd_register(&handle); + /* Just warn the user. If the installation fails, the kernel + * either load an initrd specificied in the cmdline or fail + * to boot. + * If we decide to fail the command here we need to uninstall + * the protocols efi_bootmgr_load() installed + */ + if (ret != EFI_SUCCESS) + log_warning("EFI boot manager: Failed to install Loadfile2 for initrd\n"); + } + ret = do_bootefi_exec(handle, load_options); if (ret != EFI_SUCCESS) diff --git a/include/efi_loader.h b/include/efi_loader.h index af30dbafab77..000cc942e31c 100644 --- a/include/efi_loader.h +++ b/include/efi_loader.h @@ -422,7 +422,7 @@ efi_status_t efi_gop_register(void); efi_status_t efi_net_register(void); /* Called by bootefi to make the watchdog available */ efi_status_t efi_watchdog_register(void); -efi_status_t efi_initrd_register(void); +efi_status_t efi_initrd_register(efi_handle_t *initrd_handle); /* Called by bootefi to make SMBIOS tables available */ /** * efi_acpi_register() - write out ACPI tables diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index dd8b93bd3c5a..96b5934a221d 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -212,14 +212,11 @@ config EFI_LOAD_FILE2_INITRD help Expose a EFI_FILE_LOAD2_PROTOCOL that the Linux UEFI stub can use to load the initial ramdisk. Once this is enabled using - initrd= will stop working. - -config EFI_INITRD_FILESPEC - string "initramfs path" - default "host 0:1 initrd" - depends on EFI_LOAD_FILE2_INITRD - help - Full path of the initramfs file, e.g. mmc 0:2 initramfs.cpio.gz. + initrd= will stop working. The protocol will only be + installed if bootmgr is used and the file is found on the defined + path. A boot entry of Boot0001 will try to match Initrd0001 and use + it. Initrd EFI variable format should be ' ' + i.e 'mmc 0:1 boot/initrd' config EFI_SECURE_BOOT bool "Enable EFI secure boot support" diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index 4ec55d70979d..6289957c97bc 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -5,7 +5,9 @@ #include #include +#include #include +#include #include #include #include @@ -43,40 +45,7 @@ static const struct efi_initrd_dp dp = { }; /** - * get_file_size() - retrieve the size of initramfs, set efi status on error - * - * @dev: device to read from, e.g. "mmc" - * @part: device partition, e.g. "0:1" - * @file: name of file - * @status: EFI exit code in case of failure - * - * Return: size of file - */ -static loff_t get_file_size(const char *dev, const char *part, const char *file, - efi_status_t *status) -{ - loff_t sz = 0; - int ret; - - ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY); - if (ret) { - *status = EFI_NO_MEDIA; - goto out; - } - - ret = fs_size(file, &sz); - if (ret) { - sz = 0; - *status = EFI_NOT_FOUND; - goto out; - } - -out: - return sz; -} - -/** - * efi_load_file2initrd() - load initial RAM disk + * efi_load_file2_initrd() - load initial RAM disk * * This function implements the LoadFile service of the EFI_LOAD_FILE2_PROTOCOL * in order to load an initial RAM disk requested by the Linux kernel stub. @@ -96,21 +65,15 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, struct efi_device_path *file_path, bool boot_policy, efi_uintn_t *buffer_size, void *buffer) { - char *filespec; efi_status_t status = EFI_NOT_FOUND; loff_t file_sz = 0, read_sz = 0; - char *dev, *part, *file; - char *pos; int ret; + struct load_file_info info; + char initrd[] = "Initrd"; EFI_ENTRY("%p, %p, %d, %p, %p", this, file_path, boot_policy, buffer_size, buffer); - filespec = strdup(CONFIG_EFI_INITRD_FILESPEC); - if (!filespec) - goto out; - pos = filespec; - if (!this || this != &efi_lf2_protocol || !buffer_size) { status = EFI_INVALID_PARAMETER; @@ -128,24 +91,11 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, goto out; } - /* - * expect a string with three space separated parts: - * - * * a block device type, e.g. "mmc" - * * a device and partition identifier, e.g. "0:1" - * * a file path on the block device, e.g. "/boot/initrd.cpio.gz" - */ - dev = strsep(&pos, " "); - if (!dev) - goto out; - part = strsep(&pos, " "); - if (!part) - goto out; - file = strsep(&pos, " "); - if (!file) + status = efi_get_fp_from_var(initrd, &info); + if (status != EFI_SUCCESS) goto out; - file_sz = get_file_size(dev, part, file, &status); + file_sz = get_file_size(&info, &status); if (!file_sz) goto out; @@ -153,23 +103,25 @@ efi_load_file2_initrd(struct efi_load_file_protocol *this, status = EFI_BUFFER_TOO_SMALL; *buffer_size = file_sz; } else { - ret = fs_set_blk_dev(dev, part, FS_TYPE_ANY); + ret = fs_set_blk_dev(info.dev, info.part, + FS_TYPE_ANY); if (ret) { status = EFI_NO_MEDIA; goto out; } - ret = fs_read(file, map_to_sysmem(buffer), 0, *buffer_size, - &read_sz); - if (ret || read_sz != file_sz) + ret = fs_read(info.filename, map_to_sysmem(buffer), 0, + *buffer_size, &read_sz); + if (ret || read_sz != file_sz) { + status = EFI_DEVICE_ERROR; goto out; + } *buffer_size = read_sz; status = EFI_SUCCESS; } out: - free(filespec); return EFI_EXIT(status); } @@ -183,13 +135,22 @@ out: * * Return: status code */ -efi_status_t efi_initrd_register(void) +efi_status_t efi_initrd_register(efi_handle_t *efi_initrd_handle) { - efi_handle_t efi_initrd_handle = NULL; efi_status_t ret; + struct load_file_info info; + char initrd[] = "Initrd"; + + ret = efi_get_fp_from_var(initrd, &info); + /* + * Don't fail here. If we don't install the protocol the efi-stub will + * try to load and initrd parsing the kernel cmdline + */ + if (ret != EFI_SUCCESS) + return EFI_SUCCESS; ret = EFI_CALL(efi_install_multiple_protocol_interfaces - (&efi_initrd_handle, + (efi_initrd_handle, /* initramfs */ &efi_guid_device_path, &dp, /* LOAD_FILE2 */