From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1oWH7f-0007qq-3Z for mharc-grub-devel@gnu.org; Thu, 08 Sep 2022 08:59:11 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:41620) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1oWBzQ-0003yb-EC for grub-devel@gnu.org; Thu, 08 Sep 2022 03:30:22 -0400 Received: from mail-wr1-x430.google.com ([2a00:1450:4864:20::430]:36474) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1oWBzK-0008QM-KA for grub-devel@gnu.org; Thu, 08 Sep 2022 03:30:19 -0400 Received: by mail-wr1-x430.google.com with SMTP id b17so11164631wrq.3 for ; Thu, 08 Sep 2022 00:30:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date; bh=BYBKvefnfog6brlu+T42oBrw7rDJ/U3oV7dRRMgICjg=; b=pR3nzApapIbF1qh6bkt3G+bAmIZzPsTGzPFOR+29ueB+MZY9Nc4QCkmJyWVffMhH3g KT/u2bujm4lZB5Siy/FMePO9XtJt6rEq5s/6EYoJfhJ1aFZPMZUdcFbfbqbHcr1KKguM 0VDqj4JVpgJ4ACsldYJPmbrk6Fs8ui7HPsJTh+RMktfPXSsh+kD86Vc10zyl0eYhnu0C ZSpNh4Tyz/AfIqJGclMkLBS/NjYzUyeJ0uMb5P2zFXi2POnp6rIMBkeR2679mLRp+cDh MIxw+00wLihgaakue3dXBKS4F0P+xcUPzbzoGUnqarQI1k4OVIeuaWShqkZMT+tzefqV smzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date; bh=BYBKvefnfog6brlu+T42oBrw7rDJ/U3oV7dRRMgICjg=; b=f+ADD6zgEfF0CnpdM2b2grMbGmEpzZ+vx++dc4BOvNrVrz5bzKNDFjnACbA7kFmCUF dgzsTm9iPT3KnM+xdIP3zJMw1LbpP3v6tIXSn35tCGGG3WiP2C/nB2g2IctAZsXF8eB3 Cl62xz7/BjScZWI55p2a4kangj01Lak+Xd186lGdwhpYBKeADcMc/ACPvXn9BfeA3JLO 6As3jlE3nPvKU/CMUxxxgxjs9QNYJUVMbY4TxQl/7Uiud83w9zhZKs5ofBP8ASs4NKFQ sJDvDHZdEEPBNGuFesupMOP+fniPLtaf3FW1gmVeMLzmOxA0+Rkv5pnssVuJR7ztBYn2 TJfw== X-Gm-Message-State: ACgBeo0U1UBSTxB6lsXPC9pR4nS7LIQO14XvHd+MgXALUzcY2sWaqzdC Ygm5VBiAxDO+tT4yDj6Gb89szw== X-Google-Smtp-Source: AA6agR5uQ72L3FTClNnWwWKdtCrJcSeqPU2gRXaIX5z/QkVD4GU5jcZLNyvVCnCgl1kmEMH7ClZOZA== X-Received: by 2002:a05:6000:118e:b0:228:9373:70ae with SMTP id g14-20020a056000118e00b00228937370aemr4123096wrx.467.1662622200143; Thu, 08 Sep 2022 00:30:00 -0700 (PDT) Received: from hera ([46.103.15.185]) by smtp.gmail.com with ESMTPSA id z21-20020a05600c0a1500b003b332a7b898sm601008wmp.45.2022.09.08.00.29.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 08 Sep 2022 00:29:59 -0700 (PDT) Date: Thu, 8 Sep 2022 10:29:56 +0300 From: Ilias Apalodimas To: Ard Biesheuvel Cc: grub-devel@nongnu.org, linux-efi@vger.kernel.org, grub-devel@gnu.org, Daniel Kiper , Nikita Ermakov , Atish Patra , Huacai Chen , Heinrich Schuchardt , dann frazier , Julian Andres Klode Subject: Re: [PATCH resend 8/9] efi: implement LoadFile2 initrd loading protocol for Linux Message-ID: References: <20220818085540.2075028-1-ardb@kernel.org> <20220818085540.2075028-9-ardb@kernel.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20220818085540.2075028-9-ardb@kernel.org> Received-SPF: pass client-ip=2a00:1450:4864:20::430; envelope-from=ilias.apalodimas@linaro.org; helo=mail-wr1-x430.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Thu, 08 Sep 2022 08:59:07 -0400 X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Sep 2022 07:30:23 -0000 Hi Ard, On Thu, Aug 18, 2022 at 10:55:38AM +0200, Ard Biesheuvel wrote: > Recent Linux kernels will invoke the LoadFile2 protocol installed on > a well-known vendor media path to load the initrd if it is exposed by > the firmware. Using this method is preferred for two reasons: > - the Linux kernel is in charge of allocating the memory, and so it can > implement any placement policy it wants (given that these tend to > change between kernel versions), > - it is no longer necessary to modify the device tree provided by the > firmware. > > So let's install this protocol when handling the 'initrd' command if > such a recent kernel was detected (based on the PE/COFF image version), > and defer loading the initrd contents until the point where the kernel > invokes the LoadFile2 protocol. > > Signed-off-by: Ard Biesheuvel > --- > grub-core/loader/arm64/linux.c | 129 +++++++++++++++++++- > 1 file changed, 128 insertions(+), 1 deletion(-) > > diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/linux.c > index 56ba8d0a6ea3..82c7558b4c4c 100644 > --- a/grub-core/loader/arm64/linux.c > +++ b/grub-core/loader/arm64/linux.c > @@ -48,6 +48,48 @@ static grub_uint32_t cmdline_size; > static grub_addr_t initrd_start; > static grub_addr_t initrd_end; > > +static grub_efi_guid_t load_file2_guid = GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID; > +static grub_efi_guid_t device_path_guid = GRUB_EFI_DEVICE_PATH_GUID; > +static struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; > +static grub_efi_handle_t initrd_lf2_handle; > +static int initrd_use_loadfile2; > + > +struct initrd_media_device_path { > + grub_efi_vendor_media_device_path_t vendor; > + grub_efi_device_path_t end; > +} GRUB_PACKED; > + > +#define LINUX_EFI_INITRD_MEDIA_GUID \ > + { 0x5568e427, 0x68fc, 0x4f3d, \ > + { 0xac, 0x74, 0xca, 0x55, 0x52, 0x31, 0xcc, 0x68 } \ > + } > + > +static struct initrd_media_device_path initrd_lf2_device_path = { > + { > + { > + GRUB_EFI_MEDIA_DEVICE_PATH_TYPE, > + GRUB_EFI_VENDOR_MEDIA_DEVICE_PATH_SUBTYPE, > + sizeof(grub_efi_vendor_media_device_path_t), > + }, > + LINUX_EFI_INITRD_MEDIA_GUID > + }, { > + GRUB_EFI_END_DEVICE_PATH_TYPE, > + GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE, > + sizeof(grub_efi_device_path_t) > + } > +}; > + > +static grub_efi_status_t > +grub_efi_initrd_load_file2(grub_efi_load_file2_t *this, > + grub_efi_device_path_t *device_path, > + grub_efi_boolean_t boot_policy, > + grub_efi_uintn_t *buffer_size, > + void *buffer); > + > +static grub_efi_load_file2_t initrd_lf2 = { > + grub_efi_initrd_load_file2 > +}; > + > grub_err_t > grub_arch_efi_linux_load_image_header (grub_file_t file, > struct linux_arch_kernel_header * lh) > @@ -78,6 +120,18 @@ grub_arch_efi_linux_load_image_header (grub_file_t file, > return grub_error(GRUB_ERR_FILE_READ_ERROR, "failed to read COFF image header"); > } > > + /* > + * Linux kernels built for any architecture are guaranteed to support the > + * LoadFile2 based initrd loading protocol if the image version is >= 1. > + */ > + if (lh->coff_image_header.optional_header.major_image_version >= 1) > + initrd_use_loadfile2 = 1; > + else > + initrd_use_loadfile2 = 0; > + > + grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n", > + initrd_use_loadfile2 ? "en" : "dis"); > + > return GRUB_ERR_NONE; > } > > @@ -197,6 +251,8 @@ grub_linux_boot (void) > static grub_err_t > grub_linux_unload (void) > { > + grub_efi_boot_services_t *b; > + > grub_dl_unref (my_mod); > loaded = 0; > if (initrd_start) > @@ -208,6 +264,19 @@ grub_linux_unload (void) > grub_efi_free_pages ((grub_addr_t) kernel_addr, > GRUB_EFI_BYTES_TO_PAGES (kernel_size)); > grub_fdt_unload (); > + > + if (initrd_lf2_handle) > + { > + b = grub_efi_system_table->boot_services; > + b->uninstall_multiple_protocol_interfaces (initrd_lf2_handle, > + &load_file2_guid, > + &initrd_lf2, > + &device_path_guid, > + &initrd_lf2_device_path, > + NULL); > + initrd_lf2_handle = NULL; > + initrd_use_loadfile2 = 0; > + } > return GRUB_ERR_NONE; > } > > @@ -247,13 +316,50 @@ allocate_initrd_mem (int initrd_pages) > GRUB_EFI_LOADER_DATA); > } > > +static grub_efi_status_t > +grub_efi_initrd_load_file2(grub_efi_load_file2_t *this, > + grub_efi_device_path_t *device_path, > + grub_efi_boolean_t boot_policy, > + grub_efi_uintn_t *buffer_size, > + void *buffer) > +{ > + grub_efi_status_t status = GRUB_EFI_SUCCESS; > + grub_efi_uintn_t initrd_size; > + > + if (!this || this != &initrd_lf2 || !buffer_size) > + return GRUB_EFI_INVALID_PARAMETER; > + > + if (device_path->type != GRUB_EFI_END_DEVICE_PATH_TYPE || > + device_path->subtype != GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE) > + return GRUB_EFI_NOT_FOUND; > + > + if (boot_policy) > + return GRUB_EFI_UNSUPPORTED; > + > + initrd_size = grub_get_initrd_size (&initrd_ctx); > + if (!buffer || *buffer_size < initrd_size) > + { > + *buffer_size = initrd_size; > + return GRUB_EFI_BUFFER_TOO_SMALL; > + } > + > + grub_dprintf ("linux", "Providing initrd via LOAD_FILE2_PROTOCOL\n"); > + > + if (grub_initrd_load (&initrd_ctx, buffer)) > + status = GRUB_EFI_LOAD_ERROR; > + > + grub_initrd_close (&initrd_ctx); > + return status; > +} > + > static grub_err_t > grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), > int argc, char *argv[]) > { > - struct grub_linux_initrd_context initrd_ctx = { 0, 0, 0 }; > int initrd_size, initrd_pages; > void *initrd_mem = NULL; > + grub_efi_boot_services_t *b; > + grub_efi_status_t status; > > if (argc == 0) > { > @@ -271,6 +377,27 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), > if (grub_initrd_init (argc, argv, &initrd_ctx)) > goto fail; > > + if (initrd_use_loadfile2) > + { > + if (!initrd_lf2_handle) > + { > + b = grub_efi_system_table->boot_services; > + status = b->install_multiple_protocol_interfaces (&initrd_lf2_handle, > + &load_file2_guid, > + &initrd_lf2, > + &device_path_guid, > + &initrd_lf2_device_path, > + NULL); > + if (status == GRUB_EFI_OUT_OF_RESOURCES) > + { > + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + return grub_errno; > + } > + } > + grub_dprintf ("linux", "Using LoadFile2 initrd loading protocol\n"); > + return GRUB_ERR_NONE; > + } > + > initrd_size = grub_get_initrd_size (&initrd_ctx); > grub_dprintf ("linux", "Loading initrd\n"); > > -- > 2.35.1 > I tested this on u-boot n(which also support load_file2 for the initrd). Even if the user misconfigures the whole thing and try to install the protocol twice everything seems to be handled properly. Tested-by: Ilias Apalodimas Reviewed-by: Ilias Apalodimas