Looks good Reviewed-by: Vladimir Serbinenko phco...@gmail.com Regards Vladimir 'phcoder' Serbinenko
Le lun. 12 mai 2025, 14:55, Yair Yarom <ir...@cs.huji.ac.il> a écrit : > Initial testpci module and command used to query if PCI devices are > present. > > --- > docs/grub.texi | 39 +++++++ > grub-core/Makefile.core.def | 7 ++ > grub-core/commands/testpci.c | 194 +++++++++++++++++++++++++++++++++++ > grub-core/kern/efi/sb.c | 1 + > include/grub/file.h | 2 + > 5 files changed, 243 insertions(+) > create mode 100644 grub-core/commands/testpci.c > > diff --git a/docs/grub.texi b/docs/grub.texi > index 2b3d536d3..a5712012e 100644 > --- a/docs/grub.texi > +++ b/docs/grub.texi > @@ -4139,6 +4139,7 @@ Modules can be loaded via the @command{insmod} > (@pxref{insmod}) command. > * test_module:: > * test_blockarg_module:: > * testload_module:: > +* testpci_module:: > * testspeed_module:: > * tftp_module:: > * tga_module:: > @@ -5728,6 +5729,12 @@ argument function in GRUB internal functions via a > test command > This module is intended for performing a functional test of some file > reading / > seeking functions in GRUB internals via a test command @command{testload}. > > +@node testpci_module > +@section testpci > +This module provides support for the @command{testpci} command. This > +command can be used to test if specific PCI / PCIe devices are found on > +the system. > + > @node testspeed_module > @section testspeed > This module provides support for the @command{testspeed} command to test > and > @@ -8052,6 +8059,38 @@ either @var{expression1} or @var{expression2} is > true > @end table > @end deffn > > +@node testpci > +@subsection testpci > + > +@deffn Command testpci [@option{--file} device.lst] [@var{device} [...]] > +Test if a PCI device is present. > + > +Gets a device list to check from command line arguments, and/or from the > +@var{device.lst} file. > + > +If any of the devices in the list are present on the machine - the > +command exits with zero status. > + > +If the list is empty; Or non of the devices in the list are present; Or > +any error occurred (bad device format, missing file, memory, etc.) - a > +non-zero exit code is returned. > + > +Each @var{device} should be in the format @code{xxxx:yyyy}, where > +@code{xxxx} is the vendor id, and @code{yyyy} is the device id. All > +lower case as appear in the output of the @command{lspci} command. > + > +If @var{device.lst} file is given, each line should contain a single > +@var{device}. Space padding, comments starting with #, and empty lines > +are ignored. > + > +For example: > +@example > +if testpci --file $prefix/device.lst 10de:233b 1002:74a5; then > + set somevar=somevalue > +fi > +@end example > +@end deffn > + > @node tpm2_key_protector_init > @subsection tpm2_key_protector_init > > diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def > index f70e02e69..f18d2304d 100644 > --- a/grub-core/Makefile.core.def > +++ b/grub-core/Makefile.core.def > @@ -1032,6 +1032,13 @@ module = { > enable = pci; > }; > > +module = { > + name = testpci; > + common = commands/testpci.c; > + > + enable = pci; > +}; > + > module = { > name = memrw; > common = commands/memrw.c; > diff --git a/grub-core/commands/testpci.c b/grub-core/commands/testpci.c > new file mode 100644 > index 000000000..8af2a57a2 > --- /dev/null > +++ b/grub-core/commands/testpci.c > @@ -0,0 +1,194 @@ > +/* testpci.c - Test if PCI exists by ID. */ > +/* > + * GRUB -- GRand Unified Bootloader > + * Copyright (C) 2025 Free Software Foundation, Inc. > + * > + * GRUB is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 3 of the License, or > + * (at your option) any later version. > + * > + * GRUB is distributed in the hope that it will be useful, > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > + * GNU General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with GRUB. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#include <grub/dl.h> > +#include <grub/extcmd.h> > +#include <grub/mm.h> > +#include <grub/file.h> > +#include <grub/normal.h> > +#include <grub/pci.h> > + > +GRUB_MOD_LICENSE ("GPLv3+"); > + > +static const struct grub_arg_option options[] = { > + {"file", 'f', 0, "read device list from file", "FILE", ARG_TYPE_STRING}, > + {0, 0, 0, 0, 0, 0} > +}; > + > +struct grub_testpci_devlist { > + /* devices list */ > + char** devices; > + > + /* size of devices list */ > + int devices_size; > + > + /* number of allocated devices in the list <= devices_size */ > + int n_devices; > + > + bool found; > +}; > + > +static int > +grub_testpci_iter (grub_pci_device_t dev __attribute__ ((unused)), > + grub_pci_id_t pciid, > + void *data) { > + > + struct grub_testpci_devlist* devlist = (struct > grub_testpci_devlist*)data; > + char device[10]; > + > + grub_snprintf(device, sizeof(device), > + "%04x:%04x", pciid & 0xFFFF, pciid >> 16); > + for (int i = 0; i < devlist->n_devices; i++) { > + if (grub_strcasecmp(device, devlist->devices[i]) == 0) { > + devlist->found = true; > + return 1; > + } > + } > + > + return 0; > +} > + > +static void > +testpci_clear_device_list(struct grub_testpci_devlist* devlist) > +{ > + for (int i = 0; i < devlist->n_devices; i++) { > + grub_free(devlist->devices[i]); > + } > + grub_free(devlist->devices); > + devlist->n_devices = 0; > + devlist->devices_size = 0; > +} > + > +static grub_err_t > +testpci_add_device_to_list(struct grub_testpci_devlist* devlist, > + char* device) > +{ > + if (devlist->n_devices == devlist->devices_size) { > + devlist->devices_size *= 2; > + char** tmp = grub_realloc(devlist->devices, > + devlist->devices_size * sizeof(char*)); > + if (!tmp) { > + return grub_errno; > + } > + devlist->devices = tmp; > + } > + char* tmp = grub_strdup(device); > + if (!tmp) { > + return grub_errno; > + } > + devlist->devices[devlist->n_devices++] = tmp; > + return GRUB_ERR_NONE; > +} > + > +static grub_err_t > +grub_cmd_testpci (grub_extcmd_context_t ctxt, > + int argc, char **args) > +{ > + > + struct grub_testpci_devlist devlist; > + > + devlist.found = false; > + devlist.n_devices = 0; > + devlist.devices_size = argc + (ctxt->state[0].set ? 5 : 0); > + devlist.devices = grub_malloc(devlist.devices_size * sizeof(char*)); > + if (!(devlist.devices)) { > + return grub_errno; > + } > + > + for (int i = 0; i < argc; i++) { > + grub_err_t err = testpci_add_device_to_list(&devlist, args[i]); > + if (err) { > + testpci_clear_device_list(&devlist); > + return err; > + } > + } > + > + /* device list from file */ > + if (ctxt->state[0].set) { > + > + grub_file_t listfile = grub_file_open(ctxt->state[0].arg, > GRUB_FILE_TYPE_DEVICE_LIST); > + if (listfile) { > + > + char *buf = NULL; > + while (grub_free (buf), (buf = grub_file_getline (listfile))) { > + > + /* remove comments */ > + char *p = grub_strchr(buf, '#'); > + if (p) { > + *p = '\0'; > + } > + > + /* remove suffix spaces */ > + p = buf + grub_strlen(buf) - 1; > + while (p >= buf && *p && grub_isspace(*p)) { > + *p-- = '\0'; > + } > + > + /* remove prefix spaces */ > + p = buf; > + while (*p && grub_isspace(*p)) { > + p++; > + } > + > + /* ignore empty */ > + if (*p == '\0') > + continue; > + > + grub_err_t err = testpci_add_device_to_list(&devlist, p); > + if (err) { > + testpci_clear_device_list(&devlist); > + return err; > + } > + } > + > + grub_file_close (listfile); > + } else { > + return grub_errno; > + } > + } > + > + for (int d = 0 ; d < devlist.n_devices; d++) { > + if (grub_strlen(devlist.devices[d]) != 9 || devlist.devices[d][4] != > ':') { > + grub_printf("invalid device (%d) \"%s\", expected xxxx:xxxx\n", d, > devlist.devices[d]); > + testpci_clear_device_list(&devlist); > + return grub_error(GRUB_ERR_BAD_ARGUMENT, "invalid device"); > + } > + } > + > + grub_pci_iterate (grub_testpci_iter, (void*)&devlist); > + > + testpci_clear_device_list(&devlist); > + > + return devlist.found ? > + GRUB_ERR_NONE : grub_error(GRUB_ERR_TEST_FAILURE, "device not found"); > +} > + > +static grub_extcmd_t cmd; > + > +GRUB_MOD_INIT(testpci) > +{ > + cmd = grub_register_extcmd ("testpci", grub_cmd_testpci, 0, > + "[<devid> [...]] [--file <filename>]", > + N_("Check if any of the PCI devices > exist."), options); > +} > + > +GRUB_MOD_FINI(testpci) > +{ > + grub_unregister_extcmd (cmd); > +} > diff --git a/grub-core/kern/efi/sb.c b/grub-core/kern/efi/sb.c > index 8d3e41360..0c7f45ec5 100644 > --- a/grub-core/kern/efi/sb.c > +++ b/grub-core/kern/efi/sb.c > @@ -168,6 +168,7 @@ shim_lock_verifier_init (grub_file_t io __attribute__ > ((unused)), > case GRUB_FILE_TYPE_THEME: > case GRUB_FILE_TYPE_GETTEXT_CATALOG: > case GRUB_FILE_TYPE_FS_SEARCH: > + case GRUB_FILE_TYPE_DEVICE_LIST: > case GRUB_FILE_TYPE_LOADENV: > case GRUB_FILE_TYPE_SAVEENV: > case GRUB_FILE_TYPE_VERIFY_SIGNATURE: > diff --git a/include/grub/file.h b/include/grub/file.h > index a5bf3a792..80ebaba90 100644 > --- a/include/grub/file.h > +++ b/include/grub/file.h > @@ -126,6 +126,8 @@ enum grub_file_type > GRUB_FILE_TYPE_FS_SEARCH, > GRUB_FILE_TYPE_AUDIO, > GRUB_FILE_TYPE_VBE_DUMP, > + /* device list for testpci command */ > + GRUB_FILE_TYPE_DEVICE_LIST, > > GRUB_FILE_TYPE_LOADENV, > GRUB_FILE_TYPE_SAVEENV, > -- > 2.39.5 > > > _______________________________________________ > 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