Le ven. 9 mai 2025, 13:15, khaalid cali <khaliidca...@gmail.com> a écrit :

> From: khaalid <khaliidca...@gmail.com>
>
> This command is intended to print or dump all UEFI runtime services.
> The structure will look like efivar tool, since visually most people are
> familiar with it. If the variable content is string then dump it as
> string, otherwise for non string variables print them as raw hex; just
> the way efivar command does.
>
> Signed-off-by: khaalid <khaliidca...@gmail.com>
>
Please use correct legal name in sign off.

> ---
>  grub-core/Makefile.core.def     |   6 ++
>  grub-core/commands/efi/efivar.c | 150 ++++++++++++++++++++++++++++++++
>  2 files changed, 156 insertions(+)
>  create mode 100644 grub-core/commands/efi/efivar.c
>
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index f70e02e69..ef3dc2dd0 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -840,6 +840,12 @@ module = {
>    enable = efi;
>  };
>
> +module = {
> +  name = efivar;
> +  efi = commands/efi/efivar.c;
> +  enable = efi;
> +};
> +
>  module = {
>    name = blocklist;
>    common = commands/blocklist.c;
> diff --git a/grub-core/commands/efi/efivar.c
> b/grub-core/commands/efi/efivar.c
> new file mode 100644
> index 000000000..8d81e01ab
> --- /dev/null
> +++ b/grub-core/commands/efi/efivar.c
> @@ -0,0 +1,150 @@
> +/* efivar.c - dump runtime uefi variables. */
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2009  Free Software Foundation, Inc.
>
The date is wrong

>
> +#include <grub/dl.h>
> +#include <grub/misc.h>
> +#include <grub/command.h>
> +#include <grub/charset.h>
> +#include <grub/efi/efi.h>
> +#include <grub/efi/api.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +
> +/* Check if the data looks like UTF-16LE text */
> +static inline int
> +is_likely_utf16_string(grub_uint8_t *data, grub_size_t len)
> +{
> +    if (len < 4) return 0;
> +    for (grub_size_t i = 0; i < len; i += 2) {
> +        if (data[i] == 0 && data[i+1] == 0) return 1; // Null terminator
> in UTF-16
> +        if (data[i+1] != 0 && data[i+1] != 0x20) return 0; // High byte
> must be 0 or space-like
> +    }
> +    return 1;
> +}
>
This function is weird. What do you mean by space-like? Why null terminator
inside the string makes it "UTF-16 like"? An array 00 00 00 00 00 FF FF 00
is clearly non-UTF-16 yet this function returns 1

> +
> +static void
> +get_variable_data(const char *variable_name, grub_guid_t *variable_guid)
> +{
>
This is a dump function. Not a getter.

> +    grub_efi_status_t status;
> +    grub_efi_uint32_t attributes;
> +    grub_size_t data_size;
> +    grub_uint8_t *data;
> +
> +    status = grub_efi_get_variable_with_attributes(variable_name,
> variable_guid,
> +                                                   &data_size, (void
> **)&data, &attributes);
> +    if (status != GRUB_EFI_SUCCESS)
> +    {
> +        grub_error(GRUB_ERR_BAD_MODULE,

Bad module is for bad grub modules. It's wrong error code

"Failed to retrieve variable data 0x%" PRIxGRUB_EFI_UINTN_T, status);
> +        return;
> +    }
> +
> +    grub_printf("Attributes:\n");
>
Mark as translatable. Here and later.

> +    if (attributes & GRUB_EFI_VARIABLE_NON_VOLATILE)
> +        grub_printf("\tNon-Volatile\n");
> +    if (attributes & GRUB_EFI_VARIABLE_BOOTSERVICE_ACCESS)
> +        grub_printf("\tBoot Service Access\n");
> +    if (attributes & GRUB_EFI_VARIABLE_RUNTIME_ACCESS)
> +        grub_printf("\tRuntime Service Access\n");
> +
> +    if (is_likely_utf16_string(data, data_size))
> +    {
> +       grub_printf("Value (as UTF-16 string):\n");
> +       for (grub_size_t i = 0; i + 1 < data_size; i += 2)
> +       {
> +               grub_uint16_t ch = data[i] | (data[i+1] << 8);
> +               if (ch == 0) break;
> +               grub_printf("%c", (char)ch);  // crude but works if high
> byte is zero
>
We have a correct UTF-16 to UTF-8 converter.

> +       }
> +       grub_printf("\n");
> +    }
> +    else
> +    {
> +       grub_printf("Value (hex):\n");
> +       for (grub_size_t i = 0; i < data_size; i++)
> +       {
> +               grub_printf("%02x ", data[i]);
>
We have a good hexdump function.

> +               if ((i + 1) % 16 == 0)
> +                       grub_printf("\n");
> +       }
> +       grub_printf("\n");
> +    }
> +
> +    grub_free(data);
> +}
> +
> +static grub_err_t
> +dump_efi_variables(void)
> +{
> +       grub_efi_status_t status;
> +       grub_efi_runtime_services_t *r;
> +       grub_efi_uintn_t variable_name_size = 512;
> +       grub_efi_char16_t *variable_name;
> +       grub_uint8_t *variable_name_string = NULL;
> +       grub_guid_t vendor_guid;
> +
> +       r = grub_efi_system_table->runtime_services;
> +
> +       variable_name = grub_malloc(variable_name_size);
> +       if (!variable_name)
> +               return grub_error(GRUB_ERR_OUT_OF_MEMORY, "initial malloc
> failed");
>
Just return grub_errno.

> +       *variable_name = 0; /* Start with empty string */
> +
> +       while (1)
> +       {
> +               status = r->get_next_variable_name(&variable_name_size,
> variable_name, &vendor_guid);
> +               if (status == GRUB_EFI_NOT_FOUND)
> +                       break;
> +               variable_name_string = grub_realloc(variable_name_string,
> variable_name_size);
>
Missing error handling.

> +               grub_utf16_to_utf8(variable_name_string, variable_name,
> variable_name_size);
> +
>  grub_printf("%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x-%s\n",
> vendor_guid.data1,
>
We have %pG qualifier.

> +
>      vendor_guid.data2,
> +
>      vendor_guid.data3,
> +
>      vendor_guid.data4[0], vendor_guid.data4[1],
> +
>      vendor_guid.data4[2], vendor_guid.data4[3],
> +
>      vendor_guid.data4[4], vendor_guid.data4[5],
> +
>      vendor_guid.data4[6], vendor_guid.data4[7],
> +
>      variable_name_string);
> +               get_variable_data((char*)variable_name_string,
> &vendor_guid);
> +       }
> +
> +       grub_free(variable_name);
> +       grub_free(variable_name_string);
> +       return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t
> +grub_cmd_efivar (grub_command_t cmd __attribute__((unused)),
> +                int argc __attribute__((unused)), char **argv
> __attribute__((unused)))
> +{
> +       return dump_efi_variables();
> +}
> +
> +static grub_command_t cmd;
> +
> +GRUB_MOD_INIT(efivar)
> +{
> +       cmd = grub_register_command("efivar", grub_cmd_efivar, NULL,
> N_("Display UEFI variables."));
>
I'd rather have function lsefivar [-l] to be consistent with other similar
GRUB commands. Without -l it would skip variable contents

> +}
> +GRUB_MOD_FINI(efivar)
> +{
> +       grub_unregister_command(cmd);
> +}
> --
> 2.49.0
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to