From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from list by lists.gnu.org with archive (Exim 4.90_1) id 1lmiTr-0002ya-Jk for mharc-grub-devel@gnu.org; Fri, 28 May 2021 15:49:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36498) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lmiTo-0002xL-KA for grub-devel@gnu.org; Fri, 28 May 2021 15:49:13 -0400 Received: from mout.gmx.net ([212.227.17.21]:44473) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lmiTm-0000i1-5l for grub-devel@gnu.org; Fri, 28 May 2021 15:49:12 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1622231342; bh=gKkVnTci470YfwFHxu3f4dkuXmobFb6kj1A1GxecbJI=; h=X-UI-Sender-Class:Subject:To:Cc:References:From:Date:In-Reply-To; b=NqRMmy3qtMN61OXmipv9wiLtWLvitERJSWDd9Cq/2jE3JzqS0XwP92DGLHKVkdBmK lchxiCiYmOOfKxHtSXqmj3Xp53iH1ij6x3aok6rJuD4wdWADt3QgoQbxRF3SXAh62l Mmb2tfDgqTtEBPab7ULLQYI/odjkZgs2gOtEsjk4= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from [192.168.123.35] ([62.143.247.63]) by mail.gmx.net (mrgmx104 [212.227.17.168]) with ESMTPSA (Nemesis) id 1M8ygY-1ljzSK1qsw-0067vg; Fri, 28 May 2021 21:49:02 +0200 Subject: Re: [PATCH 3/8] efi: implemented LoadFile2 initrd loading protocol for Linux To: Nikita Ermakov , GRUB development mailing list Cc: Ard Biesheuvel , Atish Patra , Daniel Kiper , Leif Lindholm References: <20210528130457.13501-1-arei@altlinux.org> <20210528130457.13501-4-arei@altlinux.org> From: Heinrich Schuchardt Message-ID: Date: Fri, 28 May 2021 21:49:01 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.10.0 MIME-Version: 1.0 In-Reply-To: <20210528130457.13501-4-arei@altlinux.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: quoted-printable X-Provags-ID: V03:K1:McYgXusbwjrlJFCZpgBlDMth8TG8UKeFGiufnjVskFIobeMUOel CxPcjWeNa0tFru8a/TYrDjbNS2WfJEdaPXldyla2kpW46Uk1GgfasRp2Jow58OERN7arQs8 TwFiz/CS1wY+1vWPojMewbaJYUNg0XhIi0rJaksBxmZB/r5U2ugY0paReICP/rWcqsqQXYV n6gLOxHS4LfxA1lV2D5YA== X-UI-Out-Filterresults: notjunk:1;V03:K0:qtHQ5w/mNm4=:su6iIoqHvFQnFZ0BZrs1+W dSjPXepPvXHo2AgyG3ml05vuQv/fPDDnQpTgBO8QJr8SO4Hjwn3PNBm6oOM8xXhPfFW9b3tUk XcTT1hMGCXrDgDn6F9p5Qy1WI8aH0LX1Utk9+ukViaeW3T2vb168ZC8u5izCxZpwY4mije6EL SVCIuWWVWKTTFMbfGchTW6PxxR5UPsHxQm4JxXun8bm+plbNVVziq/JCJmfT/AvqWsQc0b3iD TlQXaNH9KUBSwCuuNqSRbfaQiBfE1tKcdeF5BlVsEu20kJ6dNjLR2oGXuuwmZfTCiO5YXXVmL 9nGsmDmXBE5Ss/27OchCyRCRkHis7VkCStxAaMwncVoJfuULjOBVp1Kmeg8//nLKjRMQJmh2X Xo4QMZzl31e02PTmkzrdFZrgBeSfkISFSnQkUpYDgQLDUSWnFbev3An3fhP5WhPbq83SOgFd+ nIpHMmxaHJkvtZOi/fGjHjZ4W5HOIcE5KVvRWoOJ+EL/7N07nkofWPk6Qk3cXNjj9Vo0hVbO7 5Cx4DLNtNH2hv7HVogf2+HN3uhG8WpQ1AMku+I3NOQrU5wt075rteruqIsYko3V2mwwKVzMAc h1n5AB0wirM1uurl0yO6WhSPCsfvIRoN4CtW5ecXz71DQQlC464zWWcKO5xE++a9/YA24Mrbh 9keXJ4Vx0hEC5c61KITeP+tF0z1+HOTHVbQbBxxI7kX1mIDoKgrEu7CdMWm9LXYWU5XR+7gn+ cJjYUlo6lPUCu9frRkZ+bgvcZ6bnYHwADr5dykwaQV8gCYWHFfQgkcA1IrjqhU+EDPypBb5Rc DktslPK2Hkd8K5JEXrmLxgVE+21FAMSEsjUt9HACTTuOiFUDIjKIugkWVsI9Z0RrbjempD3dm 1HgbmrSKesSsfhOAee5y4m3R/mTPy8MHHkp6IF+X5ZBhyQOkSjtg2qi8bPmDX9IbHfMSCbFUo 7/hPFpvpw4Ktnozkjf3o2N2ymjOcnQh3tGNVr3b0pAiBasVHoZLmqDz22gERAe0ina8l/V5pM 1/IiXG20cJZty2mKPbGaS/GjA1jMvXznfRwTjb90fTrMJnD9CGnIyRW4pwGJHGFs7DlyNFiyQ BwxUoqjuLMKhYl+gS7s6diwB7UsW25I56wAbeGtK+/3KOuVYUeM865WbZ45/wrIglqa95N0cD DzxQZ+tm+9hFJH8NhlxFDwooaSA8b7kLhSG9TNVHkaF2Rr4slC95Z2lu8hxG2VpZDQx50= Received-SPF: pass client-ip=212.227.17.21; envelope-from=xypron.glpk@gmx.de; helo=mout.gmx.net X-Spam_score_int: -25 X-Spam_score: -2.6 X-Spam_bar: -- X-Spam_report: (-2.6 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, FREEMAIL_FROM=0.001, NICE_REPLY_A=-0.001, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H4=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: grub-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: The development of GNU GRUB List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 28 May 2021 19:49:13 -0000 On 5/28/21 3:04 PM, Nikita Ermakov wrote: > From: Ard Biesheuvel > > 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 | 117 ++++++++++++++++++++++++++++++++- > 1 file changed, 116 insertions(+), 1 deletion(-) > > diff --git a/grub-core/loader/arm64/linux.c b/grub-core/loader/arm64/lin= ux.c > index ef3e9f944..285422c7b 100644 > --- a/grub-core/loader/arm64/linux.c > +++ b/grub-core/loader/arm64/linux.c > @@ -48,9 +48,16 @@ static grub_uint32_t cmdline_size; > static grub_addr_t initrd_start; > static grub_addr_t initrd_end; > > +static struct grub_linux_initrd_context initrd_ctx =3D { 0, 0, 0 }; > +static grub_efi_handle_t initrd_lf2_handle; > +static int initrd_use_loadfile2; > + > grub_err_t > grub_arch_efi_linux_check_image (struct linux_arch_kernel_header * lh) > { > + struct grub_pe32_coff_header *coff_header; > + struct grub_pe32_optional_header *optional_header; > + > if (lh->magic !=3D GRUB_LINUX_ARMXX_MAGIC_SIGNATURE) > return grub_error(GRUB_ERR_BAD_OS, "invalid magic number"); > > @@ -61,6 +68,21 @@ grub_arch_efi_linux_check_image (struct linux_arch_ke= rnel_header * lh) > grub_dprintf ("linux", "UEFI stub kernel:\n"); > grub_dprintf ("linux", "PE/COFF header @ %08x\n", lh->hdr_offset); > > + coff_header =3D (struct grub_pe32_coff_header *)((unsigned long)lh + = lh->hdr_offset); > + optional_header =3D (struct grub_pe32_optional_header *)(coff_header = + 1); > + > + /* > + * Linux kernels built for any architecture are guaranteed to support= the > + * LoadFile2 based initrd loading protocol if the image version is >= =3D 1. > + */ > + if (optional_header->major_image_version >=3D 1) > + initrd_use_loadfile2 =3D 1; > + else > + initrd_use_loadfile2 =3D 0; > + > + grub_dprintf ("linux", "LoadFile2 initrd loading %sabled\n", > + initrd_use_loadfile2 ? "en" : "dis"); > + > return GRUB_ERR_NONE; > } > > @@ -230,13 +252,88 @@ allocate_initrd_mem (int initrd_pages) > GRUB_EFI_LOADER_DATA); > } > > +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 =3D { > + { > + { > + 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 =3D { > + grub_efi_initrd_load_file2 > +}; > + > +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 =3D GRUB_EFI_SUCCESS; > + grub_efi_uintn_t initrd_size; > + > + if (!this || this !=3D &initrd_lf2 || !buffer_size) > + return GRUB_EFI_INVALID_PARAMETER; > + > + if (device_path->type !=3D GRUB_EFI_END_DEVICE_PATH_TYPE || > + device_path->subtype !=3D GRUB_EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE= ) > + return GRUB_EFI_NOT_FOUND; > + > + if (boot_policy) > + return GRUB_EFI_UNSUPPORTED; > + > + initrd_size =3D grub_get_initrd_size (&initrd_ctx); > + if (!buffer || *buffer_size < initrd_size) > + { > + *buffer_size =3D initrd_size; > + return GRUB_EFI_BUFFER_TOO_SMALL; > + } > + > + grub_dprintf ("linux", "Loading initrd via LOAD_FILE2_PROTOCOL\n"); GRUB is not loading anything via the EFI_LOAD_FILE2_PROTOCOL. The message text should be: "Providing initrd via LOAD_FILE2_PROTOCOL\n" Otherwise looks good. Best regards Heinrich > + > + if (grub_initrd_load (&initrd_ctx, NULL, buffer)) > + status =3D 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 =3D { 0, 0, 0 }; > int initrd_size, initrd_pages; > void *initrd_mem =3D NULL; > + grub_efi_guid_t load_file2_guid =3D GRUB_EFI_LOAD_FILE2_PROTOCOL_GUID= ; > + grub_efi_guid_t device_path_guid =3D GRUB_EFI_DEVICE_PATH_GUID; > + grub_efi_boot_services_t *b; > + grub_efi_status_t status; > > if (argc =3D=3D 0) > { > @@ -254,6 +351,24 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ (= (unused)), > if (grub_initrd_init (argc, argv, &initrd_ctx)) > goto fail; > > + if (initrd_use_loadfile2 && !initrd_lf2_handle) > + { > + b =3D grub_efi_system_table->boot_services; > + status =3D b->install_multiple_protocol_interfaces (&initrd_lf2_h= andle, > + &load_file2_guid, > + &initrd_lf2, > + &device_path_guid, > + &initrd_lf2_device_path, > + NULL); > + if (status =3D=3D GRUB_EFI_OUT_OF_RESOURCES) > + { > + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("out of memory")); > + return grub_errno; > + } > + grub_dprintf ("linux", "LoadFile2 initrd loading protocol install= ed\n"); > + return GRUB_ERR_NONE; > + } > + > initrd_size =3D grub_get_initrd_size (&initrd_ctx); > grub_dprintf ("linux", "Loading initrd\n"); > >