avnish писал(а) 24.09.2024 14:46:
> On 2024-09-22 21:30, [email protected] wrote:
>>
>> Message: 1
>> Date: Sun, 22 Sep 2024 13:05:07 +0500
>> From: Nikita Travkin <[email protected]>
>> To: [email protected]
>> Cc: Nikita Travkin <[email protected]>
>> Subject: [PATCH] loader/efi/chainloader: Add efidriver command
>> Message-ID: <[email protected]>
>> Content-Type: text/plain; charset="utf-8"
>>
>> Sometimes it's useful to load EFI drivers. Since loading a driver is
>> the same as starting it and UEFI handles cleanup after on it's own, we
>> can piggy back on existing chainloader command and just start the image
>> immediately instead of defering to "boot". Conveniently this also means
>> that grub can also run plain efi applications with the new command,
>> though the command is still called "efidriver" since it's the primary
>> intended usecase.
>>
>> Refactor chainloader to split up image loading and starting from the
>> command and loader functions and add a new "efidriver" command that
>> executes those steps immediately.
>>
>> Signed-off-by: Nikita Travkin <[email protected]>
>> ---
>> This patch adds EFI driver loading support to grub.
>>
>> Similar feature already exists in systemd-boot in a form of a dedicated
>> directory that it loads drivers from.
>>
>> A few specific examples where it can be necessary:
>>
>> Loading devicetree
>> ------------------
>>
>> Linux can't rely on ACPI on most currently existing
>> Windows-on-Snapdragon devices and instead makes use of devicetree. This
>> means that something has to load said devicetree and provide it to the
>> kerne. GRUB has a "devicetree" command for that but it has a couple of
>> shortcomings:
>>
>> - One has to know beforehand what dtb they want to load;
>> - This command doesn't verify the dtb and can't be used with UEFI
>> secure-boot.
>>
>> Instead dtb could be loaded by a dedicated efi driver such as
>> dtbloader [1]. Such driver could dynamically detect the device and load
>> appropriate dtb and since it's a normal efi driver, it's verified with
>> secure-boot, and itself can implement some security model to safely load
>> dtbs.
>>
>> This would allow distro image makers to create generic os/installer
>> images instead of adding device-specific hacks or asking the users for
>> manual action to load the dtb.
>>
>> Peforming pre-boot firmware hacks
>> ---------------------------------
>>
>> Most currently shipping WoS devices boot UEFI (and thus Linux) in EL1
>> which means Linux can't use KVM and virtualization. Windows has a custom
>> api to switch to EL2. To work around that, custom efi driver,
>> slbounce[2] can be used. This driver hooks into UEFI boot services and
>> performs EL1->EL2 transition upon EBS.
>>
>> Adding "efidriver" command to GRUB would make it easy to "dual boot"
>> EL1 and EL2 modes for users since at the moment Linux can't use some
>> hardware while running in EL2.
>>
>> [1] https://github.com/TravMurav/dtbloader
>> [2] https://github.com/TravMurav/slbounce
>> ---
>> grub-core/loader/efi/chainloader.c | 68
>> ++++++++++++++++++++++++++++++++------
>> 1 file changed, 57 insertions(+), 11 deletions(-)
>>
>> diff --git a/grub-core/loader/efi/chainloader.c
>> b/grub-core/loader/efi/chainloader.c
>> index 869307bf3..17b9c671e 100644
>> --- a/grub-core/loader/efi/chainloader.c
>> +++ b/grub-core/loader/efi/chainloader.c
>> @@ -64,9 +64,8 @@ grub_chainloader_unload (void *context)
>> }
>>
>> static grub_err_t
>> -grub_chainloader_boot (void *context)
>> +start_efi_image (grub_efi_handle_t image_handle)
>> {
>> - grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
>> grub_efi_boot_services_t *b;
>> grub_efi_status_t status;
>> grub_efi_uintn_t exit_data_size;
>> @@ -97,9 +96,20 @@ grub_chainloader_boot (void *context)
>> if (exit_data)
>> b->free_pool (exit_data);
>>
>> + return grub_errno;
>> +}
>> +
>> +static grub_err_t
>> +grub_chainloader_boot (void *context)
>> +{
>> + grub_efi_handle_t image_handle = (grub_efi_handle_t) context;
>> + grub_err_t ret;
>> +
>> + ret = start_efi_image(image_handle);
>
> Hi Nikita,
> It seems a space is missing before '('
Oh, you're right, I somehow completely missed different code style...
I will fix all of those as well as indents (probably happened due to
different tab settings in my editor) and send a v2.
Thanks for your review!
Nikita
>
>> +
>> grub_loader_unset ();
>>
>> - return grub_errno;
>> + return ret;
>> }
>>
>> static grub_err_t
>> @@ -209,8 +219,7 @@ make_file_path (grub_efi_device_path_t *dp, const
>> char *filename)
>> }
>>
>> static grub_err_t
>> -grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
>> - int argc, char *argv[])
>> +load_efi_image (int argc, char *argv[], grub_efi_handle_t *image_ret)
>> {
>> grub_file_t file = 0;
>> grub_ssize_t size;
>> @@ -400,8 +409,8 @@ grub_cmd_chainloader (grub_command_t cmd
>> __attribute__ ((unused)),
>> b->free_pages (address, pages);
>> grub_free (file_path);
>>
>> - grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload,
>> image_handle, 0);
>> - return 0;
>> + *image_ret = image_handle;
>> + return GRUB_ERR_NONE;
>>
>> fail:
>>
>> @@ -425,16 +434,53 @@ grub_cmd_chainloader (grub_command_t cmd
>> __attribute__ ((unused)),
>> return grub_errno;
>> }
>>
>> -static grub_command_t cmd;
>> +static grub_err_t
>> +grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
>> + int argc, char *argv[])
>
> alignment seems off.
> Something like this:
> grub_cmd_chainloader (grub_command_t cmd __attribute__ ((unused)),
> int argc, char *argv[])
>
>
>> +{
>> + grub_efi_handle_t image_handle = NULL;
>> + grub_err_t ret;
>> +
>> + ret = load_efi_image(argc, argv, &image_handle);
>
> Ditto. Missing space before '('
>
>> + if (ret != GRUB_ERR_NONE)
>> + return ret;
>> +
>> + grub_loader_set_ex (grub_chainloader_boot, grub_chainloader_unload,
>> image_handle, 0);
>> + return GRUB_ERR_NONE;
>> +}
>> +
>> +static grub_err_t
>> +grub_cmd_efidriver (grub_command_t cmd __attribute__ ((unused)),
>> + int argc, char *argv[])
>> +{
>> + grub_efi_handle_t image_handle = NULL;
>> + grub_err_t ret;
>> +
>> + ret = load_efi_image(argc, argv, &image_handle);
>
> Ditto. Missing space before '('
>
>> + if (ret != GRUB_ERR_NONE)
>> + return ret;
>> +
>> + ret = start_efi_image(image_handle);
>
> Ditto. Missing space before '('
>
>> +
>> + grub_dl_unref (my_mod);
>> +
>> + return ret;
>> +}
>> +
>> +static grub_command_t cmd_chainloader;
>> +static grub_command_t cmd_efidriver;
>>
>> GRUB_MOD_INIT(chainloader)
>> {
>> - cmd = grub_register_command ("chainloader", grub_cmd_chainloader,
>> - 0, N_("Load another boot loader."));
>> + cmd_chainloader = grub_register_command ("chainloader",
>> grub_cmd_chainloader,
>> + 0, N_("Load another boot loader."));
>> + cmd_efidriver = grub_register_command ("efidriver", grub_cmd_efidriver,
>> + 0, N_("Load a efi driver."));
>
> alignment seems off for above two lines. Same as mentioned earlier.
>
> Thank you!
>
> Regards,
> Avnish Chouhan
>
>> my_mod = mod;
>> }
>>
>> GRUB_MOD_FINI(chainloader)
>> {
>> - grub_unregister_command (cmd);
>> + grub_unregister_command (cmd_chainloader);
>> + grub_unregister_command (cmd_efidriver);
>> }
>>
>> ---
>> base-commit: 9c34d56c2dafcd2737db0e3e49df63bce4d8b504
>> change-id: 20240922-cmd-efidriver-5b644a784851
>>
>> Best regards,
>> --
>> Nikita Travkin <[email protected]>
>>
>>
>>
>>
>> ------------------------------
>>
>> Subject: Digest Footer
>>
>> _______________________________________________
>> Grub-devel mailing list
>> [email protected]
>> https://lists.gnu.org/mailman/listinfo/grub-devel
>>
>>
>> ------------------------------
>>
>> End of Grub-devel Digest, Vol 247, Issue 74
>> *******************************************
>
> _______________________________________________
> Grub-devel mailing list
> [email protected]
> https://lists.gnu.org/mailman/listinfo/grub-devel
_______________________________________________
Grub-devel mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/grub-devel