Initial testpci module and command used to query if PCI devices are present.
--- docs/grub.texi | 8 ++ grub-core/Makefile.core.def | 7 ++ grub-core/commands/testpci.c | 167 +++++++++++++++++++++++++++++++++++ 3 files changed, 182 insertions(+) create mode 100644 grub-core/commands/testpci.c diff --git a/docs/grub.texi b/docs/grub.texi index 2b3d536d3..296c60b72 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 @@ -8498,6 +8505,7 @@ GRUB shell may provide more information on parameters and usage. @item @command{syslinux_source} - Execute syslinux config in same context @item @command{test_blockarg} - Print and execute block argument., 0 @item @command{testload} - Load the same file in multiple ways. +@item @command{testpci} - Test if a PCI device is present. @item @command{testspeed} - Test file read speed. @item @command{tgatest} - Tests loading of TGA bitmap. @item @command{time} - Measure time used by COMMAND 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..aaeb45e55 --- /dev/null +++ b/grub-core/commands/testpci.c @@ -0,0 +1,167 @@ +/* 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", 0, 0, "read device list from file", "FILE", ARG_TYPE_STRING}, + {0, 0, 0, 0, 0, 0} +}; + +struct grub_testpci_devlist { + char** devices; + int n_devices; + int s_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 = grub_xasprintf ("%04x:%04x", pciid & 0xFFFF, pciid >> 16); + for (int i = 0; i < devlist->n_devices; i++) { + if (grub_strcasecmp(device, devlist->devices[i]) == 0) { + grub_free(device); + devlist->found = true; + return 1; + } + } + + grub_free(device); + return 0; +} + +static void +testpci_add_device_to_list(struct grub_testpci_devlist* devlist, + char* device) +{ + if (devlist->n_devices == devlist->s_devices) { + devlist->s_devices *= 2; + devlist->devices = grub_realloc(devlist->devices, + devlist->s_devices * sizeof(char*)); + if (!(devlist->devices)) { + return; + } + } + devlist->devices[devlist->n_devices++] = grub_strdup(device); +} + +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.s_devices = argc + (ctxt->state[0].set ? 5 : 0); + devlist.devices = grub_malloc(devlist.s_devices * sizeof(char*)); + if (!(devlist.devices)) { + return GRUB_ERR_OUT_OF_MEMORY; + } + + for (int i = 0; i < argc; i++) { + testpci_add_device_to_list(&devlist, args[i]); + if (!(devlist.devices)) { + return GRUB_ERR_OUT_OF_MEMORY; + } + } + + /* device list from file */ + if (ctxt->state[0].set) { + + grub_file_t listfile = grub_file_open(ctxt->state[0].arg, GRUB_FILE_TYPE_NONE); + 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; + + testpci_add_device_to_list(&devlist, p); + if (!(devlist.devices)) { + return GRUB_ERR_OUT_OF_MEMORY; + } + + } + + grub_file_close (listfile); + } + } + + for (int d = 0 ; d < devlist.n_devices; d++) { + if (grub_strlen(devlist.devices[d]) != 9 || devlist.devices[d][4] != ':') { + grub_printf("bad input device (%d) \"%s\", expected xxxx:xxxx\n", d, devlist.devices[d]); + } + } + + grub_pci_iterate (grub_testpci_iter, (void*)&devlist); + + for (int i = 0; i < devlist.n_devices; i++) { + grub_free(devlist.devices[i]); + } + grub_free(devlist.devices); + return devlist.found ? GRUB_ERR_NONE : GRUB_ERR_TEST_FAILURE; +} + +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); +} -- 2.39.5 _______________________________________________ Grub-devel mailing list Grub-devel@gnu.org https://lists.gnu.org/mailman/listinfo/grub-devel