Saving FDT subtly changes the behaviour. Image some command or even an external program modifying FDT and freeing old copy. Maybe we should call grub_efi_get_firmware_fdt every time we need fdt.
On Mon, Jun 17, 2024 at 4:08 PM Tobias Heider <tobias.hei...@canonical.com> wrote: > > The fdtdump command allows dumping arbitrary device tree properties > and saving them to a variable similar to the smbios command. > > This is useful in scripts where further actions such as selecting a > kernel or loading another device tree depend on the compatible or > model values of the device tree provided by the firmware. > > For now only the root level properties of the dtb are exposed. > > The firmware provided device-tree is not expected to change so we > load it once during module initialization and then use it where > needed. > > Signed-off-by: Tobias Heider <tobias.hei...@canonical.com> > --- > docs/grub.texi | 26 ++++++++++++++++++++ > grub-core/loader/efi/fdt.c | 49 +++++++++++++++++++++++++++++++++++++- > 2 files changed, 74 insertions(+), 1 deletion(-) > > diff --git a/docs/grub.texi b/docs/grub.texi > index f3bdc2564..a050dc0fc 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -4373,6 +4373,7 @@ you forget a command, you can run the command > @command{help} > * eval:: Evaluate agruments as GRUB commands > * export:: Export an environment variable > * false:: Do nothing, unsuccessfully > +* fdtdump:: Retrieve device tree information > * fwsetup:: Reboot into the firmware setup menu > * gdbinfo:: Provide info for debugging with GDB > * gettext:: Translate a string > @@ -4904,6 +4905,31 @@ such as @code{if} and @code{while} (@pxref{Shell-like > scripting}). > @end deffn > > > +@node fdtdump > +@subsection fdtdump > + > +@deffn Command fdtdump @ > + [@option{--prop} @var{prop}] @ > + [@option{--set} @var{variable}] > +Retrieve device tree information. > + > +The @command{fdtdump} command returns the value of a property in the device > +tree provided by the firmware. The @option{--prop} option determines which > +property to select. > + > +The default action is to print the value of the requested field to the > console, > +but a variable name can be specified with @option{--set} to store the value > +instead of printing it. > + > +For example, this will store and then display the model string. > + > +@example > +fdtdump --prop model --set machine_model > +echo $machine_model > +@end example > +@end deffn > + > + > @node fwsetup > @subsection fwsetup > > diff --git a/grub-core/loader/efi/fdt.c b/grub-core/loader/efi/fdt.c > index 439964b9c..cb0422d98 100644 > --- a/grub-core/loader/efi/fdt.c > +++ b/grub-core/loader/efi/fdt.c > @@ -1,6 +1,7 @@ > /* > * GRUB -- GRand Unified Bootloader > * Copyright (C) 2013-2015 Free Software Foundation, Inc. > + * Copyright (C) 2024 Canonical, Ltd. > * > * GRUB is free software: you can redistribute it and/or modify > * it under the terms of the GNU General Public License as published by > @@ -18,15 +19,18 @@ > > #include <grub/fdt.h> > #include <grub/mm.h> > +#include <grub/env.h> > #include <grub/err.h> > #include <grub/dl.h> > #include <grub/command.h> > +#include <grub/extcmd.h> > #include <grub/file.h> > #include <grub/efi/efi.h> > #include <grub/efi/fdtload.h> > #include <grub/efi/memory.h> > #include <grub/cpu/efi/memory.h> > > +static void *fw_fdt; > static void *loaded_fdt; > static void *fdt; > > @@ -36,6 +40,13 @@ static void *fdt; > sizeof (FDT_ADDR_CELLS_STRING) + \ > sizeof (FDT_SIZE_CELLS_STRING)) > > +static const struct grub_arg_option options_fdtdump[] = { > + {"prop", 'p', 0, N_("Get property."), N_("prop"), ARG_TYPE_STRING}, > + {"set", '\0', 0, N_("Store the value in the given variable name."), > + N_("variable"), ARG_TYPE_STRING}, > + {0, 0, 0, 0, 0, 0} > +}; > + > void * > grub_fdt_load (grub_size_t additional_size) > { > @@ -51,7 +62,7 @@ grub_fdt_load (grub_size_t additional_size) > if (loaded_fdt) > raw_fdt = loaded_fdt; > else > - raw_fdt = grub_efi_get_firmware_fdt(); > + raw_fdt = fw_fdt; > > if (raw_fdt) > size = grub_fdt_get_totalsize (raw_fdt); > @@ -167,10 +178,45 @@ out: > return grub_errno; > } > > +static grub_err_t > +grub_cmd_fdtdump (grub_extcmd_context_t ctxt, > + int argc __attribute__ ((unused)), > + char **argv __attribute__ ((unused))) > +{ > + struct grub_arg_list *state = ctxt->state; > + const char *value = NULL; > + > + if (fw_fdt == NULL) > + return grub_error (GRUB_ERR_IO, > + N_("No device tree found")); > + > + if (state[0].set) > + value = grub_fdt_get_prop (fw_fdt, 0, state[0].arg, NULL); > + > + if (value == NULL) > + return grub_error (GRUB_ERR_OUT_OF_RANGE, > + N_("failed to retrieve the prop field")); > + > + if (state[1].set) > + grub_env_set (state[1].arg, value); > + else > + grub_printf ("%s\n", value); > + > + return GRUB_ERR_NONE; > +} > + > static grub_command_t cmd_devicetree; > +static grub_extcmd_t cmd_fdtdump; > > GRUB_MOD_INIT (fdt) > { > + fw_fdt = grub_efi_get_firmware_fdt(); > + > + cmd_fdtdump = > + grub_register_extcmd ("fdtdump", grub_cmd_fdtdump, 0, > + N_("[-p] [--set variable]"), > + N_("Retrieve device tree information."), > + options_fdtdump); > cmd_devicetree = > grub_register_command_lockdown ("devicetree", grub_cmd_devicetree, 0, > N_("Load DTB file.")); > @@ -179,4 +225,5 @@ GRUB_MOD_INIT (fdt) > GRUB_MOD_FINI (fdt) > { > grub_unregister_command (cmd_devicetree); > + grub_unregister_extcmd (cmd_fdtdump); > } > -- > 2.43.0 > > > _______________________________________________ > Grub-devel mailing list > Grub-devel@gnu.org > https://lists.gnu.org/mailman/listinfo/grub-devel -- Regards Vladimir 'phcoder' Serbinenko _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel